Cascading Timers to Create a Long Delay

cascade
Here is a demonstration program that runs on an Arduino which creates a 1 minute long delay by cascading timers. The procedure is outlined in Atmel Application Note AVR133.

I’ve set timer #1 up to toggle the OCR1A pin (D9) and wired that to the T0 pin (D4) which clocks timer #0. Then I put the arduino to sleep and wait for the timer #0 interrupt to wake it. The values I’m using should toggle the pin 13 LED at a 1 minute frequency.

A much longer delay is easily possible by increasing the counter values and the timer #1 prescaler. For example, with a 1024 prescale and maximum counter values, a delay of over 35 minutes is possible (with a 16MHz system clock).

Note: the reprogrammed timer 0 and 1 trashes the original arduino functions of these timers.

// AVR 133: Atmel Application Note Long Delay Generation Demo
// Blinks LED on a 1 minute period:
// T = 2/Fs x T1P x OCR1A x (256 - TCNT0)
// T = 2/16000000x256x7500x(256-6)
// T = 60 or 1 minute
//
// connect arduino D9 to D4: 
//  T0   = PD4 (Arduino D4 as input)
//  OC1A = PB1 (Arduino D9 as output)
#include <avr/sleep.h>
#include <avr/power.h>

void setup() {
  cli();
  
  //set pins
  DDRB |= (1<<PINB1) | (1<<PINB5); //set arduino D9 and D13 as outputs
  PORTB &= ~(1<<PINB1);            //set D9 low
  PORTD &= ~(1<<PIND4);            //set D4 low

  //timer #1 toggles OCR1A on TCNT1=0 in turn toggling T0
  TCCR1A = (1<<COM1A0); //TCCR1A toggle OC1A on compare match
  TCCR1B = 0;
  TCCR1C = 0;
  OCR1A = 7500;       //output compare register on division ratio of 7500
  TIMSK1 = 0;

  //timer #0 fires interrupt when TCNT0=0 waking arduino 
  TCCR0A = 0;
  TCCR0B = 0;
  TIMSK0 = (1<<TOIE0);  //enable timer0 interrupt
  
  sei();
}

void loop() {
  //toggle led
  PORTB ^= (1<<PINB5); //toggle led pin 

  //reset timers
  TCNT0 = 6;
  TCCR0B = (1<<CS00) | (1<<CS01) | (1<<CS02); //external source (t0) rising edge
  TCNT1 = 0UL;
  TCCR1B = (1<<WGM12) | (1<<CS12); //CTC mode 4 and 256 prescaler

  //sleep and power down setup
  set_sleep_mode(SLEEP_MODE_IDLE);
  sleep_enable();
  power_adc_disable();
  power_spi_disable();
  power_timer2_disable();
  power_twi_disable();
  sleep_mode();
  //go to sleep here
  sleep_disable();

  //wake upon timer #0 interrupt here
  power_all_enable();
 
  //stop timers
  TCCR1B = 0;
  TCCR0B = 0; 
}

About Jim Eli

µC experimenter
This entry was posted in Uncategorized and tagged , , , , , , . Bookmark the permalink.

6 Responses to Cascading Timers to Create a Long Delay

  1. Ron says:

    Thank you!
    I have been working through the meaning of everything in application note and the data sheet (ATmega16/32U4).
    I have it working on a Duemilanove.
    I just connected DIGITAL 9 to DIGITAL 4 and uploaded the program copied from above..
    The on-board LED toggles once per minute.
    But my YUN and Leonardo won’t do it.
    Don’t know why yet.

    • Jim Eli says:

      @Ron, This code is for an AtMega168/328 chip and directly manipulates the timer registers. The Leonardo and Yun use a 32U4 based chip and while not completely certain, the registers will probably need to be tweaked. I’m sorry but I can’t help much.

      • Ron Hartikka says:

        I have it working on Leonardo now.

        // AVR 133: Atmel Application Note Long Delay Generation Demo // Blinks LED on a 1 minute period: // T = 2/Fs x T1P x OCR1A x (256 – TCNT0) // T = 2/16000000x256x7500x(256-6) // T = 60 or 1 minute // // connect arduino D9 to D4: // connect Leonardo/Yun D9 to D6

        // T0 = PD4 (Arduino board D4 as input) or Leonardo D6 which is 32U4’s PD7 // OC1A = PB1 (Arduino board D9 as output) or leonardo D9 which is 32U4’s PB5

        #include #include

        void setup() { cli();

        // Configure Outputs. TIMER1 will toggle OC1A. loop() will toggle on-board LED @ D13

        //DDRB |= (1<<PINB1) | (1< M328 PB1 -> board D9. PB5 -> board D13 DDRB |= (1<<PINB5) | (1< 32U4 PB5 -> board D9, PB7 -> board D13

        // Set Pins

        //PORTB &= ~(1<<PINB1); //not Leonardo or Yun: D9 low PORTB &= ~(1<<PINB5); // Leonardo Or Yun: D9 low

        // works ok (same) without this line – at least with Leonardo //PORTD &= ~(1<<PIND4); //not Leonardo or Yun: set D4 low //PORTC &= ~(1<<PINC7); // Leonardo or Yun: set D6 low. This is T0.

        //timer #1 toggles OCR1A on TCNT1=0 in turn toggling T0 TCCR1A = (1<<COM1A0); //TCCR1A toggle OC1A on compare match TCCR1B = 0; TCCR1C = 0; OCR1A = 7500; //output compare register on division ratio of 7500 TIMSK1 = 0;

        //timer #0 fires interrupt when TCNT0=0 waking arduino TCCR0A = 0; TCCR0B = 0; TIMSK0 = (1<<TOIE0); //enable timer0 interrupt

        sei(); }

        void loop() { //toggle led //PORTB ^= (1<<PINB5); // not Leonardo or Yun: toggle led pin PORTC ^= (1<<PINC7); // Leonardo or Yun: toggle led pin

        //reset timers TCNT0 = 6; TCCR0B = (1<<CS00) | (1<<CS01) | (1<<CS02); //external source (t0) rising edge TCNT1 = 0UL; TCCR1B = (1<<WGM12) | (1<<CS12); //CTC mode 4 and 256 prescaler

        //sleep and power down setup set_sleep_mode(SLEEP_MODE_IDLE); sleep_enable(); power_adc_disable(); power_spi_disable(); power_timer2_disable(); power_twi_disable(); sleep_mode(); //go to sleep here sleep_disable();

        //wake upon timer #0 interrupt here power_all_enable();

        //stop timers TCCR1B = 0; TCCR0B = 0; }

      • Jim Eli says:

        Thanks for posting.

  2. xxx says:

    Hello,
    i am trying do to cascaded timers on the Arduino due, but not to create a long delay but the timer 1 must divide the timer 0, is it possible to do so ?

    Thank you

    • Jim Eli says:

      The Arduino Due utilizes an ARM Cortex M3 microcontroller and as such has many advanced timer features available. You should be able to accomplish your goal. Description of the Timer counters start on page 856 of the datasheet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s