Mal wieder der Fehler 'ISR is not in IRAM'

Hallo,

obwohl über diesen Fehler viel geschrieben wurde, habe ich ihn nicht eliminieren können.

Board: genericESP8266 (Di Mini pro) mit Standardeinstellungen.

Muster-Sketch ButtonRotaryEncoder aus der Bibliothek IoAbstaraction

Peripherie. Encoder PinA an D3(GPIO0) und PinB an D4(GPIO2). Encoderswitch an D7(GPIO13) Zusätzlicher Taster an D6(GPIO12).

Mustersketch 1:1 übernommen mit den Änderungen bezüglich der Pinnummer/GPIO.

#include<IoAbstraction.h>

// The pin onto which we connected the rotary encoders switch
const int spinwheelClickPin = 13;

// The pin onto which we connected the repeat button switch
const int repeatButtonPin = 12;

// The two pins where we connected the A and B pins of the encoder. I recomend you dont change these
// as the pin must support interrupts.
const int encoderAPin = 0;
const int encoderBPin = 2;

// the maximum (0 based) value that we want the encoder to represent.
const int maximumEncoderValue = 128;

//
// When the spinwheel is clicked, this function will be run as we registered it as a callback
//
void onSpinwheelClicked(uint8_t pin, bool heldDown) {
  Serial.print("Button pressed ");
  Serial.println(heldDown ? "Held" : "Pressed");
}

//
// When the repeat button is pressed, this function will be repeatedly called. It's also a callback
//
void onRepeatButtonClicked(uint8_t pin, bool heldDown) {
  Serial.println("Repeat button pressed");
}

//
// Each time the encoder value changes, this function runs, as we registered it as a callback

//
// void onEncoderChange(int newValue) {

ICACHE_RAM_ATTR void onEncoderChange(int newValue){
  Serial.print("Encoder change ");
  Serial.println(newValue);
}

void setup() {

  Serial.begin(115200);

  // First we set up the switches library, giving it the task manager and tell it to use arduino pins
  // We could also of chosen IO through an i2c device that supports interrupts.
  // If you want to use PULL DOWN instead of PULL UP logic, change the true to false below.
  switches.initialise(ioUsingArduino(), true);

  // now we add the switches, we dont want the spinwheel button to repeat, so leave off the last parameter
  // which is the repeat interval (millis / 20 basically) Repeat button does repeat as we can see.
  switches.addSwitch(spinwheelClickPin, onSpinwheelClicked);
  switches.addSwitch(repeatButtonPin, onRepeatButtonClicked, 25);

  // now we set up the rotary encoder, first we give the A pin and the B pin.
  // we give the encoder a max value of 128, always minumum of 0.
  setupRotaryEncoderWithInterrupt(encoderAPin, encoderBPin, onEncoderChange);
  switches.changeEncoderPrecision(maximumEncoderValue, 100);
}

void loop() {
  taskManager.runLoop();  
}

Wegen des Fehlers ISR is not in IRAM habe ich das ICACHE_RAM_ATTR vor void onEncoderChange(int newValue) hinzugefügt. Normalerweise sollte die Fehlermeldung verschwunden sein. Bei mir aber nicht. Ich bekomme in regelmäßigen Abständen ein Reboot irgendwoher.

Auf Serial:

>>>stack>>>

ctx: cont
sp: 3ffffd30 end: 3fffffc0 offset: 01b0
3ffffee0:  00000000 4bc6a7f0 ac49ba5e 00000000  
3ffffef0:  00000000 00000000 4bc6a7f0 00000000  
3fffff00:  00000002 00000002 3ffee2e4 40100492  
3fffff10:  00000000 feefeffe feefeffe 402011de  
3fffff20:  0000499f feefeffe feefeffe 40201d68  
3fffff30:  4020368d 402037f6 00000100 40201551  
3fffff40:  00000000 3ffee27c 3ffef44c 4020163c  
3fffff50:  00000000 401000a0 00000014 00000002  
3fffff60:  00000000 401000a0 3ffee27c 4020168a  
3fffff70:  3ffef44c 00000000 00000004 402015b4  
3fffff80:  3fffdad0 00000000 3ffee27c 3ffee550  
3fffff90:  3fffdad0 00000000 3ffee27c 402010cc  
3fffffa0:  feefeffe feefeffe 3ffee520 40202850  
3fffffb0:  feefeffe feefeffe 3ffe84f4 4010077d  
<<<stack<<<

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

load 0x4010f000, len 1384, room 16 
tail 8
chksum 0x2d
csum 0x2d
v8b899c12
~ld
ISR not in IRAM!

Abort called

Ich weiß jetzt nicht wo ich weitersuchen sollte. Wer kann helfen?

Viele Grüße
Eberhard

In einem anderen Thread #3 habe ich folgende Notation gefunden

void ICACHE_RAM_ATTR revDetectorISR() {
  // ISR code
}

Was steht denn in der Dokumentation?

Da steht nur "ISRs need to have ICACHE_RAM_ATTR before the function definition."

Entweder

ICACHE_RAM_ATTR void onEncoderChange(int newValue){ .... }

oder

void ICACHE_RAM_ATTR onEncoderChange(int newValue){.....}

Ich habe beide Varianten getestet - keine Besserung. Kann es sein, dass der eigentliche Interruptaufruf in der Headerdatei passiert und wir ihn im Sketch nicht sehen?

Gruß
Eberhard

eberduino:
Ich habe beide Varianten getestet - keine Besserung. Kann es sein, dass der eigentliche Interruptaufruf in der Headerdatei passiert und wir ihn im Sketch nicht sehen?

Davon gehe ich aus, aber es ist eine Libray die nur du kennst.

Die Library ist nicht ESP8266 geeignet.

Hallo,

gib mal den Link zur Lib bekannt. Sonst wird das nichts.

Hier der Link:

Dieser Fehler wurde schon wiederholt im Netz beschrieben. Mehrere haben diese lib mit einem ESP8266 benutzt und den o.g. Fehler mit einer ältereren Boardversion wegbekommen. Ich benutze die Version 2.5.2 des Boards esp8266 by ESP8266Community. Ich glaube deshalb schon, dass die lid für den 8266 geeignet ist.

Gruß
Eberhard

Auf der Seite http://bienonline.magix.net/public/esp8266-faq.html ist viel Interessantes unter dem Punkt ISR & Interrupt Service Routinen - mit Erläuterungen.

Hallo,

überprüfe einmal deine vergebenen Pinnummern.
Bei mir kompiliert der Bsp. Sketch "buttonRotaryEncoder" bis auf paar unused Warnungen für einen Wemos D1 R1 mit

#include<IoAbstraction.h>

const int spinwheelClickPin = 4;

const int repeatButtonPin = 5;

const int encoderAPin = 2;
const int encoderBPin = 3;

Der Bsp. Sketch hat auch keine

ICACHE_RAM_ATTR void onEncoderChange(int newValue){

Funktion.

Hallo Doc,

der Fehler taucht ja auch nicht bei der Compilierung sondern im späteren Betrieb des Beispielsketches auf. Der Fehler bringt ein zyklischen Reboot (ca 10sec) mit dem Hinweis 'ISR is not in IRAM'. Deshalb:

Siehe #1

Wegen des 'Fehlers ISR is not in IRAM' habe ich das ICACHE_RAM_ATTR vor void onEncoderChange(int newValue) hinzugefügt.

Ich habe nocheinmal den ursprünglichen Sketch (mit Deinen Port und ohne ICACHE_RAM_ATTR) probiert: Sobald ich den Encoder drehe, beginnt der Fehler mit der in #1 gezeigten Fehlermeldung.

Gruß Eberhard

Hallo,

achso. Dann wäre es besser du schreibst an den Entwickler des Programms.

@TO: Serielle Ausgaben haben in einer ISR nichts zu suchen. Da gehört beim Encoder eine sinnvolle Bearbeitung des Ereignisses rein.

Gruß Tommy

Hallo,

Frage.
Ist das wirklich eine Interruptroutine?
ICACHE_RAM_ATTR void onEncoderChange(int newValue)
{ ... }

Jetzt, wo Du fragst: Nein, das ist keine. ISR haben keinen Übergabeparameter.

Die muss also irgendwo in den Tiefen der Lib sein.

Gruß Tommy

Edit: ICACHE_RAM_ATTR ist in der ganzen Lib nicht vertreten.

Hallo,

der TO sagt nicht wo die Funktion herkommt, weil im Bsp. Sketch gibt es die nicht.
Alleine schon die Syntax mit dem void mittendrin macht mich stutzig.

Ich würde empfehlen, die Lib weg zu legen und lieber bei Nick Gammon zu lesen, wie man das machen kann.
Dann kann man der ISR auch problemlos das ICACHE_RAM_ATTR verpassen.

Wenn der TO aber unbedingt auf der Lib bestehen will, dann hat er viel Arbeit vor sich, um sich durch die EierlegendeWollMilchSau zu kämpfen.

Gruß Tommy

@Tommy
:slight_smile: Auf diesen Hinweis habe ich gewartet. :slight_smile: Das war mir wohl klar, die wäre nach einem Funktionieren des Sketches wieder 'rausgeflogen. Trotzdem Danke für den Hinweis. Lieber zuviel als zuwenig.

@alle
Ich werde Tommy's Empfehlung beherzigen und den Link mit genauer ansehen. Schade um die eierlegende WollMilchSu.

Wenn durch die Interrpts, die auch in Gammons Forum verarbeitet werden, Probleme auftauchen melde ich hier wieder. Euch einstweilen meinen herzlichsten Dank.

Gruß Eberhard

/*
YF� S201 Water Flow Sensor
Water Flow Sensor output processed to read in litres/hour
Adaptation Courtesy: www.hobbytronics.co.uk
/
/
#include <LiquidCrystal.h>
// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 12, en = 11, d4 = 7, d5 = 6, d6 = 5, d7 = 4;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);*/

#define SensorPin A0 // the pH meter Analog output is connected with the Arduino’s Analog

unsigned long int avgValue; //Store the average value of the sensor feedback
float PHsensor;
int buf[10],temp;
unsigned int estimateAvg = 250;
unsigned int avarageValue = 0;
unsigned int avarageCount = 0;
unsigned int avarageResult = 0;

unsigned int checkTime = 10;
unsigned int checkTimeCount = 1;
unsigned int hour = 0;
unsigned int returnValue = 0;
unsigned int secondInput = 0;
unsigned int initialValue;
unsigned int initialValue1;
const int ledPin = 2;
const int ledPin1 = 3;
volatile int flow_frequency1;
volatile int flow_frequency; // Measures flow sensor pulses
unsigned int l_hour; // Calculated litres/hour
unsigned int l_hour1; // Calculated litres/hour
unsigned char flowsensor = D1; // Sensor Input
unsigned char flowsensor1 = D2;
unsigned long currentTime;
unsigned long cloopTime;

void flow () // Interrupt function
{
flow_frequency++;
secondInput = 1;
}
void flow1 () // Interrupt function
{
flow_frequency++;
}
void setup()
{

Serial.begin(9600);

// set up the LCD's number of columns and rows:
//lcd.begin(16, 2);
Serial.println("Ready to get PH");
delay(2000);
Serial.println("Ready to get FLOW");
delay(2000);
pinMode(flowsensor, INPUT);
pinMode(ledPin, OUTPUT);
pinMode(ledPin1, OUTPUT);
pinMode(flowsensor1, INPUT);
digitalWrite(flowsensor, HIGH); // Optional Internal Pull-Up

attachInterrupt(digitalPinToInterrupt(flowsensor), flow,CHANGE); // Setup Interrupt
attachInterrupt(digitalPinToInterrupt(flowsensor1), flow1,CHANGE); // Setup Interrupt
sei(); // Enable interrupts
currentTime = millis();
cloopTime = currentTime;
}
void flow_sensors(){
currentTime = millis();
// Every second, calculate and print litres/hour
if(currentTime >= (cloopTime + 1000))
{
// lcd.clear();
hour += (millis()/1000)/60/60;
cloopTime = currentTime; // Updates cloopTime
// Pulse frequency (Hz) = 7.5Q, Q is flow rate in L/min.
l_hour = (flow_frequency * 60 / 7.5); // (Pulse frequency x 60 min) / 7.5Q = flowrate in L/hour
flow_frequency = 0; // Reset Counter
Serial.print(l_hour, DEC); // Print litres/hour
Serial.print(" L/hour ");
Serial.println(initialValue);
if(l_hour > 0 && initialValue > 0 && secondInput != 1){
avarageValue = avarageValue + l_hour;
avarageCount+=1;
avarageResult = avarageValue / avarageCount;
}
if(secondInput == 1 && l_hour > 0){
returnValue = returnValue + 1;
}
if((millis()/500) > (checkTime * checkTimeCount)){
checkTimeCount+=1;
}
if((millis()/500) <= (checkTime * checkTimeCount) && l_hour > estimateAvg && l_hour > 0 && initialValue > 0){
//lcd.setCursor(0,0);
Serial.print("You took more");
//lcd.setCursor(0,1);
Serial.print("water");
}else{
if(l_hour < initialValue && l_hour > (initialValue-200) && l_hour > 0 && initialValue > 0){
// lcd.setCursor(0,0);
Serial.print("Waterflow Normal");
//lcd.setCursor(0,1);
Serial.print(l_hour);
//lcd.setCursor(5,1);
Serial.print("l/H");
//lcd.setCursor(9,1);
Serial.print(avarageResult);
}else if(l_hour > initialValue && initialValue > 0 && l_hour > 0){
//lcd.setCursor(0,0);
Serial.print("OVERFLOW");
//lcd.setCursor(0,1);
Serial.print(l_hour);
//lcd.setCursor(5,1);
Serial.print("l/H");
//lcd.setCursor(9,1);
Serial.print(avarageResult);
}else if(l_hour == 0 && initialValue > 0){
//lcd.setCursor(0,0);
Serial.print("NO FLOW ");
//lcd.setCursor(0,1);
Serial.print(l_hour);
//lcd.setCursor(5,1);
Serial.print("l/H");
//lcd.setCursor(9,1);

Serial.print(avarageResult);
}else if(l_hour < (initialValue-200) && l_hour > 0 && initialValue > 0){
// lcd.setCursor(0,0);
Serial.print("LEAK ");
//lcd.setCursor(0,1);
Serial.print(l_hour);
//lcd.setCursor(5,1);
Serial.print("l/H");
//lcd.setCursor(9,1);
Serial.println(avarageResult);

}

}
if(l_hour > 100 && secondInput == 1 && returnValue == 3){
initialValue = l_hour;
detachInterrupt(flowsensor);
attachInterrupt(digitalPinToInterrupt(flowsensor1), flow1, FALLING);
secondInput = 2;}}}

void Ph_sensor(){
for(int i=0;i<10;i++) //Get 10 sample value from the sensor for smooth the value
{
buf*=analogRead(SensorPin);*

  • delay(10);*
  • }*
  • for(int i=0;i<9;i++) //sort the analog from small to large*
  • {*
  • for(int j=i+1;j<10;j++)*
  • {*
    _ if(buf*>buf[j])_
    _
    {_
    _ temp=buf;
    buf=buf[j];
    buf[j]=temp;
    }
    }
    }
    avgValue=0;
    for(int i=2;i<8;i++) //take the average value of 6 center sample*

    avgValue+=buf*;
    float phValue=(float)avgValue5.0/1024/6; //convert the analog into millivolt_

    _ phValue=3.5phValue; //convert the millivolt into pH value_
    _ Serial.print(" pH:");
    Serial.print(phValue,2);
    Serial.println(" ");*_

}

void loop ()
{

* flow_sensors();
_ //delay(1000);_
Ph_sensor();
_ delay(1000);
}
I am trying to upload this code on my NodeMcu esp8266 but iam getting this error please i need your help. Thanks
connected with Kofi mifi, channel 6
dhcp client start...
Ready to get FLOW
ip:192.168.1.103,mask:255.255.255.0,gw:192.168.1.1
ISR not in IRAM!
User exception (panic/abort/assert)
Abort called
>>>stack>>>*

ctx: cont
sp: 3ffffef0 end: 3fffffc0 offset: 0000
*3ffffef0: 00000000 00000001 00000020 40100deb *
*3fffff00: 000000fe 00000000 00000000 00000000 *
*3fffff10: 00000000 00000000 00000000 00ff0000 *
*3fffff20: 5ffffe00 5ffffe00 0a0d003a 00000000 *
*3fffff30: 00000003 00000005 3ffe84cd 40202d66 *
*3fffff40: 4010051e f95283f1 3ffee600 40202d7c *
*3fffff50: 40105765 00133ab8 3ffe84cd 40203339 *
*3fffff60: 00000000 3ffee854 000007d0 3ffee750 *
*3fffff70: 3fffdad0 3ffee854 000007d0 3ffee750 *
*3fffff80: 3fffdad0 3ffe84cc 3ffe84cd 402033e8 *
*3fffff90: 3fffdad0 3ffe84cc 3ffe84cd 402010f8 *
*3fffffa0: feefeffe 00000000 3ffee710 402029b4 *
3fffffb0: feefeffe feefeffe 3ffe84f0 40101131
<<<stack<<<_

Setze Deinen Code bitte in Codetags (</>-Button oben links im Forumseditor oder [code] davor und [/code] dahinter ohne *).
Dann ist er auch auf mobilen Geräten besser lesbar.
Das kannst Du auch noch nachträglich ändern.

Außerdem entferne bitte die unnötigen Leerzeilem

Gruß Tommy.