sábado, 16 de agosto de 2014

Complexidade dos projetos e adequação

Olá pessoal,

Hoje não vamos abordar um shield ou um componente mas vamos falar de assunto importante para os desenvolvedores da plataforma Arduino: a complexidade dos projetos e sua adequação.
Nestes posts até agora percebemos que à medida que vamos adicionando funcionalidades ao projeto a sua complexidade aumenta e é importante elencarmos os fatores que devemos estar atentos para que o projeto continue funcionando e haja a devida adequação de software (código) ao hardware e vice-versa.
Dentro da minha experiência na plataforma devemos estar atentos aos seguintes fatores:

1) Aumento do tamanho dos sketches

    A medida que o projeto aumenta no uso de shields, componentes e bibliotecas é necessário cada vez mais espaço para armanezar os sketches. Os sketches são armazenados na Flash Memory. Fiz uma relação abaixo das versões do Arduino que utilizei nos meus testes e projetos:

Arduino UNO:

.


MicrocontroladorATmega328
Tensão de operação5V
Tensão de entrada(recomendado)7-12V
Tensão de entrada (limites)6-20V
Pinos de I/O Digitais14 (dos quais 6 fornecem saída PWM)
Pinos de entrada analógicos6
Corrente DC por pino de I/O 40 mA
Corrente DC Pino 3.3V50 mA
Memória Flash 32 KB (ATmega328) dos quais 0.5 KB são usados pelo bootloader
SRAM2 KB (ATmega328)
EEPROM1 KB (ATmega328)
Velocidade do Clock16 MHz

Arduino Duemilanove:



MicrocontroladorATmega168 ou ATmega328
Tensão de operação5V
Tensão de entrada(recomendado)
7-12V
Tensão de entrada (limites)6-20V
Pinos de I/O Digitais14 (dos quais 6 fornecem saída PWM)
Pinos de entrada analógicos6
Corrente DC por pino I/O 40 mA
Corrente DC pino 3.3V50 mA
Memória Flash16 KB (ATmega168) ou 32 KB (ATmega328) dos quais 2 KB são usados pelo bootloader
SRAM1 KB (ATmega168) ou 2 KB (ATmega328)
EEPROM512 bytes (ATmega168) ou 1 KB (ATmega328)
Velocidade do Clock16 MHz

Arduino Leonardo:


MicrocontroladorATmega32u4
Tensão de operação5V
Tensão de entrada(recomendado)
7-12V
Tensão de entrada (limites)6-20V
Pinos de I/O digitais20
Canais PWM7
Canais de entrada analógicos12
Corrente DC por pino I/O40 mA
Corrente DC pino 3.3V50 mA
Memória Flash32 KB (ATmega32u4) dos quais 4 KB são usados pelo bootloader
SRAM2.5 KB (ATmega32u4)
EEPROM1 KB (ATmega32u4)
Velocidade do Clock 16 MHz

Arduino Mega:


MicrocontroladorATmega2560
Tensão de operação5V
Tensão de entrada(recomendado)
7-12V
Tensão de entrada (limites)6-20V
Pinos de I/O Digitais54 (dos quais 15 fornecem saída PWM)
Pinos de entrada analógicos16
Corrente DC por pino I/O 40 mA
Corrente DC pino 3.3V50 mA
Memória Flash256 KB dos quais 8 KB são usados pelo bootloader
SRAM8 KB
EEPROM4 KB
Velocidade do Clock16 MHz
É importante adequar os sketches para utilizar menos código quando você tem um Arduino com menor espaço de armazenamento. Siga algumas dessas dicas:
a) Verifique se há alguma biblioteca desnecessária ao projeto e se for comente-a.
b) Faça debug com a Serial somente nos trechos de código que é realmente necessário checar. Debug na serial consome espaço de código.
c) Se não há mais o que otimizar no código considere a possibilidade de adquirir um outro Arduino com mais espaço para os sketches (Arduino Mega por exemplo).

2) Aumento do uso de variáveis de memória

    O uso de variáveis de memória e estruturas consomem SRAM e dependendo do Arduino podem fazer com que haja reinicializações por conta de falta de memória SRAM . Tive uma experiência em projeto em que o Arduino simplesmente reinicializava se fosse utilizando uma variável float! Siga algumas dicas para usar menos memória:
a) Defina o tamanho das arrays char no tamanho exato.
b) Evitar usar variáveis float quando os valores a serem armazenados possam ser armazenados em variáveis int.
c) Se não há mais o que otimizar no uso de variáveis considere a possibilidade de adquirir um outro Arduino com mais SRAM (Arduino Mega por exemplo). Você pode adquirir também o Arduino Leonardo porém ele tem menos Flash Memory.


3) Aumento do uso de componentes e sensores

    Se o projeto demanda por mais pinos considere utilizar um Arduino com maior quantidade de pinos de entrada/saída. Deve-se ficar atento em relação à alimentação do Arduino quando utilizar muitos componentes nas portas digitais. Relata-se bastante problemas com relês que de alguma forma fazem o Arduino reiniciar.


4) Uso de várias bibliotecas e shields.

    O uso de várias bibliotecas podem aumentar o código além de aumentar a probabilidade de conflito de componentes ou shields por utilizarem os mesmos pinos. Os shields geralmente são empilháveis porém podem trazer algumas dificuldades para conexão.
Dica: ao trabalhar com display LCD prefira os que são I2C pois eles necessitam somente de dois pinos analógicos.

5) Módulos que necessitam de mais corrente.

   Shields GSM e servos podem necessitar de mais corrente que o fornecido pelo Arduino e necessitam de alimentação externa e podem influenciar no funcionamento destes. Fiquem atentos nestes detalhes!

Espero que essas dicas sejam bastante úteis! Se você tem experiências desse tipo relate-nos.

Até a próxima!!

quinta-feira, 14 de agosto de 2014

Shield GSM/GPS SIM908

Olá pessoal,

Hoje vamos falar do shield GSM/GPRS/GPS SIM908 que dá a funcionalidade de chamadas de voz, SMS, dados via Internet e fax e mais a funcionalidade de GPS (localização). Este shield será utilizado no projeto para envio de SMS quando houver o aumento de temperatura e isto contornará o problema de monitoramento pois há maior chance do aviso chegar a uma rede GSM (celular) pois muitas vezes não temos uma conexão ativa de rede (mesmo redes móveis como 3G).
Vamos lá então!

Shield GSM/GPS SIM908

Desconectei a antena do GPS por não utilizá-la nos testes. Posteriormente vamos testar essa funcionalidade também!! Utilizei um cartão micro SIM de uma operadora e coloquei alguns créditos (você pode utilizar um cartão SIM ou micro SIM - quando usar o micro SIM encaixe com cuidado os contatos do cartão).

Esquema de ligação: este shield deve ser empilhado por último se você tiver outros shields por conta dos componentes que ele utiliza (são altos e o próprio shield não disponibiliza as barras de pinos). Eu utilizei ele sem empilhar no Arduino, fazendo as ligações com jumpers e utilizando uma mini protoboard em que eu a cortei no meio. Utilizei um quadro de distribuição Tigre para 3 ou 4 disjuntores para acomodar os componentes. Abri a caixa, retirei os suportes internos para os disjuntores. Posteriormente vou utilizá-lo para um outro projeto.
 Vejam as fotos abaixo para ter uma idéia de como fixei o shield:


Quadro de distribuição para 3/4 disjuntores


Mini protoboard cortada ao meio e colada na parte interna do quadro com dupla face
Coloquei o shield de GSM forma que os pinos 2,3,5,6 ficassem alinhadas com os furos.

Conectei os jumpers na protoboard nos pontos correspondentes aos pinos.
Em outra lado do quadro fixei o Arduino e liguei os jumpers nos pinos 2, 3,5,6 do Arduino. Conectei jumpers nos pinos 3.3V, 5V, GND e Vin.
Conectei os pinos 3.3V, 5V, GND e Vin na protoboard ligada ao shield GSM.



Importante: conectar o Arduino com fonte externa. Para acionar o shield ele necessita de mais corrente que o Arduino fornece.

A biblioteca correspodente deste shield é esta:

https://github.com/MarcoMartines/GSM-GPRS-GPS-Shield
 
Vamos ao código:

#include "SIM900.h"
#include <SoftwareSerial.h>


// Se você quiser usar as funções para gerenciar SMS, descomente as linhas abaixo
#include "sms.h"
#include "call.h"

SMSGSM sms;

// Para mudar os pinos TX e RX modifique na biblioteca GSM.cpp (o padrão é pino 2 para TX e pino 3 para RX


//GSM Shield for Arduino
//www.open-electronics.org
//this code is based on the example of Arduino Labs.

//Este sketch envia um simples SMS. Há trechos comentados para efetuar chamadas de voz e ler SMS. Descomente-os se quiser testar essas funcionalidades.

int numdata;
boolean started=false;
char smsbuffer[160];
char n[20];
int powerkey =  5;
int statuspin = 6;
int pinState = 0;

CallGSM call;


void setup()
{
  pinMode(powerkey, OUTPUT); //define pino 5 como saída
  pinMode(statuspin, INPUT); //define pino 6 como entrada
 
  pinState = digitalRead(statuspin); //Lê o estado do pino 6




  
  // Se o pino 6 estiver LOW, faz a sequencia de power on do Shield
  if(pinState==LOW){
    digitalWrite(powerkey, HIGH);   // seta o pino 5 como HIGH
    delay(2000); // espera 2 segundos
    digitalWrite(powerkey, LOW);    // seta o pino 5 como LOW
  }


  //Inicia monitoramento da serial.
  Serial.begin(9600);


  Serial.println("Testando GSM Shield.");
  //Inicia a configuração do shield GSM com a velocidade de 2400
  

  if (gsm.begin(2400)){
    Serial.println("\nstatus=READY");
    started=true; 
  }
  else Serial.println("\nstatus=IDLE");
  

  // Se o shield iniciou envia o SMS com a função SendSMS passando o número e a mensagem
  

  if(started){
     if (sms.SendSMS("015XXXXXXXXX", "Teste de SMS"))
      Serial.println("\nSMS sent OK");
    

     Se quiser testar chamadas de voz descomente as linhas abaixo
    /*
    if(call.CallStatus()!= CALL_ACTIVE_VOICE){

           Serial.println("Chamando");

           call.Call(015XXXXXXXXX);
    */
 
  }

}

void loop()
{

  // Se quiser testar a leitura de SMS descomente as linhas abaixo
  /*

  if(started){
    //Read if there are messages on SIM card and print them.
    if(gsm.readSMS(smsbuffer, 160, n, 20))
    {
      Serial.println(n);
      Serial.println(smsbuffer);
    }
    delay(1000);
  }

  */
};





Pessoal, é isso aí. Qualquer dúvida enviem seus comentários.

Até a próxima! 

sábado, 2 de agosto de 2014

Shield Ethernet Wiznet W5100 - Envio de e-mail

Olá pessoal,

Hoje vamos ver como utilizar o shield Ethernet para o envio de e-mail. No projeto de acionamento automático de ar condicionado com infravermelho seria interessante que no momento em que houvesse o aumento de temperatura acima do programado o Arduino pudesse enviar algum tipo de aviso por e-mail pois o aviso sonoro e na tela do display só seriam percebidos se alguém estivesse no ambiente em que ele está.
Há algumas considerações:
1) É necessário que a infraestrutura de rede esteja funcionando no momento em que o Arduino for enviar o e-mail. Como o Arduino e os equipamentos estão ligados em um nobreak se houver queda de energia e o ar condicionado desligar o aviso por e-mail vai funcionar.
2) É necessária uma conexão de rede ativa por parte de quem está monitorando. Seja por celular, notebook ou PC se o e-mail for enviado alguém deve estar conectado para poder receber o aviso por e-mail. Se o e-mail for enviado e ninguém lê-lo é a mesma coisa não estar monitorando! Aí talvez implique que você deva ter uma conexão móvel (3G ou qualquer coisa parecida) e manter essa conexão ativa o tempo todo.
Mesmo com essa limitação por parte de monitoramento ainda assim acredito que o envio de e-mail é interessante por registrar a falha e com isso também compormos estatísticas de falhas e tomarmos providências sejam internas ou por parte da concessionária de energia para melhorar a disponibilidade de energia.
Vamos lá então:

Esquema de ligação: o mesmo do projeto de acionamento acrescentado somente o shield Ethernet.

Código:


#include <dht11.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <IRremote.h>
#include <SPI.h>
#include <Ethernet.h>
#include "RTClib.h"

//codigo rawcode capturado do ar condiconado via IRRecvDump
unsigned int powerOn[92] = {8950,4300,650,500,700,450,650,1600,650,500,600,1650,700,450,650,500,650,500,650,450,600,1700,600,550,550,550,600,1700,600,500,600,550,600,550,600,550,600,500,700,450,600,550,600,550,600,500,600,550,600,550,600,550,550,550,600,550,600,550,600,550,550,550,600,550,600,550,600,500,600,550,650,500,600,550,600,500,600,550,600,550,600,550,550,1700,600,550,600,550,550,1700,700};

// this must be unique
static byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 
// change network settings to yours

IPAddress ip(192,168,1,177);

// Endereço do seu servidor de e-mail
char server[] = "seuservidordeemail";

EthernetClient client;

boolean enviouEmailDOWN;
boolean enviouEmailUP;
boolean enviouSMSDOWN;
boolean enviouSMSUP;

// Objeto irsend para emissor infrared 
IRsend irsend;

// Objeto rtc (relogio de tempo real)
RTC_DS1307 rtc;

// Objeto LCD com 2 linhas e 16 caracteres por linha
#define lcdAddr 0x20LiquidCrystal_I2C lcd(lcdAddr, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE);



float sinVal;
int toneVal;

//objeto sensor para DHT11 (sensor de temperatura)
dht11 sensor;


// função que envia e-mail quando desligar o ar condicionado byte sendEmailDOWN()
{
  byte thisByte = 0;
  byte respCode;

  // testa se há conexão com o servidor de e-mail na porta 25   if(client.connect(server,25)) {
    Serial.print(F("connected"));
  } else {
    Serial.print(F("connection failed"));
    return 0;
  }


  if(!eRcv()) return 0;
  Serial.print(F("Sending helo")); 

// Mude para o ip do Arduino
  client.println(F("helo <seu ip>")); //envia o helo para o servidor de e-mail

  if(!eRcv()) return 0;
  Serial.print(F("Sending From"));

// Coloque um e-mail váido do seu servidor de e-mail
  client.println(F("MAIL From: <arduino1@sorocaba.unesp.br>"));

  if(!eRcv()) return 0;

// Coloque o e-mail do destinatário
  Serial.print(F("Sending To"));
  client.println(F("RCPT To: <destinatario@seudominiodeemail.com>"));

  if(!eRcv()) return 0;

// Envie os dados do e-mail   Serial.print(F("Sending DATA"));
  client.println(F("DATA"));

  if(!eRcv()) return 0;

  Serial.print(F("Sending email"));

// Mude para o e-mail do destinatário
  client.println(F("To: Fernando <destinatario@seudominiodeemail.com>"));

// change to your address
  client.println(F("From: Arduino <arduino1@sorocaba.unesp.br>"));

  client.println(F("Subject: Temperatura alta\r\n"));

  client.println(F("Temperatura alta no datacenter"));

  client.println(F("."));

  if(!eRcv()) return 0;

  Serial.print(F("Sending QUIT"));

  //Saindo da conexão com a porta 25 do servidor de e-mail
  client.println(F("QUIT"));

  if(!eRcv()) return 0;

  client.stop();

  Serial.print(F("disconnected"));

  enviouEmailDOWN = true; //se enviou e-mail de desligado


  return 1;
  
  
}

byte sendEmailUP()
{
  byte thisByte = 0;
  byte respCode;

  if(client.connect(server,25)) {
    Serial.print(F("connected"));
  } else {
    Serial.print(F("connection failed"));
    return 0;
  }
  if(!eRcv()) return 0;
  Serial.print(F("Sending helo"));

// change to your public ip
  client.println(F("helo <seu ip"));

  if(!eRcv()) return 0;
  Serial.print(F("Sending From"));

// change to your email address (sender)
  client.println(F("MAIL From: <arduino1@sorocaba.unesp.br>"));

  if(!eRcv()) return 0;

// 
  Serial.print(F("Sending To"));
  client.println(F("RCPT To: <fernando@sorocaba.unesp.br>"));

  if(!eRcv()) return 0;

  Serial.print(F("Sending DATA"));
  client.println(F("DATA"));

  if(!eRcv()) return 0;

  Serial.print(F("Sending email"));

// Mude para o e-mail de destino
  client.println(F("To: Fernando <fernando@sorocaba.unesp.br>"));

// Mude para o e-mail do remetente
  client.println(F("From: Arduino <arduino1@sorocaba.unesp.br>"));

  client.println(F("Subject: Temperatura normalizada\r\n"));

  client.println(F("Temperatura normalizada na SALA DO STI"));

  client.println(F("."));

  if(!eRcv()) return 0;

  Serial.print(F("Sending QUIT"));
  client.println(F("QUIT"));

  if(!eRcv()) return 0;

  client.stop();

  Serial.print(F("disconnected"));

  enviouEmailUP = true;

  return 1;
}

byte eRcv()
{
  byte respCode;
  byte thisByte;
  int loopCount = 0;

  while(!client.available()) {
    delay(1);
    loopCount++;

    // Se não receber e-mail por 10 segundos
    if(loopCount > 10000) {
      client.stop();
      Serial.print(F("\r\nTimeout"));
      return 0;
    }
  }

  respCode = client.peek();

  while(client.available())
  {  
    thisByte = client.read();    
    Serial.write(thisByte);
  }

  if(respCode >= '4')
  {
    efail();
    return 0;  
  }

  return 1;
}


void efail()
{
  byte thisByte = 0;
  int loopCount = 0;

  client.print(F("QUIT"));

  while(!client.available()) {
    delay(1);
    loopCount++;

    // if nothing received for 10 seconds, timeout
    if(loopCount > 10000) {
      client.stop();
      Serial.print(F("\r\nTimeout"));
      return;
    }
  }

  while(client.available())
  {  
    thisByte = client.read();    
    Serial.write(thisByte);
  }

  client.stop();

  Serial.print(F("disconnected"));
}

void setup() {
  Serial.begin(9600);  // Inicia conexao serial para monitoramento
  while (!Serial) {
      ; // wait for serial port to connect. Needed for Leonardo only
    }
  Ethernet.begin(mac);
  delay(1000);
  
  Serial.println("Ethernet iniciada");
  
  lcd.begin(16,2); // inicializa o lcd 
  lcd.setBacklight(1);
  Serial.println("LCD iniciada");
  delay(3000);
  pinMode(8,OUTPUT);  //pino 8 para saida do alto falante

  #ifdef AVR
    Wire.begin();
  #else
    Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
  #endif
  
  
  rtc.begin();  //inicia o objeto rtc

  //Verifica se o RTC esta funcionando
  if (! rtc.isrunning()) {
    Serial.print("RTC is NOT running!");
  }
  // Ajusta o rtc para a data e hora em que o sketch foi compilado
  
//  rtc.adjust(DateTime(__DATE__, __TIME__));

  Serial.println("RTC iniciada");
  delay(3000);

  enviouEmailDOWN = true;
  enviouEmailUP = true;
}


void loop() {
    
    
    DateTime now = rtc.now(); // carrega a data e hora do RTC
    
    Serial.print("Lendo sensor: ");
    int chk = sensor.read(2);  //le a temperatura
  
    
    //Verifica o status do DHT11
    switch(chk) {
        case DHTLIB_OK:
            Serial.println("OK");
            break;
        case DHTLIB_ERROR_CHECKSUM:
            Serial.println("Erro no checksum");
            break;
        case DHTLIB_ERROR_TIMEOUT:
            Serial.println("Tempo esgotado");
            break;
        default:
            Serial.println("Erro desconhecido");
    }
    
    // Monitora a umidade e temperatura para a conexao serial
    Serial.print("Umidade (%): ");
    Serial.println(sensor.humidity, 2);
    Serial.print("Temperatura (graus Celsius): ");
    Serial.println(sensor.temperature, 2);
   
    // Carrega os valores de temperatura e umidade do sensor nas variaveis correspondentes
    int temp = sensor.temperature;  
    int humi = sensor.humidity;

    //Se a temperatura for maior que 26 graus Celsius
    if (temp > 26) {
          // envia o codigo IR para ligar o AC     
          // Aciona o ar condicionado novamente 
          irsend.sendRaw(powerOn,92,38);
      
          // Exibe o valor da temperatura lida pelo sensor
          lcd.clear();  //limpa o display do LCD.    
          lcd.home(); // Posiciona o cursos na coluna 0, linha 0
          lcd.print("Temp: ");  //imprime a string Temp: no display do LCD.                 
          lcd.print(temp); // imprime a temperatura no LCD
          lcd.write(B11011111); //Simbolo de graus celsius
          lcd.print("C"); // Imprime C
          lcd.setCursor(0,1);  //posiciona o cursor na coluna 0 linha 1 do LCD.
          lcd.print("TEMP. ALTA!"); //Imprime o aviso de temperatura alta no display do LCD.
          
          //Aciona o alarme sonoro. Envia sinal sonoro para o pino 8 - alto falante
          
          for (int x=0; x<180; x++) {
            // converte graus para radianos e depois obtem o valor do seno
            //Serial.print("Toca o som");
            sinVal = (sin(x*(3.1416/180)));
            toneVal = 2000+(int(sinVal*1000));
            tone(8, toneVal);
            delay(2);
          }

          //Seta a variável enviouEmailUP como false
          enviouEmailUP = false;

          // Se não enviou e-mail envia com a função sendEmailDOWN. Caso já enviou não envia novamente 
          if (!enviouEmailDOWN) {
              sendEmailDOWN(); //envia e-mail de temperatura alta
          }
       
        
        
         //Aguarda 5 minutos para enviar novamente o codigo IR caso a temperatura nao baixe
         delay(300000);
         
    }
    else
    { 
          
          // Temperatura normal  
          lcd.clear();  //limpa o display do LCD.     
          lcd.home(); // Posiciona o cursos na coluna 0, linha 0
          lcd.print("Temp: ");  //imprime a string no display do LCD.                 
        
          lcd.print(temp); // Imprime o valor da temperatura
          lcd.write(B11011111); //Simbolo de graus celsius
          lcd.print("C");
          //Exibindo valor da leitura da umidade no display LCD.
          lcd.setCursor(0,1);  //posiciona o cursor na coluna 0 linha 1 do LCD.
          lcd.print("Umidade: ");  //imprime a string Umidade: no display do LCD.       
          lcd.print(humi); // Imprime o valor da umidade
          lcd.print("%");
          
          delay(5000);
          
          //Exibe a data e hora no LCD
          
          lcd.clear(); //limpa o display LCD
          lcd.home(); // Posiciona o cursos na coluna 0, linha 0          lcd.print("DATA: ");
          lcd.print(now.day(), DEC); //imprime o dia 
          lcd.print('/');
          lcd.print(now.month(), DEC); // imprime o mês
          lcd.print('/');
          lcd.print(now.year(), DEC); //imprime o ano
          lcd.setCursor(0,1);
          lcd.print("HORA: "); 
          lcd.print(now.hour(), DEC); //imprime a hora
          lcd.print(':');
          lcd.print(now.minute(), DEC); //imprime o minuto
          lcd.print(':');
          lcd.print(now.second(), DEC); //imprime o segundo
          
          delay(2000);
          noTone(8); //silencia o alarme sonoro
          
          //seta a variável enviouEmailDOWN como false
          enviouEmailDOWN = false;

          // Se não enviou e-mail envia com a função sendEmailUP. Caso já enviou não envia novamente 
          if (!enviouEmailUP) {
              sendEmailUP(); //envia o e-mail de temperatura normalizada
          }
    }
  
    delay(2000);
 }

Com isso o projeto de acionamento de ar condicionado com infravermelho conta com a funcionalidade de envio de e-mail quando há o aumento de temperatura e também quando a temperatura volta ao normal.
Como vocês perceberam o sketch está aumentando em tamanho a medida que vamos acrescentando mais componentes e funcionalidades. Este é o assunto para o próximo post.

Até mais!


sexta-feira, 1 de agosto de 2014

Shield Ethernet Wiznet W5100 - como utilizá-lo

Olá pessoal,

No post anterior vimos que algumas mudanças seriam necessárias ao projeto e uma delas é de fundamental importância: a emissão de alertas via e-mail ou SMS. Para isso tinha que adquirir novos componentes que adicionassem essas funcionalidades ao projeto. O primeiro desses componentes que vamos ver hoje é o shield Ethernet Wiznet W5100.
Um shield é uma placa para Arduino que adiciona novas funcionalidades e dá a capacidade de "empilhar" uma placa na outra. Para que tenhamos a capacidade de enviar e-mail temos que ter o shield e um servidor de e-mail que pudéssemos utilizá-lo para enviar mensagens através de uma conexão SMTP. Também seria necessário criar uma conta válida de e-mail neste servidor para utilizar no Arduino.
Assumindo que a conta de e-mail já está criada e o shield já adquirido vamos à implementação individual do shield (sem outras conexões do projeto) para entendermos como ele funciona:




Esquema de ligação:

Basta encaixar o shield Ethernet no Arduino.




Lembrando um pouco de redes agora:

A tecnologia Ethernet implementa a parte física da rede (camada 1 do modelo OSI) e a parte mais em baixo nível da lógica de acesso à rede (camada 2 do modelo OSI). O shield Ethernet W5100 utiliza a biblioteca padrão Ethernet do Arduino e esta biblioteca implementa as funções de acesso à rede (camada 2), implementa também a camada de rede (camada 3 do modelo OSI) para ser utilizado em redes IP e implementa as funções de camada de transporte (camada 4 do modelo OSI). Cada dispositivo Ethernet deve ter um MAC address único e alocar um IP exclusivo dentro de uma rede.
Essas três camadas devem estar funcionando adequadamente para que a comunicação em rede seja realizada. Você deve ter uma rede já funcional (com equipamentos de rede como roteadores ou switches) e o shield Ethernet deverá alocar um IP dessa rede.
O teste básico de rede para verificar se há comunicação entre dois dispositivos configurados com IP na mesma rede é com o utilitário ping, presente nos mais diversos sistemas operacionais. Você deve testar assim em um prompt de comando ou terminal:

ping <o ip que se quer testar>

E se houver comunicação o outro dispositivo irá responder à solicitação.

Para testarmos basta carregar o sketch de exemplo WebServer:


#include <SPI.h>
#include <Ethernet.h>

// O MAC address dave ser setado aqui. Ele deve ser único na sua
// rede
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

// Se você utiliza DHCP na sua rede não precisa definir esta 
// variável. Se não utiliza coloque os quatro octetos do endereço
// separados por vírgula. Esse IP tem que estar dentro da sua
// rede IP já configurada
IPAddress ip(192,168,1,177);

// Como este sketch é para servidor devemos configurar uma porta
// que será utilizada pelo servidor para escutar solicitações.
// Como é um web server a porta padrão para o serviço Web (HTTP)
// é a porta 80
EthernetServer server(80);

void setup() {
 // Inicia a serial 
  Serial.begin(9600);
   while (!Serial) {
    ; // Espera a porta serial para conexão. Necessário somente quando estiver usando o Arduino Leonardo
  }


  // Inicia o dispositivo Ethernet e fica aguardando conexões
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}


void loop() {
  // Ouvindo para clientes
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // Uma requisição http finaliza com uma linha em branco
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
 client.println("Refresh: 5");  // refresh the page automatically every 5 sec
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          // output the value of each analog input pin
          for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
            int sensorReading = analogRead(analogChannel);
            client.print("analog input ");
            client.print(analogChannel);
            client.print(" is ");
            client.print(sensorReading);
            client.println("<br />");       
          }
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disconnected");
  }
}

Este sketch irá iniciar um web server no Arduino, o endereço IP será o 192.168.1.177 e inicializará a porta 80 e a colocará em escuta.
Você pode testar se a comunicação IP está correta utilizando o ping. 

ping 192.168.1.177

Se der resposta a comunicação até o Arduino estará correta. 

Use um navegador e digite o endereço 192.168.1.177. Se aparecer a página o web server está respondendo solicitações na porta 80 e está respondendo com um conteúdo (neste sketch ele mostra o valor das entradas analógicas do Arduino).


Com este teste básico conseguimos colocar para funcionar o shield. No próximo post vamos ver como é realizado o envio de e-mail.