Jakadinho
Jakadinho

Reputation: 701

Arduino not going to sleep when interrupt running

I wrote a small script to measure wind speed with anemometer. I want to measure for 2 seconds than sleep for 8s...

If there is no wind sleep works fine, but while anemometer is rotating arduino wont go to sleep. How would I fix my code to go to sleep no matter what.

Here is my code..

#include "LowPower.h"

const byte interruptPin = 3;  // anemomter input to digital pin
volatile unsigned long elapsedTime = 0;
int interval;
long WindAvr = 0;       // sum of all wind speed between update
int measure_count = 0;  // count each mesurement
unsigned int WindSpeed;

void setup() {
    Serial.begin(9600);
    attachInterrupt(
        digitalPinToInterrupt(interruptPin), anemometerISR,
        FALLING);  // setup interrupt on anemometer input pin, interrupt will
                   // occur whenever falling edge is detected
}

void loop() {
    WindAvr = 0;
    measure_count = 0;
    sei();        // Enables interrupts
    delay(2000);  // Wait x second to average
    cli();        // Disable interrupts
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);

    WindSpeed = WindAvr / measure_count;
    Serial.println(WindSpeed);
}
void anemometerISR() {
    cli();  // Disable interrupts
    static unsigned long previousTime = 0;
    unsigned long time = millis();

    if (time - previousTime > 15) {  // debounce the switch contact.
        elapsedTime = time - previousTime;
        previousTime = time;

        if (elapsedTime < 2000) {
            interval = (22500 / elapsedTime) * 0.868976242;
            WindAvr += interval;  // add to sum of average wind values
            ++measure_count;      // add +1 to counter

        } else {
            ++measure_count;  // add +1 to counter
        }
    }

    sei();  // Enables interrupts
}

Upvotes: 1

Views: 230

Answers (1)

David Collins
David Collins

Reputation: 3032

An external interrupt - once 'un-masked' - has the ability to wake the device up even if the global I flag is unset using cli().

Change

cli();        // Disable interrupts
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);

to

detachInterrupt(digitalPinToInterrupt(interruptPin));
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
attachInterrupt(digitalPinToInterrupt(interruptPin), anemometerISR, FALLING);

Also ... I believe that your cli() and sei() statements within the ISR are unnecessary. The global interrupt enable bit is automatically disabled / enabled when entering / exiting an ISR. From the Atmega644 manual:

When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled. The user software can write logic one to the I-bit to enable nested interrupts. All enabled interrupts can then interrupt the current interrupt routine. The I-bit is automatically set when a Return from Interrupt instruction – RETI – is executed.

Upvotes: 2

Related Questions