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!


Nenhum comentário:

Postar um comentário