Как обрабатывать одновременный HTTP-запрос при использовании прерывания

Пытаюсь сделать дверной датчик с герконом. Каждый раз, когда происходит изменение, ESP8266 отправляет HTTP-запрос веб-сервису.

К сожалению, последовательный монитор ESP8266 сбрасывает огромную трассировку стека, когда я приближаюсь к магниту к геркону:

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...

Я думаю, это потому, что ESP8266 пытается выполнять одновременные HTTP-вызовы... Как я могу решить эту проблему?

Вот код:

// 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();
}

, 👍0


1 ответ


Лучший ответ:

2

Просто: не выполняйте HTTP-запросы в прерывании.

Обычно плохо делать что-то такое тяжелое во время прерывания. Вместо этого вам следует просто установить флаг в прерывании ( Летучее логическое значение) и проверить этот флаг в 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();
}
,

Действительно, это было просто :) Спасибо. В этом случае мне может понадобиться какая-то очередь. если геркон размыкается/закрывается очень быстро, переменная состояния тем временем может измениться., @Kaymaz

Действительно, возможно. В таком случае, вместо очереди, почему бы не просто подсчитать? Если в данный момент он ВЫСОКИЙ и было 3 перехода, вы знаете, что они были бы ВЫСОКИМ, НИЗКИМ, ВЫСОКИМ, чтобы добраться до того места, где вы находитесь сейчас. Сбросьте счетчик при отправке., @Majenko