Arduino deja de funcionar despues de unas horas

Hola, tengo un Arduino UNO + EthernetShield + Modulo de 4 Relays + Tiny RTC.

Les comento un poco de que se trata mi proyecto.. Uso la ethernet para un webServer y desde una pagina controlar los relay. Tambien los relay se prenden y apagan segun la hora, es decir, funciona como un timer.

Cuando prendo el arduino, funciona todo perfectamente, pero pasadas unas 10 o 12 horas, este deja de funcionar, y ya no funciona el webServer y los relay no prenden ni apagan a la hora programada. Asique para que vuelva a funcionar tengo que reiniciar la placa.

Alguien me puede dar una mano?

¿Has probado con un adivino? Sin el código, es imposible ayudarte.

Disculpa, es mi primer proyecto en arduino y pense que quizas era un problema frecuente. Este es el codigo:

#include <SPI.h>
#include <Ethernet.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;

#define SENSOR 3
#define RELAY1  6
#define RELAY2  7               
#define RELAY3  8      

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,177);

boolean R1,R2,R3,R4; //estados de reles
boolean AUTO; //estados auto/manual

double temp;

OneWire ourWire(SENSOR);
DallasTemperature sensors(&ourWire); 

EthernetServer server(8325);
EthernetClient client;

String readString;
  
void setup() {
  Serial.begin(9600);
  
  Wire.begin();
  RTC.begin();
  if (! RTC.isrunning()) RTC.adjust(DateTime(__DATE__, __TIME__));
  
  AUTO = true;
  pinMode(RELAY1, OUTPUT);       
  pinMode(RELAY2, OUTPUT);
  pinMode(RELAY3, OUTPUT);
  digitalWrite(RELAY1, HIGH); R1 = 0;
  digitalWrite(RELAY2, HIGH); R2 = 0;
  digitalWrite(RELAY3, HIGH); R3 = 0;
  
  sensors.begin();
  
  Ethernet.begin(mac, ip);  
  server.begin();
  
}
  
void loop() { 

sensors.requestTemperatures();
temp = sensors.getTempCByIndex(0);

delay(2000);

if ( AUTO ){
  activaCoolers();
  if( !R1 | !R2 ) timerOn();
  if( R1 | R2 ) timerOff();
}
    
EthernetClient client = server.available(); // Escucha a los clientes entrantes.

if (client) { 
        while (client.connected()) { // Repite mientas existe clientes conectados:      
            if (client.available()) {
            char c = client.read();
            
                //read char by char HTTP request
                if (readString.length() < 100) {
                readString += c;
                }
                
                if (c == '\n'){
                
                Serial.println(readString); //print to serial monitor for debuging
                
                client.println("HTTP/1.1 200 OK"); 
                client.println("Content-Type: text/html");
                client.println("Connection: close");
                client.println("Refresh: 10"); 
                client.println();
                client.println("<!DOCTYPE HTML>"); // Tipo de documento.
                client.println("<html>"); // Etiqueta html inicio del documento.
                client.print("Temperatura: ");
                
                if (temp < 24 || temp > 27.5){ 
                  client.print("<font color=\"/FF0000\"/>");
                  client.print(temp);
                  client.print("</font>");   
                }else{
                  client.print("<font color=\"/00FF00\"/>");
                  client.print(temp);
                  client.print("</font>");
                }
                
                client.print("
");
                client.print("
");
              
                client.print("LUZ AZUL ");
                if( R1 ) client.println("<font color=\"/00FF00\"/>ON</font> "); else client.println("<font color=\"/FF0000\"/>OFF</font> ");	
                client.print("<a href=\"/?R1ON\">ON</a> / <a href=\"/?R1OFF\">OFF</a>");
                client.print("
");
                              
                client.print("LUZ BLANCA ");
                if( R2 ) client.println("<font color=\"/00FF00\"/>ON</font> "); else client.println("<font color=\"/FF0000\"/>OFF</font> ");	
                client.print("<a href=\"/?R2ON\">ON</a> / <a href=\"/?R2OFF\">OFF</a>");
                client.print("
");
                              
                client.print("COOLER ");
                if( R3 ) client.println("<font color=\"/00FF00\"/>ON</font> "); else client.println("<font color=\"/FF0000\"/>OFF</font> ");	
                client.print("<a href=\"/?R3ON\">ON</a> / <a href=\"/?R3OFF\">OFF</a>");
                client.print("
");
                
                client.print("AUTO ");
                if( AUTO ) client.println("<font color=\"/00FF00\"/>ON</font> "); else client.println("<font color=\"/FF0000\"/>OFF</font> ");	
                client.print("<a href=\"/?AUTOON\">ON</a> / <a href=\"/?AUTOOFF\">OFF</a>");
              
                delay(1); 
                client.stop();  
                
                checkBoton();
                readString=""; 
}}}}}

void checkBoton(){
  if (readString.indexOf("?R1ON") > 0){
    digitalWrite(RELAY1, LOW);
    R1 = 1;
  }
  if (readString.indexOf("?R1OFF") > 0){
    digitalWrite(RELAY1, HIGH);
    R1 = 0;      
  }
                  
  if (readString.indexOf("?R2ON") > 0){
    digitalWrite(RELAY2, LOW);
    R2 = 1;      
  }
  if (readString.indexOf("?R2OFF") > 0){
    digitalWrite(RELAY2, HIGH);
    R2 = 0;      
  }
  if (readString.indexOf("?R3ON") > 0){
    digitalWrite(RELAY3, LOW);
    R3 = 1;    
  }
  if (readString.indexOf("?R3OFF") > 0){
    digitalWrite(RELAY3, HIGH);
    R3 = 0;
  }
  if (readString.indexOf("?AUTOON") > 0){
    AUTO = 1;
  }
  if (readString.indexOf("?AUTOOFF") > 0){
    AUTO = 0;      
  }
}

void activaCoolers(){
  if( !R3 ){
    if(temp > 26.5){
      digitalWrite(RELAY3, LOW);
      R3 = 1;
    }
  }
  if( R3 ){
    if(temp <= 26){
      digitalWrite(RELAY3, HIGH);
      R3 = 0;
    }
  } 
}

void timerOn(){
  DateTime now = RTC.now();

  if ((now.hour() >= 14) && (now.hour() < 22)){
    digitalWrite(RELAY1, LOW);
    R1 = 1;
  }
  if ((now.hour() >= 16) && (now.hour() < 20)){
    digitalWrite(RELAY2, LOW);
    R2 = 1;
  }
}

void timerOff(){
  DateTime now = RTC.now();
  
  if(now.hour() >= 22){
    digitalWrite(RELAY1, HIGH);
    R1 = 0;
  }
  if(now.hour() >= 20){
    digitalWrite(RELAY2, HIGH);
    R2 = 0;
  }
}

Me olvide de mencionar que tambien tengo un sensor de temperatura, el cual activa un relay al llegar a determinada temperatura.

sin verlo adivino que puede estar ocurriendo. Estas consumiendo toda la RAM del arduino.
Baja la libreria AvailableMemory
Mira el ejemplo e imprime la memoria en uso.
Verás que cuando llegas a esa situación de 10 a 12hs te quedas sin ram.

Una pregunta cuando compilas, el IDE te da datos sobre % de uso de RAM y de FLASH.
Copia y pega esos datos aqui por favor

surbyte, yo en un principio pense lo mismo, que era un problema de la RAM, busque algun codigo que me indique la RAM libre y encontre este justamente en el link que me pasaste:

int freeRam()
{
	extern int __heap_start, *__brkval;
	int v;
	return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

Serial.print("  SRAM Libre: "); Serial.println(freeRam());

Al prinicipio, imprimia 300 aprox. asique fui eliminando cosas del codigo, y logre aumentar la ram libre a 750. Al subirlo a 750, note que el sistema funciona mas tiempo (antes funcionaba 4 o 5 horas).

Asique, indudablemente es un problema de ram.. que puedo hacer para solucionarlo? ya que no puedo eliminar nada mas del codigo.

PD. En este momento tengo el arduino en uso. A la noche lo conecto a la pc y te paso los datos que me sale en el IDE al compilar.

Mi primer respuesta no te va a gustar, porque es obvia, cambia a un MEGA por ejemplo.

La alternativa es mirar el código y ver porque ocupa tanto.
Asumo que es un UNO pero no lo sé, es un UNO?

La compilación con el IDE arrojó esto en mi caso

Sketch uses 22.290 bytes (72%) of program storage space. Maximum is 30.720 bytes.
Global variables use 1.228 bytes (59%) of dynamic memory, leaving 820 bytes for local variables. Maximum is 2.048 bytes.

Solo te quedan 820bytes para variables locales.
Ahora que tengo un parámetro veré que puedo mejorar, si algo se puede.
Algo que vi en un programa de alto nivel, es que todo lo que es Web se puede guardar en la flash, liberando bastante memoria.
Veamos si puedo hacerlo.

Acá el código que te comentaba

Si, es un UNO.. y la compilacion me da esos valores que pusiste. No sabia que podia guardar cosas en la flash, ya mismo voy a ver ese link, y te comento como me fue.

Te agradezco muchisimo la ayuda.

Lo estuve mirando y no es dificil adaptarlo.

Ya lo adapte, ahora me da 1100 de ram libre. Voy a probar a ver que pasa y te aviso como fue.

De verdad te agradezco.

vaya que fue rápido. Me alegro por la mejora que lograste!!!
El uso de enviar a flash este tipo de cosas es un recurso que pocos usan. Hay que difundirlo.

Bueno, lo probe algunos dias y sigue todo igual. Ahora funciona un poco mas de tiempo pero sigue pasando lo mismo. Deja de funcionar y no me queda otra que resetear el arduino.

Como resetearlo era la solucion intente lo siguiente, hacer que 3 veces por dia, el arduino se resetee a traves del siguiente codigo:

void Reset()
{
asm volatile ("  jmp 0");  
}

El arduino se resetea bien, pero no soluciona el problema, deja de funcionar igual.

Ya estoy pensando en sacar el webServer y dejar solo los procedimientos de timers, pero tampoco se si es la solucion.

Alguna otra solucion posible?

Porque no agregas lineas con Serial.print´s que te indiquen que estaba hanciendo al momento de colgarse

además de lo que te dice surbyte, sería bueno que imprimas lo que te queda de ram en cada función, lo que deberías ver es que en cada loop, los datos se repitan. En teoría, los datos deberían sobrescribirse con cada comienzo del loop, por lo que en un momento te vas a encontrar con una función que en vez de repetir los datos los estará consumiendo. Ahí ya sería más fácil saber por donde puede ir el problema.

Exacto, lo importate es detectar cuál es la rutina responsable o qué no estas haciendo que consume memoria porque no hay dudas que es eso.

Y una cosa mas, elimina de tu cabeza el uso de un reset como posible solución.
Lo que si deben pensar es en que se ejecuta azarozamente o digamos de vez en cuando, porque esta claro que no es algo que se ejecute con frecuencia porque ya lo hubieras visto.
Mira en tu código y busca las cosas que tienen poca frecuencia a ver si está por ahi el responsable.

Ok voy a ir sacando cosas del codigo y probando hasta descubrir que es lo que falla.

Les aviso como me fue! gracias.!