Arduino as cycle timer with LCD?

Thread Starter

GRNDPNDR

Joined Mar 1, 2012
545
I've got a "small" project I'd like to start working on, but before I do I thought I would check with some more knowledgeable people to see if and how it could be done.

I'm in need of a cycle timer and I wanted to do the job with an arduino and an LCD.

The cycle timer part is easy enough, I already have some code that should work, but I'm not a programmer and I wanted something a little more "fancy".

I want to get an LCD display for the Arduino and be able to change the cycle times on the fly without having to reupload more code and essentially stopping the system while that's happening.

Being that I'm an Arduino n00b, I'm hoping some of you kind folk could assist me with this project.... OR point me to a similar off the shelf cycle timer with an LCD display, as I haven't been able to locate one yet.
 

elec_mech

Joined Nov 12, 2008
1,500
I'm not sure what a cycle timer is or what you're looking for exactly. If you're asking how to add an LCD to an Arduino with a minimum of programming and wiring, then I'd suggest a 1-wire serial LCD. Sparkfun sells a bunch here. eBay sells several varieties, but I'd avoid those as most are really I2C or SPI port expanders and still require a lot of programming to make work.
 

Thread Starter

GRNDPNDR

Joined Mar 1, 2012
545
I guess I should have specified what a cycle timer is instead of assuming everyone knows. It's a small timer that will activate a relay for a set amount of time and leave it off for a set amount of time.... so like 10 secs on, 3 minutes off.
http://www.amazon.com/CanaKit-UK670CY-Cyclic-Digital-Assembled/dp/B005UTBUDC

I bought this to play around with, http://www.dfrobot.com/index.php?route=product/product&path=35_124&product_id=51

so I'd like to slap that onto my arduino and program a cycle timer that will let me use the lcd shield to set on and off times without having to change the code, reupload and test the timing that way.
 

elec_mech

Joined Nov 12, 2008
1,500
Okay, I think I understand now. So you've written a cycle timer code, but the only way to change and run it is by manually changing and uploading the code each time, correct? So you want to use the LCD shield and buttons to set the time, and start/stop the timer. Is this correct?

I don't have much Arduino experience, but I've programmed microcontrollers for years, so I think I can help until someone smarter comes along. :)

Can you post the cycle timer code you have thus far? Much easier to work with existing code than make it up from scratch.

Also, let us know how you'd like this to work along with the timing range, for example:
  • Max time is 99 minutes, 59 seconds (can be anything really since the LCD can show up to 32 characters)
  • Button A is used to set minutes (count up from 0 to 99 then back to zero)
  • Button B is used to set seconds (count up from 0 to 99 then back to zero)
  • Button C is used to start the timer
  • Button D is used to stop the timer
  • Button E is used to reset the timer to zero
Alternately, you could use buttons A-D to set each digit (button A - minutes tens place, button B - minutes ones place, etc.), then use the last button to start and stop the timer. To reset to zero, you could hold the start/stop button down for 2 seconds or more. Just some options.
 

Thread Starter

GRNDPNDR

Joined Mar 1, 2012
545
Okay, I think I understand now. So you've written a cycle timer code, but the only way to change and run it is by manually changing and uploading the code each time, correct? So you want to use the LCD shield and buttons to set the time, and start/stop the timer. Is this correct?
100% ... except I didn't write the code, I found it online from someone who did a similar project and posted the code to use.

Can you post the cycle timer code you have thus far? Much easier to work with existing code than make it up from scratch.

Also, let us know how you'd like this to work along with the timing range, for example:
  • Max time is 99 minutes, 59 seconds (can be anything really since the LCD can show up to 32 characters)
  • Button A is used to set minutes (count up from 0 to 99 then back to zero)
  • Button B is used to set seconds (count up from 0 to 99 then back to zero)
  • Button C is used to start the timer
  • Button D is used to stop the timer
  • Button E is used to reset the timer to zero
Alternately, you could use buttons A-D to set each digit (button A - minutes tens place, button B - minutes ones place, etc.), then use the last button to start and stop the timer. To reset to zero, you could hold the start/stop button down for 2 seconds or more. Just some options.
I've had to clean my workspace as it got to be quite disastrous this last year, so I haven't had a chance to even test the code to see if it works.
I've also put up a project on freelancer and have someone who has apparently already written the code, but I need to talk to him a bit more before I award that project.

His timer is 0-999 secs. no separate minute or second adjustment, and I kind of like that idea now that you mentioned it, but the buttons I have on the shield are; Select, left, right, up, down, and reset, so I don't know if it could be done the way you suggest by having button A set minutes, button B set seconds, etc.... also the reset button is to reset the arduino, I don't think it can be used to reset the digits. I don't really know for sure because I haven't really explored the Arduinos capabilities and this is the first time I've actually had a use for it.
 

elec_mech

Joined Nov 12, 2008
1,500
GRNDPNDR said:
I've also put up a project on freelancer and have someone who has apparently already written the code, but I need to talk to him a bit more before I award that project.

... except I didn't write the code, I found it online from someone who did a similar project and posted the code to use.
It's up to you. I think you can do this yourself, but I understand if you prefer to pay someone to do it for you. If you're going to pay someone however, I suggest you have them write the code to do exactly what you want. If they're just offering to sell you some code they've written that counts from 000 to 999 on an LCD, I'm pretty sure you can find a similar example online for free. This is what makes the Arduino so popular - there are tons of free codes already written for all kinds of projects. The trick is finding something similar to what you want to do and modifying it. C is not my forte, but with an example, I can reverse-engineer it. If you can post the code you found (or a link to it), that may be enough for me to work from.

GRNDPNDR said:
but the buttons I have on the shield are; Select, left, right, up, down, and reset, so I don't know if it could be done the way you suggest by having button A set minutes, button B set seconds, etc....
Keep in mind those are simply labels - up does not mean that button has to be up, etc. You'll tell the Arduino what you want each button to do. Select could be programmed to mean Start, right could programmed to mean Reset (the counter, not the Arduino), etc. Might be easier to print tiny labels that say what you want each button to do and tape them over the existing labels for ease of understanding.

GRNDPNDR said:
also the reset button is to reset the arduino, I don't think it can be used to reset the digits.
I didn't realize the board had a sixth dedicated reset button, but I didn't mean that specific button would be used for reset. The product page says there are five buttons available for use, so I just labeled them randomly A-E to better describe what you want to do.
 

Thread Starter

GRNDPNDR

Joined Mar 1, 2012
545
It's up to you. I think you can do this yourself, but I understand if you prefer to pay someone to do it for you. If you're going to pay someone however, I suggest you have them write the code to do exactly what you want. If they're just offering to sell you some code they've written that counts from 000 to 999 on an LCD, I'm pretty sure you can find a similar example online for free. This is what makes the Arduino so popular - there are tons of free codes already written for all kinds of projects. The trick is finding something similar to what you want to do and modifying it. C is not my forte, but with an example, I can reverse-engineer it. If you can post the code you found (or a link to it), that may be enough for me to work from.
His code pretty much does what I need for now, and my brief search didn't turn up anything I wanted to bother with but I didn't search very throughly.
Here is his demonstration..

Keep in mind those are simply labels - up does not mean that button has to be up, etc. You'll tell the Arduino what you want each button to do. Select could be programmed to mean Start, right could programmed to mean Reset (the counter, not the Arduino), etc. Might be easier to print tiny labels that say what you want each button to do and tape them over the existing labels for ease of understanding.

I didn't realize the board had a sixth dedicated reset button, but I didn't mean that specific button would be used for reset. The product page says there are five buttons available for use, so I just labeled them randomly A-E to better describe what you want to do.
Ya I figured the buttons could be programmed to do whatever I needed, but the product page is slightly different from what I have, I think mine is a slightly newer model? it has that 6th reset button and is lacking 3 rows of pins on the right side. Other than that it should be the same product.

Here's the code I dug up online for a basic cycle timer that doesn't include the LCD shield. But for $50 I think I might just modify the guys code from freelancer.

Code:
unsigned char relayPin[12] = {4,5,6,7};//Remainining pins: (22,23,24,25,26,27,28,29}; // Define the led's pin

//initializes the function: Zone
void Zone(unsigned long on, unsigned long off, int i);


int mode[4]={LOW,LOW,LOW,LOW}; //Initilizes mode array to LOW (OFF) Mode
unsigned long previousMillis[5]={0,0,0,0,0}; //initilizes previousMillis array
//Conversions
unsigned long Sec = 1000UL;
unsigned long Min = 60000UL;
//unsigned long Hour=60*Min;

//unsigned long daytime=43200000UL;

void setup()
{
//Initilizes the Pins as OUTPUT going through the for loop.
int i;
for(i = 0; i < 4; i++)
{
pinMode(relayPin[i],OUTPUT);
digitalWrite(relayPin[i],mode[i]);
}
}

void loop(){
//Zone(3*Min,15*Min,0);
//Zone(6000UL,900000UL,1);
Zone(4000UL,900000UL,2);
}

/*
Zone:
Recieves: On time, Off time, and Pin Number(0-4)
Note: millis() function calls time since arduino has been on, in milliseconds (ms)
psuedocode:
if (millis) - previlousMillis[i] is greater than (Off Time) and mode is equal to LOW
then set previousMillis[i] to (millis), set pin mode to HIGH(ON),
then it does it again for the ON time
*/
void Zone(unsigned long on, unsigned long off, int i){
if (millis() - previousMillis[i]>= off && mode[i]==LOW){
previousMillis[i]=millis();
mode[i]=HIGH;
digitalWrite(relayPin[i],mode[i]);
}
if (millis()-previousMillis[i]>= on && mode[i] == HIGH){
previousMillis[i]=millis();
mode[i]=LOW;
digitalWrite(relayPin[i],mode[i]);
}
}
 

Thread Starter

GRNDPNDR

Joined Mar 1, 2012
545
Here is the code from the guy I hired. I'm actually very happy with this and he's making a couple of changes to make it "perfect"

I'm just not sure how to connect my relay because Pin 13 is used by the shield.... so I can change the pin I'm just not sure which pins I can use.

Code:
//Sample using LiquidCrystal library
#include <LiquidCrystal.h>
// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// define some values used by the panel and buttons
int lcd_key  = 0;
int adc_key_in  = 0;
#define btnRIGHT  0
#define btnUP  1
#define btnDOWN  2
#define btnLEFT  3
#define btnSELECT 4
#define btnNONE  5

// define relay pin
int RelayPin = 13;

int page = 1;
boolean repeat = false;
int on_time[] = {0,0,0,0};
float on_time_value = 0;
int off_time[] = {0,0,0,0};
float off_time_value = 0;
boolean hold = false;
int cur_x = 15;
int cur_y = 0;
boolean toggle = 0;
float count = 0;


// read the buttons
int read_LCD_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
if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
/*
// 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...
}

void setup()
{
  lcd.begin(16, 2);  // start the library
  display_page(page);
  pinMode(RelayPin, OUTPUT);
  digitalWrite(RelayPin, LOW);

}
void loop()
{
lcd_key = read_LCD_buttons();  // read the buttons

switch (lcd_key)  // depending on which button was pushed, we perform an action
{
  case btnRIGHT:
  {
  if (!hold)
  {
  if (page == 2)
  {
  cur_x++;
  if (cur_x == 14)
  {
  cur_x = 15;
  }
  if (cur_x > 15)
  {
  if (cur_y == 0)
  {
  cur_y = 1;
  }
  else
  {
  cur_y = 0;
  }  
  cur_x = 11;
  }
  lcd.setCursor(cur_x,cur_y);
  }
  hold = true;
  } 
  break;
  }
  case btnLEFT:
  {
  if (!hold)
  {
  if (page == 2)
  {
  cur_x--;
  if (cur_x == 14)
  {
  cur_x = 13;
  }
  if (cur_x < 11)
  {
  if (cur_y == 0)
  {
  cur_y = 1;
  }
  else
  {
  cur_y = 0;
  }
  cur_x = 15;
  }
  lcd.setCursor(cur_x,cur_y);
  }
  hold = true;
  }  
  
  break;
  }
  case btnUP:
  {
  if (!hold)
  {
  if (page == 2)
  {
  if (cur_y == 0) //on time
  {
  if (cur_x == 15)
  {
  if (on_time[3] == 0)
  {
  on_time[3] = 5;
  }
  else
  {
  on_time[3] = 0;
  }  
  }
  else
  {
  on_time[cur_x-11]++;
  if (on_time[cur_x-11] > 9)
  {
  on_time[cur_x-11] = 0;
  }
  }
  }
  else //off time
  {
  if (cur_x == 15)
  {
  if (off_time[3] == 0)
  {
  off_time[3] = 5;
  }
  else
  {
  off_time[3] = 0;
  }  
  }
  else
  {
  off_time[cur_x-11]++;
  if (off_time[cur_x-11] > 9)
  {
  off_time[cur_x-11] = 0;
  }
  }
  }
  display_page(2);
  }
  hold = true;
  }
  break;
  }
  case btnDOWN:
  {
  if (!hold)
  {
  if (page == 2)
  {
  if (cur_y == 0) //on time
  {
  if (cur_x == 15)
  {
  if (on_time[3] == 0)
  {
  on_time[3] = 5;
  }
  else
  {
  on_time[3] = 0;
  }  
  }
  else
  {
  on_time[cur_x-11]--;
  if (on_time[cur_x-11] < 0)
  {
  on_time[cur_x-11] = 9;
  }
  }
  }
  else //off time
  {
  if (cur_x == 15)
  {
  if (off_time[3] == 0)
  {
  off_time[3] = 5;
  }
  else
  {
  off_time[3] = 0;
  }  
  }
  else
  {
  off_time[cur_x-11]--;
  if (off_time[cur_x-11] < 0)
  {
  off_time[cur_x-11] = 9;
  }
  }
  }
  display_page(2);
  }
  hold = true;
  }
  break;
  }
  case btnSELECT:
  {
  if (!hold)
  {
  if (page == 1)
  {
  repeat = false;
  page = 2;
  lcd.clear();
  }
  else if (page == 2)
  {
  page = 3;
  on_time_value = on_time[0]*100+on_time[1]*10+on_time[2]+on_time[3]*0.1;
  off_time_value = off_time[0]*100+off_time[1]*10+off_time[2]+off_time[3]*0.1;
  toggle = 0;
  count = 0;
  //set timer1 interrupt at 1Hz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 2hz increments
  OCR1A = 7812;// = (16*10^6) / (2*1024) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1024 prescaler
  TCCR1B |= (1 << CS12) | (1 << CS10); 
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  interrupts(); // enable all interrupts
  
  lcd.clear();
  }
  else if (page == 3)
  {
  page = 2;
  digitalWrite(RelayPin,LOW);
  noInterrupts(); // disable all interrupts

  lcd.clear();
  }
  display_page(page);
  hold = true;
  }
  break;
  }
  case btnNONE:
  {
  hold = false;
  break;
  }
  
}

}

void display_page(int page)
{
  switch (page)  // depending on which button was pushed, we perform an action
  {
  case 1: //welcome screen
  {
  lcd.setCursor(0,0);
  lcd.print("  Arduino  ");
  lcd.setCursor(0,1);
  lcd.print("  Cycle Timer  ");
  repeat = true;
  break;
  }
  case 2: //setting
  {
  lcd.setCursor(0,0);
  lcd.print("On Time  ");
  lcd.print(on_time[0]);
  lcd.print(on_time[1]);
  lcd.print(on_time[2]);
  lcd.print(".");
  lcd.print(on_time[3]);
  lcd.setCursor(0,1);
  lcd.print("Off Time  ");
  lcd.print(off_time[0]);
  lcd.print(off_time[1]);
  lcd.print(off_time[2]);
  lcd.print(".");
  lcd.print(off_time[3]);
  lcd.setCursor(cur_x,cur_y);
  lcd.cursor();
  lcd.blink();
  repeat = true;
  break;
  }
  case 3:  //run
  {
  lcd.noCursor();
  lcd.noBlink();
  lcd.setCursor(0,0);
  if (toggle == false)
  {
  lcd.print(" ");
  lcd.print("On=");
  lcd.print(on_time_value,1);
  lcd.print("  ");
  }
  else
  {
  lcd.print("*");
  lcd.print("On=");
  lcd.print("[");
  lcd.print(count,1);
  lcd.print("]  ");
  }

  lcd.setCursor(0,1);
  if (toggle == false)
  {
  lcd.print("*");
  lcd.print("Off=");
  lcd.print("[");
  lcd.print(count,1);
  lcd.print("]  ");
  }
  else
  {
  lcd.print(" ");
  lcd.print("Off=");
  lcd.print(off_time_value,1);
  lcd.print("  ");
  }
  
  break;  
  }  
  }
}

ISR(TIMER1_COMPA_vect)
{
  if (toggle) // On
  {
  if (count >= on_time_value)
  {
  digitalWrite(RelayPin,LOW);
  toggle = 0;
  count = 0;
  }
  }
  else // Off
  { 
  if (count >= off_time_value)
  {
  digitalWrite(RelayPin,HIGH);
  toggle = 1;
  count = 0;
  }
  }
  count = count + 0.5;
  display_page(3);
}
 

Thread Starter

GRNDPNDR

Joined Mar 1, 2012
545
I've got revised code now that changes a few things.
1.) the timer now starts as soon as it's powered on instead of showing a welcome screen. In case of a power failure it will resume operation when power is restored without anyone having to reset the time.
2.) when changing the time up it will set the next column to 1 when you reach 9 in the previous column.
3.) when setting the time it will start with the ON cycle instead of starting with the OFF cycle.

I'm very very happy with the work done. The guy was extremely professional and proficient, he was able to make the needed changes within a few mins and the timer works perfectly so far as I can see right now.

This phase of the project is done at least. It would have taken me months to achieve this. $50 and it was done overnight :)
 

elec_mech

Joined Nov 12, 2008
1,500
Here is the code from the guy I hired. I'm actually very happy with this and he's making a couple of changes to make it "perfect"
Cool beans, glad to hear he's customizing it to suit your needs.

I'm just not sure how to connect my relay because Pin 13 is used by the shield.... so I can change the pin I'm just not sure which pins I can use.
Might want to ask the other guy since he has a better idea which pins are being used and which free ones would work best. If you could put together a quick schematic of the connections thus far (even a cellphone picture of a napkin sketch), I can help further.

What kind of relay is it? Is the coil voltage rated for 5VDC? Be sure to add a diode across the coils to help prevent back EMF from damaging the Arduino pin.
 

Thread Starter

GRNDPNDR

Joined Mar 1, 2012
545
my bad, the pin isn't in use exactly, but the header on the bottom of the shield is plugged into it so I can't attach anything to it.... this shield is a little weird that way, I think I have the previous version which doesn't have sensor pins and doesn't have any headers on top of the shield.

I think what I'll have to do is buy a different 3 pin header and a 5 pin header so I can utilize the pins I need to drive the relay.

The relay I have right now I think is 5v coils, it's a little relay breakout board with a delay on relay, I'm just using this for testing and to play with.

I will need to get a similar one, but without a delay. I'm only switching 24v
 
Last edited:

Thread Starter

GRNDPNDR

Joined Mar 1, 2012
545
nevermind,thanks to the wiki I found out that there is a spot for those digital pins, I just need to solder a header onto it.
 

txpenguin

Joined Aug 24, 2015
1
GRNDPNDR any chance you could provide the revised code? I'm very new to Arduino and am attempting a similar project for an Aquaponic garden. I'd really like to compare the two versions for educational purposes/sanity check.

Much appreciated!
 
Top