Hi,
I am trying to figure out when I should be using an interrupt vs. just checking in loop(). I have a simple reed switch that I need to monitor and publish events based on the state change. I can easily do that inside loop(), but an interrupt sounds more appropriate.
So, I have been trying an interrupt, but it seems to have plenty of limitations. e.g. you have to declare variables that you change inside an interrupt as volatile
, but Spark.variable
doesn’t seem to expect a volatile
variable (which I need to expose).
I also read somewhere that Spark.publish
shouldn’t be used inside an interrupt (haven’t verified).
So, when are interrupts appropriate?
An interrupt blocks everything but higher priority interrupts, so you should make sure the code is quick and can’t hang. Spark.variable likely relies on interrupts since it’s calling WiFi, cloud and other code.
volatile ensures that a variable isn’t just held in a CPU register and ensures it’s written to physical RAM when it changes. Mostly good for multiple threads. It shouldn’t effect a function that’s not modifying it, so you should be able to get away with casting it.
A slow change method with a bit of debounce could be like this
volatile bool swAck;
volatile bool swState;
void switchIsr()
{
if(swState != swAck)
return;
swState = digitalRead(Dx);
}
...in loop...
if(swState != swAck)
{
swAck = swState;
publish change
}
...
If you expect a fast count and don’t need any debounce, try something like this for rising or falling edge interrupts. For change, you’d need to add a bit more code. Otherwise it’s counting every change but you can assume even/odd is always low/high from the initial state.
volatile int switchCnt;
void switchIsr()
{
swCount++;
}
...in setup...
pinMode(Dx, INPUT); or INPUT_PULLUP
attachInterrupt(Dx, switchIsr, RISING); or FALLING or CHANGE
...
...in loop...
if(swCount)
{
publish count here
swCount = 0;
}
...
Thanks for explanation of how the ISR should be coded. So, what’s the benefit of doing this in an ISR vs. the loop?
Polling in the main loop only checks the state of the register when you get to it. An interrupt will be called at the instant it changes. So you’re going to get the change even if it’s within a microsecond or so, while polling may miss a change or even several depending on how fast you’re reading it. It’s a bit like checking your POP3 email every hour vs. server pushes.
One thing I forgot to mention is that your normal code can be interrupted at any point. Even in the middle of checking a variable modified by the ISR, but the main code won’t run until the ISR code completes. So if volatile variables get confusing, suspect that.
I see. Sounds good. Thanks for all your insight!