Hello, my ESP32 device keeps resetting after streaming serial data over BT for a while.
Has anyone else had this issue?
Here's the errors and stacktrace decoding below:
ASSERT_PARAM(512 0), in rwbt.c at line 273
Guru Meditation Error: Core 0 panic'ed (Interrupt wdt timeout on CPU0)
Core 0 register dump:
PC : 0x40085844 PS : 0x00060034 A0 : 0x800892bc A1 : 0x3ffc05b0
A2 : 0x00000001 A3 : 0x00000000 A4 : 0x00000000 A5 : 0x60008054
A6 : 0x3ffc1030 A7 : 0x60008050 A8 : 0x80085841 A9 : 0x3ffc0590
A10 : 0x00000004 A11 : 0x00000000 A12 : 0x6000804c A13 : 0xffffffff
A14 : 0x00000000 A15 : 0xfffffffc SAR : 0x00000004 EXCCAUSE: 0x00000005
EXCVADDR: 0x00000000 LBEG : 0x40085779 LEND : 0x40085780 LCOUNT : 0x00000000
Core 0 was running in ISR context:
EPC1 : 0x4017e24a EPC2 : 0x00000000 EPC3 : 0x00000000 EPC4 : 0x40085844
Backtrace: 0x40085844:0x3ffc05b0 0x400892b9:0x3ffc05d0 0x4008994b:0x3ffc05f0 0x40081f45:0x3ffc0610 0x4017e247:0x00000000
Core 1 register dump:
PC : 0x4017e24a PS : 0x00060334 A0 : 0x8008e46a A1 : 0x3ffd1de0
A2 : 0x00000008 A3 : 0x00000001 A4 : 0x00000000 A5 : 0x3ffd1910
A6 : 0x00000000 A7 : 0x00000001 A8 : 0x3ffc829c A9 : 0x3ffc8260
A10 : 0x00000000 A11 : 0x00000001 A12 : 0x8008c8c8 A13 : 0x3ffd1ce0
A14 : 0x00000000 A15 : 0x3ffd1aa0 SAR : 0x00000000 EXCCAUSE: 0x00000005
EXCVADDR: 0x00000000 LBEG : 0x00000000 LEND : 0x00000000 LCOUNT : 0x00000000
Backtrace: 0x4017e24a:0x3ffd1de0 0x4008e467:0x3ffd1e00
Decoding 13 results
0x40085844: r_assert_param at ?? line ?
0x40085779: r_assert_param at ?? line ?
0x40085780: r_assert_param at ?? line ?
0x4017e24a: esp_vApplicationWaitiHook at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/esp32/freertos_hooks.c line 66
0x40085844: r_assert_param at ?? line ?
0x40085844: r_assert_param at ?? line ?
0x400892b9: r_rwbt_isr at ?? line ?
0x4008994b: r_rwbtdm_isr_wrapper at intc.c line ?
0x40081f45: _xt_lowint1 at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/freertos/xtensa_vectors.S line 1105
0x4017e247: esp_vApplicationWaitiHook at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/esp32/freertos_hooks.c line 66
0x4017e24a: esp_vApplicationWaitiHook at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/esp32/freertos_hooks.c line 66
0x4017e24a: esp_vApplicationWaitiHook at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/esp32/freertos_hooks.c line 66
0x4008e467: prvIdleTask at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/freertos/tasks.c line 3564
Turns out my heap gets reduced the slower I transmit, causing overflow. Must be something in my code eating up resources when I don't transmit for a few hundred ms or more for some reason. Anyone want to take a look and give me their 2 cents on what could be eating memory at slower transmit rates? At 100ms it is stable, kind of the opposite of what you'd expect huh?
#include "BluetoothSerial.h"
#include <Wire.h>
#include <Adafruit_ADS1015.h>
//#include <esp_bt.h>
//#include <ArduinoJson.h>
BluetoothSerial SerialBT;
GLOBAL VARIABLES HERE
void startADS() {
// Begin ADS
ads.begin();
ads.setGain(GAIN_SIXTEEN);
//ads.setGain(GAIN_TWOTHIRDS); // 2/3x gain +/- 6.144V 1 bit = 3mV (default)
//ads.setGain(GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 2mV
//ads.setGain(GAIN_TWO); // 2x gain +/- 2.048V 1 bit = 1mV
//ads.setGain(GAIN_FOUR); // 4x gain +/- 1.024V 1 bit = 0.5mV
//ads.setGain(GAIN_EIGHT); // 8x gain +/- 0.512V 1 bit = 0.25mV
//ads.setGain(GAIN_SIXTEEN); // 16x gain +/- 0.256V 1 bit = 0.125mV
//Start timers
startMillis = millis();
ledMillis = millis();
}
void commandESP32(char received){
if(received == 't'){
sensorEnabled = true;
digitalWrite(LED,LOW);
}
if(received == 'f'){
sensorEnabled = false;
digitalWrite(LED,HIGH);
digitalWrite(RED,LOW);
digitalWrite(IR,LOW);
}
/*
if(received == 'u'){
usbSerialEnabled = true;
}
if(received == 'b') {
usbSerialEnabled = false;
}
*/
delay(2000);
}
void setup() {
Serial.begin(115200);
pinMode(IR, OUTPUT);
pinMode(RED, OUTPUT);
//LOLIN32 ONLY
pinMode(LED,OUTPUT);
digitalWrite(LED,HIGH);
//esp_bt_sleep_disable(); // Disables sleep mode (debugging)
SerialBT.begin("My_HEG");
BLEMillis = millis();
}
void core_program() {
if(sensorEnabled == true) {
if(adcEnabled == false) {
startADS();
adcEnabled = true;
}
if(SEND_DUMMY_VALUE != true) {
currentMillis = millis();
if(currentMillis - startMillis >= sampleRate) {
// read the analog in value:
adc0 = ads.readADC_SingleEnded(0);
//Voltage = (adc0 * bits2mv);
// print the results to the Serial Monitor:
if (VIEW_ADC_VALUE == true) {
//Serial.println("ADC Value: ");
//Serial.println(adc0);
//Serial.println("\tVoltage: ");
//Serial.println(Voltage,7);
}
if (DEBUG_ADC == false) {
if(adc0 >= 7000) { // The gain is high but anything over 7000 is most likely not a valid signal, anything more than 2000 is not likely your body's signal.
//Serial.println("\nBad Read ");
badSignal = true;
//Temp: reset baseline on bad read
signalDetermined = false;
baseline = 0;
ticks0 = 0; // Reset counter
ticks1 = 0;
ticks2 = 0;
redValue = 0; // Reset values
irValue = 0;
}
else {
badSignal = false;
if(signalDetermined == false){
ticks0++;
if(ticks0 > 500) { // Wait for 500 samples of good signal before getting baseline
// IR IN 12, RED IN 13
if((ticks1 < 500) && (ticks2 < 500)) { // Accumulate samples for baseline
if(first_led == true) { // RED
redValue += adc0;
ticks1++;
}
else { // IR
irValue += adc0;
ticks2++;
}
//Serial.println("\nGetting Baseline. . .");
}
else {
signalDetermined = true;
redavg = redValue / ticks1;
iravg = irValue / ticks2;
baseline = redavg / iravg; // Set baseline ratio
ticks0 = 0; // Reset counters
ticks1 = 0;
ticks2 = 0;
redValue = 0; // Reset values
irValue = 0;
//Uncomment this
//Serial.println("\tBaseline R: ");
//Serial.print(baseline,4);
}
}
}
else {
ticks0++;
if(first_led == true) { // RED
redValue += adc0;
ticks1++;
}
else { // IR
irValue += adc0;
ticks2++;
}
if((ticks2 > samplesPerRatio) && (ticks1 > samplesPerRatio)) { // Accumulate 50 samples per LED before taking reading
redavg = redValue / ticks1; // Divide value by number of samples accumulated
//redavg = redAvg * 200 // Scalar multiplier to make changes more apparent
iravg = irValue / ticks2;
ratio = redavg / iravg; // Get ratio
ratioAvg += ratio;
p1 = p2;
p2 = ratio - baseline; // Position
posAvg += p2;
//v1 = v2;
//v2 = (p2 - p1) * ticks0 * 0.001; // Velocity in ms
//velAvg += v2;
//accel = (v2 - v1) * ticks0 * 0.001; // Acceleration in ms^2
//accelAvg += accel;
//score += ratio-baseline; // Simple scoring method
//scoreAvg += score;
ticks0 = 0; //Reset Counters
ticks1 = 0;
ticks2 = 0;
ticks3++;
redValue = 0; //Reset values to get next average
irValue = 0;
}
}
}
startMillis = currentMillis;
}
}
// Switch LEDs back and forth.
// PUT IR IN 13, AND RED IN 12
if(currentMillis - ledMillis >= ledRate) {
if(first_led == false) {
digitalWrite(RED,HIGH);
digitalWrite(IR,LOW);
first_led = true;
}
else {
digitalWrite(RED,LOW);
digitalWrite(IR,HIGH);
first_led = false;
}
ledMillis = currentMillis;
}
adcAvg += adc0;
ticks4++;
}
}
//DEBUG
if(DEBUG == true){
Serial.println("Heap after core_program cycle: ");
Serial.println(ESP.getFreeHeap());
}
}
void bluetooth() {
if(SerialBT.available()){
received = SerialBT.read();
Serial.println(received);
SerialBT.println(received);
commandESP32(received);
}
if(currentMillis - BLEMillis >= BTRate) { //SerialBT bitrate: ?/s. 100ms works, 50ms does cause hangups (which the LED flashes will reflect) - need better buffering.
SerialBT.flush();
if(SEND_DUMMY_VALUE != true) {
if(ticks4 > 0) {
adcAvg = adcAvg / ticks4;
if(ticks3 > 0) {
ratioAvg = ratioAvg / ticks3;
posAvg = posAvg / ticks3;
SerialBT.print(String(adcAvg,0) + "," + String(ratioAvg,4) + "," + String(posAvg,4)+"\r\n");
}
else {
SerialBT.print(String(adcAvg,0) + ",WAIT\r\n");
}
ratioAvg = 0;
posAvg = 0;
adcAvg = 0;
adc0 = 0;
ticks3 = 0;
ticks4 = 0;
BLEMillis = currentMillis;
}
}
else {
int rando = random(0,1000);
SerialBT.print("DUMMY,"+String(rando)+"\r\n");
}
}
if(DEBUG == true){
Serial.println("Heap after bluetooth() cycle: ");
Serial.println(ESP.getFreeHeap());
}
}
void loop() {
if(SerialBT.hasClient() == true) {
core_program();
bluetooth();
delay(1); //1 ms delay.
}
}
Your wdt is triggered, that means it is not reset for about 2.5s it will halt your program, you can reset it using yield() which will also trigger any background processes that the ESP needs to run, Put that within any of you millis() timed loops, just before or after currentMilis=millis() should fix the issue.