Arduino programmers

Reef Aquarium & Tank Building Forum

Help Support Reef Aquarium & Tank Building Forum:

By your description this must be the same sketch we have been running except we have the control buttons on the board. I'm glad you got it all sorted out. Who knew we had to be structural engineers, chemists, biologists, electricians, wood/acrylic/glass workers and computer programmers to run a reef tank.

I'll post it Cesar. This program is so much better than the older two channel. One obvious reason is that it has four channels instead of two.
The older one ramped up in ten percent increments (which was very noticeable) and this does one percent. This one also works better for the fading in and out. Right now I have channel one set to come on at 8:00 with a half hour ramp up, channel two at 8:30 with a one hour ramp up and channel three at 9:00 with a one hour ramp up. Channel four comes on at one-o-clock with a half hour ramp up to 100% for only three hours at full power. A full duration of four hours.

The one thing that had me confused about this program as opposed to the old one is that the max duration is the total light cycle including the ramp up and down phase. The old sketch kept the all three lighting cycles separate. Ramp up, max percentage, then ramp down.

Anyway, here is the new sketch. FWIW the values are set for my lights to be on from 8AM until 9PM with a max value of 70%


PHP:
/*
// Typhon firmware
// v0.2 alpha 2010-23-11
// N. Enders, R. Ensminger
// v0.9 alpha 2010-25-02
// Revised by B. Duthie
// This sketch provides firmware for the Typhon LED controller.
// It provides a structure to fade MAX_CHANNELS independent channels of LED lighting
// on and off each day, to simulate sunrise and sunset.
//
// Requires LiquidCrystal, Wire, EEPROM, EEPROMVar libraries.
// EEPROMVar is available here: http://www.arduino.cc/playground/uploads/Profiles/EEPROMVar_01.zip
//
// 02/12/12 to support leds, without use of buttons
*/

// include the libraries:
#include <LiquidCrystal.h>
#include <Wire.h>
#include <EEPROM.h>
#include <EEPROMVar.h>


/**** Define Variables & Constants ****/
/**************************************/
// printing to Serial if debugging
#define DEBUG_ON                       // General debugging
//#define DEBUG_LED                      // LED Fade

// ONLY INCLUDE THIS IF YOU ARE CHANGING VALUES STORED IN EEPROM
//#define RESET_EEPROM

// set the RTC's I2C address
#define DS1307_I2C_ADDRESS 0x68

// create the LCD
//LiquidCrystal lcd(8,  7, 5, 4, 16, 2); // Typhon
//int bkl         = 6;        // backlight pin
LiquidCrystal lcd(12, 8, 7, 6,  5, 4, 2); // Duanes
int bkl         = 13;        // backlight pin

//create manual override variables
int overSelect = 0; // allow the override menu to remember its current setting
                    // 0 = Timer, 1 = All On, 2 = All Off, 3 = % Value
int overPercent = 0;

// setting of 60, with internal delays, 0-100 percent takes about 15 seconds (per channel)
int rampDelayUp = 120; 
int rampDelayDn = 60;

// Variables making use of EEPROM memory:
EEPROMVar<int> oneStartMins = 480;     // minute to start this channel.
EEPROMVar<int> onePhotoPeriod = 780;   // photoperiod in minutes for this channel.
EEPROMVar<int> oneMin = 0;             // min intensity for this channel, as a percentage
EEPROMVar<int> oneMax = 70;           // max intensity for this channel, as a percentage
EEPROMVar<int> oneFadeDuration = 30;   // duration of the fade on and off for sunrise and sunset
                                       
EEPROMVar<int> twoStartMins = 510;
EEPROMVar<int> twoPhotoPeriod = 720;
EEPROMVar<int> twoMin = 0;             // min intensity for this channel, as a percentage
EEPROMVar<int> twoMax = 700;
EEPROMVar<int> twoFadeDuration = 60;

EEPROMVar<int> threeStartMins = 540;
EEPROMVar<int> threePhotoPeriod = 660;
EEPROMVar<int> threeMin = 0;             // min intensity for this channel, as a percentage
EEPROMVar<int> threeMax = 170;
EEPROMVar<int> threeFadeDuration = 60;
                            
EEPROMVar<int> fourStartMins = 720;
EEPROMVar<int> fourPhotoPeriod = 240;  
EEPROMVar<int> fourMin = 0;             // min intensity for this channel, as a percentage
EEPROMVar<int> fourMax = 100;          
EEPROMVar<int> fourFadeDuration = 60;  

// descriptions need to be 4 characters due to display area
char* oneDesc = "BR  ";
char* twoDesc = "RB  ";
char* threeDesc = "CW  ";
char* fourDesc = "NW";

#define MAX_CHANNELS 4

typedef struct {
  char* Desc;         // Channel Description
  int Led;            // channel pin
  int StartMins;      // minute to start this channel.
  int PhotoPeriod;    // photoperiod in minutes for this channel.
  int ledMin;            // min intensity for this channel, as a percentage
  int ledMax;            // max intensity for this channel, as a percentage
  int ledVal;            // current intensity for this channel, as a percentage
  int FadeDuration;   // duration of the fade on and off for sunrise and sunset for this channel.
  int RampDelay;
} channelVals_t;

channelVals_t channel[MAX_CHANNELS];
// freeMemory returns the amount of available memory for variables
extern unsigned int __bss_end;
extern unsigned int __heap_start;
extern void *__brkval;

int freeMemory() {
  int free_memory;

  if((int)__brkval == 0)
     free_memory = ((int)&free_memory) - ((int)&__bss_end);
  else
    free_memory = ((int)&free_memory) - ((int)__brkval);

  return free_memory;
}

/****** RTC Functions ******/
/***************************/

// Convert decimal numbers to binary coded decimal
uint8_t decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to decimal numbers
uint8_t 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((uint8_t)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((uint8_t)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());
}

/** Menu Control Functions **/
void showMainMenu () {
  Serial.println("");
  Serial.println("LED Control Actions");
  Serial.println("L+   All Max");
  Serial.println("L-   All Min");
  Serial.println("Lnnn All nnn%");
  Serial.println("LT   Timer Mode");
  Serial.println("");
}

int parseMenuCommand () {
    int command;
    int value = 0;
    int pct = 0;
    command = Serial.read();
    switch (command) {
      case 'l':
      case 'L':
        if (Serial.available() > 0) {
          value = Serial.read();
          if (value == 't' || value == 'T') {
            overSelect = 0;
            Serial.println("Setting Timer Mode");
          }
          if (value == '+') {
            overSelect = 1;
            Serial.println("All Max");
          } 
          if (value == '-') {
            overSelect = 2;
            Serial.println("All Min");
          }
          if (value >= '0' && value <= '9') {
            pct = value - '0';
            while (Serial.available() > 0) {
              value = Serial.read();
              if (value >= '0' && value <= '9') 
                pct = pct * 10 + value - '0';
              else
                break;
            }
            if (overPercent <= 100) {
              overSelect = 3;
              overPercent = pct;
              Serial.print("Setting ");
              Serial.print(overPercent);
              Serial.println("%");
            }
          }
        }
        else {  // unrecognized command
        }
    }
    Serial.flush(); // remove all incoming data 
    return (0);
}

/****** 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 c        // current channel
            )  {
   // channel values, just to make code read a little easier
    int ledPin = channel[c].Led;           // pin for this channel of LEDs
    int start  = channel[c].StartMins;     // start time for this channel of LEDs
    int period = channel[c].PhotoPeriod;   // photoperiod for this channel of LEDs
    int fade   = channel[c].FadeDuration;  // fade duration for this channel of LEDs
    int ledMin = channel[c].ledMin;           // min value for this channel
    int ledMax = channel[c].ledMax;           // max value for this channel
    int ledVal = channel[c].ledVal;           // current value for this channel
    
    int val = ledMin;   // start with the assumption that this channel is off
    int pinVal;
    
      // adjust for midnite rollover
     if (mins < start && start + period > 1439 && mins <= (start + period) % 1440)
        mins += 1440;

      //fade up or currently on or currently off
      if (mins >= start)  {
        if (mins - start <= fade) { // fading up
          val = map(mins - start, 0, fade, ledMin, ledMax);
          }
        else if (mins < start + (period - fade)) { // on
          val = ledMax;
          }
        else if (mins > start + period) { // off - nothing to do, but print debug info
          }
      }
      //fade down
      if (mins >= start + period - fade && mins <= start + period)  {
        val = map(mins - (start + period - fade), 0, fade, ledMax, ledMin);
        }
     // if All On = use ledMax, All Off = use ledMin, otherwise use set percent
     switch(overSelect){
        case 1: // All On
          val = ledMax;
          break;
        case 2: // All Off
          val = ledMin;
          break;
        case 3: // specific percent
          val = overPercent;
          break;
     }

// Ramp Up/Down slowly -- do nothing if no change
// This will also impact setting of the override % value, and all on/off options
  if (channel[c].RampDelay > 0)  // avoid using delay() in loop()
     --channel[c].RampDelay;
  if (channel[c].RampDelay == 0 && val < ledVal) {
    --ledVal;
    channel[c].RampDelay = rampDelayDn;
  }
  if (channel[c].RampDelay == 0 && val > ledVal) {
    ++ledVal;
    channel[c].RampDelay = rampDelayUp;
  }
  if (ledVal != channel[c].ledVal) {
    // ledVal is the percentage (0-100) to set for this channel
    // pinVal is the value (0-255) to set for the Arduino PWM pin
    // comment out the line you don't want to use, or create your own
//    pinVal = map(ledVal, 0, 100, 0, 255);          // normal linear value for PWM
    pinVal = min(255, (pow(2, ledVal/10.0) + 2.99) / 4.0);  // value for Meanwell "D"
    analogWrite(ledPin, pinVal); 
  }
    
#ifdef DEBUG_LED
if (ledVal != channel[c].ledVal) {
      if (start + period > 1440) 
        Serial.println("Midnite rollover ");
      Serial.print("mins =");
      Serial.print(mins);
      Serial.print(", ");
      Serial.print(channel[c].Desc);
      Serial.print(", start = ");
      Serial.print(start);
      Serial.print(", period = ");
      Serial.print(period);
      Serial.print(", fade = ");
      Serial.print(fade);
      Serial.print(", min = ");
      Serial.print(ledMin);
      Serial.print(", max = ");
      Serial.print(ledMax);
     if(overSelect){
        Serial.print(", overSelect: ");
        Serial.print(val);
        }
  Serial.print(", ledVal = ");
  Serial.print(ledVal);
  Serial.print(", PWM = ");
  Serial.print(map(ledVal, 0, 100, 0, 255), DEC);
  Serial.print(", pin = ");
  Serial.println(pinVal, DEC);
}
#endif
    
  return ledVal;
}

/**** Display Functions ****/

void printMDY (byte mm, byte dd, byte yy)
{   if(mm<10){
      lcd.print(" ");
    }
    lcd.print(mm, DEC);
    lcd.print("/");
    if(dd<10){
      lcd.print(" ");
    }
    lcd.print(dd, DEC);
    lcd.print("/");
    if(yy<10){
      lcd.print("0");
    }
    lcd.print(2000 + yy, DEC);

}
void printDay (byte dday)
    {
      char* daynames[8] = {"???","Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
      lcd.print(daynames[dday%8]);
    }

// format a number of minutes into a readable time (24 hr format)
void showMins(int mins,       //time in minutes to print
               boolean ampm = false   //print am/pm? - future implementation (or not)
              )  {
  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 showHMS (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);
}

/**** Setup ****/
/***************/

void setup() {
#ifdef RESET_EEPROM
 oneStartMins = 480;     // minute to start this channel.
 onePhotoPeriod = 780;   // photoperiod in minutes for this channel.
 oneMin = 0;             // min intensity for this channel, as a percentage
 oneMax = 70;           // max intensity for this channel, as a percentage
 oneFadeDuration = 30;   // duration of the fade on and off for sunrise and sunset for
                                       //    this channel.
 twoStartMins = 510;
 twoPhotoPeriod = 720;
 twoMin = 0;             // min intensity for this channel, as a percentage
 twoMax = 70;
 twoFadeDuration = 60;

 threeStartMins = 540;
 threePhotoPeriod = 660;
 threeMin = 0;             // min intensity for this channel, as a percentage
 threeMax = 70;
 threeFadeDuration = 60;
                            
 fourStartMins = 720;
 fourPhotoPeriod = 600;  
 fourMin = 0;             // min intensity for this channel, as a percentage
 fourMax = 100;          
 fourFadeDuration = 30;  
 #endif
 
  // Initialize channel variables. Set LED channel pin and retrieve values from EEPROM
  channel[0].Desc = oneDesc;
  channel[0].Led = 11;
  channel[0].StartMins = oneStartMins;
  channel[0].PhotoPeriod = 780;   // onePhotoPeriod;
  channel[0].ledMin = oneMin;
  channel[0].ledMax = oneMax;
  channel[0].ledVal = 0;
  channel[0].FadeDuration = oneFadeDuration;

  channel[1].Desc = twoDesc;
  channel[1].Led = 10;
  channel[1].StartMins = twoStartMins;
  channel[1].PhotoPeriod = 720;   //twoPhotoPeriod;
  channel[1].ledMin = twoMin;
  channel[1].ledMax = twoMax;
  channel[1].ledVal = 0;
  channel[1].FadeDuration = twoFadeDuration;

  channel[2].Desc = threeDesc;
  channel[2].Led = 9;
  channel[2].StartMins = threeStartMins;
  channel[2].PhotoPeriod = 660;  //threePhotoPeriod;
  channel[2].ledMin = threeMin;
  channel[2].ledMax = threeMax;
  channel[2].ledVal = 0;
  channel[2].FadeDuration = threeFadeDuration;

  channel[3].Desc = fourDesc;
  channel[3].Led = 3;
  channel[3].StartMins = fourStartMins;
  channel[3].PhotoPeriod = fourPhotoPeriod;
  channel[3].ledMin = fourMin;
  channel[3].ledMax = fourMax;
  channel[3].ledVal = 0;
  channel[3].FadeDuration = fourFadeDuration;

  Serial.begin(57600);
  Serial.println("Duanes-Reef");

for (int i = 0; i < MAX_CHANNELS; ++i) {
  Serial.print(channel[i].Desc);
  Serial.print(", Start: ");  
  Serial.print(channel[i].StartMins);
  Serial.print(", Period: ");  
  Serial.print(channel[i].PhotoPeriod);
  Serial.print(", Min: ");  
  Serial.print(channel[i].ledMin, DEC);
  Serial.print(", Max: ");  
  Serial.print(channel[i].ledMax, DEC);
  Serial.print(", Fade: ");  
  Serial.print(channel[i].FadeDuration);
  Serial.println();
}

  Wire.begin();
  pinMode(bkl, OUTPUT);    // backlight control for the lcd display
  lcd.begin(16, 2);
  digitalWrite(bkl, HIGH);
  lcd.print("Duanes-Reef");

  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  getDate(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  lcd.setCursor(0,1);
  printMDY(month, dayOfMonth, year);
  lcd.print(" - ");
  printDay(dayOfWeek);
  delay(5000);

  lcd.clear();
  
  updateEEPromVars();
  
  Serial.print("Free Memory = ");
  Serial.println(freeMemory());
  
  showMainMenu();
}

/***** Loop *****/
/****************/

void loop() {
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  int minCounter;
  
  getDate(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  minCounter = hour * 60 + minute;
  
  if (Serial.available() > 0) {
    parseMenuCommand();
    showMainMenu();
  }
  
  for (int i = 0; i < MAX_CHANNELS; i++) { //check & adjust 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;
    }
    
// set led outputs
      for (int i = 0; i < MAX_CHANNELS; i++)
        channel[i].ledVal = setLed(minCounter, i);
 
  
   doMainMenu(hour, minute, second);

}
    
void doMainMenu(byte hour,
                byte minute,
                byte second) {
  lcd.setCursor(0,0);
  showHMS(hour, minute, second);

  
// display the current intensity for each led channel
  showChannelValues();
  
//debugging function to use the select button to advance the timer by 1 minute
#ifdef DEBUG_ON
  if (0) {
    byte dayOfWeek, dayOfMonth, month, year;

    getDate(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
    ++minute;
    if (minute > 59) {
      minute = 0;
      ++hour;
      }
    if (hour > 23)
      hour = 0;
    setDate(second, minute+1, hour, dayOfWeek, dayOfMonth, month, year);
    delay(100);
    }
#endif DEBUG_ON
  }

void doOverride() {
  //Manual Override Menu
  lcd.setCursor(0,0);
  switch (overSelect){
    case 0:
      lcd.print("Control by Timer");
      break;
    case 1:
      lcd.print("LED: All Max ");
      break;
    case 2:
      lcd.print("LED: All Min ");
      break;
    case 3:
      lcd.print("All Set: ");
      if (overPercent < 10)
        lcd.print("  ");
      else if (overPercent < 100)
        lcd.print(" ");
      lcd.print(overPercent,DEC);
      lcd.print("%   ");
       break;
    default:
      overSelect = 0;
    }
//  showChannelValues(); // disabled so that changes only start after menu is selected again
} 

void showChannelValues() { // display the current intensity for each led channel
      lcd.setCursor(9,0);
      switch (overSelect) {
        case 0:
          lcd.print("Timer  ");
          break;
        case 1:
          lcd.print("All Max");
          break;
        case 2:
          lcd.print("All Min");
          break;
        case 3:
          lcd.print("All ");
          if (overPercent < 10)
            lcd.print(" ");
          lcd.print(overPercent);
          lcd.print("%");
          break;
        }
      
    lcd.setCursor(0,1);
    for (int i = 0; i < MAX_CHANNELS; i++) {
      lcd.print(" ");
      if (channel[i].ledVal < 10)
        lcd.print("  ");
      else if (channel[i].ledVal < 100)
        lcd.print(" ");
      lcd.print(channel[i].ledVal);
      }
}


// Actually needs to become a feature of the EEPromVar library -- later
// should just be a function of the assignment operators

void updateEEPromVars() {
  // Update EEProms with any values that may have changed
  // Only updates values that have changed
#ifdef DEBUG_ON
  Serial.println("Updating EEPromVars");
#endif
  if (channel[0].StartMins != oneStartMins) {
    oneStartMins = channel[0].StartMins;
  }
  if (channel[0].PhotoPeriod != onePhotoPeriod) {
    onePhotoPeriod = channel[0].PhotoPeriod;
  }
  if (channel[0].ledMin != oneMin) {
    oneMin = channel[0].ledMin;
  }
  if (channel[0].ledMax != oneMax) {
    oneMax = channel[0].ledMax;
  }
  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].ledMin != twoMin) {
    twoMax = channel[1].ledMax;
  }
  if (channel[1].ledMax != twoMax) {
    twoMax = channel[1].ledMax;
  }
  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].ledMin != threeMin) {
    threeMin = channel[2].ledMin;
  }
  if (channel[2].ledMax != threeMax) {
    threeMax = channel[2].ledMax;
  }
  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].ledMin != fourMin) {
    fourMin = channel[3].ledMin;
  }
  if (channel[3].ledMax != fourMax) {
    fourMax = channel[3].ledMax;
  }
  if (channel[3].FadeDuration != fourFadeDuration) {
    fourFadeDuration = channel[3].FadeDuration;
  }
}
 
By your description this must be the same sketch we have been running except we have the control buttons on the board. I'm glad you got it all sorted out. Who knew we had to be structural engineers, chemists, biologists, electricians, wood/acrylic/glass workers and computer programmers to run a reef tank.

Pretty much, In this sketch, there is code written into it to override the programming for a set temporary time from the computer instead of with the buttons. I just don't know how to use it yet.

Well, You dont have to be structural engineers, chemists, biologists, electricians, wood/acrylic/glass workers and computer programmers to run a reef tank, but it sure saves alot of money over hiring someone to do all of those things for you. :)
 
By your description this must be the same sketch we have been running except we have the control buttons on the board. I'm glad you got it all sorted out. Who knew we had to be structural engineers, chemists, biologists, electricians, wood/acrylic/glass workers and computer programmers to run a reef tank.

Haha, you are very right. And a good manipulator? We need to manipulate who ever so that they will let us have our reef hobby, and toys, and whatever. haha
 
I'm really glad to see you all getting some use from this code.
The current version supports changing the percentages for all the leds at once from the serial monitor.
all max
all min
all a set percentage from 0-100

I suppose I should also add a "demo" mode that will quickly cycle through an entire day.

I'm working on version 3, which will support changing the individual led settings on the fly:
start time
end time
fade duration
min percentage
max percentage

This sketch currently supports up to 4 channels by changing the value of MAX_CHANNELS.

A future version will be supported by my own implementation of an EEPROM manager, and till support any number of channels, with the only issue being how to display the current value of more than 4 channels.

A question for everyone using Arduinos -- would your prefer code build for the old 0022, or the new version 1.0?

Feel free to PM me with your answer.
 
Last edited:
Thanks for chiming in Brian. Rather than PMing or E-mailing you, I'll ask in public so everyone can get the answer.
What exactly do I need to type into the serial monitor to change the values? Ive tried a few things with no luck.
 
First thing, make sure your serial monitor is set to 57600, or change the serial.begin() in the sketch to match your serial monitor setting.

This code displays the available options:
void showMainMenu () {
Serial.println("");
Serial.println("LED Control Actions");
Serial.println("L+ All Max");
Serial.println("L- All Min");
Serial.println("Lnnn All nnn%");
Serial.println("LT Timer Mode");
Serial.println("");
}

L+<return/send> will set all leds to max setting
L-<return/send> will set all leds to min setting
L0<return/send> will set all leds to 0 percent
L100<return/send> will set all leds to 100 percent
LT<return/send> will return back to timer control mode

not elegant, but it works
 
what is serial monitor? stupid question. lol.

Not stupid IMO. I asked it yesterday.

Its a "pop up" window you can open that shows information that is being transfered between your computer and the arduino. Its on the right side of the green tool bar that contains the verify, save, open and transfer tool. Typically when I open it it only shows hieroglyphics. Brian explained that those are debugging codes.
 
what is serial monitor? stupid question. lol.
in the Arduino programming environment, it is the last icon in the menu bar.
clicking the icon will open a new window that "monitors" the serial port.
it is where any Serial.print() command will send its output.
uses the same cable you use to upload your sketch.

There are also many applications that will let you use the serial connection to your Arduino, without having to use the programming environment.

There are no "stupid" questions :doh:
 
Not stupid IMO. I asked it yesterday.

Its a "pop up" window you can open that shows information that is being transfered between your computer and the arduino. Its on the right side of the green tool bar that contains the verify, save, open and transfer tool. Typically when I open it it only shows hieroglyphics. Brian explained that those are debugging codes.

Those hieroglyphics just show that the communications rate don't match.

Your serial monitor setting needs to match the setting in the Serial.begin(xxxx) statement.

My stupid question - why does a post I sent at 8:47 have a time stamp of 11:47?
 
Last edited:
ok another question. On the first part of the sketch you defined the eeprom variables.... But later in the middle part of the sketch, you defined it again.... Does this mean that when you want to change the time when to start channel 1, you will have to define it in two places?

btw, thanks for the explanation on the monitor thingy.I kept wondering how to use that and what trido said... Its all rubbish.
 
ok another question. On the first part of the sketch you defined the eeprom variables.... But later in the middle part of the sketch, you defined it again.... Does this mean that when you want to change the time when to start channel 1, you will have to define it in two places?

The first part of the sketch, where the variables are defined like this:
EEPROMVar<int> oneStartMins = 480; // minute to start this channel.

This just establishes that the variable will be stored in EEPROM. The value assignment (= 480) just gives it something useful to use for the first time the sketch is used.
Those assignments could all actually be removed.
If you have never run the sketch on a specific Arduino, then these are the values that are used.

The second part of the sketch where the variables are "retrieved" from EEPROM as in:
channel[0].StartMins = oneStartMins;
channel[0].PhotoPeriod = 780; // onePhotoPeriod;
In this case, StartMins is being used from EEPROM, and PhotoPeriod is having a new value assigned to it.
Normally, the code for PhotoPeriod should be:
channel[0].PhotoPeriod = onePhotoPeriod;

What you should do to change the values, is to add a line:
#define RESET_EEPROM
right at the start of the setup() code
set the values you want, compile and run the sketch, remove the line, compile and then continue using the new sketch.

Hope that helps to explain what is happening.

I'll work on some changes to make this all clear in the next revision that includes the ability to change the values from the "monitor thingy".

In summary:
Add the #define RESET_EEPROM in setup()
Change the values in setup()
compile and run the sketch
remove the #define RESET_EEPROM in setup() by adding back in the // at the start of the line
compile and use the sketch

the start of setup() should look like this:
/**** Setup ****/
/***************/

void setup() {
//#define RESET_EEPROM // remove the // at the start of this line to change the EEPROM values
#ifdef RESET_EEPROM
oneStartMins = 480; // minute to start this channel.

I'm planning the revise the code to use my new EEPROM library, and that will make things much clearer.
 
Last edited:
Normally, the code for PhotoPeriod should be:
channel[0].PhotoPeriod = onePhotoPeriod;


Yes, there you go... this is how I understand it.... tnx...
 
Holy Cow... And here I thought programming computer game code for MAME was cazy stuff. Now I am going to have to learn to program the arduino. Must admit it looks somewhat the same as MAME programming. :lol:

THx for the awesome code and putting on here for everyone to see and enjoy. I think a lot of folks probably get scared when thinking of programming there own light controller.

Cheers,
Alex
 
First thing, make sure your serial monitor is set to 57600, or change the serial.begin() in the sketch to match your serial monitor setting.

This code displays the available options:
void showMainMenu () {
Serial.println("");
Serial.println("LED Control Actions");
Serial.println("L+ All Max");
Serial.println("L- All Min");
Serial.println("Lnnn All nnn%");
Serial.println("LT Timer Mode");
Serial.println("");
}

L+<return/send> will set all leds to max setting
L-<return/send> will set all leds to min setting
L0<return/send> will set all leds to 0 percent
L100<return/send> will set all leds to 100 percent
LT<return/send> will return back to timer control mode

not elegant, but it works
Sorry I missed this Brian. This is a very cool option. In my opinion its easier than buttons would be provided that the menu interface of the typhon is anything like my Neptune. I find that typing is far easier than pushing a series of buttons repetitively. Luck for me my tank is next to my computer. Even if it wasn't, I would still likely drag a laptop over to the tank if I wanted to play with my controller like I have done in the past.
 
On a side note, Trido. I checked your 210 build, and it was a fresh water discus tank. Does this mean you are back?
 
On a side note, Trido. I checked your 210 build, and it was a fresh water discus tank. Does this mean you are back?

LOL, yes. The 210 is still a planted discus tank but I have also had a little 30G reef with T-5s for a year. I recently upgraded to a 65G that was not being used.

I would change my sig but every time I try to intentionally do it I cant seem to figure out how to do it.

Here it is.

http://www.reeffrontiers.com/forums/f70/rebirth-65-a-63374/
 
Back
Top