The microcontroller of my aeroponic system died and I have created a replacement using Arduino Uno, a 2 relay relay board, 7 LEDs and three buttons. The system works fine for a few hours and then hangs. I have rewritten the code three times, added capacitors to all inputs to no avail. As this is my first Arduino project and also the first encounter I have with C++ I suspect the problem is with my code rather than the harware. To make the system work for more than a few hours I added a watchdog to the code which keeps the system running but forgets the user choices every few hours.
The user interface consists of three buttons
#1 for selecting mode: Vegetables, Herbs, Flowers, Others
#2 for selecting phase: Seeding, Growing, Ripening
#3 for toggling growing light on and off.
In addition there are 7 leds that indicate mode and phase.
This is the Arduino Uno board I am using
Link to the relay board I am using.
Any idea to the reason why the system hangs after a few hours would be greatly appreciated.
Timo
// Arduino replacement for Aerponics controller board
// Version 1.2
// Author timo121357 25.7.2019
// Watchdog - Version: Latest
#include <Watchdog.h>
// Buttons of Aeroponics unit and corresponding Arduino IO pins
const byte leftButton = A0;
const byte middleButton = A1;
const byte lightButton = A2;
// LEDs of Aerponics unit and corresponding Arduino IO pins
const byte others = 3;
const byte flowers = 4;
const byte herbs = 5;
const byte vegetables = 2;
const byte ripening = 7;
const byte growing = 8;
const byte seeding = 6;
// Relay board and corresponding Arduino IO pins
const byte light = 9;
const byte pump = 10;
// States
byte mode = 0; // 0=Vegetables, 1=Herbs, 2=Flowers, 3=Other
byte phase = 2; // 0,1=Seeding, 2,3=Growing, 4,5=Ripening
unsigned long pumpChanged=0; // time when pump state last was changed
unsigned long lightChanged=0; // time when light state last was changed
// light timers in hours: On, Off: Seeding, Growing, Ripening
unsigned long lightTimer[][6] = {
{4,20,20,4,20,4}, // mode 0: Vegetables
{4,20,20,4,20,4}, // mode 1: Herbs
{4,20,20,4,20,4}, // mode 2: Flowers
{4,20,20,4,20,4} // mode 3: Others
};
// pump timers in seconds: On, Off: Seeding, Growing, Ripening
unsigned long pumpTimer[][6] = {
{30,30,5,240,5,480}, // mode 0: Vegetables
{30,30,5,115,3,177}, // mode 1: Herbs
{30,30,5,60,3,300}, // mode 2: Flowers
{60,120,60,180,60,600}// mode 3: Others
};
Watchdog watchdog; // Watchdog declaration
void setup()
{
Serial.begin(9600); // initialize serial communications at 9600 bps
pinMode(leftButton, INPUT_PULLUP);
pinMode(middleButton, INPUT_PULLUP);
pinMode(lightButton, INPUT_PULLUP);
pinMode(vegetables, OUTPUT);
pinMode(herbs, OUTPUT);
pinMode(flowers, OUTPUT);
pinMode(others, OUTPUT);
pinMode(seeding, OUTPUT);
pinMode(growing, OUTPUT);
pinMode(ripening, OUTPUT);
pinMode(pump, OUTPUT);
pinMode(light, OUTPUT);
digitalWrite(light, HIGH);
digitalWrite(pump, HIGH);
watchdog.enable(Watchdog::TIMEOUT_2S);
}
void loop()
{
watchdog.reset();// Watchdog gets a bone
readButtons(); // read input from buttons
// Set indicator LEDs:
// Mode LED
if (mode == 0) digitalWrite(vegetables,HIGH); else digitalWrite(vegetables,LOW);
if (mode == 1) digitalWrite(herbs,HIGH); else digitalWrite(herbs,LOW);
if (mode == 2) digitalWrite(flowers,HIGH); else digitalWrite(flowers,LOW);
if (mode == 3) digitalWrite(others,HIGH); else digitalWrite(others,LOW);
// Phase LED
if (phase == 0 || phase == 1) digitalWrite(seeding,HIGH); else digitalWrite(seeding,LOW);
if (phase == 2 || phase == 3) digitalWrite(growing,HIGH); else digitalWrite(growing,LOW);
if (phase == 4 || phase == 5) digitalWrite(ripening,HIGH); else digitalWrite(ripening,LOW);
// store current time before timer controls start
unsigned long currentMillis = millis();
// control the light time
if (digitalRead(light) == HIGH){
if ((unsigned long)(currentMillis - lightChanged >= 3600000 * lightTimer[mode][phase])){
digitalWrite(light,LOW); //turn light off after timer has expired
lightChanged = currentMillis;
}
}
else if ((unsigned long)(currentMillis - lightChanged >= 3600000 * lightTimer[mode][phase+1])){
digitalWrite(light,HIGH); //turn light back on after timer has expired
lightChanged = currentMillis;
}
// control pump time
if (digitalRead(pump) == HIGH){
if ((unsigned long)(currentMillis - pumpChanged >= 1000 * pumpTimer[mode][phase])){
digitalWrite(pump,LOW); //turn pump off after timer has expired
pumpChanged = currentMillis;
}
}
else if ((unsigned long)(currentMillis - pumpChanged >= 1000*pumpTimer[mode][phase+1])){
digitalWrite(pump,HIGH); //turn pump back on after timer has expired
pumpChanged = currentMillis;
}
}
void readButtons() // read input from buttons
{
delay(200); // to avoid multiple presses in one occasion
if (digitalRead(leftButton) == LOW){
mode += 1;
if (mode > 3) mode = 0;
}
else if (digitalRead(middleButton) == LOW){
phase += 2; // phase has on and off times for each mode, hence increments in 2
if (phase > 5) phase = 0;
}
else if (digitalRead(lightButton) == LOW){
digitalWrite(light, !digitalRead(light)); //toggle light
}
}