35

TL;DR : When writing an Interrupt Service Routine (ISR): Keep it short Don't use delay () Don't do serial prints Make variables shared with the main code volatile Variables shared with main code may need to be protected by "critical sections" (see below) Don't try to turn interrupts off or on What are interrupts? Most processors have interrupts. ...


27

You can do this using external interrupts. Most Arduinos only support this on a limited number of pins though. For full details, see the documentation on attachInterrupt(). Assuming you're using an Uno, you could do it like this: void pinChanged() { //... } void setup() { pinMode(2, INPUT); attachInterrupt(0, pinChanged, CHANGE); } void loop()...


17

There are two types of "pin change" type interrupts. The external interrupts, of which there are two on the Uno. They are called 0 and 1, however they refer to digital pins 2 and 3 on the board. These can be configured to detect rising, falling, change (rising or falling) or LOW. In addition to that are "pin change" interrupts, which detect a change to the ...


16

The other answers are very good, but I want to elaborate on how micros() works. It always reads the current hardware timer (possibly TCNT0) which is constantly being updated by the hardware (in fact, every 4 µs because of the prescaler of 64). It then adds in the Timer 0 overflow count, which is updated by a timer overflow interrupt (multiplied by 256). ...


14

First, it's volatile not Volatile. I cover these concepts in my page about Interrupts however to avoid giving a link-only answer I'll repeat the relevant bits. What are "volatile" variables? Variables shared between ISR functions and normal functions should be declared volatile. This tells the compiler that such variables might change at any time, and thus ...


11

Interrupts are what you would use in this situation. The rates that you have mentioned are slow enough where you probably would be able to count it inside of a loop, however this is not recommended, as a typical loop will take many clock cycles to complete, and depending on the number of instuctiuons per loop, you may miss some counts. Interrupts are made ...


9

volatile only informs the compiler's code generator that the variable may be modified by something other than the code being generated, so not to assume any copy of it remains accurate. ISR code must be written/generated under the assumption that it has no context at entry, and preserve the CPU's context around its (ISR's) own operation. So, as with the ...


9

Handling multiple patterns at the same time is certainly possible with a platform like Arduino, and there are a number of ways you could go about it. One method I would consider is writing functions which effectively represent each pattern mathematically. You'd just pass it the total time that's elapsed in your program so far, and it will do the appropriate ...


9

You need to reset IRQCount back to 0 before attaching the interrupt again. Otherwise it will just continue counting from where it stopped last time. I would actually keep the interrupt attached and just reset the variable just before the delay. That way the overhead of attach/detachinterrupt doesn't get added to the 25ms delay. volatile int IRQcount; int ...


9

You need to learn about critical sections. What is probably happening is that the variables are being changed by the interrupt routines mid-way through the calculations. Your 'fix' reduces the time spent doing the calculation with the volatile variables thus making it less likely that there is a collision. What you should do is copy the volatile variables ...


9

Here is an analogy for you to help you understand why using the IRQ is a good idea. Imagine you are at a conference. There's hundreds of you in the audience, and you are in a question and answer session with the person on the stage. Maybe their presentation has just come to the end and they're fielding questions from the audience. Lots of people have ...


9

Just because a pin is called "interrupt" doesn't mean that you have to read it using an interrupt input. The INTx pins of the ADXL345 are simple "level" outputs. All the time there is an "interrupt" pending (a signal from the ADXL345 that something has happened) the corresponding INT pin is held LOW. It remains LOW until the interrupt has been handled by ...


8

There are two types of interrupts. What the Arduino Playground said: The processor at the heart of any Arduino has two different kinds of interrupts: “external”, and “pin change”. There are only two external interrupt pins on the ATmega168/328 (ie, in the Arduino Uno/Nano/Duemilanove), INT0 and INT1, and they are mapped to Arduino pins 2 and 3. These ...


8

sleep_enable() allows the MCU to sleep, but it does not cause it to sleep. Call sleep_cpu() after enabling.


8

After some digging around in the core, it seems like Arduino updates millis() with a 8 bit timer: it uses overflow with a prescaler value of 64. In simpler terms, it has it set up so a certain piece of code (the ISR) is run approximately once per millisecond on a 16MHz system (and proportionately less frequently on slower clocked systems). When that ISR is ...


8

Imagine that you have the circuit below: simulate this circuit – Schematic created using CircuitLab Let's say that you wanted to catch the user pressing the button. The input signal will go from high to low, which is a falling edge. So you would use a FALLING interrupt to catch this event. Easy, right? Now let's say you wanted to catch a user ...


8

It is not wrong to use millis() or micros() within an interrupt routine. It is wrong to use them incorrectly. The main thing here is that while you are in an interrupt routine "the clock isn't ticking". millis() and micros() won't change (well, micros() will initially, but once it goes past that magic millisecond point where a millisecond tick is required ...


8

You cannot use Serial inside an interrupt. Transmitting Serial relies on interrupts being available, and from inside an interrupt they aren't. All Serial communication must be done from loop(). So you need to just count the switch toggles and check to see if that value has changed in your loop. volatile uint32_t toggles = 0; uint32_t old_toggles = 0; ...


7

Have a look at the code for attachInterrupt() and detachInterrupt() in /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/WInterrupts.c (well, that's where they are on a Mac, anyway. Arduino file structure on other OSes' probably looks similar in the lower levels of the path). It appears that attachInterrupt() assumes that the ...


7

This is what I have managed to achieve ... Library IRLib - GitHub Version 1.51 March 2015 Copyright 2013-2015 by Chris Young http://tech.cyborg5.com/irlib/ This library is a major rewrite of IRemote by Ken Shirriff which was covered by GNU LESSER GENERAL PUBLIC LICENSE ... Code Modified code (from the demo IRrecord example): /* Example ...


7

the timer will set the Timer Interrupt Flag (TIFR0 register) The ISR will be called, and the flag will be cleared you do some long calculations or something the timer will match OCR0A, and set the interrupt flag again. you calculations are done, and the ISR function will end. the uC will jump back to the main loop code, and execute 2 1 instructions. The uC ...


6

The interrupt pins are used to notify the MCU that a device needs attention. The INTx pins are chosen first because they are easy to program for; each gets a dedicated interrupt vector and hence ISR. There is another type of external interrupt though, the Pin Change interrupt. This can be invoked via any of the PCINTxx pins on the device; on the '328 any ...


6

Use the analog comparator in the ATmega328P to trigger an interrupt once the input voltage rises enough to indicate a button press. Connect the analog network to both the analog input and D6. If your lowest analog voltage is not greater than 1.2V then apply a voltage greater than 0V but more than 40mV less than your lowest analog voltage to D7. If you have ...


6

On a Uno, all of the digital and analog pins can trigger a pin-change interrupt. That gives you 20 inputs straight away. The Mega also has pin change interrupts but not on all its pins. The pins that the Mega supports for pin-change interrupts are documented on the Software Serial page. Not all pins on the Arduino Mega and Arduino Mega 2560 support change ...


6

Well, this code worked. In this code, MPU's INT PIN is Active Low so generates Ground on motion which is than connected to INT0 or arduino UNO pin 2 which generates interrupt and wakes UP the MCU #include <avr/sleep.h> #include <Wire.h> //Analog port 4 (A4) = SDA (serial data) //Analog port 5 (A5) = SCL (serial clock) #define SIGNAL_PATH_RESET ...


6

You would want your bool LED_STATE = false; to be volatile qualified like volatile bool LED_STATE = false; otherwise the compiler's optimizer may assume that the value cannot be changing between loads and this can cause bugs in the generated code. This sounds like the principal problem you're having. The ISC01 and ISC00 in MCUCR are for controlling edges ...


5

Any state of change on any pin configured as digital input can create an interrupt. Unlike the unique vectors for the interrupts causes by INT1 or INT2 the PinChangeInt feature uses a common vector and then Interrupt Service Routine (aka ISR) for this vector needs to then determine which pin changed. Fortunately PinChangeInt Library makes this easy. ...


5

Turns out the problem was that timer 0 and 2 on the arduino uno are 8 bit. Set a different prescaler and I'm golden // set up Timer 2 TCCR2A = 0; // normal mode TCCR2B = 0; // TCCR2A = bit(WGM21) | bit(CS21); // CTC, scale to clock / 8 TCCR2A = (1 << WGM21); //Enables CTC for timer TCCR2B |= (1 << CS21); TCCR2B |= (...


Only top voted, non community-wiki answers of a minimum length are eligible