I'm building a tank controller for my planted aquarium to include CO2 regulation via PH (works great) and dimming lights (the point of this post) with sunrise time, sunset time, minimum PWM, maximum PWM, and fade rate all settable by the user. Note that I have 2 arrays of lights, 18W of blues and 50W of whites. I found a way to do so with the TimeAlarms library so that an alarm is set, then when the alarm triggers and calls the event it resets the alarm time plus the calculated few seconds and dims the lights. My main problem is that I can't seem to get the alarms to reset once they are redefined with a new trigger time, once the trigger time is hit or the associated event is called the program should continue on its own until it reaches the minimum or maximum PWM, alas it does not. I'm sure my code is dirty, been kinda trying everything but from my knowledge this should be close to functional. If there is a better way to do this I am not in objection to redoing the whole thing. The time alarms library seemed ideal because I would handle both the alarms and repetitive triggering with the same function. I am currently not using an RTC but I should be able to squeeze it in on my next version of the PCB. For now I would be content being able to set the time or even just plug it in at 12 but might as well. This code is stripped down and does not really use any of the menus and keypad input that the old version did, I simply need assistance with the alarms before I make another butchered program trying to get everything to work at once.
#include <TimeAlarms.h>
#include <Time.h>
#include <LiquidCrystal.h>
#include <Keypad.h>
const int fadeIncr = 4;
const int riseIncr = 2;
const byte rows = 4; //four rows
const byte cols = 3; //three columns
const int solPin = 11, sunPin = 9, moonPin = 10;
const int maxSunDuty = 255;
const int maxMoonDuty = 255;
const int minMoonDuty = 25;
int moonDuty = 0, sunDuty=0;
int phVal=0;
int sensorPin = A0; // PHProbe analog in
int sensorValue = 0;
int solState = LOW; //CO2 injector solenoid state
AlarmID_t sunRise;
AlarmID_t sunSet; // alarm IDs
AlarmID_t moonSet;
time_t initTime = AlarmHMS(12,0,0) ; // initial time
time_t startSunRise=AlarmHMS(12,0,15); //start the sunrise shortly after power on
// Follow with device setup
char keys[rows][cols] = {
{'1','2','3' },
{'4','5','6' },
{'7','8','9' },
{'*','0','#' }
};
byte rowPins[rows] = {
7, 6, 5, 4}; //connect to the row pinouts of the keypad
byte colPins[cols] = {
3, 2, 1}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, rows, cols );
LiquidCrystal lcd(8, 15, 16, 17, 18, 19);
void setup() {
// put your setup code here, to run once:
lcd.begin(20, 4);
setTime(12,0,0,1,1,13);
pinMode(solPin, OUTPUT);
void menu();
//sunRise = Alarm.alarmRepeat(startSunRise, sunRiseEvent); // set the on alarm time
//sunSet = Alarm.alarmRepeat(initTime, sunSetEvent); // set the sun off alarm time
//moonSet = Alarm.alarmRepeat(initTime, moonSetEvent); // set the moon off alarm time
Alarm.timerRepeat(15, checkPH); //check PH every 15
//Alarm.enable(sunRise);
//Alarm.disable(sunSet);
//Alarm.disable(moonSet);
}
void sunRiseEvent(){
if (sunDuty < maxSunDuty)
{
time_t newOnTime = now() + riseIncr;
Alarm.write(sunRise , newOnTime);
Alarm.enable(sunRise);
sunDuty++;
analogWrite(sunPin, sunDuty);
}
else if (moonDuty < maxMoonDuty)
{
time_t newOnTime = now() + riseIncr;
Alarm.write(sunRise , newOnTime);
Alarm.enable(sunRise);
moonDuty++;
analogWrite(moonPin, moonDuty);
}
if(sunDuty>=maxSunDuty && moonDuty>=maxMoonDuty)
{
Alarm.disable(sunRise);
}
}
void sunSetEvent(){
if (sunDuty > 0)
{
time_t newOnTime = now() + fadeIncr;
Alarm.write(sunSet , newOnTime);
Alarm.enable(sunSet);
sunDuty--;
analogWrite(sunPin, sunDuty);
}
else
{
Alarm.disable(sunSet);
Alarm.enable(moonSet);
moonSetEvent();
}
}
void moonSetEvent(){
if(moonDuty>minMoonDuty)
{
time_t newOnTime = now() + fadeIncr;
Alarm.write(moonSet , newOnTime);
Alarm.enable(moonSet);
moonDuty--;
analogWrite(sunPin, sunDuty);
}
else
{
Alarm.disable(moonSet);
}
}
void checkPH(){
phVal=0;
for (int num = 0; num < 5; num++) {
sensorValue=analogRead(sensorPin);
phVal=phVal+sensorValue;
}
phVal=phVal/5; //concatenated avg of 5 reads
if (phVal<968) solState=HIGH;
else solState=LOW;
digitalWrite(solPin, solState);
return;
}
void loop() {
Alarm.delay(10);
// put your main code here, to run repeatedly:
char key=keypad.getKey();
switch (key){
case '1':
analogWrite(sunPin, 255); //SetTime
Alarm.enable(sunRise);
sunRiseEvent();
Alarm.disable(sunSet);
Alarm.disable(moonSet);
break;
case '2':
analogWrite(moonPin, 255); //SetCycles
Alarm.enable(sunSet);
Alarm.disable(sunRise);
Alarm.disable(moonSet);
sunSetEvent();
break;
case '*':
menu();
break;
}
lcd.setCursor(0, 3);
lcd.print(phVal);
}
void menu() {
lcd.clear();
lcd.print("1:Sunrise");
lcd.setCursor(0, 1);
lcd.print("2:Sunset");
return;
}
Schematic Pic
Thanks,
-B&C