Duo crashes after hours

Hey good people, my code controls relays and fans in a box. The code works great but it locks up after only a few hours. Ive taken out everything I can to make it less work, but it still manages to lock up after a few hours.
I ended up making it reset itself after 4 hours in an effort to beat this but it only runs a few days then stops.

I have a few things to add to the system, like a data logger. Was thinking I might have to go to a Arduino Mega to have enough pins, would that make any differnece?


#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#define DHTPIN 11  // what pin we're connected to

//#define DHTTYPE DHT11  // DHT 11
#define DHTTYPE DHT22  // DHT 22 (AM2302)
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
// Initialize DHT sensor for normal 16mhz Arduino
DHT dht(DHTPIN, DHTTYPE);
//DHT dht(DHTPIN, DHTTYPE, 30);
int humidfan = 2;         //  Intake fan for Humid box
int humidv = 3;           //  Valve for humud intake
int freshfan = 4;         // fresh fan
int freshv = 5;           //  fresh valve, air from outside
int exfan = 6;            // exhaust fan
int exv = 7;              // exhaust valve
int dryfan = 8;           // intake fan for dry box
int dryv = 9;             // dry box valve
const int resetPin = 10;  // button to reset cycle
// DHT pin 11
int DHTpower = 13;  // constant 5v to DHT11
int fridge = 12;    // relay to fridge 240v

int buttonState = 0;  // variable for reading the pushbutton
void(* resetFunc) (void) = 0;

const int TEMP_LOWER = 19;         // low
const int TEMP_UPPER = 21;         //
unsigned long previousMillis = 0;  // will store last time LED was updated
const long interval = 14400000;       //the value is a number of milliseconds - 4 hours 14400000
float temperature;

LiquidCrystal_I2C lcd(0x27, 20, 4);  // Set the LCD address to 0x27 for a 20x4 display

void setup() {
  pinMode(humidfan, OUTPUT);
  pinMode(dryfan, OUTPUT);
  pinMode(fridge, OUTPUT);
  pinMode(humidv, OUTPUT);
  pinMode(dryv, OUTPUT);
  pinMode(exfan, OUTPUT);
  pinMode(exv, OUTPUT);
  pinMode(freshfan, OUTPUT);
  pinMode(freshv, OUTPUT);
  pinMode(DHTpower, OUTPUT);
  pinMode(resetPin, OUTPUT);
  digitalWrite(resetPin, HIGH);
  digitalWrite(humidfan, LOW);
  digitalWrite(dryfan, LOW);
  digitalWrite(humidv, LOW);
  digitalWrite(dryv, LOW);
  digitalWrite(exfan, LOW);
  digitalWrite(exv, LOW);
  digitalWrite(freshfan, LOW);
  digitalWrite(freshv, LOW);
  digitalWrite(DHTpower, HIGH);
  digitalWrite(fridge, LOW);
  Serial.begin(9600);
  lcd.init();       // Initialize the LCD
  lcd.backlight();  // Turn on the backlight
  lcd.clear();      // Clear the LCD screen
  lcd.setCursor(5, 1);
  lcd.print("The Green");
  lcd.setCursor(6, 2);
  lcd.print("Ninja");
  delay(2200);  // Display the startup message for 2 seconds
  lcd.clear();
  dht.begin();
}

void loop() {
  unsigned long currentMillis = millis();
  float h = dht.readHumidity();
  // Read temperature as Celsius
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit
  float f = dht.readTemperature(true);
  // float currentDew = dewPoint(t, h);  // Dew Point for setting pins high

  temperature = dht.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Failed to read");
    lcd.setCursor(0, 1);
    lcd.print("from DHT sensor");
    return;
  }

  temperature = dht.readTemperature();

  if (temperature < TEMP_LOWER) {
    digitalWrite(fridge, LOW);  // turn on
    lcd.setCursor(0, 2);
    lcd.print("Cooling Off     ");
  }
  if (temperature > TEMP_UPPER) {
    digitalWrite(fridge, HIGH);  // turn on
    lcd.setCursor(0, 2);
    lcd.print("Cooling On       ");
  }

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
    resetCycle(h);
  }
  if ((h > 58 && (h < 65))) {
    humPointOk(h);
  }
  if (h > 65.5) {  //   High dew point, send to dry box
    humPointHigh(h);
  }
  if (h < 57.5) {  // Dew point low, send to humid box
    humPointLow(h);
  }
}
void resetCycle(float h) {
  digitalWrite(humidfan, LOW);
  digitalWrite(dryfan, LOW);
  digitalWrite(humidv, LOW);
  digitalWrite(dryv, LOW);
  lcd.clear();
  lcd.print("Exhaust fan on");
  lcd.setCursor(0, 1);
  lcd.print("Fresh air in");
  lcd.setCursor(0, 2);
  lcd.print("Cooling on       ");
  digitalWrite(exv, HIGH);
  digitalWrite(freshv, HIGH);
  digitalWrite(fridge, HIGH);
  delay(4000);
  digitalWrite(freshfan, HIGH);
  digitalWrite(exfan, HIGH);
  delay(150000);
  resetFunc();
}

void humPointOk(float h) {
  digitalWrite(humidfan, LOW);
  digitalWrite(humidv, LOW);
  digitalWrite(dryfan, LOW);
  digitalWrite(dryv, LOW);
  digitalWrite(exfan, LOW);
  digitalWrite(exv, LOW);
  digitalWrite(freshfan, LOW);
  digitalWrite(freshv, LOW);

  //lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Humidity");
  lcd.setCursor(14, 0);
  lcd.print(dht.readHumidity());
  lcd.setCursor(19, 0);
  lcd.print("%");

  lcd.setCursor(0, 1);
  lcd.print("Temp");
  lcd.setCursor(14, 1);
  lcd.print(dht.readTemperature());
  lcd.setCursor(19, 1);
  lcd.print("c");
  lcd.setCursor(0, 3);
  lcd.print("Valves Closed");
  delay(4000);
}

void humPointHigh(float h) {
  digitalWrite(humidv, LOW);
  digitalWrite(humidfan, LOW);
  digitalWrite(dryv, HIGH);
  digitalWrite(exv, LOW);
  digitalWrite(exfan, LOW);
  digitalWrite(freshv, LOW);
  digitalWrite(freshfan, LOW);

  //lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Humidity");
  lcd.setCursor(14, 0);
  lcd.print(dht.readHumidity());
  lcd.setCursor(19, 0);
  lcd.print("%");

  lcd.setCursor(0, 1);
  lcd.print("Temp");
  lcd.setCursor(14, 1);
  lcd.print(dht.readTemperature());
  lcd.setCursor(19, 1);
  lcd.print("c");
  lcd.setCursor(0, 3);

  lcd.print("Dry Box On     ");
  delay(4000);
  digitalWrite(dryfan, HIGH);
}

void humPointLow(float h) {  // humid box on
  digitalWrite(humidv, HIGH);
  digitalWrite(dryv, LOW);
  digitalWrite(exv, LOW);
  digitalWrite(exfan, LOW);
  digitalWrite(freshv, LOW);
  digitalWrite(freshfan, LOW);

  //lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Humidity");
  lcd.setCursor(14, 0);
  lcd.print(dht.readHumidity());
  lcd.setCursor(19, 0);
  lcd.print("%");

  lcd.setCursor(0, 1);
  lcd.print("Temp");
  lcd.setCursor(14, 1);
  lcd.print(dht.readTemperature());
  lcd.setCursor(19, 1);
  lcd.print("c");
  lcd.setCursor(0, 3);
  lcd.print("Humid Box On");
  delay(4000);
  digitalWrite(humidfan, HIGH);
}

Which Arduino are you using?

This should be unsigned long:

const long interval = 14400000;

Strong hint: that is four hours, and the failure happens after four hours.

How long are the wires between your microcontroller and the LCD?

Your are using I2C which is intended to use on distcances shorter than 30 cm
If a single voltage-change on I2C is missing this can make the code hang completely.

Additional for analysing the problem you should keep the microcontroller connected to your computer and print to a serial terminal-software which can store all received characters into a textfile

best regards Stefan

Hey,

Im using the Arduino Uno. Before i made it reset after 4 hours sometimes it would last 2 or 3 hours then lock up, or it could run for 6 or 7 hours before it stopped.
4 hours was just me trying to beat it to locking up.

I will change that to and unsigned long, thank you.

You may be running out of memory. To save dynamic memory, convert all .print statements to put character constants in program memory.
Change this

   lcd.print("Fresh air in");

to this

  lcd.print(F("Fresh air in"));

And, of course, if you have not carefully isolated and shielded the motor/fan/etc. electrical systems from the Arduino power, random crashes due to motor noise can be expected.

Hey Stefan,

The wires the LCD are probably around 50cm long. I will make it shorter and see if that helps.

You are right about connecting to a serial terminal-software, its next on my list.

Thank you

You are reading the DHT-values very often, sometimes the same parameter 3 times subsequently.
I guess it is sufficient to read those values every 15 to 60 seconds.

Hey Jremington,

I will change the lcd.print statements, thank you.

I didn't even really think about shielding, going to have to look into it. The wiring is a bit of a mess since it been changed so many times.

Unshielded wires longer than about 5 cm are excellent antennas for picking up electrical noise from overhead lighting, motors, fans, relays and pumps.

Damn, how do i go about shielding them?

Im going to have to rewire the whole thing soon to keep power away from signal wires.

Or you put the hole thing in a metal box (aka Faraday's cage).

That is one of the starting points. In severe cases, use shielded wire, or as suggested above, put the sensitive circuitry in a grounded metal box.

sit rep

Pulled the power out for the screen, wires were nearly 600mm long, now they are 250mm and the screen even looks different.

Moved power wires away from signal wires.

changed the LCD print code.

tiz running away, short of a faraday cage ive tried it all.

Thank you.

To save memory, as well as improove your code, I suggest you write a general screen update function. Or maybe 2 of them for different cases.

What is supposed to happen if temp is higher than ok, but below max?

thank you, that sounds like something I should look at.

it never goes out of the lower and upper temps, that was when I was trying to work out why it was just stopping after a few hours.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.