"one shot" timer/interrupt

I tried to find some examples but I failed. Most examples work with infinitive timers (blinking LED) and most examples start with commands like "stop all interrupts" and "start all interrupts". I don't want to do this!

I am writing a short program which turns a motor controlled by an infrared remote control. The program must work absolutely reliably, that means: the motor must not turn until I press the right key on the remote control. That's why I count the successful detection of IR pulses and I switch the motor on if there are 10 correct pulses which means I have to press the key for about 1,5 seconds. This counter is set to zero if a wrong key is pressed.

The program works already quite well, but I also want to have a timer which sets the counter to zero if 10 pulses have not been counted within 2 seconds.

This means: I want to start a timer when the first pulse is detected and after 2 seconds an interrupt function should set the counter to zero and should also disable the timer. And of course I want to start/stop only this timer because the IR detection uses another timer and must not be disturbed.

Is there an example how I can do this?

Paul

Big difference between disabling a timer and turning it on-off. Which do you really want?

Paul

The program works already quite well, but I also want to have a timer which sets the counter to zero if 10 pulses have not been counted within 2 seconds.

You don’t need any complicated interrupt for this. Use millis:

pseudocode:

if(get signal from IR remote){
   lastSignal = millis();  // record time of last signal
}

if(millis() - lastSignal >= 2000){  // if 2 secnods or more since last signal
  counter = 0;  // or whatever to reset your count.
}

Paul_KD7HB:
Big difference between disabling a timer and turning it on-off. Which do you really want?

Paul

2 seconds after event "A" I want to trigger event "B", but only one time, event "B" must not be triggered again after another 2 seconds. I don't care whether I disable the timer or switch it off - what is easier?

Plenz:
what is easier?

Forget the timer and use millis.

Delta_G:
You don't need any complicated interrupt for this. Use millis:

pseudocode:

if(get signal from IR remote){

lastSignal = millis();  // record time of last signal
}

if(millis() - lastSignal >= 2000){  // if 2 secnods or more since last signal
 counter = 0;  // or whatever to reset your count.
}

I have this loop:

void loop() {
  if (irrecv.decode(&results)) {
       // do something
    }
    irrecv.resume(); // Receive the next value
  }
}

AFAIK, "irrecv.resume()" stops and waits until there is a new result. During the waiting time, I can not execute any code. But I want the counter to be set to zero after 2 seconds, so I have to use an interrupt.

AFAIK, "irrecv.resume()" stops and waits until there is a new result

That is not even remotely true. Where did you hear that? It just resets things so that it can get a new result. But it doesn't block.

I wouldn't tell you that you don't need an interrupt if you did.

Delta_G:
That is not even remotely true. Where did you hear that? It just resets things so that it can get a new result. But it doesn't block.

I wouldn't tell you that you don't need an interrupt if you did.

I did not hear this, I tried it out. But it seems that I made a mistake or misunderstood something.

Now I tried it again and it works perfectly. Thank you very much for your suggestions.

So you want something like
Event 1 Appeands
Timer
Event 2 appeands
Continue normal loop()

Question: do you want that normal loop can continue during timer? If no you can simply use

if (A())
{
delay (timer);
B();
}

Else you can

if (A())
{
flag=1;
timeprec=millis();
}
if (flag && millis use)
{
B();
flag=0;
}

Silente:
Question: do you want that normal loop can continue during timer? If no you can simply use

Sorry, but this is easy stuff and I wrote it already by myself. I am not a beginner (even if I make stupid mistakes sometimes) and I needed only some know-how about timers and interrupts.

Paul_KD7HB:
Big difference between disabling a timer and turning it on-off. Which do you really want?

Do we have any register level bit (s) that enable/disable TC0/TC1/TC2 of ATmega328? like the TWIEN and ADEN bits for TWI Bus and ADC Module.

TC0/TC1/TC2 come into 'run (start/ON)' state when they are connected with clocking pulses, the source of which could be the internal oscillator (or from from external source -- only for TC0/TC1). The connection is established via the TC Prescaler Register. The TCs become OFF when the clocking pulses are disconnected using the same prescaler register.

The TCs have interrupts generating capabilities which could be enabled/disabled by manipulating the relevant bits of the respective control registers.

Plenz:
Sorry, but this is easy stuff and I wrote it already by myself. I am not a beginner (even if I make stupid mistakes sometimes) and I needed only some know-how about timers and timer interrupts.

The following diagram which depicts the internal structure of TC1 of the ATmega328P MCU of the Arduino UNO Board. It could be helpful for you.

(1) There are many modes of operations of TC1 Module. The book name is TC1 and the software name is TCNT1. It is a 16-bit register.

(2) When the TC1 receives its clocking pulse (clkTC1) from the internal oscillator, we say that the TC1 is working as Timer-1. The frequency of the clkTC1 can be varied by changing the switches of the 'TC1 Clock Prescaler'. The switch position of 'System Clock Prescaler' is permanently fixed at divide by 1 position by the UNO initialization routine.

(3) The TC1 is said to be working as Counter-1 when it receives the clocking pulse from external source via its physical pin-11 (DPIn-5 of UNO).

(4) In 'normal counter' mode operation, the TC1 just works as a up-counter register and begins counting from 0x0000. The full count is 0xFFFF. After the arrival of the next clocking pulse, the count turns from all 1s to all 0s (FFFF + 1 = 1 0000). In such case, we say that an overflow/roll-over event has occurred. When the overflow event occurs, the TOV1 flag is automatically assumes LH-state.

(5) If SW1 and SW2 switches (software switches) are kept in closed conditions, the TOV1 flag of Step-4 can interrupt the MCU.

(6) The MCU (user program) can detect the overflow event through interrupt or by polling (looking time-to-time) the value of TOV1 flag.

(7) Generation of 2-sec time delay using Timer-1 to blink L (built-in LED of UNO) at 2-sec interval.

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

  //compute preset value (n) with clkTC1 = clkSYS/1024 =16525 Hz
  //0x10000 = n + 16525x2 (counts for 2-sec)
  // n =32486 = 0x7EE6
  TCNT1 = 0x7EE6;
  TCCR1B = 0x05;   //Timer-1 ON with clkTC1 = 16525 Hz  
}

void loop() 
{
  while(bitRead(TIFR1,0) != HIGH)   // Edit: reading value of TOV1 flag and testing it against HIGH
    ;                             //wait until overflow happens
  bitSet(TIFR1, 0);     //clear TOV1 flag
  TCNT1 = 0x7EE6;       //reload preset value
  digitalWrite(13, !digitalRead(13)); //blink L at 2-sec interval 

}

I don't understand:
In loop you use an empty while{}, and you commented "waiting the overflow". But in the while condiction there is a bitread of a variable. How can variable change, if prigram enter in the while?

Silente:
I don't understand:
In loop you use an empty while{}, and you commented "waiting the overflow". But in the while condiction there is a bitread of a variable. How can variable change, if prigram enter in the while?

Interrupts, In this case TIFR1. It is the timer1 overflow flag.
Its not a variable just a bit in a register, but it could be (a variable)just as easily.

Silente:
I don't understand:
In loop you use an empty while{}, and you commented "waiting the overflow". But in the while condiction there is a bitread of a variable. How can variable change, if prigram enter in the while?

1. We have to wait until 2-sec time has elapsed from the time of the 'START' of TC1.

2. At the end of 2-sec time, the TOV1 flag of the following TIFR1 Register assumes LH-state. The flag makes a a transition from LL to LH exactly at the time when overflow/roll-over event happens.

3. Now, we can write the following algorithm to check the value of TOV1 flag against LH.

L1: bool n = bitRead(TIFR1, 0);     //reading the value of TOV1 flag bit
if (n == HIGH)
{
   //2-sec has elapsed
   bitSet(TIFR1, 0);                //TOV1 flag is cleared by writing LH into its position
   TCNT1 = 0x7EE6;              //reload preset value 
}

else
{
   goto L1;           //check gaian
}

If I am asked to shorten the above codes, I would write the following using while-do structure:

while(bitRead(TIFR1, 0) != HIGH)
{
   ;
}
//2-sec has elapsed
bitSet(TIFR1, 0);                //TOV1 flag is cleared by writing LH into its position
TCNT1 = 0x7EE6;              //reload preset value

Once again @Golam, you have severely overcomplicated this issue. OP had working code without all this mess way back at #7. There's no need for any hardware timer magic here.