[SOLVED] Arduino starts doing weird things after 15 minutes working

Hi, I've been working on a new project recently about a domotic greenhouse. I've almost finished the project, the problem is the lcd stops displaying the water level of the tank after exactly 15 min, but the temperature, the humidity and all the other values keep displaying in the lcd without problem. Also, at the same time the lcd stops displaying the water level, it stops being able to open the SD card file. When this happens I reset the Arduino manually from the board, and it continues working without problem. I thought I could solve this introducing the watchdog, but I was wrong because when this happens the watchdog doesn't do anything. I hope someone can tell me where is the mistake or a way to reset the Arduino automatically after 15 min. Here is the code:

#include <SD.h>
#include <SPI.h>
#include <avr/wdt.h>
#include <DHT.h>
#include <Servo.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "RTClib.h"

#define HIGH 0x0
#define LOW 0x1
#define DHTPIN A2
#define DHTTYPE DHT22
#define llumPin A1
#define humsolPin A0
#define relebombaPin 2
#define relebombillaPin 3
#define releledPin 7
#define relefanPin 8
#define pinTrig 6
#define pinEcho 5
#define ledPin A3
#define pinCS 53
#define numLecturas 100
#define velSon 34000
#define distancia100 0.88
#define distanciaVacio 19.75

byte cuentaSD = 0;
int cuentaPump = 0;
int lecturaActual = 0;   
float lecturas[numLecturas]; 
float total = 0; 
float media = 0;
unsigned long coolDownTime = 18000;
unsigned long timeToCoolDownFan = 0;
unsigned long timeToCoolDownBombilla = 0;
unsigned long timeToCoolDownStripe = 0;
bool primeraMedia = false;
bool firstTimeFanOn = true;
bool firstFanOffLoop = true;
bool firstTimeBombillaOn = true;
bool firstBombillaOffLoop = true;
bool firstTimeStripeOn = true;
bool firstStripeOffLoop = true;
bool firstTimePumpOn = true;

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
DHT dht(DHTPIN, DHTTYPE);
RTC_DS3231 rtc;
File logFile;
Servo servoMotor1;
Servo servoMotor2;

void setup()
{
  wdt_disable();
  wdt_enable(WDTO_8S);

  Serial.begin(9600);
  
  lcd.begin(16, 2);
  dht.begin();
  servoMotor1.attach(9);
  servoMotor2.attach(10);
  // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  pinMode(relebombaPin, OUTPUT);
  pinMode(relebombillaPin, OUTPUT);
  pinMode(releledPin, OUTPUT);
  pinMode(relefanPin, OUTPUT);
  pinMode(pinTrig, OUTPUT);
  pinMode(pinEcho, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(pinCS, OUTPUT);
  
  digitalWrite(relebombaPin, LOW);
  digitalWrite(relebombillaPin, LOW);
  digitalWrite(releledPin, LOW);
  digitalWrite(relefanPin, LOW);
  digitalWrite(ledPin, HIGH);
  
  if (SD.begin(SS))
  {
    Serial.println(F("Tarjeta SD iniciada correctament"));
  } 
  else
  {
    Serial.println(F("No s'ha pogut iniciar la tarjeta SD"));
    return;
  }
  
  for (int i = 0; i < numLecturas; i++)
  {
    lecturas[i] = 0;
  }
}

void loop()
{
  total = total - lecturas[lecturaActual];
  
  DateTime now = rtc.now();

  iniciarTrigger();

  unsigned long tiempo = pulseIn(pinEcho, LOW);
  float hum;  
  float temp; 
  
  int humsol = analogRead(humsolPin);
  int llum = analogRead(llumPin);
    
  hum = dht.readHumidity();
  temp = dht.readTemperature();
    
  float dist = tiempo * 0.000001 * velSon / 2.0;
    
  lecturas[lecturaActual] = dist;
  total = total + lecturas[lecturaActual];
  lecturaActual = lecturaActual + 1;

  if ((temp > 30) || (hum > 80))
  {
   if ((millis() - timeToCoolDownFan >= coolDownTime) || (firstTimeFanOn == true))
   {
     servoMotor1.write(180);
     servoMotor2.write(180);
     digitalWrite(relefanPin, HIGH);
     firstTimeFanOn = false;
     firstFanOffLoop = true;
   }
  }
  else
  {
    servoMotor1.write(0);
    servoMotor2.write(0);
    digitalWrite(relefanPin, LOW);
    if (firstFanOffLoop == true) 
    {
      timeToCoolDownFan = millis();
      firstFanOffLoop = false;
    }
  }

  if (temp < 20)
  {
   if ((millis() - timeToCoolDownBombilla >= coolDownTime) || (firstTimeBombillaOn == true))
   {
     digitalWrite(relebombillaPin, HIGH);
     firstTimeBombillaOn = false;
     firstBombillaOffLoop = true;
   }
  }
  else
  {
    digitalWrite(relebombillaPin, LOW);
    if (firstBombillaOffLoop == true) 
    {
      timeToCoolDownBombilla = millis();
      firstBombillaOffLoop = false;
    }
  }

  cuentaPump = cuentaPump + 1;
  
  if (cuentaPump == 400) 
  {  
    cuentaPump = 0;
  }
  
  Serial.print(F("Compte enrere per regar: "));
  Serial.println(399 - cuentaPump);
  
  if (humsol > 700)
  { 
    if ((cuentaPump == 399) || (firstTimePumpOn == true))
    { 
      digitalWrite(relebombaPin, HIGH);
      primeraMedia = false;
      lecturaActual = 0;
      cuentaPump = 0;
      firstTimePumpOn = false;
    }
  }
  else digitalWrite(relebombaPin, LOW);

  if ((llum < 500) && (now.hour() < 20) && (now.hour() > 8)) 
  {
    if ((millis() - timeToCoolDownStripe >= coolDownTime) || (firstTimeStripeOn == true))
   {
     digitalWrite(releledPin, HIGH);
     firstTimeStripeOn = false;
     firstStripeOffLoop = true;
   }
  }
  else 
  {
    digitalWrite(releledPin, LOW);
    if (firstStripeOffLoop == true) 
    {
      timeToCoolDownStripe = millis();
      firstStripeOffLoop = false;
    }
  }
    
  if (lecturaActual >= numLecturas)
  {
    primeraMedia = true;
    lecturaActual = 0;
  }

  media = total / numLecturas;

  if (primeraMedia == true)
  {
    float distanciaLleno = distanciaVacio - media;
    float cantidadLiquido = distanciaLleno * 100 / distancia100;
    int porcentaje = (int) (distanciaLleno * 100 / distanciaVacio);
  
    lcd.clear();
    lcd.print("Quant: " + String(cantidadLiquido) + "ml");
    lcd.setCursor(0, 1);
    lcd.print("Percent: " + String(porcentaje) + "%");

    Serial.print(F("Mitjana: "));
    Serial.print(media);
    Serial.print(F(" cm, Quantitat de liquid: "));
    Serial.print(cantidadLiquido);
    Serial.println(F(" ml"));

    if (porcentaje <= 10) digitalWrite(ledPin, LOW);
    else digitalWrite(ledPin, HIGH);
  }  
  else
  {
    lcd.clear();
    lcd.print("Calculant: " + String(lecturaActual));
  }

  SD.begin(SS);
  logFile = SD.open("datalog.txt", FILE_WRITE);

  cuentaSD = cuentaSD + 1;
  
  if (cuentaSD == 66) cuentaSD = 0;
  
  if (logFile) 
  {
    Serial.print(F("Compte enrere per guardar dades: "));
    Serial.println(65 - cuentaSD);
    
    if (cuentaSD == 65)
    {
      Serial.println(F("Escribint..."));
      logFile.print("Data: ");
      logFile.print(now.day());
      logFile.print("/");
      logFile.print(now.month());
      logFile.print("/");
      logFile.print(now.year());
      logFile.print(", Hora: ");
      logFile.print(now.hour());
      logFile.print(":");
      logFile.print(now.minute());
      logFile.print(":");
      logFile.print(now.second());
      logFile.print(" , Temperatura: ");
      logFile.print(temp);
      logFile.print(" ºC, Humitat: ");
      logFile.print(hum);
      logFile.println(" %");
      
      if(logFile.available()) Serial.write(logFile.read());
      
      logFile.close();
      cuentaSD = 0;
    }
  }
  else 
  {
    Serial.println(F("No s'ha pogut obrir l'arxiu"));
  }
  
    delay(1500);      
        
    lcd.clear();
    lcd.print("Temp: ");
    lcd.print(temp);
    lcd.write((char)223);
    lcd.print("C");
    lcd.setCursor(0,1);
    lcd.print("Hum: ");
    lcd.print(hum);
    lcd.print("%");
    
    delay(1500);

    digitalWrite(relebombaPin, LOW);

    lcd.clear();
    lcd.print("Hum sol: ");
    lcd.print(humsol);
    lcd.setCursor(0,1);
    lcd.print("Llum: ");
    lcd.print(llum);
    
    delay(1500);

    wdt_reset();
}

void iniciarTrigger()
{
  #define HIGH 0x1
  #define LOW 0x0
  
  digitalWrite(pinTrig, HIGH);
  delayMicroseconds(2);
  
  digitalWrite(pinTrig, LOW);
  delayMicroseconds(10);
  
  digitalWrite(pinTrig, HIGH);
}

Thanks :slight_smile:

#define HIGH 0x0
#define LOW 0x1

Why?

#define pinTrig 6
#define pinEcho 5

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);Hmmm.

#1
Because without that my relays turn on with LOW and turn off with HIGH.

#2
What do you mean?

#1 {facepalm}

#2 scratch that - I missed the I2C reference

#4 Do you think doing that is bad?

...
void loop()
{
...
  lecturas[lecturaActual] = dist;
  total = total + lecturas[lecturaActual];
  lecturaActual = lecturaActual + 1;
...
  if (humsol > 700)
  { 
    if ((cuentaPump == 399) || (firstTimePumpOn == true))
    { 
      digitalWrite(relebombaPin, HIGH);
      primeraMedia = false;
      lecturaActual = 0;
      cuentaPump = 0;
      firstTimePumpOn = false;
    }
  }
  else digitalWrite(relebombaPin, LOW);

  if ((llum < 500) && (now.hour() < 20) && (now.hour() > 8)) 
  {
...
  if (lecturaActual >= numLecturas)
  {
    primeraMedia = true;
    lecturaActual = 0;
  }
...

The bounding conditions on lecturaActual look suspiciously incomplete.

I understand, what should I do?

Firsr of all for resetting Arduino after 15 min working you need a 15 min timer.
Second you can OR directly use a pin that is vonnected,witch a resistor, to the reset pin on the board, OR you can make a function that quite reset Arduino (it reports all variables at theyr begin state, all pin in LOW state (the true LOW), 'destroy' all the objects used and calls setup(). After it, in the timer, you can call 'continue;' that restart loop()

Or, you just fix the damn bug...

I solved it introducing the SdFat library. Thanks.