Temperature monitor Sketch crashes after a few hours

i built a project to monitor and control temp in my mini server room using a DHT22, Arduino UNO and a relay. The sketch is supposed to check temp, if it goes above 78F turn on fan (activate relay) for 10 min, check temp and deactivate relay if temp is below 78F.

I believe the crash results from memory shortage. I've read the guidance on use of millis(), and tried just about everything i can think of to fix the crashing/hanging. After an hour or so the sketch "hangs" and i have to reset the Arduino.

Sketch uses 29686 bytes (92%) of program storage space. Maximum is 32256 bytes.
Global variables use 1515 bytes (73%) of dynamic memory, leaving 533 bytes for local variables. Maximum is 2048 bytes.

Can someone take a look at my code? I would really appreciate any suggestions.

#define BLYNK_PRINT Serial
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);                    // set the LCD address to 0x27

#include <SPI.h>
#include <Ethernet.h>
#include <BlynkSimpleEthernet.h>
#include <DHT.h>

char auth[] = "XXXXXXXXXXXXXXXXXXXXXXXX";      // Auth Token Blynk

#define DHTTYPE DHT22

unsigned long startMillis;
unsigned long currentMillis;
const int DHTPIN = 2;                                  // digital DHT sensor pin
const int RelayPin = 4;                                // digital relay pin
const unsigned int MaxTemp = 78;                       // defined temperature threshold
const unsigned long FanRunTime = 10 * 60 * 1000UL;     // fan run time
// unsigned long interval;

DHT dht(DHTPIN, DHTTYPE);                              // initialize DHT sensor

BlynkTimer timer;

void setup() {
  pinMode(RelayPin, OUTPUT);                           // pin for relay module set as output
  digitalWrite(RelayPin, HIGH);                        // set default relay pin state, inactive = high
  Serial.begin(9600);
  Serial.println("DHT22");                             // serial print sensor type
  Blynk.begin(auth);
  dht.begin();
  lcd.begin();                                         // initialize the LCD
  lcd.setCursor(3, 0);
  lcd.print("XXXX");
}

void loop() {
  Blynk.run();
  delay(2000);                                         // Wait a few seconds between measurements
  float h = dht.readHumidity();                        // read humidity as percentages
  float t = dht.readTemperature();                     // read temperature as Celsius (the default)
  float f = dht.readTemperature(true);                 // read temperature as Fahrenheit (isFahrenheit = true)
  if (isnan(h) || isnan(t) || isnan(f)) {              // check if any reads failed and exit early (to try again)
    Serial.println("Failed to read from DHT sensor");
    return;
  }

  Blynk.virtualWrite(V5, h);                           // display state on Blynk
  Blynk.virtualWrite(V6, f);                           // display state on Blynk 
  Blynk.virtualWrite(V7, dht.computeHeatIndex(f, h));  // display state on Blynk

  float hif = dht.computeHeatIndex(f, h);              // Compute heat index in Fahrenheit (the default)
  float hic = dht.computeHeatIndex(t, h, false);       // Compute heat index in Celsius (isFahreheit = false)

  Serial.print("RS: ");                                // serial print relay state, 0 = on, 1 = off
  Serial.print(digitalRead(RelayPin));
  Serial.print("\t");
  Serial.print("Humidity: ");                          // serial print temperature (C & F)
  Serial.print(h);
  Serial.print(" %\t");
  lcd.setCursor(0, 2);                                 // display humidity on LCD
  lcd.print("Humidity:     ");
  lcd.print(dht.readHumidity());
  lcd.print("%");
  Serial.print("Temperature: ");                       // serial print temperature (C & F)
  Serial.print(t);
  Serial.print(" *C ");
  Serial.print(f);
  Serial.print(" *F\t");
  lcd.setCursor(0, 1);                                 // display temperature (F) on LCD
  lcd.print("Temperature:  ");
  lcd.print(dht.readTemperature(true));
  lcd.print("F");
  Serial.print("Heat index: ");                        // serial print heatindex
  Serial.print(hic);
  Serial.print(" *C ");
  Serial.print(hif);
  Serial.println(" *F");

  int relayState = digitalRead(RelayPin);              // read relay state
  if (relayState == LOW) {                             // if relay active
    lcd.setCursor(0, 3),                               // display value on LCD
                  lcd.print("Fan Status:       ON"),   // display fan status
                  Blynk.virtualWrite(V8, "ON");        // display state on Blynk
  }

  else {                                               // relay inactive
    lcd.setCursor(0, 3),                               // display value on LCD
                  lcd.print("Fan Status:      OFF"),   // display fan status
                  Blynk.virtualWrite(V8, "OFF");       // display state on Blynk
  }

  if (f > MaxTemp ) {                                  // check temperature and compare to threshold
    currentMillis = millis();                          // get the current time
    digitalWrite(RelayPin, LOW);                       // activate relay if above threshold
   }

  if (currentMillis - startMillis >= FanRunTime) {     // check clock for time elapsed on interval
    startMillis = currentMillis;                       // save the start time
    digitalWrite(RelayPin, HIGH);                      // deactivate relay if interval complete
  }
}

from what I remember of Blynk, I think it was not a good idea to prevent Blynk.run() from running as this is used for keeping your connection alive. When you use a delay() , you are possibly breaking the connection to Blynk Cloud and then all bets are off

In order to not "spam" their server, you might want to use BlynkTimer to send the data from time to time or handle that yourself using millis()

EDIT: found this article on their site, seems to confirm the above

Thank you J-M-L, modifying code now.

cleaned up code to best of my ability and implemented blynk timer set to 10sec interval.

very useful!

EDIT: found this article on their site, seems to confirm the above

i will see in an hour if it did the trick.

revised code:

#define BLYNK_PRINT Serial
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
#include <SPI.h>
#include <Ethernet.h>
#include <BlynkSimpleEthernet.h>
#include <DHT.h>
#define DHTTYPE DHT22

char auth[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";      // Auth Token Blynk
const int DHTPIN = 2;                                  // DHT22 sensor pin
const int RelayPin = 4;                                // digital relay pin 0 = on, 1 = off
unsigned long startMillis;
unsigned long currentMillis;
const unsigned int MaxTemp = 78;                       // defined temperature threshold
const unsigned long FanRunTime = 10 * 60 * 1000UL;     // fan run time

DHT dht(DHTPIN, DHTTYPE);                              // initialize DHT sensor
BlynkTimer timer;

void sensorData() {
  float h = dht.readHumidity();                        // read humidity as percentages
  float t = dht.readTemperature();                     // read temperature as Celsius (the default)
  float f = dht.readTemperature(true);                 // read temperature as Fahrenheit (isFahrenheit = true)
  float hif = dht.computeHeatIndex(f, h);              // Compute heat index in Fahrenheit (the default)
  float hic = dht.computeHeatIndex(t, h, false);       // Compute heat index in Celsius (isFahreheit = false)
  int relayState = digitalRead(RelayPin);              // read relay state

  if (isnan(h) || isnan(t) || isnan(f)) {              // check if any reads failed and exit early (to try again)
    Serial.println("Failed to read from DHT sensor");
    return;
  }

  Blynk.virtualWrite(V5, h);
  Blynk.virtualWrite(V6, f);
  Blynk.virtualWrite(V7, dht.computeHeatIndex(f, h));
  Serial.print("RS: ");
  Serial.print(digitalRead(RelayPin));
  Serial.print("\t");
  Serial.print("Humidity: ");
  Serial.print(h);
  Serial.print(" %\t");
  lcd.setCursor(0, 2);
  lcd.print("Humidity:     ");
  lcd.print(dht.readHumidity());
  lcd.print("%");
  Serial.print("Temperature: ");
  Serial.print(t);
  Serial.print(" *C ");
  Serial.print(f);
  Serial.print(" *F\t");
  lcd.setCursor(0, 1);
  lcd.print("Temperature:  ");
  lcd.print(dht.readTemperature(true));
  lcd.print("F");
  Serial.print("Heat index: ");
  Serial.print(hic);
  Serial.print(" *C ");
  Serial.print(hif);
  Serial.println(" *F");

  if (relayState == LOW) {                             // if relay active
    lcd.setCursor(0, 3),
                  lcd.print("Fan Status:       ON"),
                  Blynk.virtualWrite(V8, "ON");
                  }
  else {                                               // relay inactive
    lcd.setCursor(0, 3),
                  lcd.print("Fan Status:      OFF"),
                  Blynk.virtualWrite(V8, "OFF");
  }

  if (f > MaxTemp ) {                                  // check temperature and compare to threshold
    currentMillis = millis();                          // get the current time
    digitalWrite(RelayPin, LOW);                       // activate relay if above threshold
  }
  if (currentMillis - startMillis >= FanRunTime) {     // check clock for time elapsed on interval
    startMillis = currentMillis;                       // save the start time
    digitalWrite(RelayPin, HIGH);                      // deactivate relay if interval complete
  }
}

void loop() {
  Blynk.run();
  timer.run();                                         // run timer every 10 seconds
}

void setup() {
  pinMode(RelayPin, OUTPUT);                           // pin for relay module set as output
  digitalWrite(RelayPin, HIGH);                        // set default relay pin state, inactive = high
  Serial.begin(115200);
  Serial.println("DHT22");
  Blynk.begin(auth);
  dht.begin();
  lcd.begin();
  lcd.setCursor(3, 0);
  lcd.print("xxxxxx");
  timer.setInterval(10*1000L, sensorData);             // timer will run every 10 sec
}

ethfluidity:
i built a project to monitor and control temp in my mini server room using a DHT22, Arduino UNO and a relay.

.....
Sketch uses 29686 bytes (92%) of program storage space. Maximum is 32256 bytes.
Global variables use 1515 bytes (73%) of dynamic memory, leaving 533 bytes for local variables. Maximum is 2048 bytes.

I hope you have solved your problem. I had (once upon a time) a similar sketch with heater, blower, ventilation and water gardening, w/ dht22 and lcd, and keeping log (8 times per day) on eeprom. Sketch was about 1000 lines, ~8k program and ~1500bytes for variables.

For me, it looks e x t r e m e l y strange with ~100 lines of code to have a memory usage of 92% (?toomany libraries for no reason?) and a ram use ~1500bytes with no apparent extreme usage of variables
?

Totally possible that it can be slimmed down, i just don't know how yet. This is my first Arduino project. As of right now (~6hrs) it's still running :slight_smile:

I'll do some searching on eliminating/replacing some libraries...

If anybody has a pointer or two, I'd be most grateful

Seems better than before :slight_smile: