Skip to main content
Arduino

Return to Revisions

1 of 2
hobbs
  • 234
  • 1
  • 7

Majenko's answer is useful — you can simply forego the use of interrupts for this and poll the pin directly in your main loop. Especially on AVR where the external pins are exposed as registers which can be read as fast as main memory this is a reasonable approach. But what if you really want the code to be "interrupt-fast" without writing code that might deadlock an ISR handler? Given the case of a fall or impact sensor, latency might be a genuine issue. Well, there are some things you can do.

First, structure your code so that you never go too long without polling the pin. That means that every bit of code needs to either return to the main loop within an acceptably short period of time, or else needs to take on the job of periodically polling the pin itself. Large compute tasks should have polls sprinkled into them, or be broken into subtasks that can be run by a state machine in the main loop. Long delays should be rewritten in the form

start = micros();
while (micros() - start < howLong) {
 // poll the ADXL interrupt
}

or, again, avoided entirely by having the thing that would have delayed queue up work for the main loop to run later.

Second, consider using direct port access for the polling. A check like if (PORTB & (1<<3)) compiles down to a bare couple of instructions, and costs 2 cycles if the interrupt isn't actually asserted (which will be the usual case). Doing if (digitalRead(port)) does a call to a function which takes around 25 times as long. It's still only a few microseconds, but if you've taken the advice of the previous step to poll as frequently as possible to minimize latency, then you don't want all of those microseconds to add up and impact the performance of other code.

Lastly, a technique that doesn't make a lot of sense for this scenario, but could be applicable if you were running on a system other than an AVR-based Arduino, or if you wanted to react to some interrupt other than a level-triggered pin interrupt: instead of polling the port directly, you could keep the ISR, but instead of doing any work, the ISR would set a global volatile variable to true and then immediately return. Everywhere you would poll the port, you check the value of that variable instead, and if it's true, then you run your "interrupt handler" code (and reset the variable to false, of course!). The handler runs shortly after the interrupt triggers, but it's run in an interrupts-on context where it's safe to do slower operations or operations that require timer interrupts to work. This is equivalent to the old Linux concept of "bottom halves".

hobbs
  • 234
  • 1
  • 7

AltStyle によって変換されたページ (->オリジナル) /