Continue to Site

# [AVR]Arduino Led blinking at 0.125 Hz with Timer1 using ISR

Status
Not open for further replies.

#### shomikc

##### Member level 4
Hi.

I am new to Arduino. I am not able to understand how to get 0.125 Hz with Timer1. I know it has something to do with Prescaling

but I could not find any documentation on the internet. The problem is to blink built-in LED at 1 Hz if a button is not pressed and

to blink the LED at 0.125 Hz if the button is pressed. Please help. If you can point me to any good document on Timer1 calculations

that would be very helpful. Thankyou.

Code:
const int button_pin_number = 2;

const int led_pin_number =  13;

int button_unpressed_pressed = 0;

void setup() {

pinMode(led_pin_number, OUTPUT);

pinMode(button_pin_number, INPUT);

noInterrupts();

TCCR1A = 0;

TCCR1B = 0;

TCNT1 = 0;

TCCR1B |= (1 << CS12);

TIMSK1 |= (1 << TOIE1);

interrupts();
}

ISR(TIMER1_COMPA_vect)

{

if (button_unpressed_pressed == LOW)

{   OCR1A = 15624;

}

if (button_unpressed_pressed == HIGH)

{  OCR1A = 124992;

}

}

void loop()

{

}

#### KlausST

##### Super Moderator
Staff member
Hi,

It's one of the most often asked question, million explanations here in this forum in the internet.
There are even (thousands of) videos, and online calculators.
You surely need to improve your search skills.
******

I did not read datasheet .... but you have to!

Most important: timer has an input clock. Without giving information about input clock frequency no one can give detailed support.

Independent of manufacturer and exact microcontroller type most timer periferals (including sw) work the same:

Input_clock --> eventual_fixed_prescaler --> configurable_prescaler --> adjustable_count_number --> eventual_software_count_number --> output

Let's say your input clock is 4MHz.
And you want a blink frequency of 0.125Hz with 50%duty cycle => 4s ON , 4s OFF

So you need to count 4MHz x 4s = 16 clock cycles = 16,000,000.
I do it the mathematical way: prime factorisation: (there are online prime factorisation tools)
But it's simple: 16 = 4 × 4 = 2 × 2 × 2 × 2 = 2^4
1,000,000 = 10^6 = (2 × 5)^6 = 2^6 × 5^6
In total: 2^10 × 5^6

AVRs usually have no fixed_prescaler, and configurable prescalers of 256 and 16 bit counter registers.
So with a prescaler of 256 = 2^8 ... the remaining count number is: 2^10 × 5^6 / 2^8 = 2^2 × 5^6 = 62500
Luckily 62500 is within the 16bit range, so you don't need a software counter.

*****
* it misses input frequency information (at least as comment)
* it misses prescaler information (at least as comment)
* it says: OCR1A = 124992 --> this value is beyond 16 bit limit of 65535.

Klaus

### shomikc

Points: 2

#### tsan500

##### Member level 2
Another thread just inspired to make a sketch using ATMEGA328 timers. I assume it's Arduino UNO and clock frequency is 16 Mhz. The highest clock divider is 1024 which makes it easy to make 1 Hz without sw variables so I made an example of that. This code was tested with Arduino Duemilanove and I think UNO is pretty close to the same. It blinks the led using the timer. I see these differences to your code, but might be more:
-I set wave generation mode
-I have CS12 and CS10 on prescaler
-I activate different interrupt in TIMSK1, OCIE1A instead of TOIE1

Code:
void setup() {
pinMode(LED_BUILTIN, OUTPUT);

noInterrupts();
TCCR1A = 0;
TCCR1B = 0;
//Waveform Generation Mode 4, CTC
//WGM13 WGM12 WGM11 WGM10
//  0     1     0     0
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS12) | (1 << CS10) ;//prescaler clk/1024 -> 15625 Hz
OCR1A=15624;//1 Hz
TIMSK1 = (1 << OCIE1A);//output compare interrupt
interrupts();
}

void loop() {
// put your main code here, to run repeatedly:
}

//toggle led
ISR(TIMER1_COMPA_vect) {
}

Last edited by a moderator:

### shomikc

Points: 2

This is a quick and dirty way to do your function. Using block language, kids in school
use it to program robots.

You drag and drop blocks onto design canvas, config, then hit upload. mBlock then
generates the C code, shown on right, from your block config. I think this would fit in
an ATTINY85 8 pin, you would use an Arduino Nano or Uno board to program the
ATTINY85.

Its not optimal, or engineering at its finest, just simple. There are other block languages,
like Snap4Arduino, Ardublock, flowcode.....that offer other/more capabilities in the
blocks. Like a tethered situation where you easily create a talking voltmeter using windows
OS calls (you dont get into weeds on this, just use a block to speak the A/D value).....

Lots of fun, dont have to get into the weeds on a part when you are in a hurray
or dont feel like breaking out your C programming card and chip manual.

Here is example doing timed events -

Regards, Dana.

#### Attachments

• 1628329486468.png
201 KB · Views: 73
Last edited:

### shomikc

Points: 2

#### KlausST

##### Super Moderator
Staff member
Hi,

one little issue I sse regarding the solution of post#3:
You toggle every 1.00 second. So the LED is ON for 1s and OFF for 1s making a total of 2s. = 0.5Hz

My recommendation (modifications to code of post#3):
Code:
* set prescaler to 256
* set OCR1A to 31249  (to run the ISR every 0.5s)

// (pseudo code)
volatile uint8 LED_mode; (0 = OFF, 1=ON, 2=1Hz, 3=0.125Hz);
volatile boolean LED8;

ISR(TIMER1_COMPA_vect) {
boolean LED = false:
sw_blink++; (counts up every 0.5s, so bit 0 "blinks" with 1Hz, bit1 with 0.5Hz, bit2 with 0.25Hz, bit3 with 0.125Hz...)
if LED_mode == 1 then LED = true;
if LED_mode == 2 then LED = sw_blink & 0x01;
if LED_mode == 3 then LED = sw_blink & 0x08;
digitalWrite(LED_BUILTIN, LED));
}

### shomikc

Points: 2

#### tsan500

##### Member level 2
You toggle every 1.00 second. So the LED is ON for 1s and OFF for 1s making a total of 2s. = 0.5Hz
I saw OP used 15624 so I used that, but yes frequency is not 1 Hz. I also completely omitted 0.125 Hz and button presses. My idea was to give a working example regarding timer settings.

Points: 2