Board: DOIT ESP32 Devkit v1
Core Installation/update date: 10. Dec. 2017
IDE name: Arduino IDE 1.8.5 / Visual Micro
Flash Frequency: 80Mhz
Upload Speed: 921600
I am using an external hall effect sensor in order do measure the rotation of a wheel. To get the most accurate results, I am using an interrupt which triggers on the falling edge of the hall-sensor input.
In most cases the measurement goes just fine and I get reasonable results. In some cases, which cannot be distinguished by an obvious factor by myself, the ESP32 crashes.
(Maybe and only maybe multiple interrupts happens in a very short period of time and this causes the issue? But why?)
For testing I have replaced the hall sensor with a simple push button, the pin is pulled high by an external resistor (and an internal one too, initially I only used the internal one; same problem).
I have implemented a Screen-Lock in software. The device can be unlocked via RFID. If an interrupt occurs while the device is locked, it instantly crashes.
(the whole sketch is attached too)
All variables accessed by the interrupt function are declared as volatile.
//Libraries
#include <require_cpp11.h> //RFID
#include <MFRC522Hack.h> //RFID
#include <MFRC522Extended.h>//RFID
#include <MFRC522Debug.h> //RFID
#include <MFRC522.h> //RFID
#include <deprecated.h> //RFID
#include <WiFi.h> //OTA
#include <ESPmDNS.h> //OTA
#include <WiFiUdp.h> //OTA
#include <ArduinoOTA.h> //OTA
#include <TFT_eSPI.h> //Display Library
#include <string.h> //String Library for Time Enhancement
#include <math.h> //Maths Library
#include <ESP32_Servo.h> //Servo Library for Speed Control with VESC
#include <SPI.h> //For Display
#include <Adafruit_GFX.h> //For Display
const byte speed_hall_pin = 27; //Hall Effect Pin for Speed measurement
void setup() {
//other stuff
pinMode(speed_hall_pin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(speed_hall_pin), hall_interrupt, FALLING);
}
void loop() {
//other stuff
}
void hall_interrupt() {
hall_millis_current = millis(); //Current time for Reference
if (hall_millis_current > hall_millis_last + 100) {
time_for_rotation = hall_millis_current - hall_millis_last; //Calculate Time of Rotation
kmph = (56.8 * float(circumference)) / float(time_for_rotation);
kmph = kmph * 1.60934; //Convert to km/h
hall_millis_last = hall_millis_current; //(Re)Set reference Point
}
}
serial Output:
Opening port
ets Jun 8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:812
load:0x40078000,len:0
load:0x40078000,len:10212
entry 0x40078a00
Card detected, UID: 1891469948 <output of my code
Access granted! <output of my code
Unlocked - Started <output of my code
<me pressing the button>
Guru Meditation Error: Core 1 panic'ed (Coprocessor exception
[ESP32_InterruptException.zip](https://github.com/espressif/arduino-esp32/files/1592923/ESP32_InterruptException.zip)
)
Register dump:
PC : 0x400d187b PS : 0x00060031 A0 : 0x800811f8 A1 : 0x3ffc0b10
A2 : 0x3ffc34f4 A3 : 0x00000001 A4 : 0x0000006e A5 : 0x00000000
A6 : 0x00000001 A7 : 0x00000001 A8 : 0x3ffc34fc A9 : 0x3ffc0bb0
A10 : 0x0000006e A11 : 0x3ffce980 A12 : 0x00000020 A13 : 0x80000020
A14 : 0x00000008 A15 : 0x00000000 SAR : 0x00000013 EXCCAUSE: 0x00000004
EXCVADDR: 0x00000000 LBEG : 0x00000000 LEND : 0x00000000 LCOUNT : 0x00000000
Backtrace: 0x400d187b:0x3ffc0b10 0x400811f5:0x3ffc0bf0 0x40082a41:0x3ffc0c10 0x400ea7f3:0x00000000
Rebooting...
Decoded with EspExceptionDecoder:
Decoding 4 results
0x400d187b: hall_interrupt() at E:\Documents\Arduino\Arduino Sketches\E-BIKE\EBikeMainProject_V2_ESP32/EBikeMainProject_V2_ESP32.ino line 961
0x400811f5: __onPinInterrupt at E:\Documents\Arduino\hardware\espressif\esp32\cores\esp32/esp32-hal-gpio.c line 211
0x40082a41: _xt_lowint1 at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/freertos/./xtensa_vectors.S line 1105
0x400ea7f3: esp_vApplicationIdleHook at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/esp32/./freertos_hooks.c line 62
@Manuauto
a couple of changes, you need to tell the compiler to always have the ISR in RAM. This processor ESP32 loads program from FLASH into RAM where it executes it. It only has 128Kbytes of RAM for ICACHE (instruction cache) so it switches out unused code on the fly. When an interrupt is triggered it bypasses the Cache load operation and jumps right to the specified code (ISR) location. If that ISR is not in RAM it panics.
void IRAM_ATTR hall_interrupt() {
hall_millis_current = millis(); //Current time for Reference
// this if() will cause integer rollover problems, if millis_last + 100 in at or
// near maximum int value, and millis() has already rolled over it will miss.
// and never trigger until aproximately 49 days later! (millis() 32bit millisecond rollover)
// if (hall_millis_current > hall_millis_last + 100) {
// change it to this order, the integer rollover will be correctly handled
if(hall_millis_current - hall_millis_last >100){
time_for_rotation = hall_millis_current - hall_millis_last; //Calculate Time of Rotation
kmph = (56.8 * float(circumference)) / float(time_for_rotation);
kmph = kmph * 1.60934; //Convert to km/h
hall_millis_last = hall_millis_current; //(Re)Set reference Point
}
}
Chuck.
@stickbreaker
Thanks for taking the time and going over my code!
Many thanks for an actual explanation of what I did wrong / what caused the issue. This was really helpful!
I have implemented the changes and the issue seems to be gone!
Today I went on a test ride and the issue seems to be still there.
In order to decode the debug output I tried to compile the code with the Arduino IDE. This does not work with the changes suggested by @stickbreaker.
'hall_interrupt' was not declared in this scope
Previously I used VisualMicro to compile which worked fine for some reason.
Now I used Visual Micro to compile (with apparent fix) and uploaded it. i reproduced the error and decoded it with the Arduino IDE _(Here I compiled the code Without the Fix, otherwise it would not compile)_
The Output is as follows:
Decoding 4 results
0x40080ed6: __analogInit at E:\Documents\Arduino\hardware\espressif\esp32\cores\esp32/esp32-hal-adc.c line 98
0x400812e9: __pinMode at E:\Documents\Arduino\hardware\espressif\esp32\cores\esp32/esp32-hal-gpio.c line 115
0x40082b35: _xt_medint3 at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/freertos/./xtensa_vectors.S line 1256
0x400ea783: esp_event_process_default at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/esp32/./event_default_handlers.c line 136
Might my pin-selection be unfortunate?
Hi, I just wanted to say that I had a similar problem where an external interrupt (generated every second by a DS3231 RTC) was causing OTA updates to fail. I added IRAM_ATTR to the ISR as suggested by stickbreaker and it seems that it solved the issue :)
I had a lots of problems with OTA as well. What I learned to get OTA working is
stop all
in ArduinoOTA.onStart()
@Manuauto Can we close this issue?
Yes, I'll close it.
The reason for crashes even after adding IRAM_ATTR was that I did "a lot" of relatively complicated calculations in the ISR. By offloading those to the main loop() I resolved this issue completely.
Thanks for the help.
If hall_millis_current == hall_millis_current then you get a divide by zero error!
I think this is the problem.
Test time_for_rotation !=0 and do the computation only if it is true !
time_for_rotation = hall_millis_current - hall_millis_last; //Calculate Time of Rotation
if (time_for_rotation != 0) kmph = (56.8 * float(circumference)) / float(time_for_rotation);
Or use micros() insted of millis(). A miilisecond is a long time ;)
Most helpful comment
@Manuauto
a couple of changes, you need to tell the compiler to always have the ISR in RAM. This processor ESP32 loads program from FLASH into RAM where it executes it. It only has 128Kbytes of RAM for ICACHE (instruction cache) so it switches out unused code on the fly. When an interrupt is triggered it bypasses the Cache load operation and jumps right to the specified code (ISR) location. If that ISR is not in RAM it panics.
Chuck.