Ethernet Shield – Problemas

Dec 10
2010

Logo a seguir a ter escrito o post anterior Temperatura+Arduino+Mysql=RDDTool deparei-me com o LED do meu arduino, que ate à cinco minutos estava a actualizar perfeitamente, completamente acesso e os logs do webservice parados…Mas o que poderia estar a correr mal uma vez que o sketch que estava a usar ainda ontem funcionava sem problemas. La me decidi a ir ao google uma vez que isto ja me tinha acontecido algo parecido mas nunca pensei que fosse realmente da parte do hardware e não do software, aka código feito por mim.

E relamente encontrei logo nas primeiras pesquisas um forum onde alguem se queixava do mesmo problema e assim que removia o micro-SD card da slot que começava tudo a funcionar sem problemas…e não é que aconteceu mesmo isso? Assim que removi o cartão o shield começou imediatamente a funcionar sem qualquer problemas e ja esta assim a cerca de 2 horas.

Entretanto ja tentei meter novamente o cartao e pumba, voltou a crashar, nao sei se crashar será bem o termo correcto, será se calhar preferivel chamar-lhe “freezar” porque é o que faz, assim que removo o cartao começa novamente a funcionar sem problemas. Já mandei alguns mails e estou a espera de respostas. A parte mais estranha é que nem sequer estou a usar as libs para o cartão, a sdFatLib.

Por isso, para quem tem a nova EthernetShield com SD card, cuidado se por acaso de repente aquilo ficar “freezado”, testem sempre remover o cartão, para confirmar se é do cu ou das calças

Boa sorte…

Ja agora se alguém tiver uma solução para isto, por favor digam-me qualquer coisa. Como sempre a gerência agradece.

Temperatura+Arduino+Mysql=RDDTool

Dec 10
2010

Epa…tanta coisa num so titulo… a realidade é que é mesmo tudo isso que tenho andado a montar nos últimos dias. Isto porque temporariamente tive que, devido a falta de peças, abandonar o projecto Good Morning Dave, e focar-me mais no projecto “Save a Plant…by Twitter”.

Para aqueles que me seguem no twitter, ja perceberem que o arduino ja esta a mandar tweets com alguns bitaques, nomeadamente, as horas e a temperatura da sala, por isso ja posso dizer que a primeira parte do projecto “Save a Plant…by Twitter” estava feita, ou seja a parte do Twitter.

Por isso a segunda parte da ideia era de colocar os dados dos varios sensores numa base de dados para poder com esses dados gerar uns graficos todos bonitos, e poder fazer umas estatisticas caso seja necessario. Nao sou fã de estatisticas, mas ei, porque nao prevenir ja.

Mais uma vez, tudo parecia facil, era so montar um Webclient no Arduino e invocar um php ou um cgi que fazia a parte da inserção dos dados na BD(mysql)…mais uma vez erradoooo….

Eu em casa, por motivos de poupança de electricidade não tenho nada de servidores ligados, e isto porque um dia recebi um acerto da EDP de 370€ de luz e achei que estava na altura de NÃO ter servidores em casa, por isso surgia aqui o primeiro problema, que era onde é que vou por uma BD de mysql  e correr os scripts. Bem, a hipótese mais simples era usar este mesmo site, uma vez que tem tudo o que preciso, posso correr scripts, tenho BD!

Surgia aqui o meu segundo problema…DNS, por isso rapidamente abandonei a ideia de usar este estaminé. Num outro post falarei de porque abandonei o DNS.

Bem..tem que ser, vamos instalar um linux ca por casa com Mysql+Php+Perl+Apache+RDDTool+alltherest.

Esta foi a parte facil, demorou cerca de 1 hora e pumba tinha o servidor pronto, agora era so começar a inserir os dados na BD.

Para quem nunca usou o arduino para inserir dados extraidos de um sensor numa base de dados, o melhor é começar por fazer um webclient usando um dos exemplos e depois esquecer tudo aquilo que viu..wait!!?! say what!?!? pois isso mesmo, é que um dos maiores problemas que tenho tido com os exemplos é que sao quase sempre apontados para coisas com a Serial Port e eu quero mesmo é coisas que nao usem a Serial Port mas sim variaveis and stuff..

Depois de muito pesquisar e muito bater com a cabeça eis o codigo que usei para retirar os dados do sensor de temperatura que ja falei anteriormente e inserir na BD.

#include 
#include 
#include 
#include 
 
byte mac[] = { 0xDE, 0xDE, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 2, 177 };
byte server[] = { 192, 168, 2, 70 }; // DB
 
Client client(server, 80);
 
// Time Settings
byte SNTP_server_IP[]    = { 81, 92, 212, 46 }; // 3.pt.pool.ntp.org
time_t prevDisplay = 0; // when the digital clock was displayed
const  long timeZoneOffset = 0L; // set this to the offset in seconds to your local time;
 
// Temperature
int analoginput=0;
int value=0;
int R1=1000;
int Vin=5;
float tmp=0.0;
float Vout=0.0;
float f=0.0;
int lastTempReport = 0;
int currentTempReport = 0;
 
// Clock
int hora, minutos, ano, mes, dia;
 
int ID=69; //sensor ID
 
void setup()
{
  Ethernet.begin(mac, ip);
  Serial.begin(9600);
 
   //Clock Begin
  Serial.println("waiting for sync");
  setSyncProvider(getNtpTime);
  while(timeStatus()== timeNotSet)
    ; // wait until the time is set by the sync provider
 
}
 
void loop()
{
      addDB();
}
 
void addDB() {
 temperatura();
  int currentHumReport=10;
  Serial.print("CurrentHumReport");
  Serial.println(currentHumReport);
  delay(1000);
   char date[144] ="";
   char horas[144] ="";
   ano=(year());
   mes=(month());
   dia=(day());
   hora=(hour());
   minutos=(minute());
 
   sprintf(date, "%.2d-%.2d-%.2d", ano, mes, dia);
   sprintf(horas, "%.2d:%.2d", hora, minutos);
  if (client.connect()) {
    Serial.println("connected");
    delay(1000);
    client.print("GET /cgi-bin/sensor/inserir.cgi?date=");
        Serial.print("GET /cgi-bin/sensor/inserir.cgi?date=");
    client.print(date);
        Serial.print(date);
    client.print("&time=");
        Serial.print("&time=");
    client.print(horas);
        Serial.print(horas);
    client.print("&id=");
        Serial.print("&id=");
    client.print(ID);
        Serial.print(ID);
    client.print("&temperatura=");
        Serial.print("&temperatura=");
    client.print(currentTempReport);
        Serial.print(currentTempReport);
    client.print("&humidade=");
        Serial.print("&humidade=");
    client.print(currentHumReport);
        Serial.print(currentHumReport);
    client.println(" HTTP/1.1");
        Serial.println(" HTTP/1.1");
    client.println("Host: arduino.rechena.com");
        Serial.println("Host: arduino.rechena.com");
    client.println("User-Agent: Arduino");
        Serial.println("User-Agent: Arduino");
    client.println("Accept: text/html");
        Serial.println("Accept: text/html");
    client.println("Connection: close");
        Serial.println("Connection: close");
    client.println();
        Serial.println();
  }
  else {
    while (client.connected() && client.available()) {
      char c = client.read();
      Serial.print(c);
    }
  client.stop();
  delay(5000);
}
}
 
void temperatura () {
 
  Vout=1023-analogRead(0); // Invert the number because of setup
  Vout=(Vout/1024.0)*5;
  f=1000*exp(-20000/298.15); // 298.15K = 25C, 20000 seems to be the B value for a standard 1kOhm NTC
  tmp=(R1*Vin)/Vout-R1;
  value=(20000/log(tmp/f))-273.15;
   currentTempReport = value+7;
}
 
/*-------- NTP code ----------*/
 
unsigned long getNtpTime()
{
  sendNTPpacket(SNTP_server_IP);
  delay(1000);
  if ( UdpBytewise.available() ) {
    for(int i=0; i < 40; i++)
       UdpBytewise.read(); // ignore every field except the time
    const unsigned long seventy_years = 2208988800UL + timeZoneOffset;
    return getUlong() -  seventy_years;
  }
  return 0; // return 0 if unable to get the time
}
 
unsigned long sendNTPpacket(byte *address)
{
  UdpBytewise.begin(123);
  UdpBytewise.beginPacket(address, 123);
  UdpBytewise.write(B11100011);   // LI, Version, Mode
  UdpBytewise.write(0);    // Stratum
  UdpBytewise.write(6);  // Polling Interval
  UdpBytewise.write(0xEC); // Peer Clock Precision
  write_n(0, 8);    // Root Delay & Root Dispersion
  UdpBytewise.write(49);
  UdpBytewise.write(0x4E);
  UdpBytewise.write(49);
  UdpBytewise.write(52);
  write_n(0, 32); //Reference and time stamps
  UdpBytewise.endPacket();
}
 
unsigned long getUlong()
{
    unsigned long ulong = (unsigned long)UdpBytewise.read() << 24;
    ulong |= (unsigned long)UdpBytewise.read() << 16;
    ulong |= (unsigned long)UdpBytewise.read() << 8;
    ulong |= (unsigned long)UdpBytewise.read();
    return ulong;
}
 
void write_n(int what, int how_many)
{
  for( int i = 0; i < how_many; i++ )
    UdpBytewise.write(what);
}

Como podem ver o código é bastante simples. E funciona, a parte da BD não vou explicar com muito detalhade, ate porque o que não falta por ai são howtos de mysql e podem querer usar outras BD’s. Mas assim por alto tem uma tabela com um ID, Data, Hora, SensorID, Temperatura, Humidade. Algo importante é que o ID seja do tipo auto-increment, porque facilita bastante depois o tirar os dados para inserir nos gráficos de RDDTool.

Para a parte de tirar os dados da BD tambem nao vou falar nisso porque eu usei perl, muitos preferem php, python, etc, por isso em vez de criar uma guerra, usem cada um o seu. Se quiserem que mande os scripts e o export da bd que usei, avisem ai nos comentários ou email. Aviso que não é um codigo bonito, mas funciona 😉

Um pormenor importante, eu insiro da hora e data na BD directamente do arduino, podem cortar este passo e usar o proprio script que invocam no servidor, sempre torna o sketch do arduino mais leve, mas eu como quero depois usar este sketch para outros projectos onde me convém ter a hora e data directamente no arduino, vou usar assim, e não noto muita diferença em ter e não ter a hora/data no arduino. Também nao uso tudo directamente no void loop() por motivos de arrumação, assim quando quero fazer testes basta retirar a invocação do void especifico do loop e pumba esta a funcionar, ou nao…

Os graficos:

Nao é mais do que um rrdtool que recebe dois valores, um da temperatura e um da humidade e gera o grafico. Mas ei, funciona e faz gráficos, claro que se pode melhorar alguns pormenores, mas isto ainda é um prototipo do prototipo.

Peças necessarias:

1- Arduino

2- Sensor de Temperatura

3- Ethernet Shield

4 – Servidor com mysql+rrdtool+apache+etc

5- Tempo e paciencia.

No geral é tão simples quanto isto:

1 – Saca os dados do sensor
2- Formata os dados dos sensores
3- Insere os dados na BD do servidor
4- Formata os dados no servidor
5- Gera um grafico.

Como sempre, convém avisar que não percebo nada disto, e não me responsabilizo de usarem o meu código e derem cabo de qualquer coisa no vosso servidor ou no vosso arduino ;). Duvidas e sugestões, como sempre são muito bem vindas.

No futuro a ideia é usar o SD card do ethernet shield como backup caso a BD esteja em baixo, ou simplesmente tirar a BD da equação e guardar tudo no SD card e ir uma vez por dia via script buscar os dados ao SD card…

Follow Me