Dual Core task crashing even though same command works elsewhere

abasel
Posts: 2
Joined: Thu Jun 24, 2021 12:59 am

Dual Core task crashing even though same command works elsewhere

Postby abasel » Thu Jun 24, 2021 1:10 am

I have ventured beyond my ability in this one.

This project is for an IoT demo to some students. Using Telegram they can control some lighting as well as receive some notifications to events.

The following are confirmed to be working:
  • All lighting and lighting telegram messages
  • Temperature sensor and telegram messages
  • Door bell but NOT the telegram message
If "bot.sendMessage(chat_id, "Someone is at the door.", "");" is added to the soundDoorbell() function then the following crash occurs
CORRUPT HEAP: Bad head at 0x3fff479c. Expected 0xabba1234 got 0x3ffffff8
abort() was called at PC 0x40086cd1 on core 0

ELF file SHA256: 0000000000000000

Backtrace: 0x40088904:0x3ffdc5d0 0x40088b81:0x3ffdc5f0 0x40086cd1:0x3ffdc610 0x40086dfd:0x3ffdc640 0x400f6bcf:0x3ffdc660 0x400f2ebd:0x3ffdc920 0x400f2e4c:0x3ffdc970 0x4008d25d:0x3ffdc9a0 0x40081f1e:0x3ffdc9c0 0x4008208d:0x3ffdc9e0 0x40123ca6:0x3ffdca00 0x4011706a:0x3ffdca20 0x400d3a28:0x3ffdca40 0x400d3629:0x3ffdca60 0x400d37fb:0x3ffdca80 0x400d38f1:0x3ffdcab0 0x400d464d:0x3ffdcad0 0x400d707d:0x3ffdcb00 0x400d15cd:0x3ffdcba0 0x400d16a3:0x3ffdcbc0 0x40089b92:0x3ffdcc00

Rebooting...
ets Jun 8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x17 (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:1044
load:0x40078000,len:10124
load:0x40080400,len:5856
entry 0x400806a8

The decode stack shows:
0x40088904: invoke_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c line 156
0x40088b81: abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c line 171
0x40086cd1: lock_acquire_generic at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/locks.c line 143
0x40086dfd: _lock_acquire_recursive at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/locks.c line 171
0x400f6bcf: _vfiprintf_r at ../../../.././newlib/libc/stdio/vfprintf.c line 860
0x400f2ebd: fiprintf at ../../../.././newlib/libc/stdio/fiprintf.c line 50
0x400f2e4c: __assert_func at ../../../.././newlib/libc/stdlib/assert.c line 59
0x4008d25d: multi_heap_free at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/multi_heap_poisoning.c line 218
0x40081f1e: heap_caps_free at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/heap_caps.c line 268
0x4008208d: esp_mbedtls_mem_free at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/mbedtls/port/esp_mem.c line 35
0x40123ca6: mbedtls_free at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/mbedtls/mbedtls/library/platform.c line 98
0x4011706a: mbedtls_ssl_free at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/mbedtls/mbedtls/library/ssl_tls.c line 8992
0x400d3a28: stop_ssl_socket(sslclient_context*, char const*, char const*, char const*) at C:\Users\abas034\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WiFiClientSecure\src\ssl_client.cpp line 272
0x400d3629: WiFiClientSecure::stop() at C:\Users\abas034\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WiFiClientSecure\src\WiFiClientSecure.cpp line 93
0x400d37fb: WiFiClientSecure::connect(char const*, unsigned short, char const*, char const*, char const*) at C:\Users\abas034\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WiFiClientSecure\src\WiFiClientSecure.cpp line 154
0x400d38f1: WiFiClientSecure::connect(char const*, unsigned short) at C:\Users\abas034\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WiFiClientSecure\src\WiFiClientSecure.cpp line 112
0x400d464d: UniversalTelegramBot::sendGetToTelegram(String const&) at C:\Users\abas034\UOA\OneDrive - The University of Auckland\Documents\Arduino\libraries\UniversalTelegramBot\src\UniversalTelegramBot.cpp line 73
0x400d707d: UniversalTelegramBot::getUpdates(long) at C:\Users\ab\UOA\OneDrive - The University of Auckland\Documents\Arduino\libraries\UniversalTelegramBot\src\UniversalTelegramBot.cpp line 369
0x400d15cd: checkTelegramBot() at C:\Users\ab\OneDrive\Documents\Projects\WorkingOn\IoT-Demo\HomeAutomationV3/HomeAutomationV3.ino line 315
0x400d16a3: nonloopingCode(void*) at C:\Users\ab\OneDrive\Documents\Projects\WorkingOn\IoT-Demo\HomeAutomationV3/HomeAutomationV3.ino line 343
0x40089b92: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143
Given that the "bot.sendMessage" function works everywhere else, I can't work out why it would fail in this instance.

Code: Select all

#include <FastLED.h>
#include <Wire.h>
#include <Adafruit_BMP280.h>

#ifdef ESP32
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
#endif
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>   
#include <ArduinoJson.h>

#include "DHTesp.h"

//Wifi & Telgram credentials
#include "config.h"

// Sensors & Control

#define pin_DHT11 4 //
#define pin_alarmsensor 2 //RCWL-0516
#define pin_siren 19
#define pin_led_veranda 26
#define pin_led_bedroom 25
#define pin_doorbell 27

DHTesp dht;

#define DATA_PIN    18
#define LED_TYPE    WS2812 
#define COLOR_ORDER GRB
#define NUM_LEDS   12
CRGB leds[NUM_LEDS];

#define BRIGHTNESS          50
#define FRAMES_PER_SECOND  120

bool alarmArmed = false;
bool alarmTriggered = false;
bool partyledson = false;
bool livingroomledson = false;

int buttonState;             
int lastButtonState = LOW;   
unsigned long lastDebounceTime = 0;  
unsigned long debounceDelay = 50;    

WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

int botRequestDelay = 50;
unsigned long lastTimeBotRan;

char textoption;

String chat_id;

TaskHandle_t loopingTasks;
TaskHandle_t nonloopingTasks;


void GetTemperature() { //implemented
  String message = "Temperature: ";
  TempAndHumidity newValues = dht.getTempAndHumidity();
  message.concat(String(newValues.temperature)); message.concat(".");
  bot.sendMessage(chat_id, message, "");
}

void ToggleAlarm() {
  alarmArmed = !alarmArmed;

  if (alarmArmed) {
    bot.sendMessage(chat_id, "Alarm armed.", "");
  }
  else bot.sendMessage(chat_id, "Alarm disarmed.", "");

}

void TogglePartylights() {
  partyledson = !partyledson;
  if (partyledson) {
    livingroomledson = false;
    bot.sendMessage(chat_id, "Party lights switched on.", "");
  }
  else bot.sendMessage(chat_id, "Party lights switched off.", "");
}

void ToggleVerandaLights() {
  bool LightStatus = digitalRead(pin_led_veranda);
  LightStatus = !LightStatus;
  digitalWrite(pin_led_veranda, LightStatus);
  LightStatus = digitalRead(pin_led_veranda);
  if (LightStatus) {
    bot.sendMessage(chat_id, "Veranda light switched on.", "");
  }
  else bot.sendMessage(chat_id, "Veranda light switched off.", "");
}

void ToggleLivingRoomLights() {
  partyledson = false;
  bool LightStatus = livingroomledson;
  livingroomledson = !livingroomledson;
  if (livingroomledson) {
    for ( int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB::White;
    }
    FastLED.show();
    bot.sendMessage(chat_id, "Livingroom light switched on.", "");
  }
  else {
    FastLED.clear();
    FastLED.show();
    bot.sendMessage(chat_id, "Livingroom light switched off.", "");
  }
}

void ToggleBedroomLights() {
  bool LightStatus = digitalRead(pin_led_bedroom);
  LightStatus = !LightStatus;
  digitalWrite(pin_led_bedroom, LightStatus);
  LightStatus = digitalRead(pin_led_bedroom);
  if (LightStatus) {
    bot.sendMessage(chat_id, "Bedroom lights switched on.", "");
  }
  else bot.sendMessage(chat_id, "Bedroom lights switched off.", "");

}

void soundAlarm() {
  digitalWrite(pin_siren, HIGH);
  delay(500);
  digitalWrite(pin_siren, LOW);
  delay(500);
}

void GetSystemStatus() {
  String message = "";

  if (alarmArmed) {
    message += "Alarm is armed";
  }
  else message += "Alarm is disarmed.\n";
  if (digitalRead(pin_siren)) {
    message += "and sounding.\n";
  }
  else if (alarmArmed) message += ".\n";

  if (digitalRead(pin_led_bedroom)) {
    message += "Bedroom lights are on.\n";
  }
  else message += "Bedroom lights are off.\n";

  if (partyledson) {
    message += "Party lights are on.\n";
  }
  else message += "Partylights are off off.\n";

  if (livingroomledson) {
    message += "Livingroom lights are on.\n";
  }
  else message += "Livingroom lights are off.\n";

  message += "Temperature: ";
  TempAndHumidity newValues = dht.getTempAndHumidity();
  message.concat(String(newValues.temperature)); message.concat("ºC.\n");

  if (digitalRead(pin_led_veranda)) {
    message += "Veranda lights are on.\n";
  }
  else message += "Veranda lights are off.\n";

  bot.sendMessage(chat_id, message, "");
}

// Handle what happens when you receive new messages
void handleNewMessages(int numNewMessages) {
  Serial.println("handleNewMessages");
  Serial.println(String(numNewMessages));

  for (int i = 0; i < numNewMessages; i++) {
    // Chat id of the requester
    chat_id = String(bot.messages[i].chat_id);
    if (chat_id != CHAT_ID) {
      bot.sendMessage(chat_id, "Unauthorized user", "");
      Serial.println("Unauthorized user");
      continue;
    }

    // Print the received message
    String text = bot.messages[i].text;
    Serial.println(text);

    String from_name = bot.messages[i].from_name;
    if (text == "/temperature") {
      textoption = 't';
    }
    else if (text == "/status") {
      textoption = 's'; 
    }
    else if (text == "/alarm") {
      textoption = 'a';
    }
    else if (text == "/party") {
      textoption = 'p';
    }
    else if (text == "/veranda_lights") {
      textoption = 'v';
    }
    else if (text == "/livingroom_lights") {
      textoption = 'l';
    }
    else if (text == "/bedroom_lights") {
      textoption = 'b';
    }
    else textoption = 'x';

    switch (textoption) {
      case 't' : {
          GetTemperature();
          break;
        }
      case 's' : {
          GetSystemStatus();
          break;
        }
      case 'a' : {
          ToggleAlarm();
          break;
        }
      case 'p' : {
          TogglePartylights();
          break;
        }
      case 'v' : {
          ToggleVerandaLights();
          break;
        }
      case 'l' : {
          ToggleLivingRoomLights();
          break;
        }
      case 'b' : {
          ToggleBedroomLights();
          break;
        }
      default : {
          bot.sendMessage(chat_id, "Invalid command. \nUse one of:\n\/alarm\n/bedroom_lights\n/livingroom_lights\n/party\n/temperature\n/veranda_lights", "");
          break;
        }
    }
  }
}
void setup() {
  delay(3000);

  Serial.begin(115200);

  dht.setup(pin_DHT11, DHTesp::DHT11);
#ifdef ESP8266
  client.setInsecure();
#endif

  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.setBrightness(BRIGHTNESS);
  FastLED.clear();
  FastLED.show();
  Serial.println("Started");

  pinMode(pin_siren, OUTPUT);
  pinMode(pin_led_veranda, OUTPUT);
  pinMode(pin_led_bedroom, OUTPUT);
  pinMode(pin_alarmsensor, INPUT);
  pinMode(pin_doorbell, INPUT_PULLUP);

  // Connect to Wi-Fi
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  client.setCACert(TELEGRAM_CERTIFICATE_ROOT);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }
  // Print ESP32 Local IP Address
  Serial.println(WiFi.localIP());

  Serial.println("Bot started?");
  bot.sendMessage(CHAT_ID, "System restarted", "");

  //create a task that will be executed in the Task1code() function, with priority 1 and executed on core 0
  xTaskCreatePinnedToCore(
    nonloopingCode,   /* Task function. */
    "nonloopingTasks",     /* name of task. */
    16384,       /* Stack size of task */
    NULL,        /* parameter of the task */
    1,           /* priority of the task */
    &nonloopingTasks,      /* Task handle to keep track of created task */
    0);          /* pin task to core 0 */
  delay(500);

  xTaskCreatePinnedToCore(
    juggle,   /* Task function. */
    "loopingTasks",     /* name of task. */
    16384,       /* Stack size of task */
    NULL,        /* parameter of the task */
    1,           /* priority of the task */
    &loopingTasks,      /* Task handle to keep track of created task */
    1);          /* pin task to core 1 */
  delay(500);

}

void checkTelegramBot() {
  if (millis() > lastTimeBotRan + botRequestDelay) {
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);

    while (numNewMessages) {
      Serial.println("Got response");
      handleNewMessages(numNewMessages);
      numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    }
    lastTimeBotRan = millis();
  }
}

void nonloopingCode(void * pvParamters) {
  Serial.print("nonloopingCode running on core ");
  Serial.println(xPortGetCoreID());
  for (;;) {

    if ((!partyledson) && (!livingroomledson)) {
      FastLED.clear();
      FastLED.show();
    }
    if (alarmArmed) {
      if (digitalRead(pin_alarmsensor)) {
        bot.sendMessage(chat_id, "Alarm triggered", "");
        partyledson = false;
        alarmTriggered = true;
      }
    }

    checkTelegramBot();
  }
}
void juggle(void * pvParamters) {
  Serial.print("Juggle running on core ");
  Serial.println(xPortGetCoreID());
  for (;;) {
    checkDoorbell();
    if (alarmTriggered)soundAlarm();
    if (partyledson) {
      fadeToBlackBy( leds, NUM_LEDS, 20);
      byte dothue = 0;
      int i = 0;
      while ((i < 8) && partyledson) {
        leds[beatsin16( i + 7, 0, NUM_LEDS - 1 )] |= CHSV(dothue, 200, 255);
        dothue += 32;
        i += 1;
      }
      // send the 'leds' array out to the actual LED strip
      if (!partyledson) FastLED.clear();
      FastLED.show();
      // insert a delay to keep the framerate modest
      FastLED.delay(1000 / FRAMES_PER_SECOND);
    }
  }
}

void soundDoorbell() {
  bot.sendMessage(chat_id, "Someone is at the door.", "");
  soundAlarm(); soundAlarm();
}

void checkDoorbell() {
  int reading = digitalRead(pin_doorbell);
  if (reading != lastButtonState) {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
   if (reading != buttonState) {
      buttonState = reading;
      if (buttonState == LOW) {
        soundDoorbell();
      }
    }
  }
  lastButtonState = reading;
}

void loop() {
}

ESP_Sprite
Posts: 9730
Joined: Thu Nov 26, 2015 4:08 am

Re: Dual Core task crashing even though same command works elsewhere

Postby ESP_Sprite » Thu Jun 24, 2021 1:43 am

In general, you're calling the telegram bot code from multiple tasks. Are you sure this library is threadsafe / re-entrant? The library may not like getUpdates running on one core while sendmessage is running on the other at the same time. (A solution if it is not would be to use FreeRTOS mutexes to make sure only one task calls into the API at a time, btw.)

abasel
Posts: 2
Joined: Thu Jun 24, 2021 12:59 am

[SOLVED Re: Dual Core task crashing even though same command works elsewhere

Postby abasel » Thu Jun 24, 2021 4:10 am

Thanks for that. I don't think it's threadsafe.

Using FreeRTOS mutexes (https://microcontrollerslab.com/arduino ... heritance/), I managed to get it to work although there is lots of lag but that is an easier issue to sort out :)

Who is online

Users browsing this forum: No registered users and 53 guests