Snippet to use analog pin instead of digital for buttons

Hi

I have a working code that is for a diy led that is used for reef tanks and it uses 4 discreet buttons.

I can make the board very simply using 1 ds1307, 1 Arduino uno, 1 lcd shield and a few relays.

The light is already purchased but I am having a hard time modifying the code to use A0 to read all the buttons instead of using the digital pin code included in the sketch.

1st question before things get harder. Can anyone suggest an easy way perhaps using a code snippet to substitute an analog value for a digital pin?

IE tell the Arduino digital pin 14 is actually A0, 1023

digital pin 15 is actually A0, <50 etc

Really hoping the answer is yes because I have attempted to re code it, I am a beginner and my buttons seem to overlap so they all seem to select instead of increasing, decreasing values etc.

Will post the code and ask a new question if the answer is no.

Thanks in advance

Steve

Not without knowing how you have the 4 switches setup in regards to the arduino. And how they together create an analog voltage. Schematic please.

Sorry that would make it easier wouldn’t it

I am using a DFRobot lcd shield. The 6 buttons are connected to A0 and the screen is connected as per the attachment.

The only other thing connected is a DS1307 connected to A4, A5,gnd and 5v

It does indeed help if we know what thing we are talking about. Is this the lcd shield in question?

http://www.dfrobot.com/index.php?route= … duct_id=51

If so, then the code in this Wiki page suggests that there are 2 board versions requiring different threshold levels for the buttons. The code you use may differ from the ratios of the resistor values (see schematic) on your particular board version. Try to narrow down which board version applies to you.

Wiki:

http://www.dfrobot.com/wiki/index.php/L … U:_DFR0009

Schematic.

http://www.dfrobot.com/image/data/DFR00 … %20SCH.pdf

[EDIT] I have NO idea which example code you are using now. Or what it does with a digital pin input. Again, you will have to clarify what you have at this point in terms of code. Either link to it, or post it here (inside [ /code] blocks).

yes mine seem to be the v1 threshold values

if (adc_key_in < 50)   return btnRIGHT;  
 if (adc_key_in < 195)  return btnUP; 
 if (adc_key_in < 380)  return btnDOWN; 
 if (adc_key_in < 555)  return btnLEFT; 
 if (adc_key_in < 790)  return btnSELECT;

Running the following code

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 13, 4, 5, 6, 7);
int a=0;
int bkl         = 6; 
        
byte bklIdle    = 10;       
byte bklOn      = 100;       
int bklDelay    = 10000;   
unsigned long bklTime = 0;


void setup()
{
  pinMode(bkl, OUTPUT);
  digitalWrite(bkl, HIGH);

lcd.begin(16, 2);

pinMode(A0, INPUT);

}
void loop()
{
a = analogRead(0);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("  analogRead() ");
lcd.setCursor(0,1);
lcd.print("  value is :");
lcd.print(a);
delay(250);
}

(I think. Have uploaded a lot of sketches trying to get this working but the sketch I used worked and provided me with the following values)

My measured values were

btnNONE 1023

btnRIGHT 0

btnUP 100

btnDOWN 257

btnSELECT 643

btnLEFT 409

Please note the EDIT I added. I’m still lost on what you need with the digital input (or output?) pins.

Okay

I never wrote either of these but I am trying to get the second one working.

The first code is the working one that uses digital buttons

//Typhon Arduino Sketch
//Typhon LED controller Arduino Sketch

/*
// 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 <LiquidCrystal.h>
#include <Wire.h>
#include <EEPROM.h>
#include <EEPROMVar.h>
#include <Button.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 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 millisecond

int 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(&minus)) {
       overpercent--;
       bklTime = millis();
     }
   }
 }
 
//invert PWM 
//Modified by NetSurge
/* Moved to Main Menu and not in Overide Menu

if(menuSelect == 4){
  if(inverted == true)
 lcd.print("PWM Inverted:YES ");
  if(inverted == false)
 lcd.print("PWM Inverted:NO ");
 if (checkButtonAction(&minus) || 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(&minus)) {
     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(&minus)) {
   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(&minus)) {
     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(&minus)) {
     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(&minus) || 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(&minus)) {
   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(&minus)) {
   if (*minute > 0) {
     (*minute)--;
   } 
  else {
     *minute = 59;
   }
   bklTime = millis();
 }
 setDate(second, *minute, hour, dayOfWeek, dayOfMonth, month, year);
}

The second one has been modified but not to a working state. At least I cannot make it work. It seems to only reference 2 buttons and 1 instance of a 3rd whereas the original code uses 4 buttons.

The code compiles and uploads correctly however the buttons seem to overlap because they all act to increment through the menus and sometimes randomly increase or decrease the values but not consistently.

I understand the usage of the adc code etc but cannot work out an easier method of altering the first code due to the use of the button library and variables such as unique press.

/*
// 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 <EEPROM.h>
#include <EEPROMVar.h>


/**** Define Variables & Constants ****/
/**************************************/

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

// create the LCD
LiquidCrystal lcd(12, 13, 4, 5, 6, 7);
// define some values used by the panel and buttons
int lcd_key     = 0;
int adc_key_in  = 0;
int key=-1;
int oldkey=-1;
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

int read_LCD_buttons(){               // read the buttons
    adc_key_in = analogRead(0);       // read the value from the sensor 

    // my buttons when read are centered at these valies: 0, 144, 329, 504, 741
    // we add approx 50 to those values and check to see if we are close
    // We make this the 1st option for speed reasons since it will be the most likely result

    if (adc_key_in > 1000) return btnNONE; 

    // For V1.1 us this threshold
   /*
    if (adc_key_in < 50)   return btnRIGHT;  
    if (adc_key_in < 250)  return btnUP; 
    if (adc_key_in < 450)  return btnDOWN; 
    if (adc_key_in < 650)  return btnLEFT; 
    if (adc_key_in < 850)  return btnSELECT;  
*/
   // For V1.0 comment the other threshold and use the one below:
   
     if (adc_key_in < 50)   return btnRIGHT;  
     if (adc_key_in < 195)  return btnUP; 
     if (adc_key_in < 380)  return btnDOWN; 
     if (adc_key_in < 555)  return btnLEFT; 
     if (adc_key_in < 790)  return btnSELECT;   
   

    return btnNONE;                // when all others fail, return this.
}
// set up backlight
int bkl         = 6;        // backlight pin
byte bklIdle    = 50;       // PWM value for backlight at idle
byte bklOn      = 200;       // 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;

// 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 4

int 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.write(0);
   Wire.write(decToBcd(second));
   Wire.write(decToBcd(minute));
   Wire.write(decToBcd(hour));
   Wire.write(decToBcd(dayOfWeek));
   Wire.write(decToBcd(dayOfMonth));
   Wire.write(decToBcd(month));
   Wire.write(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.write(0);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
  *second     = bcdToDec(Wire.read() & 0x7f);
  *minute     = bcdToDec(Wire.read());
  *hour       = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek  = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month      = bcdToDec(Wire.read());
  *year       = bcdToDec(Wire.read());
}

/****** 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
            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;
 
 
       
 
  //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
  read_LCD_buttons();
  if (adc_key_in <380){
    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: ");
    read_LCD_buttons();
    if (adc_key_in < 555){
      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 (adc_key_in < 195 && overpercent <100)
        {
          overpercent++;
          delay(btnCurrDelay(btnCurrIteration-1));
          bklTime = millis();
        }
       read_LCD_buttons();
        if (adc_key_in < 380 && 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);
   read_LCD_buttons();
    if (adc_key_in < 195 && oneStartMins < 1440){
        oneStartMins++;
        if(onePhotoPeriod >0){onePhotoPeriod--;}
        else{onePhotoPeriod=1439;}
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    read_LCD_buttons();
    if (adc_key_in < 380 && 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);
    read_LCD_buttons();
    if (adc_key_in < 195){
      if(onePhotoPeriod < 1439){
      onePhotoPeriod++;}
      else{
        onePhotoPeriod=0;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    read_LCD_buttons();
    if (adc_key_in < 380){
      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);
    read_LCD_buttons();
    if (adc_key_in < 195 && (oneFadeDuration < onePhotoPeriod/2 || oneFadeDuration == 0)){
      oneFadeDuration++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    read_LCD_buttons();
    if (adc_key_in < 380 && 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("  ");
    read_LCD_buttons();
    if (adc_key_in < 195 && oneMax < 100){
      oneMax++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    read_LCD_buttons();
    if (adc_key_in < 380 && 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);
    read_LCD_buttons();
    if (adc_key_in < 195 && twoStartMins < 1440){
        twoStartMins++;
        if(twoPhotoPeriod >0){twoPhotoPeriod--;}
        else{twoPhotoPeriod=1439;}
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    read_LCD_buttons();
    if (adc_key_in < 380 && 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);
    read_LCD_buttons();
    if (adc_key_in < 195){
      if(twoPhotoPeriod < 1439){
      twoPhotoPeriod++;}
      else{
        twoPhotoPeriod=0;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    read_LCD_buttons();
    if (adc_key_in < 380){
      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);
    read_LCD_buttons();
    if (adc_key_in < 195 && (twoFadeDuration < twoPhotoPeriod/2 || twoFadeDuration == 0)){
      twoFadeDuration++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    read_LCD_buttons();
    if (adc_key_in < 380 && 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("  ");
    read_LCD_buttons();
    if (adc_key_in < 195 && twoMax < 100){
      twoMax++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    read_LCD_buttons();
    if (adc_key_in < 380 && 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);
    read_LCD_buttons();
    if (adc_key_in < 195 && threeStartMins < 1440){
        threeStartMins++;
        if(threePhotoPeriod >0){threePhotoPeriod--;}
        else{threePhotoPeriod=1439;}
        delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    read_LCD_buttons();
    if (adc_key_in < 380 && 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);
    read_LCD_buttons();
    if (adc_key_in < 195){
      if(threePhotoPeriod < 1439){
      threePhotoPeriod++;}
      else{
        threePhotoPeriod=0;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    read_LCD_buttons();
    if (adc_key_in < 380){
      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);
    read_LCD_buttons();
    if (adc_key_in < 195 && (threeFadeDuration < threePhotoPeriod/2 || threeFadeDuration == 0)){
      threeFadeDuration++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    read_LCD_buttons();
    if (adc_key_in < 380 && 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("  ");
    read_LCD_buttons();
    if (adc_key_in < 195 && threeMax < 100){
      threeMax++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    read_LCD_buttons();
    if (adc_key_in < 380 && 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);
    read_LCD_buttons();
    if (adc_key_in < 195 && fourStartMins < 1440){
        fourStartMins++;
        if(fourPhotoPeriod >0){fourPhotoPeriod--;}
        else{fourPhotoPeriod=1439;}
        delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    read_LCD_buttons();
    if (adc_key_in < 380 && 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);
    read_LCD_buttons();
    if (adc_key_in < 195){
      if(fourPhotoPeriod < 1439){
      fourPhotoPeriod++;}
      else{
        fourPhotoPeriod=0;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    read_LCD_buttons();
    if (adc_key_in < 380){
      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);
    read_LCD_buttons();
    if (adc_key_in < 195 && (fourFadeDuration < fourPhotoPeriod/2 || fourFadeDuration == 0)){
      fourFadeDuration++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    read_LCD_buttons();
    if (adc_key_in < 380 && 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("   ");
    read_LCD_buttons();
    if (adc_key_in < 195 && fourMax < 100){
      fourMax++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    read_LCD_buttons();
    if (adc_key_in < 380 && 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);
    read_LCD_buttons();
    if (adc_key_in < 195 && hour < 23){
      hour++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    read_LCD_buttons();
    if (adc_key_in < 380 && 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);
    read_LCD_buttons();
    if (adc_key_in < 195 && minute < 59){
      minute++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    read_LCD_buttons();
    if (adc_key_in < 380 && minute > 0){
      minute--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  setDate(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
  }
}

/*Hide details

Change log
r20 by dwizum on Oct 15, 2011   Diff

[No log message]

Go to: 	
Project members, sign in to write a code review

Older revisions
r15 by ryanensminger on Nov 23, 2010   Diff
r14 by ryanensminger on Nov 23, 2010   Diff
r13 by ryanensminger on Nov 23, 2010   Diff
All revisions of this file

File info
Size: 23483 bytes, 830 lines
View raw file 
*/

I don’t see where the first one does change any digital inputs or outputs, asside from the backlight output pin. Or the 4 PWM pins used for manipulating some RGB ledstrips. PWM is technically speaking a digital output being only high or low at any instant, but depending on the driven actuator can appear to be partially on, or somewhere between 0 and 1. So, I still don’t understand what you are after with this digital pin stuff.

The second code one does have a snippet of code that looks like it is the read_LCD_button function from the Wiki example. But it doesn’t use it effectivly. It ignores the return value that the function can deliver based on the measurement and the value fitting in one of the ranges. At each point in the code where it checks a menu function it compares the adc_key_in variable to a hardcoded value. That is not the smart way to do it, as it is easy to overlook these places when correcting the values. Also, a number is less interpretive in its meaning than a descriptive named constant. The fact that it is not working for you may be because there might still be a buggy value somewhere not cooperating with your resistor values. The code is too long for me to dig through it in a short time.

Instead, one would check in the if-statements if the return value of read_LCD_button is equal to one of the defined constants btnRIGHT, btnUP, btnDOWN, btnLEFT, btnSELECT 4 or btnNONE. That is what the Wiki code is doing, albeit it is printing something to the LCD, and not change a digital pin or something.

...
 read_LCD_buttons();
    if (adc_key_in < 555){ //do whatever }  //compares variable adc_key_in to hardcoded value 
...

vs.

...

    if (read_LCD_buttons()==btnLEFT) { //do a lefty }   // compare read_LCD_buttons function result with constant
...

HOLD ON!!! That adc_key_in is defined globally with value 0. Only in the read_LCD_buttons is it declared again and filled with the ADC value. But that is only valid inside that function, and ceases to exist beyond it’s } bracket. So all conditional logic based on adc-key_in in that main loop-code compares the globally defined 0 to whatever other value (unless I missed it being re-assigned to some other value somewhere).

Ah. I see. I did change it as you suggested once but received an IO c++ comparator error I couldn’t work out. So shall I remove the global definitions at the top because I need the references to the adc values more? And the digital pin thing you cannot see that I am talking about is simply because I didn’t explain it well. Must have been tired but you are seeing what I want to do. Use 4 of the adc buttons instead of 4 discreet buttons for menu, select, plus and minus. It is not done very well in the second code at all because several functions have been deleted in order to make use of the analogread function

Change all

read_LCD_buttons();

statements to

adc_key_in= read_LCD_buttons();

OR

change all the if-statements to compare the read_LCD_buttons() function-return to a constant as suggested in my code window. The latter will improve your understanding of the code at a later stage. Learn early to make your code understandable for you and others. It will save many a headache later down the line. But the former might be easier, yet lack clarity because of the hardcoded values.

The adc_key_in can be left in, but it would not serve a purpose. In any event that it does get used somewhere else in the code then the compiler (the C++ language doesn’t know about comparators, that’s a hardware component inside the microcontroller :wink: will tell you via error messages during compiling. If you have problems with understanding errors them then copy them in a next post and we’ll see if we can figure it out. I’ll readily admit that they can be quite cryptic.

Okay I will go ahead and do that and see if I get any errors like I previously had. There are a few instances where you see this

if(menuCount == 2){
    //Manual Override Menu
    lcd.setCursor(0,0);
    lcd.print("Manual Overrides");
    lcd.setCursor(0,1);
    lcd.print("All: ");
    read_LCD_buttons();
    if (adc_key_in < 555){
      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 (adc_key_in < 195 && overpercent <100)
        {
          overpercent++;
          delay(btnCurrDelay(btnCurrIteration-1));
          bklTime = millis();
        }
       read_LCD_buttons();
        if (adc_key_in < 380 && overpercent > 0)
        {
          overpercent--;
          delay(btnCurrDelay(btnCurrIteration-1));
          bklTime = millis();
        }
      }
}

There is a read_LCD_buttons() call at the top, not one in the middle at the next if (adc_key_in statement then another read_LCD_buttons() call further down. I don’t understand how to alter the code like you said for the one in the middle

Wish I had seen that last edit about changing the read_LCD_buttons before I started :slight_smile: I edited the section I showed you. Using the values I gave in the top posts does this look correct so far?

if(menuCount == 2){
    //Manual Override Menu
    lcd.setCursor(0,0);
    lcd.print("Manual Overrides");
    lcd.setCursor(0,1);
    lcd.print("All: ");
    if (read_LCD_buttons()==btnSELECT){
      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 (read_LCD_buttons()==btnDOWN && overpercent <100)
        {
          overpercent++;
          delay(btnCurrDelay(btnCurrIteration-1));
          bklTime = millis();
        }
       if (read_LCD_buttons()==btnLEFT && overpercent > 0)
        {
          overpercent--;
          delay(btnCurrDelay(btnCurrIteration-1));
          bklTime = millis();
        }
      }
}

Dammit, I made a hasty edit on an edit because my initial suggestion wasn’t wrong after all and I was just silly thinking. And now you already responded also. This is starting to get complicated now. Sigh, early bedtime this evening.

Ok, that is starting to look good.

Except be careful of logical operator precedence. Encapsulate each individual comparison in parenthesis ()-brackets to force the execution the right way. Or else you might get the wrong parts of the entire logical statement evaluated out of order.

See at the end of the link:

http://www.cplusplus.com/doc/tutorial/operators/

if (read_LCD_buttons()==btnDOWN && overpercent <100)

would become

if ( (read_LCD_buttons()==btnDOWN) && (overpercent <100) )

And

if (read_LCD_buttons()==btnLEFT && overpercent > 0)
        {

would become

if  ( (read_LCD_buttons()==btnLEFT) &&  (overpercent > 0) )
        {

Okay. Thanks for your help.

I can already see there is a further error in this persons code because there is only btnLEFT and btnDOWN used in all these calls to read_LCD_buttons but I will get to that shortly.

Okay. Thanks to your help It is getting there.

I have altered the code because btnLEFT was decreasing values and btnDOWN was increasing them.

Still a little work to do. The select key is random. It doesn’t cycle through the menus in order, it skips from one to another. Perhaps due to not having any debounce?

the plus and minus also don’t have one so they often increase or decrease the amount by too much making it difficult to set.

It is useable as is but could be better.

Also I noted in the description of the original code it had a menu button also so I will have a read up and see what each function was used for.

Okay. I have debounced the analog buttons and gotten that working correctly.

Button functions are:

Menu-cycle through functions

Select-make changes within menu(seems to only be used in one menu at menu count=2)

plus-increase values

minus-decrease values

Plus and minus both work perfectly now and select(if it is only used on the one screen)

3 questions remaining.

  1. Can you have a look and make a suggestion on the debounce code please because although it works it is not good enough for the menu button because it keeps skipping menus.

  2. Is there a line in there to go straight back to the main screen which shows the current time and the ramp output of all 4 channels?

  3. The outputs are on digital pins 9,10,11 and 3 correct? I have 4 ldd’s 3 meanwell ldd-700h and 1 meanwell ldd-1000h not currently attached to any pins. They are 9-56v dc input attached to a coralux 4 up board. So 4 pins from the Arduino should go to 4 pwm pins on the ldd’s.

In setup the only output I can see is the backlight

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;
}
/*
// 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 <EEPROM.h>
#include <EEPROMVar.h>


/**** Define Variables & Constants ****/
/**************************************/

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

// create the LCD
LiquidCrystal lcd(12, 13, 4, 5, 6, 7);
// define some values used by the panel and buttons
int lcd_key     = 0;
int adc_key_in  = 0;
int adc_key_prev = 0;
int key=-1;
int oldkey=-1;
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

int read_LCD_buttons(){               // read the buttons
    adc_key_in = analogRead(0);       // read the value from the sensor 
    delay(10);
    int k=(analogRead(0) - adc_key_in);
    if (10 < abs(k)) return btnNONE;
    // my buttons when read are centered at these valies: 0, 144, 329, 504, 741
    // we add approx 50 to those values and check to see if we are close
    // We make this the 1st option for speed reasons since it will be the most likely result

    if (adc_key_in > 1000) return btnNONE; 

    // For V1.1 us this threshold
   /*
    if (adc_key_in < 50)   return btnRIGHT;  
    if (adc_key_in < 250)  return btnUP; 
    if (adc_key_in < 450)  return btnDOWN; 
    if (adc_key_in < 650)  return btnLEFT; 
    if (adc_key_in < 850)  return btnSELECT;  
*/
   // For V1.0 comment the other threshold and use the one below:
   
     if (adc_key_in < 50)   return btnRIGHT;  
     if (adc_key_in < 195)  return btnUP; 
     if (adc_key_in < 380)  return btnDOWN; 
     if (adc_key_in < 555)  return btnLEFT; 
     if (adc_key_in < 790)  return btnSELECT;   
   

    return btnNONE;                // when all others fail, return this.
}
// set up backlight
int bkl         = 6;        // backlight pin
byte bklIdle    = 50;       // PWM value for backlight at idle
byte bklOn      = 200;       // 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;

// 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 4

int 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.write(0);
   Wire.write(decToBcd(second));
   Wire.write(decToBcd(minute));
   Wire.write(decToBcd(hour));
   Wire.write(decToBcd(dayOfWeek));
   Wire.write(decToBcd(dayOfMonth));
   Wire.write(decToBcd(month));
   Wire.write(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.write(0);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
  *second     = bcdToDec(Wire.read() & 0x7f);
  *minute     = bcdToDec(Wire.read());
  *hour       = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek  = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month      = bcdToDec(Wire.read());
  *year       = bcdToDec(Wire.read());
}

/****** 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
            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;
 
 adc_key_prev = lcd_key ;       // Looking for changes
  lcd_key = read_LCD_buttons();  // read the buttons

  if (adc_key_prev != lcd_key)
       
 
  //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 (read_LCD_buttons()==btnSELECT){
    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 (read_LCD_buttons()==btnLEFT){
      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 ((read_LCD_buttons()==btnUP) && (overpercent <100))
        {
          overpercent++;
          delay(btnCurrDelay(btnCurrIteration-1));
          bklTime = millis();
        }
       if ((read_LCD_buttons()==btnDOWN) && (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 ((read_LCD_buttons()==btnUP) && (oneStartMins < 1440)){
        oneStartMins++;
        if(onePhotoPeriod >0){onePhotoPeriod--;}
        else{onePhotoPeriod=1439;}
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if ((read_LCD_buttons()==btnDOWN) && (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 (read_LCD_buttons()==btnUP){
      if(onePhotoPeriod < 1439){
      onePhotoPeriod++;}
      else{
        onePhotoPeriod=0;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if (read_LCD_buttons()==btnDOWN){
      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 ((read_LCD_buttons()==btnUP) && (oneFadeDuration < onePhotoPeriod/2 || oneFadeDuration == 0)){
      oneFadeDuration++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if ((read_LCD_buttons()==btnDOWN) && (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 ((read_LCD_buttons()==btnUP) && (oneMax < 100)){
      oneMax++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if ((read_LCD_buttons()==btnDOWN) && (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 ((read_LCD_buttons()==btnUP) && (twoStartMins < 1440)){
        twoStartMins++;
        if(twoPhotoPeriod >0){twoPhotoPeriod--;}
        else{twoPhotoPeriod=1439;}
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if ((read_LCD_buttons()==btnDOWN) && (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 (read_LCD_buttons()==btnUP){
      if(twoPhotoPeriod < 1439){
      twoPhotoPeriod++;}
      else{
        twoPhotoPeriod=0;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if (read_LCD_buttons()==btnDOWN){
      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 ((read_LCD_buttons()==btnUP) && (twoFadeDuration < twoPhotoPeriod/2 || twoFadeDuration == 0)){
      twoFadeDuration++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if ((read_LCD_buttons()==btnDOWN) && (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 ((read_LCD_buttons()==btnUP) && (twoMax < 100)){
      twoMax++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if ((read_LCD_buttons()==btnDOWN) && (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 ((read_LCD_buttons()==btnUP) && (threeStartMins < 1440)){
        threeStartMins++;
        if(threePhotoPeriod >0){threePhotoPeriod--;}
        else{threePhotoPeriod=1439;}
        delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if ((read_LCD_buttons()==btnDOWN) && (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 (read_LCD_buttons()==btnUP){
      if(threePhotoPeriod < 1439){
      threePhotoPeriod++;}
      else{
        threePhotoPeriod=0;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if (read_LCD_buttons()==btnDOWN){
      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 ((read_LCD_buttons()==btnUP) && (threeFadeDuration < threePhotoPeriod/2 || threeFadeDuration == 0)){
      threeFadeDuration++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if ((read_LCD_buttons()==btnDOWN) && (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 ((read_LCD_buttons()==btnUP) && (threeMax < 100)){
      threeMax++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if ((read_LCD_buttons()==btnDOWN) && (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 ((read_LCD_buttons()==btnUP) && (fourStartMins < 1440)){
        fourStartMins++;
        if(fourPhotoPeriod >0){fourPhotoPeriod--;}
        else{fourPhotoPeriod=1439;}
        delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if ((read_LCD_buttons()==btnDOWN) && (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 (read_LCD_buttons()==btnUP){
      if(fourPhotoPeriod < 1439){
      fourPhotoPeriod++;}
      else{
        fourPhotoPeriod=0;
      }
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if (read_LCD_buttons()==btnDOWN){
      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 ((read_LCD_buttons()==btnUP) && (fourFadeDuration < fourPhotoPeriod/2 || fourFadeDuration == 0)){
      fourFadeDuration++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if ((read_LCD_buttons()==btnDOWN) && (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 ((read_LCD_buttons()==btnUP) && (fourMax < 100)){
      fourMax++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if ((read_LCD_buttons()==btnDOWN) && (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 ((read_LCD_buttons()==btnUP) && (hour < 23)){
      hour++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if ((read_LCD_buttons()==btnDOWN) && (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 ((read_LCD_buttons()==btnUP) && (minute < 59)){
      minute++;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
    if ((read_LCD_buttons()==btnDOWN) && (minute > 0)){
      minute--;
      delay(btnCurrDelay(btnCurrIteration-1));
      bklTime = millis();
    }
  setDate(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
  }
}

/*Hide details

Change log
r20 by dwizum on Oct 15, 2011   Diff

[No log message]

Go to: 	
Project members, sign in to write a code review

Older revisions
r15 by ryanensminger on Nov 23, 2010   Diff
r14 by ryanensminger on Nov 23, 2010   Diff
r13 by ryanensminger on Nov 23, 2010   Diff
All revisions of this file

File info
Size: 23483 bytes, 830 lines
View raw file 
*/

1: As the schematic of the LCD shield has no capacitor to ground on the analog pin to filter out bouncing I would consider that the first mod to make. Much easier than implementing a software debounce which needs to play nice all over the rest of the code. (I have a small robot “Asuro” that has a similar switch solution using a 4.7 nF capacitor to filter bouncing. But it uses resistors with upwards powers of 2 (k) in a parallel fashion, instead of series as in this shield. And yours has much lower values. So you may have to experiment with the value to get the right timeconstant.)

2: I’m sorry, I don’t have the time to dig that deep into the code.

3: All pins with PWM functionality should have a tilde character printed on the board. So, yes, those numbers on the Arduino Uno should be ok.

There is the function setLed which performs the analogWrite function to change the PWM of a specific ledPin. Additionally there is the function ovrSetAll which sets all 4 LED PWM outputs to the same level with analogWrite. I think the analogWrite function takes care out setting the pin to output mode. (if it is even needed) So you do not have to do that in Setup. Atleast I’ve never come across a sketch where it is done.

Thanks Valen

Appreciate the help in getting it working

Consider this one solved.