- Code: Select all
/*******************************************************************************
*
* Purpose: Aquarium Controller
*
*
* Arduino Version 022
*
*
*
* Originally written by Martin, liquidartstattoos@gmail.com
*
* Initial version 1.0 5.21.2011
*
* Changes Date Details
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or banned FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*******************************************************************************/
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68 //set rtc
#include <LiquidCrystal.h> // initialize the library with the numbers of the interface pins
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 9 //Define the pin of the DS18B20
int moon = 2; // moon light
int fan = 49; // Fan power relay connected to analog pin 0
int heater = 31; // heater
int iBlueIntensity; //declare the integer of blue intensity
float fBlueIntensity; //declare the floating point version of blue intensity
// RTC variables
byte second, rtcMins, oldMins, rtcHrs, oldHrs, dayOfWeek, dayOfMonth, month, year, psecond;
LiquidCrystal lcd(22,23,24,25,26,27);
//LiquidCrystal lcd(12,13,4,5,6,7); // typically 8, 9, 4, 5, 6, 7
// Set up the custom fish icon
byte newChar[8] = {
B00000,
B00000,
B10001,
B11011,
B11111,
B11111,
B11001,
B10000
};
byte newChar1[8] = {
B00001,
B00010,
B11101,
B11010,
B11111,
B11110,
B11100,
B00000
};
byte newChar2[8] = {
B00000,
B00000,
B10001,
B11011,
B11111,
B11111,
B10011,
B00001
};
byte newChar3[8] = {
B10000,
B01000,
B10111,
B01011,
B11111,
B01111,
B00111,
B00000
};
byte newChar4[8] = {
B00111,
B01110,
B11100,
B11000,
B11000,
B11100,
B01110,
B00111
};
byte newChar5[8] = {
B01010,
B10000,
B00010,
B01001,
B00100,
B10000,
B00100,
B10001
};
byte newChar6[8] = {
B01010,
B00100,
B00001,
B11011,
B00011,
B00001,
B01000,
B10010
};
byte newChar7[8] = {
B10010,
B00100,
B10000,
B11011,
B11000,
B10000,
B00010,
B01001
};
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// LED variables (Change to match your needs)
byte bluePins[] = {3,4}; // PWM pins for blues - if you plan to use the photo stagger, please place the pins in the order you would like them to start
byte whitePins[] = {5,6}; // PWM pins for whites - if you plan to use the photo stagger, please place the pins in the order you would like them to start
byte blueChannels = 2; // how many PWMs for blues (count from above)
byte whiteChannels = 2; // how many PWMs for whites (count from above)
int photoStagger = 0; // offset for east - west delay on each channel in minutes
int startOffset = 0; // offset for start times in minutes - used if you want to change the start and finish time of the cycle. i.e move it to a later time in the day
int colourOffset = 30; // offset for whites to start after blues start in minutes
byte blueLevel[] = {255,255}; // max intensity for Blue LED's
byte whiteLevel[] = {255,255}; // max intensity for White LED's
// Month Data for Start, Stop, Photo Period and Fade (based off of actual times, best not to change)
int daysInMonth[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; //Days in each month
int minMinuteStart[12] = {310, 332, 348, 360, 372, 386, 394, 387, 364, 334, 307, 298}; //Minimum start times in each month
int maxMinuteStart[12] = {331, 347, 360, 372, 386, 394, 388, 365, 335, 308, 298, 309}; //Max start time in each month
int minMinuteFade[12] = {350, 342, 321, 291, 226, 173, 146, 110, 122, 139, 217, 282}; //Minimum fade time in each month
int maxMinuteFade[12] = {342, 321, 291, 226, 173, 146, 110, 122, 139, 217, 282, 350}; //Max fade time in each month
int minMinuteStop[12] = {1122, 1120, 1102, 1073, 1047, 1034, 1038, 1050, 1062, 1071, 1085, 1105}; //minimum stop times each month
int maxMinuteStop[12] = {1121, 1103, 1074, 1048, 1034, 1038, 1050, 1061, 1071, 1084, 1104, 1121}; //maximum stop times each month
// Weather variables
int weather = 1; // 0 off, 1 on
int clearDays[12] = {15, 12, 20, 23, 28, 37, 43, 48, 51, 41, 29, 23};
int cloudyDays[12] = {60, 61, 62, 60, 64, 63, 68, 66, 63, 54, 52, 53};
float clearDay = 0.25; // Max cloud value on clear day (percent of max string value)
float cloudyDay = 0.75; // Max cloud value on cloudy day (percent of max string value)
float normalDay = 0.5; // Max cloud value on normal day (percent of max string value)
byte value;
int day, fadeOn, fadeOff, time, pause, count, cloud;
long start, finish;
// Other variables - Do not need to be changed.
int minCounter; // counter that resets at midnight
long secCounter; // counter for seconds - needed for weather
int fadeDuration; // minutes to fade - calculated by map above
int ledStartMins; // minute to start led’s - calculated by map above
int ledStopMins; // minute to stop led’s - calculated by map above
byte blueMax[] = {0}; // used for over temp protection
byte whiteMax[] = {0}; // used for over temp protection
byte valueBlue[] = {0}; // value for clouds
byte valueWhite[] = {0}; // value for clouds
/****** LED Functions ******/
/***************************/
//function to set LED brightness according to time of day
byte setLed(
int mins, // current time in minutes
byte ledPin, // pin for this channel of LEDs
int start, // start time for this channel of LEDs
int fade, // fade duration for this channel of LEDs
int stop, // stop time for this channel of LEDs
byte ledMax, // max value for this channel of LEDs
long begin, // time cloud cycle begins in seconds
long secs, // current time in seconds
int on, // time for cloud to fade on in seconds
int off, // time for cloud to fade off in seconds
long time, // time of cloud
byte value // value for cloud
// max value for this channel
) {
byte ledVal = 0;
if (mins <= start || mins >= stop) //this is when the LEDs are off, thus ledVal is 255;
{
ledVal = 0;
}
if (mins > start && mins <= start + fade) //this is sunrise
{
ledVal = map(mins, start, start + fade, 0, ledMax);
}
if (mins > start + fade && mins < stop - fade && weather == 1)
{
ledVal = ledMax;
if (count == 1){
if (secs >= begin && secs < begin + fadeOn)
{
ledVal = map(secs, begin, begin + on, ledMax, value);
}
if (secs >= begin + on && secs < begin + on + time)
{
ledVal = value;
}
if (secs >= begin + on + time && secs < begin + on + time + off)
{
ledVal = map(secs, begin + on + time, begin + on + time + off, value, ledMax);
}
if (secs >= begin + on + time + off)
{
ledVal = ledMax;
}
if (secs >= finish)
{
count = 0;
}
}
}
if (mins > start + fade && mins < stop - fade && weather == 0)
{
ledVal = ledMax;
}
if (mins < stop && mins >= stop - fade) //this is the sunset
{
ledVal = map(mins, stop - fade, stop, ledMax, 0);
}
analogWrite(ledPin, ledVal);
return ledVal;
}
/***** RTC Functions *******/
/***************************/
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers
void setDateDs1307(byte second, // 0-59
byte minute, // 0-59
byte hour, // 1-23
byte dayOfWeek, // 1-7
byte dayOfMonth, // 1-28/29/30/31
byte month, // 1-12
byte year) // 0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0);
Wire.send(decToBcd(second)); // 0 to bit 7 starts the clock
Wire.send(decToBcd(minute));
Wire.send(decToBcd(hour)); // If you want 12 hour am/pm you need to set
// bit 6 (also need to change readDateDs1307)
Wire.send(decToBcd(dayOfWeek));
Wire.send(decToBcd(dayOfMonth));
Wire.send(decToBcd(month));
Wire.send(decToBcd(year));
Wire.endTransmission();
}
// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
// Reset the register pointer
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
// A few of these need masks because certain bits are control bits
*second = bcdToDec(Wire.receive() & 0x7f);
*minute = bcdToDec(Wire.receive());
*hour = bcdToDec(Wire.receive() & 0x3f); // Need to change this if 12 hour am/pm
*dayOfWeek = bcdToDec(Wire.receive());
*dayOfMonth = bcdToDec(Wire.receive());
*month = bcdToDec(Wire.receive());
*year = bcdToDec(Wire.receive());
}
int moonPhase(int moonYear, int moonMonth, int moonDay)
{
int dayFromYear, dayFromMonth;
double julianDay;
int phase;
if (moonMonth < 3) //keep the month before march
{
moonYear--; //take away a year
moonMonth += 12; //add an extra 12 months (the year taken away from before)
}
++moonMonth;
dayFromYear = 365.25 * moonYear; //get days from current year
dayFromMonth = 30.6 * moonMonth; //get number of days from the current month
julianDay = dayFromYear + dayFromMonth + moonDay - 694039.09; //add them all
julianDay /= 29.53; //divide by the length of lunar cycle
phase = julianDay; //take integer part
julianDay -= phase; //get rid of the int part
phase = julianDay*8 + 0.5; //get it between 0-8 and round it by adding .5
phase = phase & 7; //get a number between 1-7
return phase; //1 == new moon, 4 == full moon
}
/*||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| D E F I N E : O N E S E C O N D |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
void onesecond() //function that runs once per second while program is running
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
lcd.setCursor(0, 0);
if(hour>0)
{
if(hour<=12)
{
lcd.print(hour, DEC);
}
else
{
lcd.print(hour-12, DEC);
}
}
else
{
lcd.print("12");
}
lcd.print(":");
if (minute < 10) {
lcd.print("0");
}
lcd.print(minute, DEC);
//lcd.print(":");
//if (second < 10) {
// lcd.print("0");
//}
//lcd.print(second, DEC);
if(hour<12)
{
lcd.print("am");
}
else
{
lcd.print("pm");
}
lcd.print(" ");
delay(1000);
}
void setup() {
pinMode(heater, OUTPUT); //Set Heater Relay
pinMode(fan, OUTPUT); // Set analog pin 0 as a output
sensors.begin(); // Start up the DS18B20 Temp library
// init I2C
Serial.begin(9600);
Wire.begin();
randomSeed(analogRead(1));
/*||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| S E T U P - D I S P L A Y |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
Wire.begin();
// Change these values to what you want to set your clock to.
// You probably only want to set your clock once and then remove
// the setDateDs1307 call.
second = 00;
minute = 50;
hour = 6;
dayOfWeek = 0; // Sunday is 0
dayOfMonth = 22;
month = 5;
year = 11;
setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
lcd.createChar(0, newChar);
lcd.createChar(1, newChar1);
lcd.createChar(2, newChar2);
lcd.createChar(3, newChar3);
lcd.createChar(4, newChar4);
lcd.createChar(5, newChar5);
lcd.createChar(6, newChar6);
lcd.createChar(7, newChar7);
lcd.begin(20, 4); // set up the LCD's number of rows and columns:
// Print a message to the LCD.
lcd.setCursor(3, 0);
lcd.write(0);
lcd.write(1);
lcd.setCursor(6, 0);// set the cursor to column 4, line 0
lcd.print("SaltyDog's");
lcd.setCursor(15, 0);
lcd.write(3);
lcd.write(2);
lcd.setCursor(3, 2);
lcd.print("ReefController");
delay(5000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.write(0);
lcd.write(1);
lcd.setCursor(3, 0);// set the cursor to column 0, line 0
lcd.print("My Marine Tank");
lcd.setCursor(18, 0);
lcd.write(3);
lcd.write(2);
lcd.setCursor(11, 1);
lcd.print("L: ");
lcd.setCursor(0, 1);
lcd.print("W: ");
lcd.setCursor(1, 2);
lcd.print("Heater: ");
lcd.setCursor(12, 2);
lcd.print("Fans: ");
}
/***** Main Loop ***********/
/***************************/
void loop(){
onesecond();
float fSecond, fHour, fMinute; //turn the times read from the RTC into float for math ops
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; //declare variables to hold the times
getDateDs1307(&second, &rtcMins, &rtcHrs, &dayOfWeek, &dayOfMonth, &month, &year);
fSecond = (float) second; //sets fSecond as the float version of the integer second from the RTC
fMinute = (float) minute; //same as above, but for the minute
fHour = (float) hour; //ditto, but for the hour
int lunarCycle = moonPhase(year, month, dayOfMonth); //get a value for the lunar cycle
//--------MOON LED SETUP----------//
if ( ((hour == 7) && (minute < 00)) || (hour < 7))//Off at 730am.
{
fBlueIntensity = 255; //...then we want the blue LED at the max brightness (255)
}
else if (hour > 17) //&& (hour < 19)) // On at 5pm
{
fBlueIntensity = 255 * (((fHour - 19) + (fMinute / 59)) / 7); //...set intensity out of 255 based on time since 17:00
}
else
{
fBlueIntensity = 0;
}
//---------account for the moon cycle with the blue LEDs---------//
if (lunarCycle == 0) //new moon
{
fBlueIntensity /= 2;
}
if ((lunarCycle == 1) || (lunarCycle == 7)) //cresent
{
fBlueIntensity /= 1.75 ;
}
if ((lunarCycle == 2) || (lunarCycle == 6)) //half moon
{
fBlueIntensity /= 1.5;
}
if ((lunarCycle == 3) || (lunarCycle == 5)) //gibbous
{
fBlueIntensity /= 1.25;
}
//full moon is full intensity
//----------FLOAT TO INT-------------//
iBlueIntensity = (int) fBlueIntensity;
//---prepare the intensities to be written to pin----//
if (iBlueIntensity < 0) //if the blue intensity is less then 0, set it to 0
{
iBlueIntensity = 0;
}
//------------and finally, we write the values of the lights to the pins--------------//
analogWrite(moon, iBlueIntensity);
delay(1000);
minCounter = rtcHrs * 60 + rtcMins;
secCounter = (long)minCounter * 60 + (long)second;
// Start and Stop Times, Fade Time Functions
ledStartMins = map(dayOfMonth, 1, daysInMonth[month-1], minMinuteStart[month-1], maxMinuteStart[month-1]) + startOffset; //LED Start time
fadeDuration = map(dayOfMonth, 1, daysInMonth[month-1], minMinuteFade[month-1], maxMinuteFade[month-1]); //LED Fade time
ledStopMins = map(dayOfMonth, 1, daysInMonth[month-1], minMinuteStop[month-1], maxMinuteStop[month-1]) + startOffset; // LED Stop time
// Weather Functions
if (minCounter == 0 && second == 0 || day == 0){
{
day = random(1,101);
}
}
if (count == 0){
if (day <= clearDays[month-1]) // Clear Day
{
int t;
for (t = 0; t < blueChannels; t++)
{
valueBlue[t] = random(blueLevel[t]*clearDay,blueLevel[t]);
}
for (t = 0; t < whiteChannels; t++)
{
valueWhite[t] = random(whiteLevel[t]*clearDay,whiteLevel[t]);
}
}
if (day > clearDays[month-1] && day <= cloudyDays[month-1]) // Cloudy Day
{
int t;
for (t = 0; t < blueChannels; t++)
{
valueBlue[t] = random(blueLevel[t]*normalDay,blueLevel[t]*cloudyDay);
}
for (t = 0; t < whiteChannels; t++)
{
valueWhite[t] = random(whiteLevel[t]*normalDay,whiteLevel[t]*cloudyDay);
}
}
if (day > cloudyDays[month-1]) // Normal Day
{
int t;
for (t = 0; t < blueChannels; t++)
{
valueBlue[t] = random(blueLevel[t]*normalDay,blueLevel[t]);
}
for (t = 0; t < whiteChannels; t++)
{
valueWhite[t] = random(whiteLevel[t]*normalDay,whiteLevel[t]);
}
}
fadeOn = random(5,8); // Fade on of cloud in seconds
fadeOff = random(5,8); // Fade off of cloud in seconds
time = random(30,300); // Length of cloud in seconds
pause = random(5,300); // Time between clouds in seconds
start = secCounter; // Sets cycle start time
finish = start + fadeOn + time + fadeOff + pause; // Sets cylce finish time in seconds
count = 1;
}
int t;
for (t = 0; t < blueChannels; t++)
{
blueMax[t] = blueLevel[t];
}
for (t = 0; t < whiteChannels; t++)
{
whiteMax[t] = whiteLevel[t];
}
// LED State and Serial Print
if (psecond != second){
psecond = second;
update_leds();
}
delay(50);
}
void update_leds( void ){
int i;
byte ledVal;
for (i = 0; i < blueChannels; i++){
ledVal = setLed(minCounter, bluePins[i], ledStartMins + (photoStagger * (i+1)), fadeDuration, ledStopMins - (photoStagger * (i+1)), blueMax[i], start, secCounter, fadeOn, fadeOff, time, valueBlue[i]);
}
for (i = 0; i < whiteChannels; i++){
ledVal = setLed(minCounter, whitePins[i], ledStartMins + colourOffset + (photoStagger * (i+1)), fadeDuration, ledStopMins - colourOffset - (photoStagger * (i+1)), whiteMax[i], start, secCounter, fadeOn, fadeOff, time, valueWhite[i]);
}
// DS18B20 display
sensors.requestTemperatures(); // Send the command to get temperatures
delay(250);
lcd.setCursor(13, 1);
float temp1=0, temp2=0;
//lcd.print("Led Temp:");
temp1=sensors.getTempFByIndex(1);
lcd.print(sensors.getTempFByIndex(1));
lcd.print((char)223);
lcd.print("F");
lcd.setCursor(2, 1);
//lcd.print("Tank Temp: ");
temp2=sensors.getTempFByIndex(0);
lcd.print(sensors.getTempFByIndex(0));
lcd.print((char)223);
lcd.print("F");
if ( (temp1) > 98)
{
digitalWrite(fan, HIGH);
lcd.setCursor(17,2);
lcd.print("On");
}
else if ( (temp1) < 92)
{
digitalWrite(fan, LOW);
lcd.setCursor(17,2);
lcd.print("Off");
}
if ( (temp2) < 78 )
{
digitalWrite(heater, HIGH);
lcd.setCursor(8,2);
lcd.print("On");
}
else if ( (temp2) > 82 )
{
digitalWrite(heater, LOW);
lcd.setCursor(8,2);
lcd.print("Off");
}
// lcd.print(sensors.getTempCByIndex(0));
// lcd.print((char)223);
// lcd.print("C");
//delay(500);
}
i get all these error messages
sketch_apr15c:329: error: 'class TwoWire' has no member named 'send'
As of Arduino 1.0, the Wire.send() function was renamed to Wire.write() for consistency with other libraries.
sketch_apr15c.cpp: In function 'void getDateDs1307(byte*, byte*, byte*, byte*, byte*, byte*, byte*)':
sketch_apr15c:344: error: 'class TwoWire' has no member named 'send'
As of Arduino 1.0, the Wire.send() function was renamed to Wire.write() for consistency with other libraries.
sketch_apr15c:350: error: 'class TwoWire' has no member named 'receive'
As of Arduino 1.0, the Wire.receive() function was renamed to Wire.read() for consistency with other libraries.
sketch_apr15c:351: error: 'class TwoWire' has no member named 'receive'
As of Arduino 1.0, the Wire.receive() function was renamed to Wire.read() for consistency with other libraries.
sketch_apr15c:352: error: 'class TwoWire' has no member named 'receive'
As of Arduino 1.0, the Wire.receive() function was renamed to Wire.read() for consistency with other libraries.
sketch_apr15c:353: error: 'class TwoWire' has no member named 'receive'
As of Arduino 1.0, the Wire.receive() function was renamed to Wire.read() for consistency with other libraries.
sketch_apr15c:354: error: 'class TwoWire' has no member named 'receive'
As of Arduino 1.0, the Wire.receive() function was renamed to Wire.read() for consistency with other libraries.
sketch_apr15c:355: error: 'class TwoWire' has no member named 'receive'
As of Arduino 1.0, the Wire.receive() function was renamed to Wire.read() for consistency with other libraries.
sketch_apr15c:356: error: 'class TwoWire' has no member named 'receive'
As of Arduino 1.0, the Wire.receive() function was renamed to Wire.read() for consistency with other libraries.
sketch_apr15c.cpp: In function 'void setup()':
sketch_apr15c:472: error: call of overloaded 'write(int)' is ambiguous
D:\New Folder (2)\arduino-1.0\libraries\LiquidCrystal1/LiquidCrystal.h:82: note: candidates are: virtual size_t LiquidCrystal::write(uint8_t)
D:\New Folder (2)\arduino-1.0\hardware\arduino\cores\arduino/Print.h:49: note: size_t Print::write(const char*)
sketch_apr15c:484: error: call of overloaded 'write(int)' is ambiguous
D:\New Folder (2)\arduino-1.0\libraries\LiquidCrystal1/LiquidCrystal.h:82: note: candidates are: virtual size_t LiquidCrystal::write(uint8_t)
D:\New Folder (2)\arduino-1.0\hardware\arduino\cores\arduino/Print.h:49: note: size_t Print::write(const char*)

