2

I want to use interrupts on my ESP 8266 to monitor the digital outputs of a power meter and water meter.

The idea is to increment a counter in the ISRs and at some point to take the value of the counter and to set the counter back to 0 in the loop() function. I've red about critical sections, noInterrupts() and interrupts() and then I started to wonder if an ISR will be executed while the code is between noInterrupts() and interrupts(). On theory it should be because the interrupt flag in the chip will be raised and the ISR will be invoked after the code exits the critical section. I wrote a program to test it, but my findings prove the opposite.

#include <Arduino.h>
 
#define REPORT_TIME 5000
#define INTERRUPT_PIN D1

unsigned long base_time;

volatile unsigned int interrupt_counter = 0;


void IRAM_ATTR isr() {
  interrupt_counter++;
}

void setup() {
  Serial.begin(115200);

  // The interrupt will be FALLING EDGE
  pinMode(INTERRUPT_PIN, INPUT_PULLUP);
  pinMode(LED_BUILTIN_AUX, OUTPUT);
  digitalWrite(LED_BUILTIN_AUX, HIGH);
  attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), isr, FALLING);

  base_time = millis();
}

bool written = false;

void loop() {

  if (!written)
  {
    written = true;
    for (int i = 0; i < 100; i++)
    {
      digitalWrite(LED_BUILTIN_AUX, LOW);
      digitalWrite(LED_BUILTIN_AUX, HIGH);
    }
  }
  

  unsigned long time_now = millis();
  if (time_now - base_time >= REPORT_TIME)
  {

    written = false;

    base_time = time_now;

    unsigned int interrupt_counter_local;

    //Guard the critical section
    noInterrupts();
    interrupt_counter_local = interrupt_counter;
    interrupts();

    digitalWrite(LED_BUILTIN_AUX, LOW);
    digitalWrite(LED_BUILTIN_AUX, HIGH);

    Serial.print("counter ");
    Serial.println(interrupt_counter_local);
    Serial.println();
  }
}

Using a wire I attached the pin of the builtin led to the interrupt pin and in the serial monitor I could see the values are:

counter 100
counter 201
counter 302

When I modify the critical section to be like:

noInterrupts();
interrupt_counter_local = interrupt_counter;
digitalWrite(LED_BUILTIN_AUX, LOW);
digitalWrite(LED_BUILTIN_AUX, HIGH);
interrupts();

I expect the same output as above but the values are:

counter 100
counter 200
counter 300

Am I missing something or the interrupts doesn't work as I expect?

1 Answer 1

1

After some additional experiments I found that moving

digitalWrite(LED_BUILTIN_AUX, HIGH);

utside the critical section gives me the expected result, so I'm not blocked anymore and more importantly the chip will not drop an interrupt. If someone knows why it doesn't work with my initial version I will be happy to hear the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.