#include <Wire.h>
#include <SPI.h>
#include <RTClib.h>
/*
Dread240 reef aquarium controller project. Scope of controller to include full
dimming and control capabilities for maxwellen 750ma constant current LED drivers,
16 programmable 120vac relay, 3 BNC inputs for use in PH, ORP and Salinity monitoring,
4 x 20 LCD screen for monitoring, temperature monitoring and control, top off functions
and dosing parameters, and whatever else crazy gadgets I decide to come up with or get
motivated to do
*/
RTC_DS1307 RTC;
//slaveSelectPin is different on mega2560 boards. All other boards use pin 10 as slaveSelectPin
const int slaveSelectPin = 53;
/*
User Define Variables --- If using the ad5206 Digital Pot like I specified, the correct step amount
is 255. The variable is only in here so that if you opt for a different pot you can change it here and
all the calculations will scale to new pot. Please note that you only set your start points for the fades
here, not the start and finish times. Your actual FINISH time will be your p#FadeOffStart + p#TimeToFade.
You do not have to fill in every variable. If you're only using 2 channels of the pot, you can simply input
your start times on that. Start and Fade times are ALL configured by what SECOND of the day you want it to
occur. If you want your FadeOnStart to be 12:00 (noon), your value to input here is 12hrs x 60 min x 60 sec.
The value to enter would be 43200. In a GUI you would see this as a time, but welcome to only working on the
code side of things. If you need more help pm me on reefcentral till I get the website going
*/
int potSteps = 255;
long p1TimeToFade = 0;
long p1FadeOnStart = 0;
long p1FadeOffStart = 0;
long p2TimeToFade = 0;
long p2FadeOnStart = 0;
long p2FadeOffStart = 0;
long p3TimeToFade = 600;
long p3FadeOnStart = 78000;
long p3FadeOffStart = 79000;
long p4TimeToFade = 0;
long p4FadeOnStart = 0;
long p4FadeOffStart = 0;
long p5TimeToFade = 60;
long p5FadeOnStart = 80350;
long p5FadeOffStart = 80550;
long p6TimeToFade = 0;
long p6FadeOnStart = 0;
long p6FadeOffStart = 0;
//Program Defined Variables ****do not touch****
int p1CurrentPosition;
int p2CurrentPosition;
int p3CurrentPosition;
int p4CurrentPosition;
int p5CurrentPosition;
int p6CurrentPosition;
int p1NewPosition;
int p2NewPosition;
int p3NewPosition;
int p4NewPosition;
int p5NewPosition;
int p6NewPosition;
long seconds_of_day;
long lastPrint;
long p1LastStep;
long p2LastStep;
long p3LastStep;
long p4LastStep;
long p5LastStep;
long p6LastStep;
long p1FadeOnEnd = (p1FadeOnStart + p1TimeToFade);
long p1FadeOffEnd = (p1FadeOffStart + p1TimeToFade);
long p2FadeOnEnd = (p2FadeOnStart + p2TimeToFade);
long p2FadeOffEnd = (p2FadeOffStart + p2TimeToFade);
long p3FadeOnEnd = (p3FadeOnStart + p3TimeToFade);
long p3FadeOffEnd = (p3FadeOffStart + p3TimeToFade);
long p4FadeOnEnd = (p4FadeOnStart + p4TimeToFade);
long p4FadeOffEnd = (p4FadeOnStart + p4TimeToFade);
long p5FadeOnEnd = (p5FadeOnStart + p5TimeToFade);
long p5FadeOffEnd = (p5FadeOffStart + p5TimeToFade);
long p6FadeOnEnd = (p6FadeOnStart + p6TimeToFade);
long p6FadeOffEnd = (p6FadeOffStart + p6TimeToFade);
long p1SecBetweenStep = (p1TimeToFade / potSteps);
long p2SecBetweenStep = (p2TimeToFade / potSteps);
long p3SecBetweenStep = (p3TimeToFade / potSteps);
long p4SecBetweenStep = (p4TimeToFade / potSteps);
long p5SecBetweenStep = (p5TimeToFade / potSteps);
long p6SecBetweenStep = (p6TimeToFade / potSteps);
void setup () {
pinMode (slaveSelectPin, OUTPUT);
Serial.begin(57600);
Wire.begin();
RTC.begin();
SPI.begin();
if (! RTC.isrunning()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
RTC.adjust(DateTime(__DATE__, __TIME__));
}
}
void loop () {
DateTime now = RTC.now();
seconds_of_day = now.second() + (now.minute() * 60L) + ((now.hour() * 60L) * 60L);
/************* Conditional statements and controls for pot 1 *****************/
if (seconds_of_day < p1FadeOnStart)
p1NewPosition = 1;
if (seconds_of_day > p1FadeOffEnd)
p1NewPosition = 1;
if (seconds_of_day >= p1FadeOnStart){
if (seconds_of_day <= p1FadeOnEnd){
if (p1NewPosition <= potSteps){
p1NewPosition = (seconds_of_day - p1FadeOnStart) / p1SecBetweenStep;
}
}
}
if (seconds_of_day > p1FadeOnEnd){
if (seconds_of_day < p1FadeOffStart){
if (p1NewPosition != potSteps){
p1NewPosition = potSteps;
}
}
}
if (seconds_of_day >= p1FadeOffStart){
if (seconds_of_day <= p1FadeOffEnd){
if (p1NewPosition >= 1){
p1NewPosition = (p1FadeOffEnd - seconds_of_day) / p1SecBetweenStep;
}
}
}
if (p1NewPosition < 1){
p1NewPosition = 1;
}
if (p1NewPosition > potSteps){
p1NewPosition = potSteps;
}
//Send updated values to digital pot if a change is necessary
if (p1NewPosition != p1CurrentPosition){
digitalWrite(slaveSelectPin,LOW);
delay(10);
SPI.transfer(0);
SPI.transfer(p1NewPosition);
delay(10);
digitalWrite(slaveSelectPin,HIGH);
p1CurrentPosition = p1NewPosition;
p1LastStep = seconds_of_day;
}
/************* Conditional statements and controls for pot 2 *****************/
if (seconds_of_day < p2FadeOnStart)
p2NewPosition = 1;
if (seconds_of_day > p2FadeOffEnd)
p2NewPosition = 1;
if (seconds_of_day >= p2FadeOnStart){
if (seconds_of_day <= p2FadeOnEnd){
if (p2NewPosition < potSteps){
p2NewPosition = (seconds_of_day - p2FadeOnStart) / p2SecBetweenStep;
}
}
}
if (seconds_of_day > p2FadeOnEnd){
if (seconds_of_day < p2FadeOffStart){
if (p2NewPosition != potSteps){
p2NewPosition = potSteps;
}
}
}
if (seconds_of_day >= p2FadeOffStart){
if (seconds_of_day <= p2FadeOffEnd){
if (p2NewPosition >= 1){
p2NewPosition = (p2FadeOffEnd - seconds_of_day) / p2SecBetweenStep;
}
}
}
if (p2NewPosition < 1){
p2NewPosition = 1;
}
if (p2NewPosition > potSteps){
p2NewPosition = potSteps;
}
//Send updated values to digital pot if a change is necessary
if (p2NewPosition != p2CurrentPosition){
digitalWrite(slaveSelectPin,LOW);
delay(10);
SPI.transfer(1);
SPI.transfer(p2NewPosition);
delay(10);
digitalWrite(slaveSelectPin,HIGH);
p2CurrentPosition = p2NewPosition;
p2LastStep = seconds_of_day;
}
/************* Conditional statements and controls for pot 3 *****************/
if (seconds_of_day < p3FadeOnStart)
p3NewPosition = 1;
if (seconds_of_day > p3FadeOffEnd)
p3NewPosition = 1;
if (seconds_of_day >= p3FadeOnStart){
if (seconds_of_day <= p3FadeOnEnd){
if (p3NewPosition <= potSteps){
p3NewPosition = (seconds_of_day - p3FadeOnStart) / p3SecBetweenStep;
}
}
}
if (seconds_of_day > p3FadeOnEnd){
if (seconds_of_day < p3FadeOffStart){
if (p3NewPosition != potSteps){
p3NewPosition = potSteps;
}
}
}
if (seconds_of_day >= p3FadeOffStart){
if (seconds_of_day <= p3FadeOffEnd){
if (p3NewPosition >= 1){
p3NewPosition = (p3FadeOffEnd - seconds_of_day) / p3SecBetweenStep;
}
}
}
if (p3NewPosition < 1){
p3NewPosition = 1;
}
if (p3NewPosition > potSteps){
p3NewPosition = potSteps;
}
//Send updated values to digital pot if a change is necessary
if (p3NewPosition != p3CurrentPosition){
digitalWrite(slaveSelectPin,LOW);
delay(10);
SPI.transfer(2);
SPI.transfer(p3NewPosition);
delay(10);
digitalWrite(slaveSelectPin,HIGH);
p3CurrentPosition = p3NewPosition;
p3LastStep = seconds_of_day;
}
/************* Conditional statements and controls for pot 4 *****************/
if (seconds_of_day < p4FadeOnStart)
p4NewPosition = 1;
if (seconds_of_day > p4FadeOffEnd)
p4NewPosition = 1;
if (seconds_of_day >= p4FadeOnStart){
if (seconds_of_day <= p4FadeOnEnd){
if (p4NewPosition <= potSteps){
p4NewPosition = (seconds_of_day - p4FadeOnStart) / p4SecBetweenStep;
}
}
}
if (seconds_of_day > p4FadeOnEnd){
if (seconds_of_day < p4FadeOffStart){
if (p4NewPosition != potSteps){
p4NewPosition = potSteps;
}
}
}
if (seconds_of_day >= p4FadeOffStart){
if (seconds_of_day <= p4FadeOffEnd){
if (p4NewPosition >= 1){
p4NewPosition = (p4FadeOffEnd - seconds_of_day) / p4SecBetweenStep;
}
}
}
if (p4NewPosition < 1){
p4NewPosition = 1;
}
if (p4NewPosition > potSteps){
p4NewPosition = potSteps;
}
//Send updated values to digital pot if a change is necessary
if (p4NewPosition != p4CurrentPosition){
digitalWrite(slaveSelectPin,LOW);
delay(10);
SPI.transfer(3);
SPI.transfer(p4NewPosition);
delay(10);
digitalWrite(slaveSelectPin,HIGH);
p4CurrentPosition = p4NewPosition;
p4LastStep = seconds_of_day;
}
/************* Conditional statements and controls for pot 5 *****************/
if (seconds_of_day < p5FadeOnStart)
p5NewPosition = 0;
if (seconds_of_day > p5FadeOffEnd)
p5NewPosition = 0;
if (seconds_of_day >= p5FadeOnStart){
if (seconds_of_day <= p5FadeOnEnd){
if (p5NewPosition <= potSteps){
p5NewPosition = (seconds_of_day - p5FadeOnStart) / p5SecBetweenStep;
}
}
}
if (seconds_of_day > p5FadeOnEnd){
if (seconds_of_day < p5FadeOffStart){
if (p5NewPosition != potSteps){
p5NewPosition = potSteps;
}
}
}
if (seconds_of_day >= p5FadeOffStart){
if (seconds_of_day <= p5FadeOffEnd){
if (p5NewPosition >= 0){
p5NewPosition = (p5FadeOffEnd - seconds_of_day) / p5SecBetweenStep;
}
}
}
if (p5NewPosition < 0){
p5NewPosition = 0;
}
if (p5NewPosition > potSteps){
p5NewPosition = potSteps;
}
//Send updated values to digital pot if a change is necessary
if (p5NewPosition != p5CurrentPosition){
digitalWrite(slaveSelectPin,LOW);
delay(10);
SPI.transfer(4);
SPI.transfer(p5NewPosition);
delay(10);
digitalWrite(slaveSelectPin,HIGH);
p5CurrentPosition = p5NewPosition;
p5LastStep = seconds_of_day;
}
/************* Conditional statements and controls for pot 6 *****************/
if (seconds_of_day < p6FadeOnStart)
p6NewPosition = 1;
if (seconds_of_day > p6FadeOffEnd)
p6NewPosition = 1;
if (seconds_of_day >= p6FadeOnStart){
if (seconds_of_day <= p6FadeOnEnd){
if (p6NewPosition <= potSteps){
p6NewPosition = (seconds_of_day - p6FadeOnStart) / p6SecBetweenStep;
}
}
}
if (seconds_of_day > p6FadeOnEnd){
if (seconds_of_day < p6FadeOffStart){
if (p6NewPosition != potSteps){
p6NewPosition = potSteps;
}
}
}
if (seconds_of_day >= p6FadeOffStart){
if (seconds_of_day <= p6FadeOffEnd){
if (p6NewPosition >= 1){
p6NewPosition = (p6FadeOffEnd - seconds_of_day) / p6SecBetweenStep;
}
}
}
if (p6NewPosition < 1){
p6NewPosition = 1;
}
if (p6NewPosition > potSteps){
p6NewPosition = potSteps;
}
//Send updated values to digital pot if a change is necessary
if (p6NewPosition != p6CurrentPosition){
digitalWrite(slaveSelectPin,LOW);
delay(10);
SPI.transfer(5);
SPI.transfer(p6NewPosition);
delay(10);
digitalWrite(slaveSelectPin,HIGH);
p6CurrentPosition = p6NewPosition;
p6LastStep = seconds_of_day;
}
/* Serial Reporting to computer... inside an IF statement so that delay isn't used and hangs calculations on controller*/
if (seconds_of_day >= (lastPrint + 3L)){
Serial.print("seconds into day : ");
Serial.print(seconds_of_day);
Serial.println();
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print('/');
Serial.print(now.year(), DEC);
Serial.println();
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
Serial.print("Digital Pot channel and positiong reporting");
Serial.println();
Serial.print("Channel #1: ");
Serial.print(p1CurrentPosition, DEC);
Serial.print(" last step: ");
Serial.print(p1LastStep, DEC);
Serial.print(" Seconds Between Steps: ");
Serial.print(p1SecBetweenStep, DEC);
Serial.println();
Serial.print("Channel #2: ");
Serial.print(p2CurrentPosition, DEC);
Serial.print(" last step: ");
Serial.print(p2LastStep, DEC);
Serial.print(" Seconds Between Steps: ");
Serial.print(p2SecBetweenStep, DEC);
Serial.println();
Serial.print("Channel #3: ");
Serial.print(p3CurrentPosition, DEC);
Serial.print(" last step: ");
Serial.print(p3LastStep, DEC);
Serial.print(" Seconds Between Steps: ");
Serial.print(p3SecBetweenStep, DEC);
Serial.println();
Serial.print("Channel #4: ");
Serial.print(p4CurrentPosition, DEC);
Serial.print(" last step: ");
Serial.print(p4LastStep, DEC);
Serial.print(" Seconds Between Steps: ");
Serial.print(p4SecBetweenStep, DEC);
Serial.println();
Serial.print("Channel #5: ");
Serial.print(p5CurrentPosition, DEC);
Serial.print(" last step: ");
Serial.print(p5LastStep, DEC);
Serial.print(" Seconds Between Steps: ");
Serial.print(p5SecBetweenStep, DEC);
Serial.println();
Serial.print("Channel #6: ");
Serial.print(p6CurrentPosition, DEC);
Serial.print(" last step: ");
Serial.print(p6LastStep, DEC);
Serial.print(" Seconds Between Steps: ");
Serial.print(p6SecBetweenStep, DEC);
Serial.println();
Serial.println();
Serial.println();
lastPrint = seconds_of_day;
if (lastPrint >= 86400){
lastPrint = lastPrint - 86400;
}
}
}