ISR not in IRAM ! ESP8266

Hallo Kommunity,

ich weiß das Problem hier schon sehr oft besprochen wurde, jedoch versuche ich schon seit Stunden den Fehler zu finden... Jedoch ohne Erfolg
Vielleicht wäre jemand so nett und würde sich mal mein Problem anschauen ^^!

ich habe versucht eine kleine Wetterstation nachzubauen auf der ESP8266 Basis mit Verbindung zu einem mqtt_Broker

#include "DHT.h"
#include <ESP8266WiFi.h> // Enables the ESP8266 to connect to the local network (via WiFi)
#include <PubSubClient.h> // Allows us to connect to, and publish to the MQTT broker
//#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <ArduinoJson.h>



#define DHTPIN D2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

#define LdrPin A0

String JsonObj;

float temperature = 0;
float humidity = 0;
int windspeed = 0;
int pressure = 0;
int light = 0;

const char* ssid = ""; 
const char* wifi_password = ""; 

const char* mqtt_server = "192.168.137.158";
const char* mqtt_topic = "Wetterstation";
const char* mqtt_username = "ESP32";
const char* mqtt_password = "esp32";
// The client id identifies the ESP8266 device. Think of it a bit like a hostname (Or just a name, like Greg).
const char* clientID = "ESP_Wetterstation";



unsigned long  next_timestamp = 0;
volatile unsigned long i = 0;
float wind = 0;
float last_wind = 0;
int count = 0;
volatile unsigned long last_micros;
long debouncing_time = 5; //in millis
int input_pin = D7;
char charBuffer[32];



// Initialise the WiFi and MQTT Client objects
WiFiClient wifiClient;
PubSubClient client(mqtt_server, 1883, wifiClient); // 1883 is the listener port for the Broker

void receivedCallback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message received: ");
  Serial.println(topic);
  Serial.print("payload: ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
}



void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  
  Serial.begin(115200);
  
  pinMode(input_pin, INPUT_PULLUP);//D7
  pinMode(LdrPin, INPUT);

  // Begin Serial on 115200
  // Remember to choose the correct Baudrate on the Serial monitor!
  // This is just for debugging purposes

  Serial.print("Connecting to ");
  Serial.println(ssid);

  // Connect to the WiFi
  WiFi.begin(ssid, wifi_password);

  // Wait until the connection has been confirmed before continuing
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  // Debugging - Output the IP Address of the ESP8266
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  // Connect to MQTT Broker
  // client.connect returns a boolean value to let us know if the connection was successful.
  // If the connection is failing, make sure you are using the correct MQTT Username and Password (Setup Earlier in the Instructable)
  if (client.connect(clientID, mqtt_username, mqtt_password)) {
    Serial.println("Connected to MQTT Broker!");
  }
  else {
    Serial.println("Connection to MQTT Broker failed...");
  }
 dht.begin(); 
  attachInterrupt(input_pin,Interrupt,RISING);
}


const size_t bufferSize = JSON_OBJECT_SIZE(5) + 70;
DynamicJsonBuffer jsonBuffer(bufferSize);

const char* json = "{\"Temperatur\":\"temperature\",\"Luftfeuchtigkeit\":\"humidity\",\"Windgeschwindigkeit\":\"windspeed\",\"Luftdruck\":\"pressure\",\"Hellichkeit\":\"light\"}";

JsonObject& root = jsonBuffer.parseObject(json);

const char* Temperatur = root["Temperatur"]; // "dht.readTemperature"
const char* Feuchtigkeit = root["Feuchtigkeit"]; // "dht.readHumidity"
const char* Windgeschwindigkeit = root["Windgeschwindigkeit"]; 
const char* Luftdruck = root["Luftdruck"]; 
const char* Helligkeit = root["Helligkeit"]; 




void Interrupt()
{
  if((long)(micros() - last_micros) >= debouncing_time * 1000) {
    i++;
    last_micros = micros();
  }
}



void mqttconnect() {
  while (!client.connected()) {
    Serial.print("MQTT connecting ...");

      String clientId = "ESP_Wetterstation";

    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
    } else {
      Serial.print("failed, status code =");
      Serial.print(client.state());
      Serial.println("try again in 5 seconds");
      delay(5000);
    }
  }
}



void loop() {
//client.loop();
 if (!client.connected()) {
    mqttconnect();
  }


  if (millis() > next_timestamp )    
  { 
    detachInterrupt(input_pin);
    count++; 
    float rps = i/2; //computing rounds per second 
    if(i == 0)
      wind = 0.0;
    else
      wind = 1.761 / (1 + rps) + 3.013 * rps;// found here: https://www.amazon.de/gp/customer-reviews/R3C68WVOLJ7ZTO/ref=cm_cr_getr_d_rvw_ttl?ie=UTF8&ASIN=B0018LBFG8 (in German)
    
     
   //     Serial.print("Wind: ");
   //     Serial.print(wind);
   //     Serial.println(" km/h");
      
      
    i = 0;
    last_wind = wind;
    
    next_timestamp  = millis()+1000; //intervall is 1s
    attachInterrupt(input_pin,Interrupt,RISING);
  }
  yield();

client.loop();

    light = analogRead(LdrPin)*0.09765625;
    windspeed = wind;
    temperature = dht.readTemperature();
    humidity = dht.readHumidity();
    if (!isnan(temperature)) {


const size_t bufferSize = JSON_OBJECT_SIZE(5);
DynamicJsonBuffer jsonBuffer(bufferSize);

JsonObject& root = jsonBuffer.createObject();
root["Temperatur"] = temperature;
root["Luftfeuchtigkeit"] = humidity;
root["Windgeschwindigkeit"] = windspeed;
root["Luftdruck"] = 1500;
root["Helligkeit"] = light;



String JSBuffer;
 root.printTo(JSBuffer);


Serial.print("Temperatur: ");
Serial.println(temperature);
Serial.print("Feuchtigkeit: ");
Serial.println(humidity);
Serial.print("Windgeschwindigkeit: ");
Serial.println(wind);
Serial.print("Licht: ");
Serial.println(light);

    // PUBLISH to the MQTT Broker (topic = mqtt_topic, defined at the beginning)
    // Here, "Button pressed!" is the Payload, but this could be changed to a sensor reading, for example.
    client.publish(mqtt_topic,(char*) JSBuffer.c_str(), true);
    }
  digitalWrite(LED_BUILTIN, LOW);   
  delay(1000);                      
  digitalWrite(LED_BUILTIN, HIGH);  
  delay(2000);
  digitalWrite(LED_BUILTIN, LOW);   
  delay(1000);                      
  digitalWrite(LED_BUILTIN, HIGH);  
  delay(2000);
  digitalWrite(LED_BUILTIN, LOW);
delay(10000); 
  }

Daraus entsteht dieser Fehler:

...WiFi connected
IP address: 192.168.137.104
Connected to MQTT Broker!
ISR not in IRAM!

User exception (panic/abort/assert)
--------------- CUT HERE FOR EXCEPTION DECODER ---------------

Abort called

>>>stack>>>

ctx: cont
sp: 3ffffee0 end: 3fffffc0 offset: 0000
3ffffee0:  000010dd 00000020 00000020 4020576c  
3ffffef0:  000000fe 00000000 00000000 00000000  
3fffff00:  00000000 00000000 00000000 00ff0000  
3fffff10:  5ffffe00 5ffffe00 cf5c28f5 3ffe85ec  
3fffff20:  00000000 00000001 0000000d 40205eda  
3fffff30:  40100699 3ffe8a3b 40100395 40205eec  
3fffff40:  000010dd 3ffe8a3b 0000000d 4020642d  
3fffff50:  3ffe85cc 00000019 3ffee9f4 3ffe85ec  
3fffff60:  3ffe85cc 3ffee8c8 3ffee9f4 402064cc  
3fffff70:  3ffe85cc 3ffee8c8 3ffee9f4 40201756  
3fffff80:  40208910 6889a8c0 feefeffe feefeffe  
3fffff90:  feefeffe feefeffe feefeffe 3ffeeb80  
3fffffa0:  3fffdad0 00000000 3ffeeb6c 402057ac  
3fffffb0:  feefeffe feefeffe 3ffe8600 40100f55  
<<<stack<<<

--------------- CUT HERE FOR EXCEPTION DECODER ---------------

 ets Jan  8 2013,rst cause:2, boot mode:(3,2)

load 0x4010f000, len 3460, room 16 
tail 4
chksum 0xcc
load 0x3fff20b8, len 40, room 4 
tail 4
chksum 0xc9
csum 0xc9
v000470d0
~ld

Was kann man nun tun?

Viele Grüße und ein schönes Wochenende !

https://arduino-esp8266.readthedocs.io/en/latest/Troubleshooting/stack_dump.html

Kann es sein, das der WatchDog zuschlägt?
Ich habe keinen ESP und keine Ahnung davon.

Was machst Du hier?
Das sehe ich kritisch:

  digitalWrite(LED_BUILTIN, LOW);
  delay(1000);
  digitalWrite(LED_BUILTIN, HIGH);
  delay(2000);
  digitalWrite(LED_BUILTIN, LOW);
  delay(1000);
  digitalWrite(LED_BUILTIN, HIGH);
  delay(2000);
  digitalWrite(LED_BUILTIN, LOW);
  delay(10000);

Und wenn ich mal kurz das nehme, was mir die Suchmaschine der schlechtesten Wahl ausgibt, dann....
... könnte das der Auslöser für einen WD-Reset sein.

Hallo,

Normalerweise gehört beim ESP ICACHE_RAM_ATTR vor die ISR function

Heinz

Die ISR ist nicht im IRAM.
Sorge dafür, dass sie da landet.

Nein.
delay ruft yield auf, und dabei wird auch der WD gefüttert.

Hm. Stimmt. Hatte ich an anderer Stelle gelesen. Jetzt wird das klarer.

Nur für mich und vollkommen ohne Wertung Ja / Nein?:
void ICACHE_RAM_ATTR Interrupt();
Egal wie die Antwort ausfällt - ich frag nicht weiter.

Hallo Heinz,

und wie genau sieht das dann aus ?

So?

void ICACHE_RAM_ATTR Interrupt()

Grüße

Hallo,
ich muss mich erst mal selber korrigieren. Anscheinend ist das in dem angegebene Link auch nicht ganz richtig. Das hier ist richtig.
https://arduino-esp8266.readthedocs.io/en/latest/reference.html#interrupts

demnach sollte das so aussehen

IRAM_ATTR void myISR()

ich hab dann mal in meiner Bastelkiste ein Beispiel für einen UNO rausgesucht und das für einen ESP8266 Node Modul geändert.
Es wir eine Frequenzmessung gemacht mit einer Torzeit von 1s. Damit die Messung unabhängig von der Loopzeit ist wird die tatsächliche Zeitdifferenz gemessen und mit verrechnet. Da bei hohen Frequenzen >1000Hz millis() nicht mehr reichen würde habe ich micros verwendet.
Ob es bei einem ESP (16 32 Bit System ) nötig ist die Interrupts zu sperren wenn auf den ISR 16 32 Bit Messwert zugegriffen wir denke ich nicht. ich hab´s aber mal drin gelassen. Der delay() im loop ist natürlich völliger Quatsch und dient nur dazu eine stark schwankende loop zeit zu erzeugen. Mit dem Sketch lassen sich Frequenzen bis 10 KHz ganz vernünftig messen.

/*
   Beispiel Frequenzmessung mit ESP und ISR
   Testfrequenz auf D2
   Frequenzeingang aud D1
  zum Test mit tone Brücke verwenden
   
*/

const byte isrpin = D1;
volatile unsigned int i_count; // geändert
unsigned int count; // geändert
float frequenz;

// ISR Function 
IRAM_ATTR void myISR() {
  i_count++;
}


void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("start");
  pinMode(isrpin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(isrpin), myISR, FALLING);
  tone(D2, 10000); // testfrequenz Brücke von D2 auf D1
}

void loop() {
  // put your main code here, to run repeatedly:

  messen();
  delay(random(100)); // zum testen damit die loop Zeit schwankt
}

void messen() {
  static uint32_t altzeit;
  uint32_t messzeit, jetzt;
  jetzt = micros();
  if (jetzt - altzeit >= 1000000) {
    messzeit = jetzt - altzeit;
    detachInterrupt(digitalPinToInterrupt(isrpin));
    count = i_count;  // schief geht
    i_count = 0;
    attachInterrupt(digitalPinToInterrupt(isrpin), myISR, FALLING);
    altzeit = micros();

    frequenz = count * 1000000.0 / messzeit;
    Serial.print("Counter "); Serial.print(count);
    Serial.print("     Messzeit "); Serial.print(messzeit);
    Serial.print("us   Frequenz "); Serial.println(frequenz);
  } 
}

Nene, das war oben schon richtig, denn die heisst bei ihm ja:

:slight_smile:

Naja...
Der ESP ist ein 32Bit System.

Damit hat diese Variable auch 32 Bit.

Warum lässt du da negative Werte zu?
Und einen verbotenen/undefinierten signed Überlauf.

Hallo,
tja gute Frage , danke für den Hinweis. Werd´s noch ändern

Gurß Heinz

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.