Using TIMER1 to blink a LED once per second for 50ms

I am able to blink LED 1 sec on, 1sec off with below code. I would like to keep the LED on only for i.e. 50ms. How to achieve this?

int timer1_counter;

void setup() {
  noInterrupts();           // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;

  timer1_counter = 10000; //34286;   // preload timer 65536-16MHz/256/2Hz
  
  TCNT1 = timer1_counter;   // preload timer
  TCCR1B |= (1 << CS12);    // 256 prescaler 
  TIMSK1 |= (1 << TOIE1);   // enable timer overflow interrupt
  interrupts();             // enable all interrupts
}

ISR(TIMER1_OVF_vect)        // interrupt service routine 
{
  TCNT1 = timer1_counter;   // preload timer
  digitalWrite(LED_GREEN_PIN, digitalRead(LED_GREEN_PIN) ^ 1);
}

If you need to ask why I am not using delays or millis() - I am using some library which I can't work without and sadly it uses state machine for network communication and so the main loop can sometimes take a few secs or more.

I am using some library which I can't work without and sadly it uses state machine for serial communication via UART and so the main loop can sometimes take 5sec or more.

Total rubbish! POST YOUR CODE!

Mark

holmes4, I appreciate you taking your time for this but please be respectful.

The library, or even better, the specific function I call is is ArduinoHttpClient's get() function, which in turn calls startRequest(). As stated, I need this library and it has nothing to do with the main point of my question.

Let me add that I was able to solve this by having a timer which triggers every 50ms and then I only light up the led on n-th cycle and turn it off on (n+1)-th cycle and then do nothing for the other 19 cycles.

c0dehunter:
Let me add that I was able to solve this by having a timer which triggers every 50ms and then I only light up the led on n-th cycle and turn it off on (n+1)-th cycle and then do nothing for the other 19 cycles.

Care to share, for the benefit of future questioners?

c0dehunter:
I am able to blink LED 1 sec on, 1sec off with below code. I would like to keep the LED on only for i.e. 50ms. How to achieve this?

1. What is the meaning of 'blink LED'?

'Blink of LED' consists of 4 events: (a) 'LED ON', (b) 'remain ON for a while', (c) 'LED OFF'. and (d) 'remain OFF for a while'. When these events are mapped against time axis, we get the following line diagram:
blink1-sec.png
Figure-1: Events that form a Blink

In Fig-1, we will say that the LED is blinking at '1-sec interval' when the 'ON-period + OFF-period' is equal to 1-sec.

2. Do you want to implement the events of Fig-1 using TC1 (Timer/Counter Module 1) of the MCU where the On-period is 50 ms and the OFF-period is also 50 ms? We will be blinking L (built-in LED of UNO) at 100 ms interval.

(1) Be familiar with the structure/architecture of TC1 as Timer/Counter (L circuit is added/shown as an extra)


Figure-2: Structure/architecture of TC1 as Timer/Counter

(2) TC1 is said to be working as a 'Timer 1' when its receives the clocking/counting pulses (clkTC1) from the 16 MHz oscillator via these two clock dividers: 'System clock prescaler' and 'TC1 clock prescaler'; where the 'division factor' of the former is fixed at /1 by Arduino (divide by 1) and the 'division factor' of the later is to be set by the user as needed. TCNT1 stands for 'Timer/Counter Register 1', and it is the 'software name' for TC1; TOV1 stands for 'Timer/Counter 1 overflow flag'. Please, consult the data sheets to get the meanings of the remaining symbolic names (like CLKRR, TOIE1, etc.) used in Fig-2.

(3) Configure/initialize TC1 in such a way so that TOV1 flag gets activated (Logic High is the active state) at every 50 ms. This flag will help you to change the states of L (built-in LED of UNO) from ON to OFF and vice versa. The procedures are:

(a) Configure TC1 as 'Normal Up Counter' and keep it at 'OFF' condition with the help of TCCR1A and TCCR1B Registers (see data sheets).

TCCR1A = 0x00;
TCCR1B = 0x00;

(b) Assume clkTC1 = 16 MHz/256 (62500); calculate pre-set (n) value for TCNT1 so that TOV1 flag becomes active after counting k (known figure) number of clkTC1 pulses which is equivalent to the elapsed time of 50 ms.

0x10000 (overflow condition/count of TC1) = n + k
==> 0x10000 (overflow condition of TC1 = n + 62500*50*10[sup]-3[/sup]
==> n = 0x10000 -  3125 = 0x10000 - 0x0C35 
==> n = 0xF3CB

(c) Load the value of n into TCNT1.

TCNT1 = 0xF3CB;

(d) Start TC1 with this frequency: 62500 Hz with the help of TCCR1B Register (see data sheets).

TCCR1B = 0x04;

3. The codes are:

void setup()
{
   Serial.begin(9600);
   pinMode(13, OUTPUT);
   digitalWrite(13, LOW);         //L is OFF
   TCCR1A = 0x00;
   TCCR1B = 0x00;

   TCNT1 = 0xF3CB;     //pre-set value at clkTC1 = 16 MHz/256
   TCCR1B = 0x04;       //TC1 is running
}

void loop()
{
    while(bitRead(TIFR1, 0) !=HIGH)      //checking if TOV1 flag is acive; see data sheets for TIFR1 Register
    {
         ;     //wait until TOV1 becomes active at the elapse of 50 ms time
    }
    bitClear(TIFR1, 0);                         //clear TOV1 flag
    TCNT1 = 0xF3CB;                          //reload pre-set value
    digitalWrite(13, !digitalRead(13));     //L is OFF --> ON ---> OFF ---- 
}

BTW: To be sure that the program is working, make a visible affect of the result by changing the blink interval time to 2-sec (1-sec ON-period + 1-sec OFF-period).

blink1-sec.png

I am using some library which I can't work without

Fine.

Next question, please.

If it's blinking a LED, timing is not critical (a few milliseconds more or a few milliseconds less does not matter). So you can use millis() to achieve your LED timing. A small statemachine to indicate if you're in the 'off' mode or in the 'on' mode and a millis() based timing and the problem is solved.

@GolamMostafa, sterretje and others who are still suggesting to use millis() and loop(); let me explain a bit better why I can't use this (correct me please if I am wrong). Sometimes, I need to send some data to my server through GPRS and for that I use widely used ArduinoHttpClient (referenced in 3rd post), which uses state machine to handle this. The execution of this can sometimes take up to 5 seconds. In this time loop() will of course not run, so blinking of led will be paused. So, I am not able to use any solution based on loop() and millis().

I am sure the developers of ArduinoHttpClient optimized the code as much as possible. I don't want to write this code on my own just to keep a LED blinking.

@GolamMostafa, still thanks for the awesome information you provided. But since it is relying on regular loop() execution, I can't use this.

My solution is here (constructive critics welcome):

int timer1_counter;
volatile short timer1_entries = 0;

void setup() {
	noInterrupts();           // disable all interrupts
	TCCR1A = 0;
	TCCR1B = 0;
	
	timer1_counter = 0xF3CB; 	// 50ms
	
	TCNT1 = timer1_counter;   // preload timer
	TCCR1B |= (1 << CS12);    // 256 prescaler 
	TIMSK1 |= (1 << TOIE1);   // enable timer overflow interrupt
	interrupts();             // enable all interrupts
}

void loop() {
	if(someCondition)
		http.get("myserver.com/notify.php?flags=123"); // this can take up to 5 sec, but I'd like the LED to keep blinking
}

ISR(TIMER1_OVF_vect)        // interrupt service routine 
{
	TCNT1 = timer1_counter;   // preload timer
	timer1_entries++;
	if(timer1_entries == 0) {
		digitalWrite((LED_GREEN_PIN, HIGH);
	} else if(timer1_entries == 1) {
		digitalWrite(LED_GREEN_PIN, LOW);
	} else if(timer_entries == 19) {
		timer_entries = 0;
	}
}

c0dehunter:
@GolamMostafa, still thanks for the awesome information you provided. But since it is relying on regular loop() execution, I can't use this.

Then you can use the interrupt version of this, which is:

volatile bool flag1 = false;
void setup()
{
   Serial.begin(9600);
   pinMode(13, OUTPUT);
   digitalWrite(13, LOW);         //L is OFF
   TCCR1A = 0x00;
   TCCR1B = 0x00;

   TCNT1 = 0xF3CB;     //pre-set value at clkTC1 = 16 MHz/256

   bitSet(TIMSK1, 0);    //TOV1 interrupt is enabled
   bitSet(SREG, 7);       //global interrupt bit is enabled
 
   TCCR1B = 0x04;       //TC1 is running
}

void loop()
{
    if(flag1 == true)
    {
        digitalWrite(13, !digitalRead(13));     //change state of L: L is OFF --> ON ---> OFF ---- 
        flag1 = false;
    }
}

ISR(TIMER1_OVF_vect)
{
    TCNT1 = 0xF3CB;                          //reload pre-set value
     flag1 = true;
}

@c0dehunter

Since you’re committed to doing this with a hardware timer, you might as well do it in the most efficient way possible. Using an ISR and calling digitalWrite (ugh) from within it is very sub-optimal (and IMO, kind of hacky) considering you could have the hardware do everything for you.

Instead, you could use Timer 1 to create a 1 Hz PWM signal that has a 50 ms “On” time. Doing it this way would restrict you to using signals PB1 or PB2 (pins 9 / 10 on an Uno) for your output. But, in exchange for that restriction, this technique would require no interaction from your code other than initializing the proper register values in your setup() function. After that, the hardware will take care of the rest.

if you have network access you can use a cloud based timer such as blynk, that way you don't have to put your code into loop()

this is how I did my clock timer