Skip to content

Instantly share code, notes, and snippets.

@ilmaestro
Created December 13, 2014 04:09
Show Gist options
  • Select an option

  • Save ilmaestro/0bc0ba78f5ee739bb706 to your computer and use it in GitHub Desktop.

Select an option

Save ilmaestro/0bc0ba78f5ee739bb706 to your computer and use it in GitHub Desktop.

Revisions

  1. ilmaestro created this gist Dec 13, 2014.
    249 changes: 249 additions & 0 deletions AquaLight.pde
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,249 @@
    /*****
    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;
    }
    }

    137 changes: 137 additions & 0 deletions LEDFunctions.pde
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,137 @@

    /***********
    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;
    }
    60 changes: 60 additions & 0 deletions SerialLCD.pde
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,60 @@
    /***********
    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);
    }

    69 changes: 69 additions & 0 deletions TimerFunctions.pde
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,69 @@
    /*****
    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;
    }