Problem mit Interrupt
- Jo
- Autor
- Offline
- New Member
Weniger
Mehr
- Beiträge: 3
- Dank erhalten: 0
01 Mär 2020 11:05 #640
von Jo
Jo erstellte das Thema Problem mit Interrupt
Hallo allerseits
Habe ein hartnäckiges Problem mit einem Interrupt. Folgender Code läuft auf einer ESP8266
NodeMCU:
Der Interrupt an sich läuft zuverlässig auf "CHANGE", doch bei der Abfrage des momentanen Zustandes vom Eingang
"interruptGate" (in der ISR-Routine) erhält die Variable dr nicht immer den richtigen Wert.
Alle Hardwareteile sind geprüft und nicht defekt. Habe das auch mit externen Pullup-Widerständen getestet, von
10K runter auf 680R - keine Besserung.
Mit der Debounce-Time habe ich auch variiert, der Wert 20 reicht völlig,
Habe viele Varianten getestet, doch nichts war wirklich zuverlässig.
Was stimmt hier nicht?
Freundliche Grüße
Jo
Habe ein hartnäckiges Problem mit einem Interrupt. Folgender Code läuft auf einer ESP8266
NodeMCU:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// Wifi Connection
const char* ssid = "xxx";
const char* password = "xxx";
// MQTT Server address
const int mqtt_port = 1983;
const char* mqtt_server = "192.168.178.xx";
//Topics
const char* gate_topic = "Garage/Gate";
const int interruptGate = D7;//D7
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
Serial.begin(9600);
setup_wifi();
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
//Gate In/Out
pinMode(interruptGate, INPUT_PULLUP);
//digitalWrite(interruptGate, HIGH);
attachInterrupt(digitalPinToInterrupt(interruptGate), handleInterruptGate, CHANGE);
}
void setup_wifi() {
delay(2);
// We start by connecting to a WiFi network
Serial.println();
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length) {
//Car In
if (strcmp(topic, gate_topic) == 0) {
Serial.print("Message arrived\ntopic = ");
Serial.print(topic);
Serial.print(" - ");
String spayload = "";
for (int i = 0; i < length; i++) {
spayload = spayload + (char)payload[i];
}
Serial.print("payload = " + spayload + "\n");
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("Combi_Switch")) {
Serial.println("connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
ICACHE_RAM_ATTR void handleInterruptGate() {
static unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = millis();
if (interrupt_time - last_interrupt_time > 20)
{
int dr = digitalRead(interruptGate); <--- Das funktioniert nicht zuverlässig!
if(dr == LOW) {
client.publish(gate_topic, "true", true);
} else {
client.publish(gate_topic, "false", true);
}
last_interrupt_time = interrupt_time;
}
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
}
Der Interrupt an sich läuft zuverlässig auf "CHANGE", doch bei der Abfrage des momentanen Zustandes vom Eingang
"interruptGate" (in der ISR-Routine) erhält die Variable dr nicht immer den richtigen Wert.
Alle Hardwareteile sind geprüft und nicht defekt. Habe das auch mit externen Pullup-Widerständen getestet, von
10K runter auf 680R - keine Besserung.
Mit der Debounce-Time habe ich auch variiert, der Wert 20 reicht völlig,
Habe viele Varianten getestet, doch nichts war wirklich zuverlässig.
Was stimmt hier nicht?
Freundliche Grüße
Jo
Bitte Anmelden oder Registrieren um der Konversation beizutreten.
- der_gerd
- Offline
- New Member
Weniger
Mehr
- Beiträge: 11
- Dank erhalten: 1
09 Apr 2020 06:54 #663
von der_gerd
Problem mit Interrupt
Du hast sehr zeitaufwändigen Code in deiner ISR. Im allgemeinen sollte eine ISR möglichst schnell wieder verlassen werden. Verlagere doch mal die Kommunikationsanweisungen in die loop(). Dazu brauchst du ein globales Flag oder einen Semaphor.
Und überhaupt ergibt es praktisch wenig Sinn, den eingelesenen Wert nur in der ISR zu behalten.
Prinzip (in der Arduino Syntax bin ich momentan nicht sehr sicher):
Mit Flag (ist leichter)
global:
bool intrOccured = false; // globales Flag
char* boolstr[] = {"false","true"}; //Zugabe meinerseits
int dr;
ICACHE_RAM_ATTR void handleInterruptGate() {
// dein debounce
dr = digitalRead(interruptGate);
intrOccured = true;
//...
}
loop(){
// der MQTT Kram
if (intrOccured) {
intrOccured = false;
client.publish(gate_topic, boolstr[dr], true); // Mehr Datenstruktur -> weniger Ablaufstrutur
}
}
Entschuldige bitte die fehlenden Einrückungen, hab's mal eben reingehackt.
Wenn's vielleicht nicht hilft, so kannst du damit zumindest deinen Tastendruck weiterverarbeiten.
Ist es nicht so, dass die ISR mit ICACHE_RAM_ATTR in's rare RAM geladen wird? Dann ist es eh besser, sie klein zu halten.RAM ist für die Daten da, nicht für Programm. Die ISR im RAM laufen halt schneller ab, was sie auch sollten.
Viel Erfolg
Und überhaupt ergibt es praktisch wenig Sinn, den eingelesenen Wert nur in der ISR zu behalten.
Prinzip (in der Arduino Syntax bin ich momentan nicht sehr sicher):
Mit Flag (ist leichter)
global:
bool intrOccured = false; // globales Flag
char* boolstr[] = {"false","true"}; //Zugabe meinerseits
int dr;
ICACHE_RAM_ATTR void handleInterruptGate() {
// dein debounce
dr = digitalRead(interruptGate);
intrOccured = true;
//...
}
loop(){
// der MQTT Kram
if (intrOccured) {
intrOccured = false;
client.publish(gate_topic, boolstr[dr], true); // Mehr Datenstruktur -> weniger Ablaufstrutur
}
}
Entschuldige bitte die fehlenden Einrückungen, hab's mal eben reingehackt.
Wenn's vielleicht nicht hilft, so kannst du damit zumindest deinen Tastendruck weiterverarbeiten.
Ist es nicht so, dass die ISR mit ICACHE_RAM_ATTR in's rare RAM geladen wird? Dann ist es eh besser, sie klein zu halten.RAM ist für die Daten da, nicht für Programm. Die ISR im RAM laufen halt schneller ab, was sie auch sollten.
Viel Erfolg
Bitte Anmelden oder Registrieren um der Konversation beizutreten.
- Aktuelle Seite:
- Startseite
- Impressum / Datenschutz / ...
- ESP8266 spezifisch
- Codebesprechung
- Problem mit Interrupt