Jump to content

Reprogramming the Typhon


MeepNand

Recommended Posts

Nothing to do while I wait for another DS1302, so it's time to start looking at the Boostled Typhon code. I'm thinking half-hour by half-hour control.

I'll post any updates here.

 

Updated 2/23/14.

Features:

-Bell curve option instead of straight line

-255 dimming steps

-Calculations each second

-5 dimming settings per channel

-Lighting test to preview different mixes of power

-Acclimation mode from 0 to 60 days

 

Download the INVERTED code if you are using buckpucks. Otherwise, the normal one below will do fine.

 

Link to board layout: http://www.nano-reef.com/topic/328216-reprogramming-the-typhon/?p=4642901

 

To download:

1. Extract and drag the Typhon_Code_Meep folder to your "sketches" folder. Extract the DS1307 library in the extra_libraries folder to your libraries folder.

2. Open the Arduino program.

3. Open the sketch (inverted or normal)

4. Select COM port (Look in "Devices and printers" to find out the COM port of the Typhon)

5. Select "Arduino Duemilanove w/ Atmega328" from "Boards".

6. Attach the FTDI cable. The bottom of the FTDI will be facing up towards the LCD screen on the Typhon when you plug it in.

6. Hit upload.

extra_libraries.zip

Typhon_code_Meep.zip

Link to comment
  • 2 weeks later...
jedimasterben

Here are the libraries the Typhons use: http://www.boostled.com/v/vspfiles/downloadables/ExtraLibraries.zip

 

The library and PDE file must be loaded into Arduino IDE version 22 or lower, otherwise it will not load properly, here is the download link for it: http://arduino.googlecode.com/files/arduino-0022.zip

 

This is the code from the BoostLED Typhon:

/*
// Typhon firmware
// v0.2 alpha 2010-23-11
// N. Enders, R. Ensminger
// Changes made by BoostLED have notations as below.
// This sketch provides firmware for the Typhon LED controller.
// It provides a structure to fade 4 independent channels of LED lighting
// on and off each day, to simulate sunrise and sunset.
//
// Current work in progress:
// - store all LED variables in EEPROM so they are not reset by a loss of power
//
// Future developments may include:
// - moon phase simulation
// - storm simulation
//
// Sketch developed in Arduino-18
// Requires LiquidCrystal, Wire, EEPROM, EEPROMVar, and Button libraries.
// Button is available here: http://www.arduino.cc/playground/Code/Button
// EEPROMVar is available here: http://www.arduino.cc/playground/uploads/Profiles/EEPROMVar_01.zip
*/// include the libraries:
#include
#include
#include
#include
#include/**** Define Variables & Constants ****/
/**************************************/// set the RTC's I2C address
#define DS1307_I2C_ADDRESS 0x68// create the LCD
LiquidCrystal lcd(8, 7, 5, 4, 16, 2);// set up backlight
int bkl         = 6;        // backlight pin
byte bklIdle    = 10;       // PWM value for backlight at idle
byte bklOn      = 70;       // PWM value for backlight when on
int bklDelay    = 10000;    // ms for the backlight to idle before turning off
unsigned long bklTime = 0;  // counter since backlight turned on// create the menu counter
int menuCount   = 1;
int menuSelect = 0;//create manual override variables
boolean override = false;
byte overmenu = 0;
int overpercent = 0;// create the buttons
Button menu     = Button(12,PULLDOWN);
Button select   = Button(13,PULLDOWN);
Button plus     = Button(14,PULLDOWN);
Button minus    = Button(15,PULLDOWN);// Button state constants.
byte buttonNotPressed  = 0;
byte buttonUniquePress = 1;
byte buttonIsPressed   = 2;
byte slowCount = 3;         // number of intervals to do a "slowDelay" when holding a button
int slowDelay = 1000;       // milliseconds to delay when initially holding a button
int fastDelay = 100;        // milliseconds to delay after holding the button for "slowCount" intervals// LED variables. These control the behavior of lighting. Change these to customize behavoir
int minCounter = 0;         // counter that resets at midnight.
int oldMinCounter = 0;      // counter that resets at midnight.EEPROMVar inverted = false; //Modified by NetSurge// Used for button hold down
int intervalCounter = 0;
int oldIntervalCounter;
unsigned long currMil = 0;         // current millisecondint oneVal = 0;             // current value for channel 1
int twoVal = 0;             // current value for channel 2
int threeVal = 0;           // current value for channel 3
int fourVal = 0;            // current value for channel 4// Variables making use of EEPROM memory:
EEPROMVar oneStartMins = 750;     // minute to start this channel.
EEPROMVar onePhotoPeriod = 720;   // photoperiod in minutes for this channel.
EEPROMVar oneMax = 100;           // max intensity for this channel, as a percentage
EEPROMVar oneFadeDuration = 60;   // duration of the fade on and off for sunrise and sunset for
                                      //    this channel.
EEPROMVar twoStartMins = 810;
EEPROMVar twoPhotoPeriod = 600;
EEPROMVar twoMax = 100;
EEPROMVar twoFadeDuration = 60;
EEPROMVar threeStartMins = 810;
EEPROMVar threePhotoPeriod = 600;
EEPROMVar threeMax = 100;
EEPROMVar threeFadeDuration = 60;
EEPROMVar fourStartMins = 480;
EEPROMVar fourPhotoPeriod = 510; 
EEPROMVar fourMax = 100;         
EEPROMVar fourFadeDuration = 60; typedef struct {
int Led;            // channel pin
int StartMins;      // minute to start this channel.
int PhotoPeriod;    // photoperiod in minutes for this channel.
int Max;            // max intensity for this channel, as a percentage
int FadeDuration;   // duration of the fade on and off for sunrise and sunset for
                     //    this channel.
}
channelVals_t;
channelVals_t channel[4];/*
int oneStartMins = 1380;    // minute to start this channel.
int onePhotoPeriod = 120;   // photoperiod in minutes for this channel.
int oneMax = 100;           // max intensity for this channel, as a percentage
int oneFadeDuration = 60;   // duration of the fade on and off for sunrise and sunset for
                            //    this channel.                                   
int twoStartMins = 800;
int twoPhotoPeriod = 60;
int twoMax = 100;
int twoFadeDuration = 15;
int threeStartMins = 800;
int threePhotoPeriod = 60;
int threeMax = 100;
int threeFadeDuration = 30;
int fourStartMins = 800;
int fourPhotoPeriod = 120; 
int fourMax = 100;         
int fourFadeDuration = 60; 
*//****** RTC Functions ******/
/***************************/// Convert decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}// Convert binary coded decimal to decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}// Sets date and time, starts the clock
void setDate(byte second,        // 0-59
byte minute,        // 0-59
byte hour,          // 1-23
byte dayOfWeek,     // 1-7
byte dayOfMonth,    // 1-31
byte month,         // 1-12
byte year)          // 0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0);
Wire.send(decToBcd(second));
Wire.send(decToBcd(minute));
Wire.send(decToBcd(hour));
Wire.send(decToBcd(dayOfWeek));
Wire.send(decToBcd(dayOfMonth));
Wire.send(decToBcd(month));
Wire.send(decToBcd(year));
Wire.endTransmission();
}// Gets the date and time
void getDate(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
*second     = bcdToDec(Wire.receive() & 0x7f);
*minute     = bcdToDec(Wire.receive());
*hour       = bcdToDec(Wire.receive() & 0x3f);
*dayOfWeek  = bcdToDec(Wire.receive());
*dayOfMonth = bcdToDec(Wire.receive());
*month      = bcdToDec(Wire.receive());
*year       = bcdToDec(Wire.receive());
}/****** LED Functions ******/
/***************************/
//function to set LED brightness according to time of day
//function has three equal phases - ramp up, hold, and ramp down
int   setLed(int mins,    // current time in minutes
int ledPin,  // pin for this channel of LEDs
int start,   // start time for this channel of LEDs
int period,  // photoperiod for this channel of LEDs
int fade,    // fade duration for this channel of LEDs
int ledMax   // max value for this channel
)  {
int val = 0;//fade up
if (mins > start || mins <= start + fade)  {
   val = map(mins - start, 0, fade, 0, ledMax);
}//fade down
if (mins > start + period - fade && mins <= start + period)  {
   val = map(mins - (start + period - fade), 0, fade, ledMax, 0);
}//off or post-midnight run.
if (mins <= start || mins > start + period)  {
   if((start+period)%1440 < start && (start + period)%1440 > mins )
   {
     val=map((start+period-mins)%1440,0,fade,0,ledMax);
   }
   else 
     val = 0;
}
//invert for BuckPuck Functions
//Added by NetSurge
if(inverted){
//  val=~val;
//  val=val&255;
//  ledMax=~ledMax;
//  ledMax=100-ledMax;
}
if (val > ledMax)  {
   val = ledMax;
}if (val < 0) {
   val = 0;
}
if(inverted){
analogWrite(ledPin, map(val, 0, 100, 255, 0));
}
else{
analogWrite(ledPin, map(val, 0, 100, 0, 255));
}//Debugging info 0-255 PWM Output
//Modified by NetSurge
/*
if(inverted){
if(ledPin == 9){
lcd.setCursor(0,0);
lcd.print(map(val, 0, 100, 255, 0));
}if(ledPin == 10){
lcd.setCursor(4,0);
lcd.print(map(val, 0, 100, 255, 0));
}if(ledPin == 11){
lcd.setCursor(8,0);
lcd.print(map(val, 0, 100, 255, 0));
}if(ledPin == 3){
lcd.setCursor(12,0);
lcd.print(map(val, 0, 100, 255, 0));
}
}
else{
if(ledPin == 9){
lcd.setCursor(0,0);
lcd.print(map(val, 0, 100, 0, 255));
}if(ledPin == 10){
lcd.setCursor(4,0);
lcd.print(map(val, 0, 100, 0, 255));
}if(ledPin == 11){
lcd.setCursor(8,0);
lcd.print(map(val, 0, 100, 0, 255));
}if(ledPin == 3){
lcd.setCursor(12,0);
lcd.print(map(val, 0, 100, 0, 255));
}
}*/if(override){
   val=overpercent;
}return val;
}/**** Display Functions ****/
/***************************/// format a number of minutes into a readable time (24 hr format)
void printMins(int mins,       //time in minutes to print
boolean ampm    //print am/pm?
)  {
int hr = (mins%1440)/60;
int mn = mins%60;
if(hr<10){
   lcd.print(" ");
}
lcd.print(hr);
lcd.print(":");
if(mn<10){
   lcd.print("0");
}
lcd.print(mn);
}// format hours, mins, secs into a readable time (24 hr format)
void printHMS (byte hr,
byte mn,
byte sec      //time to print
) 
{if(hr<10){
   lcd.print(" ");
}
lcd.print(hr, DEC);
lcd.print(":");
if(mn<10){
   lcd.print("0");
}lcd.print(mn, DEC);
lcd.print(":");
if(sec<10){
   lcd.print("0");
}
lcd.print(sec, DEC);
}void ovrSetAll(int pct){
analogWrite(channel[0].Led, map(pct,0,100,0,255));
analogWrite(channel[1].Led, map(pct,0,100,0,255));
analogWrite(channel[2].Led, map(pct,0,100,0,255));
analogWrite(channel[3].Led, map(pct,0,100,0,255));
}byte buttonCheck(Button *button) {
if (button->uniquePress()) {
   return buttonUniquePress;
}
else if (button->isPressed()) {
   return buttonIsPressed;
}
else {
   return buttonNotPressed;
}
}boolean checkButtonAction(Button *button) {
byte buttonState = buttonCheck(button);
unsigned long mil = millis();
if (buttonState == buttonUniquePress) {
   intervalCounter = slowCount;
   currMil = mil;
   return true;
}
else if (buttonState == buttonIsPressed) {
   if (intervalCounter > 0) {
     if (currMil < (mil - slowDelay)) {
       intervalCounter--;
       currMil = mil;
       return true;
     }
   }
   else {
     if (currMil < (mil - fastDelay)) {
       currMil = mil;
       return true;
     }
   }
}
return false;
}/**** Setup ****/
/***************/void setup() {
// Initialize channel variables. Set LED channel pin and retrieve values from EEPROM
channel[0].Led = 9;
channel[0].StartMins = oneStartMins;
channel[0].PhotoPeriod = onePhotoPeriod;
channel[0].Max = oneMax;
channel[0].FadeDuration = oneFadeDuration;
channel[1].Led = 10;
channel[1].StartMins = twoStartMins;
channel[1].PhotoPeriod = twoPhotoPeriod;
channel[1].Max = twoMax;
channel[1].FadeDuration = twoFadeDuration;
channel[2].Led = 11;
channel[2].StartMins = threeStartMins;
channel[2].PhotoPeriod = threePhotoPeriod;
channel[2].Max = threeMax;
channel[2].FadeDuration = threeFadeDuration;
channel[3].Led = 3;
channel[3].StartMins = fourStartMins;
channel[3].PhotoPeriod = fourPhotoPeriod;
channel[3].Max = fourMax;
channel[3].FadeDuration = fourFadeDuration;// Title & Credits added
Wire.begin();
pinMode(bkl, OUTPUT);
lcd.begin(16, 2);
digitalWrite(bkl, HIGH);
lcd.setCursor(0,0); //Modified by NetSurge
lcd.print("Typhon Reef LED");
lcd.setCursor(0,1);
lcd.print("Controller");
delay(1000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("by N. Enders &");
lcd.setCursor(0,1);
lcd.print("R. Ensminger    ");
delay(1000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Brought to you  ");
lcd.setCursor(0,1);
lcd.print("by BoostLED     ");
delay(2000);
lcd.clear();
analogWrite(bkl,bklIdle);
}/***** Loop *****/
/****************/void loop() {
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
getDate(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
oldMinCounter = minCounter;
minCounter = hour * 60 + minute;int i;
for (i=0; i<4; i++) {
   //check & set fade durations
   if(channel[i].FadeDuration > channel[i].PhotoPeriod/2 && channel[i].PhotoPeriod >0) {
     channel[i].FadeDuration = channel[i].PhotoPeriod/2;
   }
   if(channel[i].FadeDuration<1){
     channel[i].FadeDuration=1;
   }
}//check & set any time functions
//set outputs
if(!override){
   oneVal = setLed(minCounter, channel[0].Led, channel[0].StartMins, channel[0].PhotoPeriod, channel[0].FadeDuration, channel[0].Max);
   twoVal = setLed(minCounter, channel[1].Led, channel[1].StartMins, channel[1].PhotoPeriod, channel[1].FadeDuration, channel[1].Max);
   threeVal = setLed(minCounter, channel[2].Led, channel[2].StartMins, channel[2].PhotoPeriod, channel[2].FadeDuration, channel[2].Max);
   fourVal = setLed(minCounter, channel[3].Led, channel[3].StartMins, channel[3].PhotoPeriod, channel[3].FadeDuration, channel[3].Max);
}
else{
   oneVal = overpercent;
   twoVal = overpercent;
   threeVal = overpercent;
   fourVal = overpercent;
   ovrSetAll(overpercent);
}
// Update EEProms with any values that may have changed
if (channel[0].StartMins != oneStartMins) {
   oneStartMins = channel[0].StartMins;
}
if (channel[0].PhotoPeriod != onePhotoPeriod) {
   onePhotoPeriod = channel[0].PhotoPeriod;
}
if (channel[0].Max != oneMax) {
   oneMax = channel[0].Max;
}
if (channel[0].FadeDuration != oneFadeDuration) {
   oneFadeDuration = channel[0].FadeDuration;
}
if (channel[1].StartMins != twoStartMins) {
   twoStartMins = channel[1].StartMins;
}
if (channel[1].PhotoPeriod != twoPhotoPeriod) {
   twoPhotoPeriod = channel[1].PhotoPeriod;
}
if (channel[1].Max != twoMax) {
   twoMax = channel[1].Max;
}
if (channel[1].FadeDuration != twoFadeDuration) {
   twoFadeDuration = channel[1].FadeDuration;
}
if (channel[2].StartMins != threeStartMins) {
   threeStartMins = channel[2].StartMins;
}
if (channel[2].PhotoPeriod != threePhotoPeriod) {
   threePhotoPeriod = channel[2].PhotoPeriod;
}
if (channel[2].Max != threeMax) {
   threeMax = channel[2].Max;
}
if (channel[2].FadeDuration != threeFadeDuration) {
   threeFadeDuration = channel[2].FadeDuration;
}if (channel[3].StartMins != fourStartMins) {
   fourStartMins = channel[3].StartMins;
}
if (channel[3].PhotoPeriod != fourPhotoPeriod) {
   fourPhotoPeriod = channel[3].PhotoPeriod;
}
if (channel[3].Max != fourMax) {
   fourMax = channel[3].Max;
}
if (channel[3].FadeDuration != fourFadeDuration) {
   fourFadeDuration = channel[3].FadeDuration;
}//  if (intervalCounter > 0) {
//    unsigned long milsec = millis();
//    if ((currMil < (milsec - 1000)) || (currMil > milsec)) {
//      currMil = milsec;
//      intervalCounter--;
//    }
//  }//turn the backlight off and reset the menu if the idle time has elapsed
if(bklTime + bklDelay < millis() && bklTime > 0 ){
   analogWrite(bkl,bklIdle);
   menuCount = 1;
   lcd.clear();
   bklTime = 0;
}//iterate through the menus
if(menu.uniquePress()){
   analogWrite(bkl,bklOn);
   bklTime = millis();
   if(menuCount < 21){  //Modified by NetSurge
     menuCount++;
   }
  else {
     menuCount = 1;
   }
   lcd.clear();
}switch (menuCount) {
case 1:
   doMainMenu(minCounter, oldMinCounter, hour, minute, second,
   oneVal, twoVal, threeVal, fourVal);
   break;
case 2:
   doOverride(second);
   break;
case 3:
   doStartTime(0);
   break;
case 4:
   doEndTime(0);
   break;
case 5:
   doFadeDuration(0);
   break;
case 6:
   doMaxIntensity(0);
   break;
case 7:
  doStartTime(1);
   break;
case 8:
   doEndTime(1);
   break;
case 9:
   doFadeDuration(1);
   break;
case 10:
   doMaxIntensity(1);
   break;
case 11:
   doStartTime(2);
   break;
case 12:
   doEndTime(2);
   break;
case 13:
   doFadeDuration(2);
   break;
case 14:
   doMaxIntensity(2);
   break;
case 15:
   doStartTime(3);
   break;
case 16:
   doEndTime(3);
   break;
case 17:
   doFadeDuration(3);
   break;
case 18:
   doMaxIntensity(3);
   break;
case 19:
   setHour(&hour, minute, second, dayOfWeek, dayOfMonth, month, year);
   break;
case 20:
   setMinute(hour, &minute, second, dayOfWeek, dayOfMonth, month, year);
   break;
case 21:
doinvertPWM();
break;
}
}void doMainMenu(int minCounter,
int oldMinCounter,
byte hour,
byte minute,
byte second,
int oneVal,
int twoVal,
int threeVal,
int fourVal) {
//main screen turn on!!!
if (minCounter > oldMinCounter){
   lcd.clear();
}
lcd.setCursor(0,0);//Take out display time and uncomment in the led funtion for PWM value debugging
//NetSurge
lcd.print("Time: "); // Displays Time.
printHMS(hour, minute, second);
lcd.setCursor(0,1);
lcd.print(oneVal);
lcd.setCursor(4,1);
lcd.print(twoVal);
lcd.setCursor(8,1);
lcd.print(threeVal);
lcd.setCursor(12,1);
lcd.print(fourVal);if(inverted){
  lcd.setCursor(15,0);
  lcd.print("V");
}
//debugging function to use the select button to advance the timer by 1 minute
//if(select.uniquePress()){setDate(second, minute+1, hour, dayOfWeek, dayOfMonth, month, year);}
}void doOverride(byte second) {
//Manual Override Menu
lcd.setCursor(0,0);
lcd.print("SETTING MODE:        "); // Changed by BoostLED
lcd.setCursor(0,1);//if(menuSelect ==4){
//menuSelect = 0;            //modified by NetSurge
//}if(select.uniquePress()){
   if(menuSelect < 4){
     menuSelect++;
   }
   else{
     menuSelect = 0;
   }
   bklTime = millis();
}if(menuSelect == 0){
   lcd.print("Timer           "); // Changed by BoostLED
   override = false;
}
if(menuSelect == 1){
   lcd.print("All Channels ON "); // Changed by BoostLED
   overpercent = 100;
   override = true;
}
if(menuSelect == 2){
   lcd.print("All Channels OFF"); // Changed by BoostLED
   overpercent = 0;
   override = true;
}   
if(menuSelect == 3){
   override = true;
   lcd.print("Custom ");   // Added by BoostLED
   lcd.print(overpercent,DEC);
   lcd.print("%        ");
   if (overpercent < 100) {
     if (checkButtonAction(&plus)) {
       overpercent++;
       bklTime = millis();
     }
    }
   if (overpercent > 0) {
     if (checkButtonAction(−)) {
       overpercent--;
       bklTime = millis();
     }
   }
}

//invert PWM
//Modified by NetSurge
/* Moved to Main Menu and not in Overide Menuif(menuSelect == 4){
  if(inverted == true)
lcd.print("PWM Inverted:YES ");
  if(inverted == false)
lcd.print("PWM Inverted:NO ");
if (checkButtonAction(−) || checkButtonAction(&plus)) {
  inverted = !inverted;
}
override = false;
}
*/
}void doStartTime(int val) {
//set start time
lcd.setCursor(0,0);
lcd.print("Channel ");
lcd.print(val+1);
lcd.print(" Start");
lcd.setCursor(0,1);
printMins(channel[val].StartMins, true);
if (channel[val].StartMins < 1440) {
   if (checkButtonAction(&plus)) {
     channel[val].StartMins++;
     if (channel[val].PhotoPeriod > 0) {
       channel[val].PhotoPeriod--;
     }
    else {
        channel[val].PhotoPeriod = 1439;
     }
     bklTime = millis();
   }
}
if (channel[val].StartMins > 0) {
   if (checkButtonAction(−)) {
     channel[val].StartMins--;
     if (channel[val].PhotoPeriod < 1439) {
       channel[val].PhotoPeriod++;
     }
    else {
       channel[val].PhotoPeriod=0;
     }
     bklTime = millis();
   }
}
}void doEndTime(int val) {
//set end time
lcd.setCursor(0,0);
lcd.print("Channel ");
lcd.print(val+1);
lcd.print(" End");
lcd.setCursor(0,1);
printMins(channel[val].StartMins+channel[val].PhotoPeriod, true);
if (checkButtonAction(&plus)) {
   if(channel[val].PhotoPeriod < 1439){
     channel[val].PhotoPeriod++;
   }
   else {
     channel[val].PhotoPeriod=0;
   }
   bklTime = millis();
}
if (checkButtonAction(−)) {
   if(channel[val].PhotoPeriod > 0){
     channel[val].PhotoPeriod--;
   }
   else {
     channel[val].PhotoPeriod = 1439;
   }
   bklTime = millis();
}
}void doFadeDuration(int val) {
//set fade duration
lcd.setCursor(0,0);
lcd.print("Channel ");
lcd.print(val+1);
lcd.print(" Fade");
lcd.setCursor(0,1);
lcd.print("Duration ");
printMins(channel[val].FadeDuration, false);
if (channel[val].FadeDuration < channel[val].PhotoPeriod/2 || channel[val].FadeDuration == 0) {
   if (checkButtonAction(&plus)) {
     channel[val].FadeDuration++;
     bklTime = millis();
   }
}
if (channel[val].FadeDuration > 1) {
   if (checkButtonAction(−)) {
     channel[val].FadeDuration--;
     bklTime = millis();
   }
}
}
void doMaxIntensity(int val) {
//set intensity
lcd.setCursor(0,0);
lcd.print("Channel ");
lcd.print(val+1);
lcd.print(" Max");
lcd.setCursor(0,1);
lcd.print("Level: "); // Added by BoostLED
lcd.print(channel[val].Max);
lcd.print("%        "); // Added by BoostLED
if (channel[val].Max < 100) {
   if (checkButtonAction(&plus)) {
     lcd.clear();
     channel[val].Max++;
     bklTime = millis();
   }
}
if (channel[val].Max > 0) {
   if (checkButtonAction(−)) {
     lcd.clear();
     channel[val].Max--;
     bklTime = millis();
   }
}
}//Select Inverted PWM or not
//Added  By NetSurge
void doinvertPWM() {
lcd.setCursor(0,0);
lcd.print("PWM Inverted... ");
lcd.setCursor(0,1);
  if(inverted == true)
lcd.print("YES ");
  if(inverted == false)
lcd.print("NO ");
if (checkButtonAction(−) || checkButtonAction(&plus)) {
  inverted = !inverted;
}
}void setHour(byte *hour, byte minute, byte second,
byte dayOfWeek, byte dayOfMonth, byte month, byte year) {
//set hours
lcd.setCursor(0,0);
lcd.print("Set Time: Hrs");
lcd.setCursor(0,1);
printHMS(*hour, minute, second);
if (checkButtonAction(&plus)) {
   if (*hour < 23) {
     (*hour)++;
   }
  else {
     *hour = 0;
   }
   bklTime = millis();
}
if (checkButtonAction(−)) {
   if (*hour > 0) {
     (*hour)--;
   }
   else {
     *hour = 23;
   }
   bklTime = millis();
}
setDate(second, minute, *hour, dayOfWeek, dayOfMonth, month, year);
}void setMinute(byte hour, byte *minute, byte second,
byte dayOfWeek, byte dayOfMonth, byte month, byte year) {
//set minutes
lcd.setCursor(0,0);
lcd.print("Set Time: Mins");
lcd.setCursor(0,1);
printHMS(hour, *minute, second);
if (checkButtonAction(&plus)) {
   if (*minute < 59) {
     (*minute)++;
   }
  else {
     *minute = 0;
   }
   bklTime = millis();
}
if (checkButtonAction(−)) {
   if (*minute > 0) {
     (*minute)--;
   }
  else {
     *minute = 59;
   }
   bklTime = millis();
}
setDate(second, *minute, hour, dayOfWeek, dayOfMonth, month, year);
}

 

 

 

 

 

 

This is the code for the generic Typhon, but will work with BoostLED's model (v0.2) and Steve's (v1.0) and really any other Typhon as long as it is based on the same hardware from the Google code site.

 

/*
// Typhon firmware
// v0.3 alpha 2011-16-11
// N. Enders, R. Ensminger
//
// This sketch provides firmware for the Typhon LED controller.
// It provides a structure to fade 4 independent channels of LED lighting
// on and off each day, to simulate sunrise and sunset.
//
// Current work in progress:
// - store all LED variables in EEPROM so they are not reset by a loss of power
// - allow for signals to be inverted for buckpucks or other drivers that consider 0 to be "on"
//
// Future developments may include:
// - moon phase simulation
// - storm simulation
// - support for plugin hardware modules for temperature, pH, relay control, etc.
//
// Sketch developed in Arduino-22
// Requires LiquidCrystal, Wire, EEPROM, EEPROMVar, and Button libraries.
// Button is available here: http://www.arduino.cc/playground/Code/Button
// EEPROMVar is available here: http://www.arduino.cc/playground/uploads/Profiles/EEPROMVar_01.zip
*/

// include the libraries:
#include <LiquidCrystal.h>
#include <Wire.h>
#include <Button.h>
#include <EEPROM.h>
#include <EEPROMVar.h>
/**** Define Variables & Constants ****/
/**************************************/// set the RTC's I2C address
#define DS1307_I2C_ADDRESS 0x68
// create the LCD
LiquidCrystal lcd(8, 7, 5, 4, 16, 2);
// set up backlight
int bkl         = 6;        // backlight pin
byte bklIdle    = 10;       // PWM value for backlight at idle
byte bklOn      = 70;       // PWM value for backlight when on
int bklDelay    = 10000;    // ms for the backlight to idle before turning off
unsigned long bklTime = 0;  // counter since backlight turned on
// create the menu counter
int menuCount   = 1;
int menuSelect = 0;//create the plus and minus navigation delay counter with its initial maximum of 250.
byte btnMaxDelay = 200;
byte btnMinDelay = 25;
byte btnMaxIteration = 5;
byte btnCurrIteration;//create manual override variables
boolean override = false;
byte overmenu = 0;
int overpercent = 0;// create the buttons
Button menu     = Button(12,PULLDOWN);
Button select   = Button(13,PULLDOWN);
Button plus     = Button(14,PULLDOWN);
Button minus    = Button(15,PULLDOWN);// LED variables. These control the behavior of lighting. Change these to customize behavoir
int minCounter = 0;         // counter that resets at midnight.
int oldMinCounter = 0;      // counter that resets at midnight.
int oneLed = 9;             // pin for channel 1
int twoLed = 10;            // pin for channel 2
int threeLed = 11;          // pin for channel 3
int fourLed = 3;            // pin for channel 4int oneVal = 0;             // current value for channel 1
int twoVal = 0;             // current value for channel 2
int threeVal = 0;           // current value for channel 3
int fourVal = 0;            // current value for channel 4// Variables making use of EEPROM memory:EEPROMVar<int> oneStartMins = 750;      // minute to start this channel.
EEPROMVar<int> onePhotoPeriod = 720;   // photoperiod in minutes for this channel.
EEPROMVar<int> oneMax = 100;           // max intensity for this channel, as a percentage
EEPROMVar<int> oneFadeDuration = 60;   // duration of the fade on and off for sunrise and sunset for
                                       //    this channel.
EEPROMVar<int> twoStartMins = 810;
EEPROMVar<int> twoPhotoPeriod = 600;
EEPROMVar<int> twoMax = 100;
EEPROMVar<int> twoFadeDuration = 60;EEPROMVar<int> threeStartMins = 810;
EEPROMVar<int> threePhotoPeriod = 600;
EEPROMVar<int> threeMax = 100;
EEPROMVar<int> threeFadeDuration = 60;
                           
EEPROMVar<int> fourStartMins = 480;
EEPROMVar<int> fourPhotoPeriod = 510; 
EEPROMVar<int> fourMax = 100;         
EEPROMVar<int> fourFadeDuration = 60; // variables to invert the output PWM signal,
// for use with drivers that consider 0 to be "on"
// i.e. buckpucks. If you need to provide an inverted
// signal on any channel, set the appropriate variable to true.
boolean oneInverted = false;
boolean twoInverted = false;
boolean threeInverted = false;
boolean fourInverted = false;/*
int oneStartMins = 1380;      // minute to start this channel.
int onePhotoPeriod = 120;   // photoperiod in minutes for this channel.
int oneMax = 100;           // max intensity for this channel, as a percentage
int oneFadeDuration = 60;   // duration of the fade on and off for sunrise and sunset for
                                       //    this channel.                                   
int twoStartMins = 800;
int twoPhotoPeriod = 60;
int twoMax = 100;
int twoFadeDuration = 15;int threeStartMins = 800;
int threePhotoPeriod = 60;
int threeMax = 100;
int threeFadeDuration = 30;
                           
int fourStartMins = 800;
int fourPhotoPeriod = 120; 
int fourMax = 100;         
int fourFadeDuration = 60; 
*//****** RTC Functions ******/
/***************************/// Convert decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}// Convert binary coded decimal to decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}// Sets date and time, starts the clock
void setDate(byte second,        // 0-59
             byte minute,        // 0-59
             byte hour,          // 1-23
             byte dayOfWeek,     // 1-7
             byte dayOfMonth,    // 1-31
             byte month,         // 1-12
             byte year)          // 0-99
{
   Wire.beginTransmission(DS1307_I2C_ADDRESS);
   Wire.send(0);
   Wire.send(decToBcd(second));
   Wire.send(decToBcd(minute));
   Wire.send(decToBcd(hour));
   Wire.send(decToBcd(dayOfWeek));
   Wire.send(decToBcd(dayOfMonth));
   Wire.send(decToBcd(month));
   Wire.send(decToBcd(year));
   Wire.endTransmission();
}// Gets the date and time
void getDate(byte *second,
             byte *minute,
             byte *hour,
             byte *dayOfWeek,
             byte *dayOfMonth,
             byte *month,
             byte *year)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
  *second     = bcdToDec(Wire.receive() & 0x7f);
  *minute     = bcdToDec(Wire.receive());
  *hour       = bcdToDec(Wire.receive() & 0x3f);
  *dayOfWeek  = bcdToDec(Wire.receive());
  *dayOfMonth = bcdToDec(Wire.receive());
  *month      = bcdToDec(Wire.receive());
  *year       = bcdToDec(Wire.receive());
}/****** LED Functions ******/
/***************************/
//function to set LED brightness according to time of day
//function has three equal phases - ramp up, hold, and ramp downint   setLed(int mins,         // current time in minutes
            int ledPin,        // pin for this channel of LEDs
            int start,         // start time for this channel of LEDs
            int period,        // photoperiod for this channel of LEDs
            int fade,          // fade duration for this channel of LEDs
            int ledMax,        // max value for this channel
            boolean inverted   // true if the channel is inverted
            )  {
  int val = 0;
     
      //fade up
      if (mins > start || mins <= start + fade)  {
        val = map(mins - start, 0, fade, 0, ledMax);
      }
      //fade down
      if (mins > start + period - fade && mins <= start + period)  {
        val = map(mins - (start + period - fade), 0, fade, ledMax, 0);
      }
      //off or post-midnight run.
      if (mins <= start || mins > start + period)  {
        if((start+period)%1440 < start && (start + period)%1440 > mins )
          {
            val=map((start+period-mins)%1440,0,fade,0,ledMax);
          }
        else 
        val = 0;
      }
   
   
    if (val > ledMax)  {val = ledMax;}
    if (val < 0) {val = 0; }
   
  if (inverted) {analogWrite(ledPin, map(val, 0, 100, 255, 0));}
  else {analogWrite(ledPin, map(val, 0, 100, 0, 255));}
  if(override){val=overpercent;}
  return val;
}/**** Display Functions ****/
/***************************///button hold function
int btnCurrDelay(byte curr)
{
  if(curr==btnMaxIteration)
  {
    btnCurrIteration = btnMaxIteration;
    return btnMaxDelay;
  }
  else if(btnCurrIteration ==0)
  {
    return btnMinDelay;
  }
  else
  {
    btnCurrIteration--;
    return btnMaxDelay;
  }
}// format a number of minutes into a readable time (24 hr format)
void printMins(int mins,       //time in minutes to print
               boolean ampm    //print am/pm?
              )  {
  int hr = (mins%1440)/60;
  int mn = mins%60;
    if(hr<10){
      lcd.print(" ");
    }
    lcd.print(hr);
    lcd.print(":");
    if(mn<10){
      lcd.print("0");
    }
    lcd.print(mn);
}// format hours, mins, secs into a readable time (24 hr format)
void printHMS (byte hr,
               byte mn,
               byte sec      //time to print
              ) 
{
 
    if(hr<10){
      lcd.print(" ");
    }
    lcd.print(hr, DEC);
    lcd.print(":");
    if(mn<10){
      lcd.print("0");
    }
    lcd.print(mn, DEC);
    lcd.print(":");
    if(sec<10){
      lcd.print("0");
    }
    lcd.print(sec, DEC);
}
void ovrSetAll(int pct){
    analogWrite(oneLed,map(pct,0,100,0,255));
    analogWrite(twoLed,map(pct,0,100,0,255));
    analogWrite(threeLed,map(pct,0,100,0,255));
    analogWrite(fourLed,map(pct,0,100,0,255));
}/**** Setup ****/
/***************/void setup() {
  Wire.begin();
  pinMode(bkl, OUTPUT);
  lcd.begin(16, 2);
  digitalWrite(bkl, HIGH);
  lcd.print("Typhon-Reef");
  lcd.setCursor(0,1);
  lcd.print("");
  delay(5000);
  lcd.clear();
  analogWrite(bkl,bklIdle);
  btnCurrIteration = btnMaxIteration;
}/***** Loop *****/
/****************/void loop() {
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;  getDate(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  oldMinCounter = minCounter;
  minCounter = hour * 60 + minute;
 
  //reset plus & minus acceleration counters if the button's state has changed
  if(plus.stateChanged())
  {
   btnCurrDelay(btnMaxIteration);
  }
  if(minus.stateChanged())
  { 
    btnCurrDelay(btnMaxIteration);
  }
      
 
  //check & set fade durations
  if(oneFadeDuration > onePhotoPeriod/2 && onePhotoPeriod >0){oneFadeDuration = onePhotoPeriod/2;}
  if(oneFadeDuration<1){oneFadeDuration=1;}
 
  if(twoFadeDuration > twoPhotoPeriod/2 && twoPhotoPeriod >0){twoFadeDuration = twoPhotoPeriod/2;}
  if(twoFadeDuration<1){twoFadeDuration=1;}
 
  if(threeFadeDuration > threePhotoPeriod/2 && threePhotoPeriod >0){threeFadeDuration = threePhotoPeriod/2;}
  if(threeFadeDuration<1){threeFadeDuration=1;}
 
  if(fourFadeDuration > fourPhotoPeriod/2 && fourPhotoPeriod > 0){fourFadeDuration = fourPhotoPeriod/2;}
  if(fourFadeDuration<1){fourFadeDuration=1;}
 
  //check & set any time functions
 
 
  //set outputs
  if(!override){
  oneVal = setLed(minCounter, oneLed, oneStartMins, onePhotoPeriod, oneFadeDuration, oneMax, oneInverted);
  twoVal = setLed(minCounter, twoLed, twoStartMins, twoPhotoPeriod, twoFadeDuration, twoMax, twoInverted);
  threeVal = setLed(minCounter, threeLed, threeStartMins, threePhotoPeriod, threeFadeDuration, threeMax, threeInverted);
  fourVal = setLed(minCounter, fourLed, fourStartMins, fourPhotoPeriod, fourFadeDuration, fourMax, fourInverted);
  }
  else{
    ovrSetAll(overpercent);
  }
 
 
  //turn the backlight off and reset the menu if the idle time has elapsed
  if(bklTime + bklDelay < millis() && bklTime > 0 ){
    analogWrite(bkl,bklIdle);
    menuCount = 1;
    lcd.clear();
    bklTime = 0;
  }  //iterate through the menus
  if(menu.uniquePress()){
    analogWrite(bkl,bklOn);
    bklTime = millis();
    if(menuCount < 20){
      menuCount++;
    }else {
      menuCount = 1;
    }
  lcd.clear();
  }
  if(menuCount == 1){
    //main screen turn on!!!
    if (minCounter > oldMinCounter){
      lcd.clear();
    }
    lcd.setCursor(0,0);
    printHMS(hour, minute, second);
    lcd.setCursor(0,1);
    lcd.print(oneVal);
    lcd.setCursor(4,1);
    lcd.print(twoVal);
    lcd.setCursor(8,1);
    lcd.print(threeVal);
    lcd.setCursor(12,1);
    lcd.print(fourVal);
    //debugging function to use the select button to advance the timer by 1 minute
    //if(select.uniquePress()){setDate(second, minute+1, hour, dayOfWeek, dayOfMonth, month, year);}
  }
 
  if(menuCount == 2){
    //Manual Override Menu
    lcd.setCursor(0,0);
    lcd.print("Manual Overrides");
    lcd.setCursor(0,1);
    lcd.print("All: ");
    if(select.uniquePress()){
      if(menuSelect < 3){menuSelect++;}
      else{menuSelect = 0;}
      bklTime = millis();
    }
   
    if(menuSelect == 0){
      lcd.print("Timer");
      override = false;}
    if(menuSelect == 1){
      lcd.print("ON   ");
      overpercent = 100;
      override = true;}
    if(menuSelect == 2){
      lcd.print("OFF  ");
      overpercent = 0;
      override = true;}   
    if(menuSelect == 3){
      override = true;
      lcd.print(overpercent,DEC);
      lcd.print("%  ");
      if(plus.isPressed() && overpercent <100)
        {
          overpercent++;
          delay(btnCurrDelay(btnCurrIteration-1));
          bklTime = millis();
        }
       
        if(minus.isPressed() && overpercent > 0)
        {
          overpercent--;
          delay(btnCurrDelay(btnCurrIteration-1));
          bklTime = millis();
        }
      }
}


  if(menuCount == 3){
    //set start time for channel one
    lcd.setCursor(0,0);
    lcd.print("Channel 1 Start");
    lcd.setCursor(0,1);
    printMins(oneStartMins, true);
   
    if(plus.isPressed() && oneStartMins < 1440){
        oneStartMins++;
        if(onePhotoPeriod >0){onePhotoPeriod--;}
        else{onePhotoPeriod=1439;}
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && oneStartMins > 0){
        oneStartMins--;
        if(onePhotoPeriod<1439){onePhotoPeriod++;}
        else{onePhotoPeriod=0;}
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }  if(menuCount == 4){
    //set end time for channel one
    lcd.setCursor(0,0);
    lcd.print("Channel 1 End");
    lcd.setCursor(0,1);
    printMins(oneStartMins+onePhotoPeriod, true);
    if(plus.isPressed()){
      if(onePhotoPeriod < 1439){
      onePhotoPeriod++;}
      else{
        onePhotoPeriod=0;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed()){
      if(onePhotoPeriod >0){
        onePhotoPeriod--;}
      else{
        onePhotoPeriod=1439;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }  if(menuCount == 5){
    //set fade duration for channel one
    lcd.setCursor(0,0);
    lcd.print("Channel 1 Fade");
    lcd.setCursor(0,1);
    printMins(oneFadeDuration, false);
    if(plus.isPressed() && (oneFadeDuration < onePhotoPeriod/2 || oneFadeDuration == 0)){
      oneFadeDuration++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && oneFadeDuration > 1){
      oneFadeDuration--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }  if(menuCount == 6){
    //set intensity for channel one
    lcd.setCursor(0,0);
    lcd.print("Channel 1 Max");
    lcd.setCursor(1,1);
    lcd.print(oneMax);
    lcd.print("  ");
    if(plus.isPressed() && oneMax < 100){
      oneMax++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && oneMax > 0){
      oneMax--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }  if(menuCount == 7){
    //set start time for channel two
    lcd.setCursor(0,0);
    lcd.print("Channel 2 Start");
    lcd.setCursor(0,1);
    printMins(twoStartMins, true);
    if(plus.isPressed() && twoStartMins < 1440){
        twoStartMins++;
        if(twoPhotoPeriod >0){twoPhotoPeriod--;}
        else{twoPhotoPeriod=1439;}
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && twoStartMins > 0){
        twoStartMins--;
        if(twoPhotoPeriod<1439){twoPhotoPeriod++;}
        else{twoPhotoPeriod=0;}
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }  if(menuCount == 8){
    //set end time for channel two
    lcd.setCursor(0,0);
    lcd.print("Channel 2 End");
    lcd.setCursor(0,1);
    printMins(twoStartMins+twoPhotoPeriod, true);
    if(plus.isPressed()){
      if(twoPhotoPeriod < 1439){
      twoPhotoPeriod++;}
      else{
        twoPhotoPeriod=0;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed()){
      if(twoPhotoPeriod >0){
        twoPhotoPeriod--;}
      else{
        twoPhotoPeriod=1439;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }  if(menuCount == 9){
    //set fade duration for channel two
    lcd.setCursor(0,0);
    lcd.print("Channel 2 Fade");
    lcd.setCursor(0,1);
    printMins(twoFadeDuration, false);
    if(plus.isPressed() && (twoFadeDuration < twoPhotoPeriod/2 || twoFadeDuration == 0)){
      twoFadeDuration++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && twoFadeDuration > 1){
      twoFadeDuration--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }  if(menuCount == 10){
    //set intensity for channel two
    lcd.setCursor(0,0);
    lcd.print("Channel 2 Max");
    lcd.setCursor(1,1);
    lcd.print(twoMax);
    lcd.print("  ");
    if(plus.isPressed() && twoMax < 100){
      twoMax++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && twoMax > 0){
      twoMax--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }  if(menuCount == 11){
    //set start time for channel three
    lcd.setCursor(0,0);
    lcd.print("Channel 3 Start");
    lcd.setCursor(0,1);
    printMins(threeStartMins, true);
    if(plus.isPressed() && threeStartMins < 1440){
        threeStartMins++;
        if(threePhotoPeriod >0){threePhotoPeriod--;}
        else{threePhotoPeriod=1439;}
        delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && threeStartMins > 0){
        threeStartMins--;
        if(threePhotoPeriod<1439){threePhotoPeriod++;}
        else{threePhotoPeriod=0;}
        delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }  if(menuCount == 12){
    //set end time for channel three
    lcd.setCursor(0,0);
    lcd.print("Channel 3 End");
    lcd.setCursor(0,1);
    printMins(threeStartMins+threePhotoPeriod, true);
    if(plus.isPressed()){
      if(threePhotoPeriod < 1439){
      threePhotoPeriod++;}
      else{
        threePhotoPeriod=0;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed()){
      if(threePhotoPeriod >0){
        threePhotoPeriod--;}
      else{
        threePhotoPeriod=1439;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }  if(menuCount == 13){
    //set fade duration for channel three
    lcd.setCursor(0,0);
    lcd.print("Channel 3 Fade");
    lcd.setCursor(0,1);
    printMins(threeFadeDuration, false);
    if(plus.isPressed() && (threeFadeDuration < threePhotoPeriod/2 || threeFadeDuration == 0)){
      threeFadeDuration++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && threeFadeDuration > 1){
      threeFadeDuration--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }  if(menuCount == 14){
    //set intensity for channel three
    lcd.setCursor(0,0);
    lcd.print("Channel 3 Max");
    lcd.setCursor(1,1);
    lcd.print(threeMax);
    lcd.print("  ");
    if(plus.isPressed() && threeMax < 100){
      threeMax++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && threeMax > 0){
      threeMax--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }  if(menuCount == 15){
    //set start time for channel four
    lcd.setCursor(0,0);
    lcd.print("Channel 4 Start");
    lcd.setCursor(0,1);
    printMins(fourStartMins, true);
    if(plus.isPressed() && fourStartMins < 1440){
        fourStartMins++;
        if(fourPhotoPeriod >0){fourPhotoPeriod--;}
        else{fourPhotoPeriod=1439;}
        delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && fourStartMins > 0){
        fourStartMins--;
        if(fourPhotoPeriod<1439){fourPhotoPeriod++;}
        else{fourPhotoPeriod=0;}
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }  if(menuCount == 16){
    //set end time for channel four
    lcd.setCursor(0,0);
    lcd.print("Channel 4 End");
    lcd.setCursor(0,1);
    printMins(fourStartMins+fourPhotoPeriod, true);
    if(plus.isPressed()){
      if(fourPhotoPeriod < 1439){
      fourPhotoPeriod++;}
      else{
        fourPhotoPeriod=0;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed()){
      if(fourPhotoPeriod >0){
        fourPhotoPeriod--;}
      else{
        fourPhotoPeriod=1439;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }  if(menuCount == 17){
    //set fade duration for channel four
    lcd.setCursor(0,0);
    lcd.print("Channel 4 Fade");
    lcd.setCursor(0,1);
    printMins(fourFadeDuration, false);
    if(plus.isPressed() && (fourFadeDuration < fourPhotoPeriod/2 || fourFadeDuration == 0)){
      fourFadeDuration++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && fourFadeDuration > 1){
      fourFadeDuration--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }  if(menuCount == 18){
    //set intensity for channel four
    lcd.setCursor(0,0);
    lcd.print("Channel 4 Max");
    lcd.setCursor(1,1);
    lcd.print(fourMax);
    lcd.print("   ");
    if(plus.isPressed() && fourMax < 100){
      fourMax++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && fourMax > 0){
      fourMax--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  }
  if(menuCount == 19){
    //set hours
    lcd.setCursor(0,0);
    lcd.print("Set Time: Hrs");
    lcd.setCursor(0,1);
    printHMS(hour, minute, second);
    if(plus.isPressed() && hour < 23){
      hour++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && hour > 0){
      hour--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  setDate(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
  }
 
  if(menuCount == 20){
    //set minutes
    lcd.setCursor(0,0);
    lcd.print("Set Time: Mins");
    lcd.setCursor(0,1);
    printHMS(hour, minute, second);
    if(plus.isPressed() && minute < 59){
      minute++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if(minus.isPressed() && minute > 0){
      minute--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  setDate(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
  }
}

 


What I would like to have in the code:

 

  • Option for a parabolic ramp instead of a slope
  • Very randomized and realistic cloud cover mimicing this plot of light intensity on a somewhat clear day in Hawaii:

image006.jpg" alt="image006.jpg">

  • More realistic lightning using a BURST command instead of BLINK
  • Photoperiod adjusted throughout the year based on Great Barrier Reef (and adjustable for latitude) (Deckoz2302 has a very simple code for this IIRC)

 

Code for burst:

int ledPin11 = 11;
int burst; //short burst of light
int big;
int srumble;
int brumble;
int mixer;
int diming;
int delaymix;
int dark;
int lightningtimer;
int lightningtime;

void setup (){}
void loop (){
  //30 Min sunrise
  for(int fadeValue = 0; fadeValue < 191; fadeValue +=1)
  {
  analogWrite(ledPin11, fadeValue);
  delay(9411);
  }
  
  //8 hours of solid day light
  analogWrite(ledPin11, 191);
  delay(28800000);
  
  //2 Min cloud cover (Dark)
  for(int fadeValue = 191; fadeValue > 0; fadeValue -=1)
  {
  analogWrite(ledPin11, fadeValue);
  delay(628);
  }

//Random lighting storm of bursts and flickers
unsigned long now = millis();
  lightningtime = 120000;
  lightningtimer = now;

if (now - lightningtimer < lightningtime)
 {
  burst = random(10,500); //Short burst of lightning value
  big = random(1000,4000);//long burst of lightning value
  srumble = random(10,40);//lower light lighting value
  brumble = random(10,150);//higher light lightning value
  mixer = random(burst,big);//random pick of short or long bursts of lightning
  dark = random(1000,12000);//random pick of time gap for lightning
  for(int i = 0; i < mixer; i += diming++)
  {
  diming = random(1,150);
  analogWrite(ledPin11, random(srumble,brumble));//Turn on LED for short or long burst
  delay(diming);//random number delay to remain at set brightness value
}
  digitalWrite(ledPin11, LOW);    // turn the LED off
delay(dark);
  }
  //2 min cloud clearing (light)
  for(int fadeValue = 0; fadeValue < 191; fadeValue +=1)
  {
  analogWrite(ledPin11, fadeValue);
  delay(628);
}
  
  //30 min sunset//
  for(int fadeValue = 191; fadeValue > 0; fadeValue -=1)
  {
  analogWrite(ledPin11, fadeValue);
  delay(9411);
}
  
  //Delay to reach the end of psu timer.
  delay(500000);

}

For a video of this burst, see here:

Link to comment

I want to thank Jedi for offering a Typhon to me. As soon as I get it I will be able to begin testing the code I started on today.

Link to comment

Hmmm the burst code looks interesting. I may have to try muxing it with my lightning strike code could probably get a pretty visually true effect combining the two..intertesting

 

Also all the above typhoon code is coded very...well poorly and wastes an incredible amount of space. Half of that should be recoded with an access functions with passed child variables as the same code is repeated multiple times over and over

  • Like 2
Link to comment

Hmmm the burst code looks interesting. I may have to try muxing it with my lightning strike code could probably get a pretty visually true effect combining the two..intertesting

 

Also all the above typhoon code is coded very...well poorly and wastes an incredible amount of space. Half of that should be recoded with an access functions with passed child variables as the same code is repeated multiple times over and over

I'm redoing the whole thing from ground up. And I'm adding in a ds1307 library for convenience.

Link to comment
jedimasterben

Hmmm the burst code looks interesting. I may have to try muxing it with my lightning strike code could probably get a pretty visually true effect combining the two..intertesting

 

Also all the above typhoon code is coded very...well poorly and wastes an incredible amount of space. Half of that should be recoded with an access functions with passed child variables as the same code is repeated multiple times over and over

So what you're saying is that you'll help? :P

  • Like 1
Link to comment

How about I offer my functions and we call it even



//*********************************************************************************************************************************
//LED Variables
long calcSec(long,long);
long calcTime(long,long);
short Ndays;
static byte lightningchance=0;
byte cloudduration=0;
int cloudstart=0;
int rhour = 0, rmin = 0, shour = 0, smin = 0;
byte PWMports[] ={3,5,6,9,10,11};
int ChannelValue[] = {0,0,0,0,0,0};
byte SeasonsVar[]={0,0,0,0,0,0,0,0,0,0,0,0}; // PWM0, sunrisehour, sunriseminute, sunsethour, sunsetminute, cloudstarthout, cloudstartminute, cloudduration,lightningchance, PWM1,PWM2,PWM3
byte cmdnum=255;
byte datanum=255;
boolean ForceCloud=false;

//*********************************************************************************************************************************



//*********************************************************************************************************************************
// Random Cloud/Thunderstorm effects function
void CheckCloud()
{

// ------------------------------------------------------------
// Change the values below to customize your cloud/storm effect

// Frequency in days based on the day of the month - number 2 means every 2 days, for example (day 2,4,6 etc)
// For testing purposes, you can use 1 and cause the cloud to occur everyday
#define Clouds_Every_X_Days 3

// Percentage chance of a cloud happening today
// For testing purposes, you can use 100 and cause the cloud to have 100% chance of happening
#define Cloud_Chance_per_Day 0

// Minimum number of minutes for cloud duration. Don't use max duration of less than 6
#define Min_Cloud_Duration 6

// Maximum number of minutes for the cloud duration. Don't use max duration of more than 255
#define Max_Cloud_Duration 30

// Minimum number of clouds that can happen per day
#define Min_Clouds_per_Day 2

// Maximum number of clouds that can happen per day
#define Max_Clouds_per_Day 5

// Only start the cloud effect after this setting
// In this example, start could after 11:30am
#define Start_Cloud_After NumMins(16,00)

// Always end the cloud effect before this setting
// In this example, end could before 8:00pm
#define End_Cloud_Before NumMins(19,00)

// Percentage chance of a lightning happen for every cloud
// For testing purposes, you can use 100 and cause the lightning to have 100% chance of happening
#define Lightning_Change_per_Cloud 40

// Channels used by the actinic LEDs on the PWM Expansion module
// These channels will not be dimmed when the cloud effect is triggered
// Number is a binary form. B001100 means channel 2 and 3 are used for actinics
#define Actinic_Channels B010110

// Channels used by the daylight LEDs on the PWM Expansion module
// These channels will be used for the spike when lightning effect is triggered
// Number is a binary form. B000011 means channel 0 and 1 are used for daylights
#define Daylight_Channels B001001

// Note: Make sure to choose correct values that will work within your PWMSLope settings.
// For example, in our case, we could have a max of 5 clouds per day and they could last for 50 minutes.
// Which could mean 250 minutes of clouds. We need to make sure the PWMSlope can accomodate 250 minutes of effects or unforseen
// results could happen.
// Also, make sure that you can fit double those minutes between Start_Cloud_After and End_Cloud_Before.
// In our example, we have 510 minutes between Start_Cloud_After and End_Cloud_Before, so double the 250 minutes (or 500 minutes) can
//fit in that 510 minutes window.
// It's a tight fit, but it did.

//#define printdebug // Uncomment this for debug print on Serial Monitor window
#define forcecloudcalculation // Uncomment this to force the cloud calculation to happen in the boot process.


// Change the values above to customize your cloud/storm effect
// ------------------------------------------------------------
// Do not change anything below here

static byte cloudchance=255;
static byte numclouds=0;
static byte cloudindex=0;
static byte lightningstatus=0;
static int LastNumMins=0;
// Every day at midnight, we check for chance of cloud happening today
if (hour()==0 && minute()==0 && second()==0) cloudchance=255;

#ifdef forcecloudcalculation
if (cloudchance==255)
#else
if (hour()==0 && minute()==0 && second()==1 && cloudchance==255)
#endif
{
//Pick a random number between 0 and 99
cloudchance=random(100);
// if picked number is greater than Cloud_Chance_per_Day, we will not have clouds today
if (cloudchance>Cloud_Chance_per_Day) cloudchance=0;
// Check if today is day for clouds.
if ((day()%Clouds_Every_X_Days)!=0) cloudchance=0;
// If we have cloud today
if (cloudchance)
{
// pick a random number for number of clouds between Min_Clouds_per_Day and Max_Clouds_per_Day
numclouds=random(Min_Clouds_per_Day,Max_Clouds_per_Day);
// pick the time that the first cloud will start
// the range is calculated between Start_Cloud_After and the even distribuition of clouds on this day.
cloudstart=random(Start_Cloud_After,Start_Cloud_After+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));

// pick a random number for the cloud duration of first cloud.
cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration);
//Pick a random number between 0 and 99
lightningchance=random(100);
// if picked number is greater than Lightning_Change_per_Cloud, we will not have lightning today
if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0;
}
}
// Now that we have all the parameters for the cloud, let's create the effect

if (ForceCloud)
{
ForceCloud=false;
cloudchance=1;
cloudduration=10;
lightningchance=1;
cloudstart=NumMins(hour(),minute())+1;
}

if (cloudchance)
{
//is it time for cloud yet?
if (NumMins(hour(),minute())>=cloudstart && NumMins(hour(),minute())<(cloudstart+cloudduration))
{
// let's go through all channels to pick which ones will be dimmed
for (int a=0;a<6;a++)
{
if (bitRead(Actinic_Channels,a)==0)
{
// this will slope down the channel from the current PWM to 0 within 3minutes.
// then it will stay at 0 for the duration of the cycle
// and finally slope up from 0 to PWM value within 3 minutes
// it is basically an inversed slope
ChannelValue[a]=ReversePWMSlope(cloudstart,cloudstart+cloudduration,ChannelValue[a],0,180);
}
}
if (lightningchance && (NumMins(hour(),minute())==(cloudstart/*+(cloudduration/2)*/)) && second()<3)
{
int strikes = random(7);
for (int b=0;b<strikes;b++)
{
if (bitRead(Daylight_Channels,==1)
{
if (random(100)<20) lightningstatus=1;
else lightningstatus=0;
if (lightningstatus) ChannelValue[b]=100;
else ChannelValue[b]=0;
if (b==(random(strikes))) delay(5);
}
else
{
ChannelValue[b]=20;
}
}
}
}

if (NumMins(hour(),minute())>(cloudstart+cloudduration))
{
cloudindex++;
if (cloudindex < numclouds)
{
cloudstart=random(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2),(Start_Cloud_After+(((End_Cloud_Before-Start_Cloud_After)/(numclouds*2))*cloudindex*2))+((End_Cloud_Before-Start_Cloud_After)/(numclouds*2)));
// pick a random number for the cloud duration of first cloud.
cloudduration=random(Min_Cloud_Duration,Max_Cloud_Duration);
//Pick a random number between 0 and 99
lightningchance=random(100);
// if picked number is greater than Lightning_Change_per_Cloud, we will not have lightning today
if (lightningchance>Lightning_Change_per_Cloud) lightningchance=0;
}
}
}
}
//End Cloud Function
//*********************************************************************************************************************************
//*********************************************************************************************************************************
//Reverse PWM slope from cloud function
byte ReversePWMSlope(long cstart,long cend,byte PWMStart,byte PWMEnd, byte clength)
{
long n=elapsedSecsToday(now());
cstart*=60;
cend*=60;
if (n<cstart) return PWMStart;
if (n>=cstart && n<=(cstart+clength)) return map(n,cstart,cstart+clength,PWMStart,PWMEnd);
if (n>(cstart+clength) && n<(cend-clength)) return PWMEnd;
if (n>=(cend-clength) && n<=cend) return map(n,cend-clength,cend,PWMEnd,PWMStart);
if (n>cend) return PWMStart;
}
//End Reverse PWM function
//*********************************************************************************************************************************
//*********************************************************************************************************************************
//Calculate Sunrise/set by date & predefined season & rise/set times
void Seasons()
{
//Set the hour you want the calculations of rise an set to be based on
int UserRiseHour = 4;
int UserSetHour = 17;

#define forceseasoncalculation
static byte ssn , ssnp = 0 , ssnpt ;
long stime, wstime, vstime, wrtime, rtime, vrtime;
int wrhour,wrmin,wrsec,wshour,wsmin,wssec,rsec,ssec,vrhour,vrmin,vrsec,vshour,vsmin,vssec;
int iDiffrise = 0;
int iDiffset = 0;
int risediffperday = 0;
int setdiffperday = 0;
int totalrise = 0;
int totalset = 0;
byte s=0;
int DaysPerYear;

//rise and set times set by hour and minute. there are 4 seasons however there are 8 highs & lows in rise and set throughout the year
//first spot is second half of winter starting jan 1st - DO NOT CHANGE
int risehour[8]= {
UserRiseHour+1,UserRiseHour+1,UserRiseHour+1,UserRiseHour,UserRiseHour,UserRiseHour-1,UserRiseHour,UserRiseHour };/*{
7,7,7,6,6,5,6,6 };*/
int riseminute[8]={
00,30,00,30,00,30,00,30 };
int sethour[8] = {
UserSetHour-2,UserSetHour-1,UserSetHour-1,UserSetHour,UserSetHour,UserSetHour,UserSetHour,UserSetHour-1 };/*{
17,18,18,19,19,19,19,18 };*/
int setminute[8] = {
30,00,30,00,00,30,00,00 };

/* //
if (hour()==0 && minute()==0 && second()==0) ssnp=0;
#ifdef forceseasoncalculation
if (ssnp==0)
#else
if (hour()==0 && minute()==0 && second()==1 && ssnp==0)
#endif
{*/
//leapyear or not to define DaysPerYear - DO NOT CHANGE
if (year()%4 == 0 && !(year()%100 == 0 && year()%400 != 0))
{
DaysPerYear=366;
}
else
{
DaysPerYear = 365;
}
//Call Day Number Calc to determin day ie december 31st on a non leap year is day 365 - DO NOT CHANGE
DayNumber(year(),month(),day());
//define days between beginning, middle and end of seasons high peaks - DO NOT CHANGE
int seasons[9] ={
0,45,96,135,187,238,283,328,DaysPerYear };
//define season and array pulling variable - DO NOT CHANGE
for (s=0; seasons[s] < Ndays; s++) ssn = s+1, ssnpt = s+1, ssnp = s;
//set loop on array time pulling variable to go back to beginning instead of increasing array size - DO NOT CHANGE
if (ssn >= 7) ssn = 0;

//differece in seconds between two rise/set array times pulled - DO NOT CHANGE
long rise1 = calcSec(risehour[ssn],riseminute[ssn]);
long rise2 = calcSec(risehour[ssnp],riseminute[ssnp]);
iDiffrise = calcTime(rise1, rise2);
long set1 = calcSec(sethour[ssn],setminute[ssn]);
long set2 = calcSec(sethour[ssnp],setminute[ssnp]);
iDiffset = calcTime(set1,set2);

//calculate new sunrise/set difference from array value & last group of code - DO NOT CHANGE
risediffperday = iDiffrise/(seasons[ssnpt]-seasons[ssnp]);
totalrise = risediffperday*(Ndays - seasons[ssnp]);
setdiffperday = iDiffset/(seasons[ssnpt]-seasons[ssnp]);
totalset = setdiffperday*(Ndays - seasons[ssnp]);

//creating time in seconds for main sun rise/set number - DO NOT CHANGE
rtime=calcSec(risehour[ssnp],riseminute[ssnp]);
if (ssnp == 0 || ssnp == 2 || ssnp == 4 || ssnp == 6){
rtime += totalrise;
}
else {
rtime -= totalrise;
}
stime=calcSec(sethour[ssnp],setminute[ssnp]);
if (ssnp == 1 || ssnp == 3 || ssnp == 5 || ssnp == 7){
stime -= totalset;
}
else {
stime += totalset;
}

//These are the off set times, standard rtime and stime are for Royal Blues & Blues
// DO NOT CHANGE the operators in these equations ie +-
// The number is in seconds (1200) change this number to change the offset for each color
wrtime = rtime + 1800;//w r/stime is for Whites - shorter time span then blues
wstime = stime - 3600;
vrtime = rtime - 1800;//v r/stime is for Violets - Longer time then blues
vstime = stime + 1800;

//turning seconds back to Hours:Minutes:Seconds
//Blues
rhour=rtime/3600;
rtime=rtime%3600;
rmin=rtime/60;
rtime=rtime%60;
rsec=rtime;
if(rsec > 30) rmin++;
shour=stime/3600;
stime=stime%3600;
smin=stime/60;
stime=stime%60;
ssec=stime;
if(ssec > 30) smin++;
//White
wrhour = wrtime/3600;
wrtime=wrtime%3600;
wrmin=wrtime/60;
wrtime=wrtime%60;
wrsec=wrtime;
if(wrsec>30) wrmin++;
wshour = wstime/3600;
wstime=wstime%3600;
wsmin=wstime/60;
wstime=wstime%60;
wssec=wstime;
if(wssec>30) wsmin++;
//Violet
vrhour = vrtime/3600;
vrtime=vrtime%3600;
vrmin=vrtime/60;
vrtime=vrtime%60;
vrsec=vrtime;
if(vrsec>30) vrmin++;
vshour = vstime/3600;
vstime=vstime%3600;
vsmin=vstime/60;
vstime=vstime%60;
vssec=vstime;
if(vssec>30) vsmin++;

if (rmin==60)rmin=00, rhour+=1;
if (smin==60)smin=00, shour+=1;
if (wrmin==60)wrmin=00, wrhour+=1;
if (wsmin==60)wsmin=00, wshour+=1;
if (vrmin==60)vrmin=00, vrhour+=1;
if (vsmin==60)vsmin=00, vshour+=1;
//This is the PWM Slope for each channel, each channel pulls an array value from above(hour,minute) to use, how you set them is up to you.
//Just always use a Rise hour in a Rise spot, always a set hour in a set spot ect ect
ChannelValue[LEDPWM0]=PWMSlope(wrhour,wrmin,wshour,wsmin,0,2.55*28,120,ChannelValue[LEDPWM0]);
ChannelValue[LEDPWM1]=PWMSlope(vrhour,vrmin,vshour,vsmin,0,2.55*58,70,ChannelValue[LEDPWM1]);
ChannelValue[LEDPWM2]=PWMSlope(rhour,rmin,shour,smin,0,2.55*58,90,ChannelValue[LEDPWM2]);
ChannelValue[LEDPWM3]=PWMSlope(wrhour,wrmin,wshour,wsmin,0,2.55*36,105,ChannelValue[LEDPWM3]);
//ChannelValue[LEDPWM4]=PWMSlope(vrhour,vrmin,vshour,vsmin,0,2.55*90,45,ChannelValue[LEDPWM4]);
//ChannelValue[LEDPWM0]=PWMSlope(wrhour,wrmin,wshour,wsmin,0,2.55*85,180,ChannelValue[LEDPWM4]);
}
//End Seasons Calculation
//*********************************************************************************************************************************

//*********************************************************************************************************************************
//Calculators for Seasons function
long calcSec(long hr, long minu)
{
long totalseconds;
totalseconds=(hr*3600)+(minu*60);
return totalseconds;
}

long calcTime(long seconds1, long seconds2)
{
long timediff=abs(seconds1-seconds2);
return timediff;
}

void DayNumber(unsigned int y, unsigned int m, unsigned int d)
{
int days[]={
0,31,59,90,120,151,181,212,243,273,304,334 }; // Number of days at the beginning of the month in a not leap year.
//Start to calculate the number of day
if (m==1 || m==2){
Ndays = days[(m-1)]+d; //for any type of year, it calculate the number of days for January or february
} // Now, try to calculate for the other months
else if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0){ //those are the conditions to have a leap year
Ndays = days[(m-1)]+d+1; // if leap year, calculate in the same way but increasing one day
}
else { //if not a leap year, calculate in the normal way, such as January or February
Ndays = days[(m-1)]+d;
}
}
//End calculators
//*********************************************************************************************************************************


  • Like 2
Link to comment

That's a lot of code...

EDIT: Looks very programmable :). I will look at that in depth in a little.

yea its just the functions and global variables. you choose how to access them

 

only thing you need to change in the code is PWMslope. or write your own slope function everything else is easily givin child variables or accessed through your loop()

  • Like 1
Link to comment
  • 2 months later...

Here you go! I finished this a couple weeks ago, but I wanted to confirm that it worked before posting it up.

 

You will need to move the DS1307 folder into your Arduino libraries folder, then open the ARduino program, then upload the sketch.

Typhon_code_2.zip

Link to comment

Hello,

 

I have some issues opening the attached file...

 

is the file uploaded correct?

 

 

thanks

 

 

Here you go! I finished this a couple weeks ago, but I wanted to confirm that it worked before posting it up.

 

You will need to move the DS1307 folder into your Arduino libraries folder, then open the ARduino program, then upload the sketch.

  • Like 1
Link to comment

Meep,

 

maybe I missed it but what are the differences between the stock BoostLed code and the code you uploaded above?

Well, mine stores memory, makes a bell curve vs. a line, has an acclimation mode, and a lighting test to see different lighting colors.

 

sorry dumb question. But how do you upload a program to the typhon controller?

Legitimate question. You need something like this:

http://www.ebay.com/itm/FTDI-Basic-6-PIN-3-3-5V-For-Arduino-Free-USB-Cable-/230820610037?pt=LH_DefaultDomain_0&hash=item35bdfafff5

You plug it in so that the text that tells what pin is what is facing upwards, and plug the other end into the computer. If the screen lights up, you plugged it in right. If not, flip it over.

It does not plug into the place where you wire the output for the leds. It plugs into the other header that seems to have no apparent use for leds.

  • Like 1
Link to comment

Meep,

 

Is there anyway you can make this ramp per second (BoostLed code is per minute) so that it smooths out the ramping of the lights. Do you know what i mean?

Link to comment

Meep,

 

Is there anyway you can make this ramp per second (BoostLed code is per minute) so that it smooths out the ramping of the lights. Do you know what i mean?

Not really, sorry. The bell curve equation would need to be adapted for seconds instead of minutes.

I can post it up here.

 

dim = maxdim-((maxdim-mindim)/b^(x^2))
b = maxdim^(1/(cycletime^2))
That's for dawn only. Dusk is a little different.
Or, in simplified terms,
D is dim,
k is constant,
m is maxmimum level,
n is minimum level,
c is the time of the cycle (in minutes),
x is the time since the start of the cycle (in minutes).
D = m-((m-n)/k^(x^2))
k = m^(1/(c^2)
I will try swapping it out for seconds. Hold on a few minutes.
Link to comment
  • 1 month later...

What all changes did you make?

See post #1.

 

Nothing to do while I wait for another DS1302, so it's time to start looking at the Boostled Typhon code. I'm thinking half-hour by half-hour control.

I'll post any updates here.

 

Updated 10/12/13.

Features:

-Bell curve option instead of straight line

-0-255 dimming steps

-Calculations each second

-5 dimming settings per channel, plus bell curve option

-Lighting test to preview different mixes of power

-Acclimation mode from 0~30 days

  • Like 1
Link to comment

MeepNand, i cannot open the file here at work =P so can't see the program. Did you incorporate the lighting mode into the typhon program?

 

Is there anyone who has done this alredy that could give the code for it?

  • Like 1
Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recommended Discussions

×
×
  • Create New...