0

I'm trying to make a door sensor with a reed switch. Each time the there is a change, the ESP8266 sends an HTTP request to web service.

Unfortunately, the ESP8266 serial monitor dumps a huge stack trace when I'm approaching the magnet to the reed switch:

Exception (9):
epc1=0x40104b14 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000003 depc=0x00000000

ctx: sys 
sp: 3fffeb20 end: 3fffffb0 offset: 01a0

>>>stack>>>
3fffecc0:  00000002 00000006 3ffefdc4 40227108  
3fffecd0:  3ffefa74 00000002 00000014 401004e4  
3fffece0:  3ffeffbc 3ffeffc0 00000006 00000001  
3fffecf0:  402253bc 00000000 00000010 00000000  
3fffed00:  00000000 4bc6a7f0 81cac083 00000000  
3fffed10:  00000000 00000000 4bc6a7f0 00000000  
3fffed20:  40104d40 0037d809 3ffeecd0 00000000  
3fffed30:  3ffee520 3ffeecd0 3ffeffbc 40224398  
3fffed40:  00000000 00200085 40201578 00001388  
3fffed50:  3ffeecd0 00000000 00000050 00000050  
3fffed60:  00000000 3fffedd0 3ffefd34 402032e5  
3fffed70:  1301a8c0 00000031 3ffeebbc 402039cc  
3fffed80:  3ffeedb8 000000ef 000000ef 00000020  
3fffed90:  ffffffff 00000050 3fffedd0 40202d5c  
3fffeda0:  40204738 1301a8c0 40204738 1301a8c0  
3fffedb0:  3ffe8a64 00000005 000...

I think it's because the ESP8266 tries to make concurrent HTTP calls... How can I solve this?

Here is the code:

// https://www.instructables.com/id/Arduino-Software-debouncing-in-interrupt-function/
// #include "util/atomic.h" 
#include "ESP8266WiFi.h"
#include "ESP8266HTTPClient.h"
#include "Wire.h"

const char* ssid = "****";
const char* pass = "****";
const byte interruptPin = 5;
long debouncing_time = 50; //Debouncing Time in Milliseconds
volatile unsigned long last_micros;
const char* host= "192.168.1.19";
const char* doorStates[2] = {"closed", "opened"};

void connection()
{
  // Establish a WIFI connection
}

void setup()
{
  Serial.begin(115200);
  connection();
  pinMode(interruptPin, OUTPUT);

  // Attaching interrupt
  attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, CHANGE);
}

void loop()
{
  delay(1000);
}

void handleInterrupt() {
  if ((long)(micros() - last_micros) >= debouncing_time * 1000) {
    int val = digitalRead(interruptPin);
      notify(val);
  }
  last_micros = micros();
}
// Make HTTP Call to web service
void notify(int val)
{ 
  WiFiClient client;
  const String frontDoorState = doorStates[val];
  String url = "http://192.168.1.19/alarm/front-door/state/" + frontDoorState;
  client.connect(host, 80);
    client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                 "Host: 192.168.1.19\r\n" +
                 "Connection: close\r\n\r\n");
                 client.stop();
}
1

Simple: don't do HTTP requests in the interrupt.

It's usually bad to do anything heavy like that in an interrupt. Instead you should just set a flag in the interrupt (volatile bool) and examine that flag in loop().

volatile bool sendNotification = false;
volatile int notifyVal = 0;

void loop() {
    if (sendNotification) {
        notify(notifyVal);
        sendNotification = false;
    }
}

void handleInterrupt() {
    if ((long)(micros() - last_micros) >= debouncing_time * 1000) {
        notifyVal = digitalRead(interruptPin);
        sendNotification = true;
    }
    last_micros = micros();
}
  • Indeed, it was simple :) Thank you. I might need some kind of queue in this case. if the reed switch is open/close very quickly, the state variable might be changed in the meantime. – Kaymaz Jan 13 at 15:26
  • Indeed it might. In that case, instead of a queue, why not just a count? If it's currently HIGH and there have been 3 transitions, you know they would have been HIGH, LOW, HIGH to get to where you are now. Reset the count as you send it. – Majenko Jan 13 at 15:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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