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
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– Kaymaz01/13/2019 15:26:25Commented 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.Majenko– Majenko01/13/2019 15:28:15Commented Jan 13, 2019 at 15:28