Ethernet se queda congelado

Hola gente del foro, hace tiempo no pregunto nada ]:slight_smile:

Estoy con un proyecto para el control de un jardín hidroponico, el mismo consiste en mostrar en una pantalla LCD los datos relevantes y guardar esos datos en una base de datos, para esto uso un ethernet shield como cliente web mandando datos por medio de GET al servidor que esta dentro de la red de mi casa.
El sistema funciona bien, pero luego de unas horas de uso no se conecta y no pasa los datos al servidor, y queda congelado el programa de arduino.

Alguna ayuda?

Hola

sin ver el codigo, se me ocurre que podria ser:
Podría ser un bufer lleno.
el desbordamiento de millis()
desbordamiento de la memoria ram.
etc.

ok te paso el codigo

/*
PInes usados:
Ethernet: 10,11,12,13
LCD: 9,8,7,6,5,2
Temperatura: 3
Luz: A0
*/

////Includes
#include <SPI.h>
#include <Ethernet.h>
#include <LiquidCrystal.h>
#include <EEPROM.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
LiquidCrystal lcd(9, 8, 7, 6, 5, 2);

////Ethernet
byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, XXX;
IPAddress gateway(192, 168, 1, XXX);
IPAddress subnet(255, 255, 255, 0);
IPAddress server(192, 168, 1, XXX);
char serverName[] = "192.168.1.XXX";
int serverPort = 80;
EthernetClient client;
char pageAdd[64];
#define delayMillis 60000UL //60 segundos
unsigned long thisMillis = 0;
unsigned long lastMillis = 0;

////definicion de actuadores
int calefaccion = 1;
int ventilacion = 0;
int iluminacion = 0;
int extraccion = 0;
int aspersor = 0;

////definicion de minimos y maximos
int TempMax = 25;
int TempMin = 20;
int PhMax = 7;
int PhMin = 5;
int HumMin = 60;
int HumMax = 80;
int LuxMin = 100;
int LuxMax = 750;

//////////////////////
void setup()
{
pinMode(4,OUTPUT);
digitalWrite(4,HIGH);
digitalWrite(10, LOW);

  lcd.begin(16, 2);
  lcd.cursor();
  lcd.setCursor(1, 0);
  lcd.print("Inicializando");
  Serial.begin(9600);
  pinMode(calefaccion, OUTPUT);
  pinMode(ventilacion, OUTPUT);
  pinMode(iluminacion, OUTPUT);
  pinMode(extraccion, OUTPUT);
  pinMode(aspersor, OUTPUT);
  sensors.begin();
  // Start ethernet
  Serial.println(F("Starting ethernet..."));
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  
  Serial.println(Ethernet.localIP());
  delay(2000);
  Serial.println(F("Ready"));
}

void loop()
{
  ////Obtengo datos de sensores////
  sensors.requestTemperatures();
  int Temp = sensors.getTempCByIndex(0); //obtengo los datos del sensor de temperatura
  int Ph = 6; //obtengo los datos del sensor de Ph
  int Hum = 68; //obtengo los datos del sensor de humedad
  int Lux = analogRead(A0);   // Read the analogue pin
  float Vout0 = Lux * 0.0048828125;      // calculate the voltage
  Lux = 104.1 * Vout0;           // calculate the Lux

  ////Temperatura////
  if (Temp <= TempMin)
  {
    lcd.clear();
    Serial.println(F("!!--Esta frio: "));
    Serial.println(Temp);
    lcd.setCursor(1, 0);
    lcd.print("Temp. muy fria");
    lcd.setCursor(0, 1);
    lcd.print("!!");
    lcd.setCursor(6, 1);
    lcd.print(Temp);
    lcd.print("C");
    lcd.setCursor(14, 1);
    lcd.print("!!");
    digitalWrite(calefaccion, HIGH);////si esta frio prendo la calefaccion
    digitalWrite(ventilacion, LOW);////y apago la ventilacion
    delay(2000);////refresco
    Serial.println(F("!!--Calefaccion ON--!!"));
    lcd.setCursor(0, 1);
    lcd.print("!Calefaccion ON!");
    delay(1000);////refresco
  }
  if (Temp >= TempMax)
  {
    lcd.clear();
    Serial.print("!!--Esta caliente: ");
    Serial.println(Temp);
    lcd.setCursor(1, 0);
    lcd.print("Temp. muy alta");
    lcd.setCursor(0, 1);
    lcd.print("!!");
    lcd.setCursor(6, 1);
    lcd.print(Temp);
    lcd.print("C");
    lcd.setCursor(14, 1);
    lcd.print("!!");
    digitalWrite(ventilacion, HIGH);////si esta muy caluroso enciendo la ventilacion
    digitalWrite(calefaccion, LOW);////y apago la calefaccion
    delay(2000);////refresco
    Serial.print("!!--Ventilacion ON--!!");
    lcd.setCursor(0, 1);
    lcd.print("!Ventilacion ON!");
    delay(1000);////refresco
  }

  ////Ph del agua////
  if (Ph <= PhMin)
  {
    lcd.clear();
    Serial.print("!!--Agua acida: ");
    Serial.println(Ph);
    lcd.setCursor(3, 0);
    lcd.print("Ph muy bajo");
    lcd.setCursor(0, 1);
    lcd.print("!!");
    lcd.setCursor(6, 1);
    lcd.print(Ph);
    lcd.setCursor(14, 1);
    lcd.print("!!");
    delay(2000);////refresco
  }
  if (Ph >= PhMax)
  {
    lcd.clear();
    Serial.print("!!--Agua basica: ");
    Serial.println(Ph);
    lcd.setCursor(3, 0);
    lcd.print("Ph muy alto");
    lcd.setCursor(0, 1);
    lcd.print("!!");
    lcd.setCursor(6, 1);
    lcd.print(Ph);
    lcd.setCursor(14, 1);
    lcd.print("!!");
    delay(2000);////refresco
  }

  ////Humedad ambiente////
  if (Hum <= HumMin)
  {
    lcd.clear();
    Serial.print("!!--Ambiente muy seco: ");
    Serial.println(Hum);
    lcd.setCursor(2, 0);
    lcd.print("Amb. muy seco");
    lcd.setCursor(0, 1);
    lcd.print("!!");
    lcd.setCursor(6, 1);
    lcd.print(Hum);
    lcd.print("%");
    lcd.setCursor(14, 1);
    lcd.print("!!");
    digitalWrite(aspersor, HIGH);////si el ambiente esta muy seco enciendo los asperores
    digitalWrite(ventilacion, LOW);////y apago la ventilacion
    delay(2000);////refresco
  }
  if (Hum >= HumMax)
  {
    lcd.clear();
    Serial.print("!!--Ambiente muy humedo: ");
    Serial.println(Hum);
    lcd.setCursor(0, 0);
    lcd.print("Amb. muy humedo");
    lcd.setCursor(0, 1);
    lcd.print("!!");
    lcd.setCursor(6, 1);
    lcd.print(Hum);
    lcd.print("%");
    lcd.setCursor(14, 1);
    lcd.print("!!");
    digitalWrite(extraccion, HIGH);////si el ambiente esta muy humedo extraigo el aire
    digitalWrite(ventilacion, LOW);////y apago la ventilacion
    delay(2000);////refresco
    Serial.print("!!--Extraccion ON--!!");
    lcd.setCursor(0, 1);
    lcd.print("!Extraccion ON !");
    delay(1000);////refresco
  }
  ////Luz ambiente////
  if (Lux <= LuxMin)
  {
    lcd.clear();
    Serial.print("!!--Ambiente muy obscuro: ");
    Serial.println(Lux);
    lcd.setCursor(4, 0);
    lcd.print("Poca luz");
    lcd.setCursor(0, 1);
    lcd.print("!!");
    lcd.setCursor(5, 1);
    lcd.print(Lux);
    lcd.print(" lm");
    lcd.setCursor(14, 1);
    lcd.print("!!");
    digitalWrite(iluminacion, HIGH);////si esta muy obscuro prendo la luz
    delay(2000);////refresco
    Serial.print("!!--Iluminacion ON--!!");
    lcd.setCursor(0, 1);
    lcd.print("!Iluminacion ON!");
    delay(1000);////refresco
  }
  if (Lux >= LuxMax)
  {
    lcd.clear();
    Serial.print("!!--Ambiente muy luminoso: ");
    Serial.println(Lux);
    lcd.setCursor(4, 0);
    lcd.print("Mucha Luz");
    lcd.setCursor(0, 1);
    lcd.print("!!");
    lcd.setCursor(5, 1);
    lcd.print(Lux);
    lcd.print(" lm");
    lcd.setCursor(14, 1);
    lcd.print("!!");
    digitalWrite(iluminacion, LOW);////si esta muy luminoso apago la luz
    delay(2000);////refresco
    Serial.print("!!--Iluminacion OFF--!!");
    lcd.setCursor(0, 1);
    lcd.print("!Iluminacion OFF");
    delay(1000);////refresco
  }

  ////si esta todo bien muestro los datos////
  if (Lux < LuxMax && Lux > LuxMin && Hum < HumMax && Hum > HumMin && Ph < PhMax && Ph > PhMin && Temp < TempMax && Temp > TempMin)
  {
    ////si todo esta bien apago los actuadores////
    digitalWrite(calefaccion, LOW);
    digitalWrite(iluminacion, LOW);
    digitalWrite(ventilacion, LOW);
    digitalWrite(aspersor, LOW);
    digitalWrite(extraccion, LOW);

    ///imprimo por puerto serial
    Serial.println("");
    Serial.println("---------------------------");
    Serial.print("Luz ambiente optima: ");
    Serial.println(Lux);
    Serial.print("Humedad ambiente optima: ");
    Serial.println(Hum);
    Serial.print("Ph del agua optimo: ");
    Serial.println(Ph);
    Serial.print("Temperatura optima: ");
    Serial.println(Temp);
    Serial.println("---------------------------");
    Serial.println("");

    ///imprimo en el LCD////
    lcd.setCursor(0, 1);
    lcd.print("Temp ");
    lcd.print(Temp);
    lcd.print("C ");
    lcd.setCursor(8, 0);
    lcd.print("Luz ");
    lcd.print(Lux);
    lcd.print(" ");
    lcd.setCursor(0, 0);
    lcd.print("Hum ");
    lcd.print(Hum);
    lcd.print("% ");
    lcd.setCursor(9, 1);
    lcd.print("Ph ");
    lcd.print(Ph);
    lcd.print(" ");
    delay(3000);////refresco
  }

  //////////////////////////

  ////actaulizacion de mysql
  thisMillis = millis();
  if (thisMillis - lastMillis > delayMillis)
  {
    lastMillis = thisMillis;
    sprintf(pageAdd, "/hidroponia/add.php?temp=%u&&hum=%u&&luz=%u&&ph=%u", Temp, Hum, Lux, Ph);
    if (!getPage(server, serverPort, pageAdd)) Serial.print(F("Fail "));
    else Serial.print(F("Pass "));
  }
}
byte getPage(IPAddress ipBuf, int thisPort, char *page)
{
  int inChar;
  char outBuf[128];
  Serial.print(F("conectando..."));
  if (client.connect(ipBuf, thisPort))
  {
    Serial.println(F("connectado"));
    sprintf(outBuf, "GET %s HTTP/1.1", page);
    client.println(outBuf);
    sprintf(outBuf, "Host: %s", serverName);
    client.println(outBuf);
    client.println(F("Connection: close\r\n"));
  }
  else
  {
    Serial.println(F("failed"));
    return 0;
  }
  int connectLoop = 0;
  while (client.connected())
  {
    while (client.available())
    {
      inChar = client.read();
      Serial.write(inChar);
      connectLoop = 0;
    }
    connectLoop++;
    if (connectLoop > 1000)
    {
      Serial.println();
      Serial.println(F("Timeout"));
      delay(1);
      client.flush();
      delay(1);
      client.stop();
      delay(1);
    }
    delay(1);
  }
  Serial.println();
  Serial.println(F("desconectado"));
  delay(1);
  client.flush();
  delay(1);
  client.stop();
  delay(1);
  return 1;
}

Hola

He revisado el código, aunque no lo pude hacer cargar, saque algunas conclusiones interesantes que tal vez te den una pista.

//----------------------------
La verdad es un poco complejo ya que tienes muchas condicionales aunque solo se ejecutan cuando, digamos el parámetro toca los limites establecidos, entonces digamos que para que no existan errores el sistema se mantiene en un ambiente optimo y estable donde el sistema no hace ajustes; pero si hay cambios el sistema tendrá entonces que hacer los ajustes necesarios y posiblemente en la siguiente pasada reajustar algún otro parámetro; Si esto pasa el sistema puede retrasarse y entrara en un ciclo infinito si el resultado de ThisMillis - LastMillis es mayor que 60 segundos.

Nota: Los números de punto flotante no son exactos, y pueden producir resultados extraños en las comparaciones. Los cálculos matemáticos de punto flotante son también mucho más lentos que los del tipo de números enteros, por lo que debe evitarse su uso si es posible.

Al revisar el código me di cuenta de que al calcular la luz haces uso de una operación un tanto compleja con un número de punto decimal y recordé que esos números ralentizan el proceso, hice mis pruebas pero no fueron concluyentes, en el arduino multiplique 10 veces pi (3.14159265359) por el indice (del cero al nueve)y el arduino solo tardo 1 ó 2ms; después multiplique pi 10 veces por analogRead(0) y tardo un poco mas hasta 3 ó 5ms, hasta que, por ultimo dentro de ese loop le mande al serial que me imprimiera el indice y el resultado y en medio un separador y ahí si que tardo un poco mas, desde 105 a 112ms (solo aparecieron números con solo dos dígitos decimales) .

Digamos que el sistema tiene que hacer muchos ajustes y al imprimir en el serial y en el lcd y "refrescar" (hacer pausas) puede que se retarde tanto que rebase el limite de tiempo que pones en la condición para mandar los datos al servidor.
Para comprobar esto averigua cual es el tiempo máximo que tarda en dar la vuelta y ahí te vas a dar cuenta, yo creo que esta sobrado con 60s pero como no pude hacerlo correr y no tengo el setup que tienes montado no puedo decir que sea concluyente o no, tal vez el sistema hace un ultimo ajuste o varios antes de congelarse y ahí esta el detalle.

//----------------------
También se me ocurrió que pageAdd[64] se quedara corto pero no lo creo, la cadena que pones ronda los 50 caracteres.
Por otro lado en el servidor, si algo pasara en el servidor no afectaría al arduino, porque es independiente.

Aunque un poco tarde la respuesta espero que ya hayas detectado el problema.
saludos.
Por cierto muy interesante tu proyecto.

Al parecer es un error de la librería ethernet hice unos ajustes a la librería y por ahora funciona bien ( lleva 3 días pasando datos). De todas formas voy a ver cuanto demora en hacer el loop y Aumentaré el tamaño de pagadd a 100 para estar seguro.
El servidor funciona bien, así que eso lo descarto.
Voy a tratar de cambiar flota por otro tipo aunque eso va a sacar precisión a los datos.