Created
December 13, 2014 04:09
-
-
Save ilmaestro/0bc0ba78f5ee739bb706 to your computer and use it in GitHub Desktop.
Arduino LED Saltwater Light
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /***** | |
| AquaLight - Versin 2.0 (rewritten after accidentally deleting my project after a year) | |
| Ryan Kilkenny - 12/26/2010 | |
| basic functions: | |
| * RTC - timing functions | |
| * Serial LCD - Clock Display, future menu system | |
| * PWM - LED light control | |
| program | |
| * light modes | |
| 0 dark: all lights off | |
| 1 daylight: 5 hours of constant daylight | |
| 2 highlight: 2 - 3 hours of light changes, white to blue, bright blue | |
| 3 moonlight: 4 hours of dim blues | |
| * timing | |
| - start time: 2pm | |
| - daylight (2pm - 7pm) | |
| - highlight (7pm - 9pm) | |
| - moonlight (9pm - 1pm) | |
| - dark | |
| ***/ | |
| #include <Time.h> | |
| #include <TimeAlarms.h> | |
| #include <Wire.h> | |
| #include <DS1307RTC.h> | |
| #include <math.h> | |
| //global constants | |
| #define WHITE_PIN 3 | |
| #define BLUE_PIN 11 | |
| #define DARK_MODE 0 | |
| #define DAYLIGHT_MODE 1 | |
| #define HIGHLIGHT_MODE 2 | |
| #define MOONLIGHT_MODE 3 | |
| #define MODE_MENU 0 | |
| #define INTENSITY_MENU 1 | |
| #define NUM_MENUS 2 | |
| #define NUM_LIGHTMODES 4 | |
| //global variables | |
| int Lightmode = DARK_MODE; | |
| int DisplayMenu = MODE_MENU; | |
| int CurrentHour; | |
| int TestMode = 0; | |
| char* DisplayMenus[NUM_MENUS] = {"Mode", "Intensity"}; | |
| //24 hour clock times | |
| int DarkHour = 2; | |
| int DaylightHour = 14; | |
| int HighlightHour = 19; | |
| int MoonlightHour = 21; | |
| char* LightmodeStrings[NUM_LIGHTMODES] = {"Dark", "Day", "Show", "Moon"}; //light mode display values | |
| //light intensities | |
| int WhiteIntensity = 255; | |
| int BlueIntensity = 255; | |
| int WhiteVariance = 0; | |
| int BlueVariance = 0; | |
| //Timer durations | |
| int DisplayTimerDur = 1000; | |
| int DisplayTimer; | |
| int DisplayMenuTimerDur = 10000; | |
| int DisplayMenuTimer; | |
| int SetLightmodeTimerDur = 30000; | |
| int SetLightmodeTimer; | |
| int SetLightIntensityTimerDur = 500; | |
| int SetLightIntensityTimer; | |
| int HighlightTimerDur = 5000; | |
| int HighlightTimer; | |
| int HighlightLatch = 0; | |
| /*********** | |
| MAIN SETUP | |
| ***********/ | |
| void setup() | |
| { | |
| Serial.begin(9600); | |
| randomSeed(analogRead(0)); //seed with analog noise | |
| beginPwm(); | |
| beginSerialLCD(); | |
| beginRTC(); | |
| beginLightTest(); | |
| beginTimers(); | |
| clearLCD(); | |
| } | |
| /*********** | |
| MAIN LOOP | |
| ***********/ | |
| void loop() | |
| { | |
| int currentMillis = millis(); | |
| //Check display Menu | |
| //Check lightmode timer | |
| if (currentMillis - DisplayMenuTimer >= DisplayMenuTimerDur) | |
| { | |
| DisplayMenu++; | |
| if(DisplayMenu >= NUM_MENUS) | |
| DisplayMenu = MODE_MENU; | |
| DisplayMenuTimer = millis(); | |
| } | |
| //Check display timer | |
| if (currentMillis - DisplayTimer >= DisplayTimerDur) | |
| { | |
| CurrentHour = hour(); | |
| digitalDisplay(); | |
| DisplayTimer = millis(); | |
| } | |
| //Check lightmode timer | |
| if (currentMillis - SetLightmodeTimer >= SetLightmodeTimerDur) | |
| { | |
| setLightMode(); | |
| SetLightmodeTimer = millis(); | |
| } | |
| //Check intensity timer | |
| if (currentMillis - SetLightIntensityTimer >= SetLightIntensityTimerDur) | |
| { | |
| setLighting(); | |
| setIntensity(WhiteIntensity, BlueIntensity); | |
| SetLightIntensityTimer = millis(); | |
| } | |
| } | |
| /********** | |
| Display Functions | |
| **********/ | |
| void digitalDisplay(){ | |
| // digital clock display of the time | |
| selectLineOne(); | |
| Serial.print(hour()); | |
| printDigits(minute()); | |
| printDigits(second()); | |
| Serial.print(" "); | |
| Serial.print(month()); | |
| Serial.print("/"); | |
| Serial.print(day()); | |
| selectLineTwo(); | |
| switch (DisplayMenu) { | |
| case MODE_MENU: | |
| Serial.print("Mode: "); | |
| Serial.print(LightmodeStrings[Lightmode]); | |
| Serial.print(" "); | |
| break; | |
| case INTENSITY_MENU: | |
| Serial.print("Int:"); | |
| printDigits999(WhiteIntensity); | |
| Serial.print("w "); | |
| printDigits999(BlueIntensity); | |
| Serial.print("b "); | |
| break; | |
| } | |
| } | |
| /*********** | |
| Setup Functions | |
| ***********/ | |
| void beginLightTest() | |
| { | |
| TestMode = 1; | |
| for(int i = 0; i < 4; i++) | |
| { | |
| Lightmode = i; | |
| setLighting(); | |
| setIntensity(WhiteIntensity, BlueIntensity); | |
| clearLCD(); | |
| selectLineTwo(); | |
| Serial.print("Mode: "); | |
| Serial.print(i); | |
| //Serial.println(); | |
| delay(3000); | |
| } | |
| TestMode = 0; | |
| CurrentHour = hour(); | |
| setLightMode(); | |
| } | |
| void beginTimers() | |
| { | |
| //setTime(8,29,0,1,1,10); // set time to 8:29:00am Jan 1 2010 | |
| //setTime(18,0,0,26,12,10); // set time to 8:29:00am Jan 1 2010 | |
| //Alarm.timerRepeat(30, taskSetLightMode); // check lightMode every 30 seconds | |
| resetTimers(); | |
| } | |
| void beginRTC() | |
| { | |
| setSyncProvider(RTC.get); // the function to get the time from the RTC | |
| if(timeStatus()!= timeSet) | |
| Serial.println("Unable to sync with the RTC"); | |
| else | |
| Serial.println("RTC has set the system time"); | |
| } | |
| void beginSerialLCD() | |
| { | |
| delay(500); //wait | |
| clearLCD(); | |
| selectLineOne(); | |
| Serial.print("AquaLight v2.0"); | |
| delay(2000); | |
| clearLCD(); | |
| } | |
| void beginPwm() | |
| { | |
| //pins 3,11 have a base of 31250 Hz | |
| int divisor = 64; // 488.28125 Hz | |
| setPwmFrequency(WHITE_PIN, divisor); | |
| setPwmFrequency(BLUE_PIN, divisor); | |
| } | |
| void setPwmFrequency(int pin, int divisor) { | |
| byte mode; | |
| if(pin == 5 || pin == 6 || pin == 9 || pin == 10) { | |
| switch(divisor) { | |
| case 1: mode = 0x01; break; | |
| case 8: mode = 0x02; break; | |
| case 64: mode = 0x03; break; | |
| case 256: mode = 0x04; break; | |
| case 1024: mode = 0x05; break; | |
| default: return; | |
| } | |
| if(pin == 5 || pin == 6) { | |
| TCCR0B = TCCR0B & 0b11111000 | mode; | |
| } else { | |
| TCCR1B = TCCR1B & 0b11111000 | mode; | |
| } | |
| } else if(pin == 3 || pin == 11) { | |
| switch(divisor) { | |
| case 1: mode = 0x01; break; | |
| case 8: mode = 0x02; break; | |
| case 32: mode = 0x03; break; | |
| case 64: mode = 0x04; break; | |
| case 128: mode = 0x05; break; | |
| case 256: mode = 0x06; break; | |
| case 1024: mode = 0x7; break; | |
| default: return; | |
| } | |
| TCCR2B = TCCR2B & 0b11111000 | mode; | |
| } | |
| } | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /*********** | |
| Light Modes | |
| ***********/ | |
| void dark() | |
| { | |
| WhiteIntensity = 255; | |
| BlueIntensity = 255; | |
| } | |
| void daylight() | |
| { | |
| if (TestMode == 1) | |
| { | |
| WhiteIntensity = 10; | |
| BlueIntensity = 10; | |
| return; | |
| } | |
| if (random(100) == 42) | |
| { | |
| WhiteVariance = random(240); | |
| BlueVariance = random(240); | |
| } | |
| WhiteIntensity = fadeTowards(WhiteIntensity, 10 + WhiteVariance, 1); | |
| BlueIntensity = fadeTowards(BlueIntensity, 10 + BlueVariance, 1); | |
| } | |
| void highlight() | |
| { | |
| if (TestMode == 1) | |
| { | |
| WhiteIntensity = 255; | |
| BlueIntensity = 10; | |
| return; | |
| } | |
| int timerDiff = millis() - HighlightTimer; | |
| if (timerDiff >= HighlightTimerDur) | |
| { | |
| switch (HighlightLatch) { | |
| case 0: | |
| //fade out the white, fade in the blue | |
| WhiteIntensity = fadeTowards(WhiteIntensity,255,1); | |
| BlueIntensity = fadeTowards(BlueIntensity,10,1); | |
| if (BlueIntensity <= 10) | |
| HighlightLatch = 1; //goto next sequence | |
| break; | |
| case 1: | |
| //fade out the blue | |
| WhiteIntensity = fadeTowards(WhiteIntensity,255,1); | |
| BlueIntensity = fadeTowards(BlueIntensity,255,1); | |
| if (BlueIntensity > 254) | |
| HighlightLatch = 2; //goto next sequence | |
| break; | |
| case 2: | |
| //fade in the white | |
| WhiteIntensity = fadeTowards(WhiteIntensity,10,1); | |
| BlueIntensity = fadeTowards(BlueIntensity,255,1); | |
| if (WhiteIntensity < 11) | |
| HighlightLatch = 3; //goto next sequence | |
| break; | |
| case 3: | |
| //fade out the white | |
| WhiteIntensity = fadeTowards(WhiteIntensity,255,1); | |
| BlueIntensity = fadeTowards(BlueIntensity,255,1); | |
| if (WhiteIntensity < 11) | |
| HighlightLatch = 0; //goto next sequence | |
| break; | |
| } | |
| HighlightTimer = millis(); | |
| } | |
| } | |
| void moonlight() | |
| { | |
| if (TestMode == 1) | |
| { | |
| WhiteIntensity = 255; | |
| BlueIntensity = 254; | |
| return; | |
| } | |
| if (random(100) == 50) | |
| { | |
| BlueVariance = random(5); | |
| } | |
| WhiteIntensity = 255; | |
| BlueIntensity = fadeTowards(BlueIntensity, 250 + BlueVariance, 1); | |
| } | |
| /********** | |
| Light Functions | |
| **********/ | |
| void setLighting() | |
| { | |
| switch(Lightmode) { | |
| case DARK_MODE: | |
| dark(); | |
| break; | |
| case DAYLIGHT_MODE: | |
| daylight(); | |
| break; | |
| case HIGHLIGHT_MODE: | |
| highlight(); | |
| break; | |
| case MOONLIGHT_MODE: | |
| moonlight(); | |
| break; | |
| default: | |
| dark(); | |
| } | |
| } | |
| void setIntensity(int white, int blue) | |
| { | |
| analogWrite(WHITE_PIN, white); | |
| analogWrite(BLUE_PIN, blue); | |
| } | |
| int fadeTowards(int input, int dest, int increment) | |
| { | |
| int output; | |
| if (input > dest) | |
| { | |
| output = input - increment; | |
| } | |
| else if (input < dest) | |
| { | |
| output = input + increment; | |
| } | |
| else | |
| { | |
| output = input; | |
| } | |
| return output; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /*********** | |
| Sparkfun Serial LCD | |
| Functions | |
| ************/ | |
| void selectLineOne(){ //puts the cursor at line 0 char 0. | |
| Serial.print(0xFE, BYTE); //command flag | |
| Serial.print(128, BYTE); //position | |
| } | |
| void selectLineTwo(){ //puts the cursor at line 0 char 0. | |
| Serial.print(0xFE, BYTE); //command flag | |
| Serial.print(192, BYTE); //position | |
| } | |
| void goTo(int position) { | |
| //position = line 1: 0-15, line 2: 16-31, 31+ defaults back to 0 | |
| if (position<16){ Serial.print(0xFE, BYTE); //command flag | |
| Serial.print((position+128), BYTE); //position | |
| }else if (position<32){Serial.print(0xFE, BYTE); //command flag | |
| Serial.print((position+48+128), BYTE); //position | |
| } else { goTo(0); } | |
| } | |
| void clearLCD(){ | |
| Serial.print(0xFE, BYTE); //command flag | |
| Serial.print(0x01, BYTE); //clear command. | |
| } | |
| void backlightOn(){ //turns on the backlight | |
| Serial.print(0x7C, BYTE); //command flag for backlight stuff | |
| Serial.print(157, BYTE); //light level. | |
| } | |
| void backlightOff(){ //turns off the backlight | |
| Serial.print(0x7C, BYTE); //command flag for backlight stuff | |
| Serial.print(128, BYTE); //light level for off. | |
| } | |
| void serCommand(){ //a general function to call the command flag for issuing all other commands | |
| Serial.print(0xFE, BYTE); | |
| } | |
| void printDigits(int digits){ | |
| // utility function for digital clock display: prints preceding colon and leading 0 | |
| Serial.print(":"); | |
| if(digits < 10) | |
| Serial.print('0'); | |
| Serial.print(digits); | |
| } | |
| void printDigits999(int digits) | |
| { | |
| if (digits < 100) | |
| Serial.print('0'); | |
| if (digits < 10) | |
| Serial.print('0'); | |
| Serial.print(digits); | |
| } | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /***** | |
| Timer functions | |
| *****/ | |
| void resetTimers() | |
| { | |
| DisplayTimer = millis(); | |
| SetLightmodeTimer = millis(); | |
| SetLightIntensityTimer = millis(); | |
| HighlightTimer = millis(); | |
| DisplayMenuTimer = millis(); | |
| } | |
| /* | |
| taskSetLightMode - checks the current hour and sets the lighting mode | |
| get all diffs: CurrentHour - Lightmode Hour | |
| rule out any negatives (where current hour already past time) | |
| special case: when should moonlight end? | |
| if hour is between midnight and next dark hour, all diffs will already be negative | |
| if hour is 1, next dark hour is 2, and last moon hour was 21 | |
| */ | |
| void setLightMode() | |
| { | |
| int darkDiff = getHourDiff(CurrentHour, DarkHour); | |
| int daylightDiff = getHourDiff(CurrentHour, DaylightHour); | |
| int highlightDiff = getHourDiff(CurrentHour, HighlightHour); | |
| int moonlightDiff = getHourDiff(CurrentHour, MoonlightHour); | |
| //make sure these are in the same order as the lightModes.. then we won't have to compare to figure out which mode is which value. | |
| byte diffs[] = {darkDiff, daylightDiff, highlightDiff, moonlightDiff}; | |
| //set all negatives to 99 | |
| for(int i = 0; i < 4; i++) | |
| { | |
| if(diffs[i] < 0) | |
| { | |
| diffs[i] = 99; | |
| } | |
| } | |
| //find minimum value | |
| int minimum = diffs[0]; | |
| int minCount = 0; | |
| for(int i = 0; i < 4; i++) | |
| { | |
| if(diffs[i] < minimum) | |
| { | |
| minimum = diffs[i]; | |
| minCount = i; | |
| } | |
| } | |
| Lightmode = minCount; | |
| setLighting(); | |
| } | |
| int getHourDiff(int currenthour, int diffHour) | |
| { | |
| int result = 99; | |
| if (currenthour == 0) | |
| currenthour = 24; | |
| //check if we're in the special case hour | |
| if (currenthour < DarkHour && diffHour > DarkHour) | |
| { | |
| result = currenthour + (24 - diffHour); // example: 1am -> 1 + (24 - 14) = 11, so 11 hours since 2pm | |
| } else { | |
| result = currenthour - diffHour; | |
| } | |
| return result; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment