Go Down

Topic: How to create 3th interrupt (Read 10399 times) previous topic - next topic

Coding Badly

Why bother saving SREG and then restoring it? Why not just use the matching sei() call with cli()

There are times when sei() is not safe to use.  The pattern I presented is always safe to use with a very minimal cost (I believe one more machine instruction).  Basically, there's less to remember and understand so mistakes are less likely.

Secondly, isn't retrieving the value of the counter an indivisible call?

No.  Anything larger than a byte is not atomic.  (That's not entirely true.  A few 16 bit operations are atomic.  But less to remember + low cost = good so we'll always use the code I presented, right?  :D)

It would matter if he were retrieving the value, modifying it, and then writing back, but in this case he is simply retrieving the value.

It is not possible for an 8 bit processor to perform any operation atomicly on a 32 bit value.  Just reading the value requires four machine instructions; an interrupt can occur between any of them.

I do not understand why that must portion of code must be atomic.

Does the explanation above help or do I need to provide more details?


OK guys, it seems this is getting pretty complex (at least for me)  :-?.

Let me explain a bit what I'm trying to do:

I need to count pulses from 3 sensors:
  • Counter1: idle = low, pulse = high, max 1 pulse every +/- 10 secs, and every hour this pulse stays high for about 60 secs
  • Counter2: idle = low, pulse = high, max 3 pulses in 1 sec
  • Counter3: idle = high, pulse = low, max 2 pulses in 1 sec, pulse can stay low for several hours

In my current setup I just count the pulses in the loop(), push the counter values over serial to my PC every 30 secs and reset them to 0, but people told me that i will miss pulses this way. So I'm looking for a more robust/safer way to count the pulses.

Seen that there are only 2 attachInterrupts, I was looking to or add a 3th interrupt, or don't use attachInterrupt and create the 3 interrupts manually.

I'm getting great help and feedback from this wonderful community but as mentioned at the beginning of this post, it seems to become complex. Now I'm asking myself: Is this complexity needed for what I'm trying to accomplish?

In the near future, I will be replacing the serial/usb connection to my pc with a wireless connection (RFM12B).
I also have 1-Wire devices connected to this arduino, but if you guys suggest me that it would make more sense to move this to another arduino, i will do so.

Thats about what i have at the moment, but lets focus for the moment on the counter part as that is the most important one for me.

Thanks in advance,



Why not use interrupts for the two fastest pulse sources and monitor the slowest in loop, this will work if the pulse duration is always longer than the pulse duration.
What is the duration of the pulses and what else is your application doing in loop?



Pulse duration:
  • Counter1: on average 1 sec, with once an hour about 60secs
  • Counter2: 90ms iirc (need to check the datasheet at home)
  • Counter3: variable. This is a pulse contact on a water meter.

For the rest my loop checks if 30 secs are passed, and if so, send the counters to the serial and reset them to 0 again.
I also read a bunch of 1-wire temp sensors (mix of DS18S20 and DS18B20) every 60 secs, and push those readings straight to serial.



Dec 17, 2009, 11:54 am Last Edit: Dec 17, 2009, 11:56 am by mem Reason: 1
Counter 1 looks do-able from within loop.  You can monitor the duration of your loop with something like this.
Code: [Select]
unsigned long startTime = 0;
unsigned long minDuration = 999999;

void loop()
 startTime = millis();

 // your loop code here

 unsigned long dur = millis() - startTime;
 if(dur < minDuration)
   minDuration = dur;
   Serial.print("Minimum loop duration is ");

If the minimum loop duration is well under 1000 (1 second) then you should be ok handling counter 1 in loop


@Coding Badly

Great explanations. Can you please elaborate more on the following or provide some reading material. The AVR libc documentation on sei is rather brief.

There are times when sei() is not safe to use.


I too need an explanation.  I found this in interrupt.h...
Code: [Select]
# define sei()  __asm__ __volatile__ ("sei" ::)

I don't understand how this could be unsafe.

Coding Badly

Unfortunately, my replies have turned into a distraction.  I'd like to continue the ISR discussion here...


Go Up