Google Analytics

Saturday, February 4, 2012

Banjo's Arduino Timer Circuit

Banjo's Adjustable TimerCircuit
(Note: scroll down for circuit diagram and software listing)
Part 1 of 3 parts.  
TimerCircuit with time control knob and indicator lights

I've been working on a thermocouple controller for my porch's gas heater (which I'll post at some future date).  The first iteration of that controller used a timer instead of a thermocouple.  Later, after I got the thermocouple, I changed the software and the hardware.  However, I decided that some people might need a timer circuit for their projects, so I elected to put it here.  As you can see, I placed the circuit inside of an old cigar box.

Inside of TimerCircuit control box.
This is the interior after wiring....well, almost the interior.  This is actually the interior of the thermocouple control box, as you can observe by the tiny thermocouple shield attached to the Arduino on the top right corner.

At some point, I intend to 'rescue' my Arduino out of this box and replace it, along with the breadboard on the left, with a custom PCB.

The circuit
The circuit uses an Arduino Uno; however, this is way more than needed for this simple circuit.  It could be adopted to make use of an IC 555 chip too.  

Wire the device you want to energize and de-energize to the NO contact output wires.  The potentiometer (pot) will control the amount of on-time vs off-time for the relay.

You will have to determine the appropriate relay for the device you want to control, as all relay contacts have a voltage and current limitation.  In addition, the coil must be sized appropriately for use directly by the Arduino, or other circuit elements will need to be provide, as the Arduino can only supply 5vdc and 20ma directly to a circuit.

The pot used in this circuit controls the amount of time the circuit is on vs off.  The 5vdc from the Arduino is wired to one leg of the pot.  The other leg of the pot is wired to ground.  The pot wiper makes a voltage divider network.  The wiper is connected to an analog input pin on the Arduino, where the value can be read.  The value is reflected as a percentage of 5vdc, which the Arduino software actually returns as 0 - 1023 counts on this pin, with 1023 being equated to 5vdc in this case.

The Arduino controls a relay, energizing the relay when ON, and de-energizing the relay when OFF.

The output from this device is relay-contact-closed when ON, and relay-contact-open when OFF.

The RED LED is ON when the relay is energized, and OFF when the relay is de-energized.
The GREEN LED is ON when the relay is de-energized, and ON when the relay is energized.
These are mutually exclusive.

The software determines a ratio of on-to-off, based on the position of the pot.  The value returned by the Arduino on reading the pot is converted to a ratio, with 100% being full-on all the time, and 0% being full-off all the time.  One complete on and off cycle is the period.  The maximum amount of time for one period is defined in MAX_CYCLE_TIME.  So, if the MAX_CYCLE_TIME is set to 10 minutes, and the pot is set to 25%, then the on-time will be 25% of 10 minutes, or 2.5 minutes, which will mean the off time will be 7.5 minutes.

Parts Listing
- Relay: 5vdc, 1A SPST Reed Relay, something similar to Radio Shack 275-232
- Potentiometer: 10K Rotary Linear.  Value not critical, but should not be any less than 10K.  Anything between 10K and 500K should work OK.  I used 10K COM-9939 from
- LEDs: - any green and any red will do.
- Resistor: 470 ohm, any wattage will do.
- Diode: Limits Reverse Voltage Spike caused from coil.  1N4004 or similar, but depends on the coil you use!
- Arduino: I used an UNO as well as an OSEPP UNO compatible  will do, or earlier versions of the Arduino also.  Straight AVR chips if you do that.  The chip on the Arduino is the ATMEGA328P. 

Software listing
Note: some lines may wrap in the listing below.

//Author: Banjo 1/29/12
//TimerControl Rev 1.0.  This uses an adjustable timer to control a relay.  
//  Using the contacts controlled by the relay, you can control other devices.
//  The contacts of the relay are not connected to the circuitry, so it can 
//  be used to drive other devices.  Only the coil is connected to the Arduino.  
//  CAUTION: Do not exceed the rated voltage and current limitations associated with the 
//    relay contacts you use in building this circuit.
//  CAUTION: Choose a relay with a coil rated to be able to be used by the Arduino you 
//    use to build this project.  If your coil uses less than 20ma current and is 5VDC (and you
//    are using a 5VDC Arduino), then you can drive the coil directly from an Arduino; 
//    otherwise, you will have to add another device or switching transistor capable of 
//    providing sufficient current to drive the relay coil.
//  CAUTION: Use a diode to bypass coil reverse voltage spike associated with all coils
//    so you don't destroy your Arduino!
//    - adjust the time knob clockwise to increase time timer is on and decrease time timer is off.
//    - adjust the time knob counterclockwise to decrese time timer is on and increase time timer of off.
//       RED - timer contact is on.  Connected to ON_LED_PIN
//       GREEN - timer contact is off.  Connected to OFF_LED_PIN
//       Alternating RED and GREEN - Alarm() function. Time determined by ALARM_COUNTS.  Uses LEDs on both ON_LED_PIN and OFF_LED_PIN 
//For use:
//  - Wire device to be controlled to relay contacts.  The relay is controlled by this Arduino.
//    These contacts are not polarized, so it doesn't matter which contact goes to which
//    leg of the switch.  The relay you use must be correctly sized to carry the load you are going to place
//    onto the contacts.
//for testing:
//  - If you want LED for TIMER ON, then add LED at digital pin ON_LED_PIN, then through resistor to ground
//  - if you want LED for TIMER OFF, then add LED at digital pin OFF_LED_PIN, then through resistor to ground 
//  - change MAX_CYCLE_TIME to something short, like 10 * ONE_SECOND
//  - change IGNORE_MINIMUM to something short, like 2  * ONE_SECOND
//  - remember to change back!

//some handy time constants
unsigned long ONE_SECOND = 1000;  //1 second is 1000 microSeconds
unsigned long ONE_MINUTE = ONE_SECOND * 60;
int MAX_ADC_COUNTS = 1024; //ADC

unsigned long MAX_CYCLE_TIME =  10 * ONE_MINUTE; // This controls the total amount of time for a period (both 1 one and 1 off time)
unsigned long IGNORE_MINIMUM =  1 * ONE_SECOND;  // In case you are controlling something that you don't want cycled too fast.
int ALARM_COUNTS = 250;  //blink rate.  Each is on for this amount of time.

//pin assignments 
int UNO_LED_PIN = 13;  //LED on the uno board, so no external connections
int ON_LED_PIN = 9;  //LED if using an external state LED
int OFF_LED_PIN = 10;   //LED timer off 
int TIMER_OUTPUT_PIN = 8;        //This controls the onboard relay that controls the timer output contacts.
int TIMER_RATIO_INPUT_PIN = A0;  //this is the onboard potetiometer that controls the ratio of on to off

int TIMER_ON = HIGH;  //used because may use sink current at some point
int TIMER_OFF = LOW;  //used because may use sink current at some point

void setup() {                
  // initialize the digital pin as an output.
  // Pin 13 has an LED connected on most Arduino boards:
  pinMode(ON_LED_PIN, OUTPUT);

  Serial.println("setup()...Entry & Exit"); 


void loop() {
  turnTimerOff();  //de-energize the relay
  turnTimerOn();  //energize the releay

float getSetpointRatio() {
  //rather than counts of 0 - 1023 (range of the onboard ADC), return the 0% - 100% of range
  float ratio = 0.0;
  int sensorValue = 0;

  sensorValue = analogRead(TIMER_RATIO_INPUT_PIN);
  ratio = float(sensorValue) / float(MAX_ADC_COUNTS);

//  Serial.print("getSetpointRatio()....sensorValue: "); Serial.println(sensorValue); 
//  Serial.print("getSetpointRatio()....ratio: "); Serial.println(ratio);
  return ratio;


void turnTimerOn () {
  //time controlled, not temperature controlled
  unsigned long cumulativeOnTime = 0;
  unsigned long timerOnTime = 0;
  unsigned long timerOffTime = 0;  //special case; keep on if no off time
  float ratio;
  Serial.println("turnTimerOn()...time controlled...entry..............................");
  do {
    Serial.println("turnTimerOn() loop top.");  
    ratio = getSetpointRatio();
    timerOnTime = calcOnTime(ratio);
    Serial.print("turnTimerOn()...timerOnTime: "); Serial.println(timerOnTime);
    Serial.print("turnHeatherOn()...IGNORE_MINIMUM: "); Serial.println(IGNORE_MINIMUM);
    if(timerOnTime < IGNORE_MINIMUM) {  //need to refactor this
      Serial.println("turnTimerOn()...less than IGNORE_MINIMUM...exiting.");
    timerOn(); //energize the relay
    delay(SENSOR_READ_DELAY_TIME); //simple way to be able to provide approx on time.
    cumulativeOnTime += SENSOR_READ_DELAY_TIME;

    Serial.print("turnTimerOnUsingTimer()...cumulativeOnTime: ");Serial.println(cumulativeOnTime);
    Serial.print("turnTimerOnUsingTimer()...timerOnTime: ");Serial.println(timerOnTime);
  }   while(cumulativeOnTime < timerOnTime);

void turnTimerOff() {
  unsigned long cumulativeOffTime = 0;
  unsigned long timerOffTime = 0;
  float ratio = 0.0;
  Serial.println("turnTimerOff()...time controlled...entry.............................");
  do {
    Serial.println("turnTimerOffUsingTimer() loop top.");  
    ratio = getSetpointRatio();
    timerOffTime = calcOffTime(ratio);
    Serial.print("turnTimerOffUsingTimer()...timerOffTime: "); Serial.println(timerOffTime);
    Serial.print("turnHeatherOffUsingTimer()...IGNORE_MINIMUM: "); Serial.println(IGNORE_MINIMUM);
    if(timerOffTime < IGNORE_MINIMUM) {  //need to refactor this
      Serial.println("turnTimerOffUsingTimer()...less than IGNORE_MINIMUM...exiting.");
    timerOff();  //de-energize the relay

    delay(SENSOR_READ_DELAY_TIME); //simple way to be able to provide approx off time.
    cumulativeOffTime += SENSOR_READ_DELAY_TIME;
    Serial.print("turnTimerOffUsingTimer()...cumulativeOffTime: ");Serial.println(cumulativeOffTime);
    Serial.print("turnTimerOffUsingTimer()...timerOffTime: ");Serial.println(timerOffTime);
  }   while(cumulativeOffTime < timerOffTime);

unsigned long calcOnTime(float ratio) {
  //time is a function of MAX_CYCLE_TIME; if this is seconds, then return seconds; if mins, then return mins
  unsigned long onTime = 0;
  onTime = ratio * MAX_CYCLE_TIME;
  Serial.print("calcOntime()....onTime: "); Serial.println(onTime);

  return onTime;

unsigned long calcOffTime(float ratio) {
  //time is a function of MAX_CYCLE_TIME; if this is seconds, then return seconds; if mins, then return mins
  unsigned long offTime = 0;
  float offRatio = 0.0;

  //use calcOnTime for brevity
  offTime = calcOnTime(ratio);
  offTime = MAX_CYCLE_TIME - offTime;

  Serial.print("calcOffTime()....offTime: "); Serial.println(offTime);

  return offTime;

void timerOn() {
  Serial.println("timerOn() ... entry.");
  digitalWrite(TIMER_OUTPUT_PIN, TIMER_ON);   // sink current
  digitalWrite(OFF_LED_PIN, LOW);
  digitalWrite(UNO_LED_PIN, HIGH);   // set the LED on
  digitalWrite(ON_LED_PIN, HIGH);
  Serial.println("timerOn() ... exit.");

void timerOff() {
  Serial.println("timerOff() ... entry.");
  digitalWrite(TIMER_OUTPUT_PIN, TIMER_OFF);     
  digitalWrite(UNO_LED_PIN, LOW);   // set the LED on
  digitalWrite(ON_LED_PIN, LOW);
  digitalWrite(OFF_LED_PIN, HIGH);
  Serial.println("timerOff() ... exit.");

void alarm(int sensorValueCounts) {  //needs to be refactored to use timerOff()
  //NOTE: alarm function turns relay coil off.  This is left here as a convenience for
  //  code you may develop.  It is used in a later implementation of this software,
  //  where I check for gas pilot light on.
  //blink both on and off LEDs
  Serial.println("alarm()....Entry...will not exit!");

  digitalWrite(TIMER_OUTPUT_PIN, TIMER_OFF);   
  digitalWrite(OFF_LED_PIN, LOW);
  Serial.print("alarm()....sensor low. sensorValueCounts: "); Serial.println(sensorValueCounts);
  while(1) {
    //keep turning timer off!
    digitalWrite(TIMER_OUTPUT_PIN, TIMER_OFF);
    //show it by alternating blinking both LEDs
    digitalWrite(UNO_LED_PIN, HIGH);
    digitalWrite(ON_LED_PIN, HIGH);
    digitalWrite(OFF_LED_PIN, LOW);

    digitalWrite(ON_LED_PIN, LOW);
    digitalWrite(OFF_LED_PIN, HIGH);


  1. how can I add a code of my motor controller using the same uno?thank you for advance

  2. Hi,
    Thanks for the great sketch, how would I modify this to have a fixed on time (4 seconds) and a variable on time (0-30 seconds)?


  3. Correction:

    fixed "ON" time Variable "OFF" time

  4. For a fixed ON TIME and variable OFF TIME, then you would take out the 'do...while' within the turnTimerOn() function, so you only go through the code once instead of looping. Then within the delay(xxx) function, you would put the number of seconds (times 1000 because it works on thousandths of a second), or for minutes it would be Minutes * 60 * 1000. The turnTimerOff() should work as it is.

    1. Banjo,

      Thank you for your reply and instructions, I am just learning "Arduino." Your sketch(s) have been quite instructive and helpful in understanding the nuances of writing code. It is obvious that you are quite talented.

      Kind Regards,

      James Bower

    2. James,

      Thanks for the kind comments. I'm working on a cheap datalogger that will use a 4 GB SD card for the data. I hope to have it published next week sometime.

      Drop me an email via this blog for any questions or to keep me up to date on what you are doing!


    3. Banjo,

      I look forward to your datalogger! I have switched from the timer sketch to your thermocouple sketch; I am waiting for the Adafruit board to arrive so I can continue.

      Regarding what I am working on:

      I am working on a complete control system for a pellet stove. I acquired an old Whitfield pellet stove that had controller problems. When I discovered that they wanted $600.00 for the control board I decided to learn "Arduino". I have recently retired and now have the time to do some of the projects that I just could not do while employed full time.

      Your first timer sketch is really all I need to get it up and running, but your thermocouple control sketch looks like it may do a better job. I will keep you informed of my progress.



    4. James,

      I'm really interested in your project, as it's in line with some stuff I've built over the years, like a bbq smoker. Please drop me an email at "bbq and banjos at gmail dot com" (remove spaces substitute charactors for 'at' and 'dot'). Thanks!

      Re datalogger: have had success writing to 4 gbyte sd card, on a non-Arduino circuit (still using the same chip, but not the circuit board - chips are < $5., board is about $30, so big savings!) I'm doing 4 channels of thermocouples on it, will be able to handle up to 8. Still refining - want to add a date/time-stamp chip. Want to make some printed circuit boards when finished.

  5. comadreify, I'm not sure I understand your question. Are you asking me how you would use this with a motor controller? If so, I'll need to know more about the motor you are driving, and how you are driving it.

    Sorry it has taken me so long to get back to you!

  6. Hi Banjo
    I was wondering if you could tell how to use a IC 555 timer instead of using a arduino for the timer circuit. All i need is to have it on for 6-10 seconds and off for 10 on more minutes. Is it possible to use the 555 timer. Is there a schematic of this circuit? Can you help me? Thank You

  7. Thank you for the timer program. I am using it to control my live well tank in my fishing boat. I made a couple small additions so it would turn on the pump first to fill the tank and test all leds in "setup" then run normal to add water to keep the O2 level up and water temp cool in "loop" . I am not a programer but have good luck making small changes. Thanks again, Carl

  8. Hi Banjo, by removing the serial comments the code will fit in a Attiny45 if the serial is not needed anymore. the tiny has 5 useable pins with analog in pwm out and digital in out. hope this helps. just remap the pins.


  9. Hi Banjo,
    i am planning to build a 24 hour recurring timer with 12 hours on and 12 hours off for my swimming pool pump. Can i use this sketch for this purpose?


    1. Terje,

      I do not think this would be a good fit. Your pool pump would require a lot of current at either 120VAC or 240VAC. In order to switch those, you would need to isolate my circuit, adding additional relays to step up to the main relay. They make commercial controls specifically for this that would provide you with a better, safer, solution.


    2. Using this circuit, add a 12v dc power supply, connect to relay (common for positive switched). The only addition would be a pam 2 relay (it is a isolation relay), and connect the other side of the pam 2 to your 120vac. The arduino will activate the 5v relay which will switch the 12v side of the pam 2 causing it to switch your main power supply. You could also use a solid state relay, but I am unfamiliar with activation voltages. Sorry its a late reply, and I hope it helps.

  10. how i make time ON use relay run motor, lcd show 0-100 and time x run relay. potentiometer use 0-full and lcd show 0-100 i no understand. and then calculate time thats, etc, number 12 = time X and relay have on time X. then off. i need potentiometer or rotary encoder adjust numbers 0-100 and then arduino calculate number = time X (etc, 40=23 secon or 70=2 minute)
    i no know time now but how made code read inbut analog show lcd value 0-100 and then use ewery number different time run relay on thats time, sorry my english but no understand good and need make thats. or hard wersion use inbut rotary encoder change number 0-100.

  11. Matti, I'm sorry, but I've not been able to understand your question. I thought I might suggest that you write it in your native language, then use google translate to change it ton English, then post that translation here, and I will try to assist you. Thanks for your interest, and looking forward to your translated post! Banjo

  12. Hi Banjo
    How would I write the script for an uno board with 5v relays to stay on for 30sec and off for 7min. I would also like the board to turn on at 6am and off at about 4pm. Would it be possible to have the board run a clock to set the daily on and off times.
    It's for solenoids on a greenhouse but the plants are very sensitive to moisture.
    Thanks so much in advance