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 Answer 1

2

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();
}
2
  • 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. Commented Jan 13, 2019 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. Commented Jan 13, 2019 at 15:28

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.