hi there !
my plan was to make an ebb / flow aquarium controlled by an arduino mega and then from there go full IoT.
but as a first step I want to control as much as possible just on the mega.
the elements which have to be controlled are:
- an external sump/garden with lights to simulate ebb and flow
- heating element
- aquarium lights
- aquarium pump
-3 water sensors
-2 ec meters
-
1 distance sensor to measure water height
-
dht11/22
-
2 thermistor probes
-
2 light sensors
-
relays
the time i would like to control via NTP Time via Ethernet Shield
Time-Alarm (4 alarms) to call different functions for the day (Morning, Afternoon, Evening, Night)
Functions Activate Lights and Set Cycle Time of Ebb and Flow Pump
Timer which triggers 3 cycles with different parameters matching Morning Afternoon Evening and Night
1 cycle to check for NTP time every now and then
1 cycle to take sensor readings
1 cycle to activate second pump, depending on daytime this cycle is shorter or longer
interrupts for water/leakage detection via water sensors as well as distance sensor
further ideas for the project are:
ph probe
Thermocouple probe
web control of arduino via rasperry pi / mqtt / node red
alarm messages via email
all sorts of nice graphs and diagrams
webcams
future:
motion detection of fish
fish recognition
fish tracking
So I built a nice frame, set the aquarium up, did all the plumbing with a nice bell siphon, soldered the sensors and made nice acrylic cases for them. after a few tests and improvements everything works fine (except for the thermistor sensors, which react quite funny OO ?? )
As a next step I tested every single element of the device in single sketches and implemented them as they were fit and had no bugs. As you all know - this is where the real trouble starts...
my main issues at the moment are the following points:
-
thermistor probes need calibration. as they are resistors varying with temperature I think I need a voltage reference to calibrate the excact reading as V = C*I ? - any help is welcome
-
my main loop runs:
void loop () {
r.execute();
unsigned long currentMillis1 = millis();
// time to update ?
if ((unsigned long)(currentMillis1 - previousMillisUpdate1) >= intervallUpdate) {
Scheduler &s = Scheduler::currentScheduler();
Task &t = s.currentTask();
digitalClockDisplay();
previousMillisUpdate1 = currentMillis1;
}
Alarm.delay(11);
}
r.execute executes the 3 cycle callback functions:
1 cycle to check for NTP time (every 30 min, should run forever)
1 cycle to take sensor readings (every 20 seconds, should run forever)
1 cycle to activate second pump, depending on daytime this cycle is shorter or longer (hpr cycle - depending of the time of the day switching from high to low )
the ebb and flow cycle code is this:
void abc (){
Scheduler &s = Scheduler::currentScheduler();
Task &t = s.currentTask();
t1.disable();
r.deleteTask(t1);
t3.disable();
r.deleteTask(t3);
getNtpTime();
Serial.print("It is ");
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.println("");
Serial.print("Watering Plants for: ");
Serial.print (WateringTime / ((unsigned)1000));
Serial.println (" Seconds");
digitalWrite(PumpeA_Relais1, LOW);
digitalWrite(PumpeK_Relais2, HIGH);
int x = 0;
do {
unsigned long currentMillisWatering = millis();
if ((unsigned long)(currentMillisWatering - previousMillisWatering) >= intervallUpdate) {
digitalClockDisplay();
UltraSonic();
x++;
previousMillisWatering = currentMillisWatering;
}
}
while(x < (WateringTime / ((unsigned)1000)));
digitalWrite(PumpeK_Relais2, LOW);
Serial.println("Watering Plants STOP");
Serial.print("Watered Plants for: ");
Serial.print (WateringTime / ((unsigned)1000));
Serial.println (" Seconds");
Serial.print("Waiting: ");
Serial.print (FlowbackTime / ((unsigned)1000));
Serial.println (" Seconds to let Water Flow back");
int y = 0;
do {
unsigned long currentMillisafterWatering = millis();
if ((unsigned long)(currentMillisafterWatering - previousMillisafterWatering) >= intervallUpdate) {
digitalClockDisplay();
UltraSonic();
y++;
previousMillisafterWatering = currentMillisafterWatering;
}
}
while(y < (FlowbackTime / (unsigned)1000));
Serial.print("Waited: ");
Serial.print (FlowbackTime / (unsigned)1000);
Serial.println (" Seconds to let Water Flow back");
Serial.println("Turning Aquarium Pump PumpeA_Relais1 ON ");
digitalWrite(PumpeA_Relais1, HIGH);
Serial.println("Aquarium Pump PumpeA_Relais1 is ON ");
Serial.print("Wating for:");
Serial.print((CycleTime - WateringTime - FlowbackTime) / (unsigned)1000);
Serial.println(" Seconds to activate the next Cycle");
r.addTask(t1);
t1.enable();
r.addTask(t3);
t3.enable();
}
The Alarms are programmed for:
10:00 setting lights on and activate watering cycle
14:00 lights off and high ebb/flow cycle
16:00 lights on, low ebb flow cycle
21:00 lights off, watering cycle off
here are the alarm functions:
void LightsMorningON () {
Alarm.delay(11);
Scheduler &s = Scheduler::currentScheduler();
Task &t = s.currentTask();
Serial.print("Good Morning ! It is ");
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.println("");
Alarm.delay(11);
Serial.print("Turning Lights ON");
digitalWrite(PumpeA_Relais1, HIGH);
Serial.println("setting PumpeA_Relais1: HIGH");
digitalWrite(PumpeK_Relais2, LOW);
Serial.println("setting PumpeK_Relais2: LOW");
digitalWrite(LichtA_Relais3, HIGH);
Serial.println("setting LichtA_Relais3: HIGH");
digitalWrite(HeizstabA_Relais4, HIGH);
Serial.println("setting HeizstabA_Relais4: HIGH");
Alarm.delay(11);
t1.enable();
r.addTask(t1);
t3.enable();
r.addTask(t3);
t4.enable();
r.addTask(t4);
t4.setInterval(CycleTime);
Alarm.delay(11);
}
void LightsMorningOFF () {
Serial.print("Good Afternoon ! It is ");
Serial.print(hour());
printDigits(minute());
printDigits(second());
Alarm.delay(11);
Scheduler &s = Scheduler::currentScheduler();
Task &t = s.currentTask();
Serial.print("It is ");
Serial.println(hour());
printDigits(minute());
printDigits(second());
Alarm.delay(11);
Serial.print("Turning Lights OFF");
digitalWrite(LichtA_Relais3, LOW);
Serial.println("setting LichtA_Relais3: LOW");
Alarm.delay(11);
t1.enable();
r.addTask(t1);
t3.enable();
r.addTask(t3);
t4.enable();
r.addTask(t4);
t4.setInterval(CycleTimeHigh);
Serial.println("Rain: HIGH WATERING CYCLE IS ON");
Alarm.delay(11);
}
void LightsEveningON () {
Alarm.delay(11);
Scheduler &s = Scheduler::currentScheduler();
Task &t = s.currentTask();
Serial.print("Good Evening! It is ");
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.println("");
Alarm.delay(11);
Serial.println("Turning Lights ON");
digitalWrite(LichtA_Relais3, HIGH);
Serial.println("setting LichtA_Relais3: HIGH");
Alarm.delay(11);
t1.enable();
r.addTask(t1);
t3.enable();
r.addTask(t3);
t4.enable();
r.addTask(t4);
t4.setInterval(CycleTime);
Serial.println("Rain: HIGH WATERING CYCLE IS OFF");
Alarm.delay(11);
}
void LightsEveningOFF () {
Alarm.delay(11);
Scheduler &s = Scheduler::currentScheduler();
Task &t = s.currentTask();
Serial.print("Good Night ! It is ");
Serial.print(hour());
printDigits(minute());
printDigits(second());
Alarm.delay(11);
Serial.println("");
Serial.print("Turning Lights OFF");
digitalWrite(LichtA_Relais3, LOW);
Serial.println("setting LichtA_Relais3: LOW");
t1.enable();
r.addTask(t1);
Alarm.delay(11);
t3.enable();
r.addTask(t3);
Alarm.delay(11);
t4.disable();
r.deleteTask(t4);
Alarm.delay(11);
}
after trying many different options I ended up at best with the alarms getting triggered minutes after they should or not at all ...
where it gets really tricky is: whyle a ebb and flow cycle is activated, the alarm should be delayed to let the water flow back
I am helpfull for any ideas or solutions
thank you all and may the fish swim without getting electrocuted
:o