ISR not in IRAM!

Hallo,

wollte mir mal so eben eine Wetterstation bauen, Ausgangspunkt war folgende Anleitung ESP8266 Weather Station - with Wind and Rain Sensors | Tysonpower.de

wie ihr seht, nutzt der Entwickler einen Wemos D1 mini. Ich hingegen nutze einen NodeMcu Lolin V3

So weit so gut.
Also da beide ESP8266 sind, dachte ich , dass der Code kompatibel sein sollte.

#include "DHT.h"
#include <PubSubClient.h>
#include <ESP8266WiFi.h>

// Setup
#define WIFI_AP "XXX"                                         // AP SSID
#define WIFI_PASSWORD "XXXXX"                          // AP Password
char thingsboardServer[] = "192.68.176.2";                           // Thingsboard Server
#define TOKEN "THINGSBOARD TOKEN"                                                    // Thingsboard token
#define INTERVAL 30                                                 // Intervall of sending in seconds
// DHT
#define DHTPIN 2                                                    // DHT pin
#define DHTTYPE DHT22
//info config
const String device_model = "\"WEMOS D1 mini 2.3.0\"";
const String software_version = "\"ESP8266_Wetterstation_MQTT - 1.0\"";
//weather sensors
const byte windSpeedPin = 13;
const byte windDirPin = A0;
const byte rainPin = 12;
/////////////////////////////////////////////////////////////////////
WiFiClient wifiClient;
// Initialize DHT sensor.
DHT dht(DHTPIN, DHTTYPE);
PubSubClient client(wifiClient);
int status = WL_IDLE_STATUS;
unsigned int windcnt = 0;
unsigned int raincnt = 0;
unsigned long lastSend;

//////////////// SETUP //////////////////////////////////////////////
void setup() {
  Serial.begin(115200);
  // pin for Wind speed
  pinMode(windSpeedPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(windSpeedPin), cntWindSpeed, RISING);
  pinMode(rainPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(rainPin), cntRain, RISING);
  pinMode(windDirPin, INPUT);
  
  dht.begin();
  delay(10);
  InitWiFi();
  client.setServer( thingsboardServer, 1883 );

  // send device attributes
  if ( !client.connected() ) {
    reconnect();
  }  
  // Prepare a JSON payload string
  String payload = "{";
  payload += "\"Device\":"; payload += device_model; payload += ",";
  payload += "\"Firmware\":"; payload += software_version; payload += ",";
  payload += "\"Sensors\":"; payload += "DHT22 - Wind Speed";
  payload += "}";
  
  // Send the payload
  char attributes[100];
  payload.toCharArray( attributes, 100 );
  Serial.println(payload);
  client.publish( "v1/devices/me/attributes", attributes );
  Serial.println("Send device attributes.");
  
  lastSend = millis() - INTERVAL*1000;
}

//////////////// LOOP //////////////////////////////////////////////
void loop() {
  // check connection
  if ( !client.connected() ) {
    reconnect();
  }

  if ( millis() - lastSend > INTERVAL*1000 ) { // Update and send only after delay
    getAndSendTemperatureAndHumidityData();    
  }

  client.loop();        //keep connected, look for messages from server
}

//////////////// Functions //////////////////////////////////////////

 void getAndSendTemperatureAndHumidityData()
{
  Serial.println("Collecting Weather data.");

  // Reading temperature or humidity takes about 250 milliseconds!
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT sensor!");
    delay(1000);
    lastSend = millis() - INTERVAL*1000;
    return;
  }

  //Calculate Wind Speed (klicks/interval * 2,4 kmh)
  float ws = (windcnt/INTERVAL) * 2.4;
  windcnt = 0;
  //Calculate Rain
  float r = (raincnt/2)*0.2794;
  raincnt = 0;
  // get wind direction
  float dirpin = analogRead(windDirPin)*(3.3 / 1023.0);
  String wd = "other";
  
  if(dirpin > 2.60 &&  dirpin < 2.70 ){
    wd = "N";
  }
  if(dirpin > 1.60 &&  dirpin < 1.70 ){
    wd = "NE";
  }
  if(dirpin > 0.30 &&  dirpin < 0.40 ){
    wd = "E";
  }
  if(dirpin > 0.60 &&  dirpin < 0.70 ){
    wd = "SE";
  }
  if(dirpin > 0.96 &&  dirpin < 1.06 ){
    wd = "S";
  }
  if(dirpin > 2.10 &&  dirpin < 2.20 ){
    wd = "SW";
  }
  if(dirpin > 3.15 &&  dirpin < 3.25 ){
    wd = "W";
  }
  if(dirpin > 2.95 &&  dirpin < 3.05 ){
    wd = "NW";
  }    

  Serial.print("Humidity: ");
  Serial.print(h);
  Serial.print(" %\t");
  Serial.print("Temperature: ");
  Serial.print(t);
  Serial.print(" *C ");
  Serial.print("Windspeed: ");
  Serial.print(ws);
  Serial.print(" km/h ");
  Serial.print("Wind Direction: ");
  Serial.print(wd);
  Serial.print(" ");
  Serial.print("Rain: ");
  Serial.print(r);
  Serial.print(" mm ");
  

  String temperature = String(t);
  String humidity = String(h);
  String windspeed = String(ws);
  String winddir = String(wd);
  String rain = String(r);

  // Just debug messages
  Serial.print( "Sending Data : [" );
  Serial.print( temperature ); Serial.print( "," );
  Serial.print( humidity ); Serial.print( "," );
  Serial.print( windspeed ); Serial.print( "," );
  Serial.print( winddir ); Serial.print( "," );
  Serial.print( rain );
  Serial.print( "]   -> " );

  // Prepare a JSON payload string
  String payload = "{";
  payload += "\"temperature\":"; payload += temperature; payload += ",";
  payload += "\"humidity\":"; payload += humidity; payload += ",";
  payload += "\"windspeed\":"; payload += windspeed; payload += ",";
  payload += "\"winddirection\":"; payload += winddir; payload += ",";
  payload += "\"rain\":"; payload += rain;
  payload += "}";

  // Send payload
  char attributes[100];
  payload.toCharArray( attributes, 100 );
  client.publish( "v1/devices/me/telemetry", attributes );
  Serial.println( attributes );

  lastSend = millis();
}

void InitWiFi()
{
  Serial.println("Connecting to AP ...");
  // attempt to connect to WiFi network

  WiFi.begin(WIFI_AP, WIFI_PASSWORD);
  WiFi.mode(WIFI_STA);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("Connected to AP");
}


void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    status = WiFi.status();
    if ( status != WL_CONNECTED) {
      WiFi.begin(WIFI_AP, WIFI_PASSWORD);
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      Serial.println("Connected to AP");
    }
    Serial.print("Connecting to ThingsBoard node ...");
    // Attempt to connect (clientId, username, password)
    if ( client.connect("ESP8266 Device", TOKEN, NULL) ) {
      Serial.println( "[DONE]" );
    } else {
      Serial.print( "[FAILED] [ rc = " );
      Serial.print( client.state() );
      Serial.println( " : retrying in 5 seconds]" );
      // Wait 5 seconds before retrying
      delay( 5000 );
    }
  }
}

// Interupts
void cntWindSpeed() {
  windcnt++;
}

void cntRain() {
  raincnt++;
}

Allerdings hat mich nach den flashen im seriellen Monitor folgendes in dauerschleife erwartet:

0000 3ffee688 40204a5f  
3fffffb0:  feefeffe feefeffe 3ffe84f0 40100f6d  
<<<stack<<<

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

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

load 0x4010f000, len 3584, room 16 
tail 0
chksum 0xb0
csum 0xb0
v2843a5ac
~ld
ISR not in IRAM!

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

Abort called

>>>stack>>>

Nun weiß ich leider nicht mehr weiter und hoffe auf einen Hinweis.

Gruß
Thomas

Vielleicht mal die Doku lesen?!

Vielen Dank für den Hinweis auf die Doku. Leider hatte ich die schon gelesen und muss sagen, dass dies mich nicht wirklich weiter bringt.

Was für mich klar ist und ich mir zusammengereimt habe, ist:

vor die Funktion

void getAndSendTemperatureAndHumidityData()

sollte

ICACHE_RAM_ATTR

eingefügt werden.
Dies habe ich getan, was zu keiner Lösung geführt hat.

Daher bin ich offen für Vorschläge die über den Verweis auf die Doku hinaus gehen.

Gruß
Thomas

Ich sehe jetzt erstmal nicht, was die Funtion getAndSendTemperatureAndHumidityData() mit Interrupts zu tun hat. Die Interruptfunktionen sind andere:

attachInterrupt(digitalPinToInterrupt(windSpeedPin), [b][u]cntWindSpeed[/u][/b], RISING);
attachInterrupt(digitalPinToInterrupt(rainPin), [b][u]cntRain[/u][/b], RISING);

Hallo Frank-Peter,

danke für die Antwort! Sehe ich ein, dass dort die Funktionen nicht vorhanden sind.
Hast du eine Idee, warum der Fehler auftritt.
Die Funktion

attachInterrupt(digitalPinToInterrupt(windSpeedPin), cntWindSpeed, RISING);

ist aus meiner Sicht richtig.

Warum fällt der Groschen nicht?
Übrigens, meine zweiter Name ist "DokuVorLeseVerweigerer".

Damit wirst du sie (die Doku) selber noch ein paarmal selber lesen müssen!
... bis er fällt, der Groschen ...

Frage an den "DokuVorlesungsVerweigerer"!
Wieviele von deine über 13000 posts beziehen sich auf "lese die Doku"!
Und wenn du ehrlich zu dir selbst bist! Wie beantwortest du die Frage, warum bin ich in diesem Forum? Helfen oder Nerven?

Sorry an alle anderen.
Dies geht natürlich nicht an euch!

Die meisten seiner Posts sind fachlich fundierte Inhalte.

Lies Dir doch noch mal die Antworten durch, die Du bekommen hast. Da wurde Dir auch schon mitgeteilst, was Deine ISR sind. Jedenfalls nicht das, was Du dafür hälst.

Gruß Tommy

eddieari:
Die Funktion

attachInterrupt(digitalPinToInterrupt(windSpeedPin), cntWindSpeed, RISING);

ist aus meiner Sicht richtig.

Ich habe auch nicht geschrieben, dass diese Anweisungen falsch sind. Aber an diesen Anweisungen erkennst Du, was deine ISRs sind. Ich habe sie noch extra markiert. Und diese Funktionen benötigen das Attribut ICACHE_RAM_ATTR.

Hallo,

link zum lesen hast Du schon bekommen, aber sicher nicht richtig verstanden.

ich würde das so verstehen

// Interupts
ICACHE_RAM_ATTR void cntWindSpeed() {
  windcnt++;
}

Heinz

eddieari:
Frage an den "DokuVorlesungsVerweigerer"!

Gerne doch!

eddieari:
Wieviele von deine über 13000 posts beziehen sich auf "lese die Doku"!

Keine Statistik gemacht, bisher...
Denke schon, dass sich in ca 10% meiner Beiträge, Links zu maßgeblicher Information befinden

Hinzeigen ist einfach für mich.
Lesen, verstehen und anwenden, ist die Sache des Gegenübers.
Hier also deine.

eddieari:
Und wenn du ehrlich zu dir selbst bist! Wie beantwortest du die Frage, warum bin ich in diesem Forum?

Das ist einfach zu beantworten!
Ich bin in erster Linie hier um zu lernen.
Das Forum bietet mir "Probleme" und Anregungen, auf die ich aus eigener Kraft nie gekommen wäre.
Meine Dankbarkeit, dafür, möchte ich dadurch zeigen, dass ich dem ein oder anderen auf Pferd helfe.
Natürlich klappt das nicht immer, siehe dazu, wir beide.

Und sowieso halte ich Kommunikation für ein ganz spannendes Thema.
Da bin ich gerne bei, auch in Sachen Eskalation.

eddieari:
Helfen oder Nerven?

Hier könnte es evtl. sein, dass du ein Problem mit deiner Erwartungshaltung hast.
Oder, ich mit meiner.

Verflucht nochmal!
Den Link zur Doku, den ich dir habe zukommen lassen....
Ich erwarte, dass du sie liest.
Da steht im ersten Absatz ganz klar drin, was du zu tun hast.
Jetzt ist es an dir, das zu tun.
Lesen, verstehen und umsetzen.

Alternativ könntest du noch ein Weilchen erbost sein, und mit den Füßen auf dem Boden rumstampfen.
Auch die Schuld bei mir suchen.
Aber helfen, wird dir das nicht.

Danke Renter für deine hilfreiche Antwort.
Hatte mich da verrannt, denn ich hatte hinter ICACHE_RAM_ATTR void gesetzt hatte, damit hat es natürlich nicht funktioniert.
Manchmal ist ein kleiner Hinweis von extern Gold wert.

Danke

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