256dpi / arduino-mqtt

MQTT library for Arduino
MIT License
1.01k stars 232 forks source link

ESP32 crashes when using arduino-mqtt in combination with PWM #218

Closed D-ominik closed 3 years ago

D-ominik commented 3 years ago

Hello Joël,

first of all, many thanks for your great work!

I got the following situation, which reproducibly always reboots an ESP32 (Arduino IDE 1.8.13 with up-to-date libraries.):

As soon as I change only one of these parameters, the error does not happen:

To troubleshoot the problem I've created a script reduced to the bare minimum. As soon as the retained messages arrive on the topics (after the MQTT connection has been established), the ESP32 will crash.

Sample script:

//use PubSubClient (true) or arduino-mqtt (false)
#define _PUBSUB false

//use PWM (true) or simple static high level port output (false)
#define _PWM true

//the triggered PIN
#define _PIN 16

//WiFi credentials
#define _WSSID "xxx"
#define _WPASS "xxx"

//MQTT connection data
#define _MSERVER "10.0.0.50"
#define _MPORT 8883
#define _MUSER "xxx"
#define _MPASS "xxx"

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>

WiFiClientSecure webClient;

#if (_PUBSUB == true)
  #include <PubSubClient.h>
  PubSubClient mqttClient(webClient);
#else
  #include <MQTT.h>
  MQTTClient mqttClient;
#endif

void setup(){

  Serial.begin(112500);

  //Connect WiFi
  Serial.println("Connecting to WiFi network ");
  WiFi.mode(WIFI_STA);
  WiFi.begin(_WSSID, _WPASS);
  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
  }
  Serial.println("connected");

  //Connect MQTT
  Serial.print("Connecting to MQTT-Server ");
  #if (_PUBSUB == true)
    Serial.println("using PubSubClient");
    mqttClient.setServer(_MSERVER, _MPORT);
    mqttClient.setCallback(mqtt_callback_pubsub);
  #else
    Serial.println("using arduino-mqtt");
    mqttClient.begin(_MSERVER, _MPORT, webClient);
    mqttClient.onMessage(mqtt_callback_am);
  #endif

  while (!mqttClient.connected()){
    if (mqttClient.connect("debugtest", _MUSER, _MPASS)){
      Serial.println("connected");
      mqttClient.subscribe("babyfon/licht/modus");
      mqttClient.subscribe("babyfon/licht/helligkeit");
      //mqttClient.subscribe("babyfon/licht/#");
    }
  }

  //Setup Light-Pin
  #if (_PWM == true)
    ledcSetup(0, 5000, 8);
    ledcAttachPin(_PIN, 0);
  #else
    pinMode(_PIN, OUTPUT);
  #endif

}  //setup()

void loop(){
  mqttClient.loop();
  delay(1000);
}  //loop()

void mqtt_callback_pubsub(char* topic, byte* message, unsigned int length){
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  String messagestring;
  for (int i = 0; i < length; i++){
    Serial.print((char)message[i]);
    messagestring += (char)message[i];
  }
  Serial.println();

  // Helligkeit
  if (String(topic) == "babyfon/licht/helligkeit"){
    #if (_PWM == true)
      ledcWrite(0, 255);
    #else
      digitalWrite(_PIN, HIGH);
    #endif
  }

  // Licht ein- und ausschalten
  else if (String(topic) == "babyfon/licht/modus"){
    #if (_PWM == true)
      ledcWrite(0, 100);
    #else
      digitalWrite(_PIN, HIGH);
    #endif
  }
}  //mqtt_callback_pubsub()

void mqtt_callback_am(String &topic, String &message){
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  Serial.println(message);

  // Helligkeit
  if (topic == "babyfon/licht/helligkeit"){
    #if (_PWM == true)
      ledcWrite(0, 255);
    #else
      digitalWrite(_PIN, HIGH);
    #endif
  }

  // Licht ein- und ausschalten
  else if (topic == "babyfon/licht/modus"){
    #if (_PWM == true)
      ledcWrite(0, 100);
    #else
      digitalWrite(_PIN, HIGH);
    #endif
  }
}  //mqtt_callback_am()

Serial output:

...
Message arrived on topic: babyfon/licht/modus. Message: on
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c:1442 (xQueueGenericReceive)- assert failed!
abort() was called at PC 0x40088889 on core 1

Backtrace: 0x4008c454:0x3ffb1d40 0x4008c685:0x3ffb1d60 0x40088889:0x3ffb1d80 0x400d46cb:0x3ffb1dc0 0x400d176f:0x3ffb1de0 0x400d3435:0x3ffb1e00 0x400d38ab:0x3ffb1e80 0x400d3a65:0x3ffb1ee0 0x400d3ada:0x3ffb1f20 0x400d373a:0x3ffb1f50 0x400d1842:0x3ffb1f80 0x400d5173:0x3ffb1fb0 0x40088b9d:0x3ffb1fd0

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:1216
ho 0 tail 12 room 4
load:0x40078000,len:9720
ho 0 tail 12 room 4
load:0x40080400,len:6352
entry 0x400806b8

Do you have an idea what's going on?

Kind regards Dominik

256dpi commented 3 years ago

Would you be able to obtain a full stack trace of the crash? I think there is a plugin for Arduino that can decode the backtrace...

D-ominik commented 3 years ago

Hello Joël,

thanks for keeping an eye on it!

The full stack trace is:

0x4008c454: invoke_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c line 155
0x4008c685: abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c line 170
0x40088889: xQueueGenericReceive at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c line 1442
0x400d46cb: ledcWrite at C:\Users\ds\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\cores\esp32\esp32-hal-ledc.c line 193
0x400d176f: mqtt_callback_am(String&, String&) at C:\Users\ds\AppData\Local\Temp\arduino_modified_sketch_554708/sketch_oct21a.ino line 143
0x400d3435: MQTTClientHandler(lwmqtt_client_t*, void*, lwmqtt_string_t, lwmqtt_message_t) at F:\Dokumente\Arduino\libraries\MQTT\src\MQTTClient.cpp line 118
0x400d38ab: lwmqtt_cycle_until at F:\Dokumente\Arduino\libraries\MQTT\src\lwmqtt\client.c line 215
0x400d3a65: lwmqtt_subscribe at F:\Dokumente\Arduino\libraries\MQTT\src\lwmqtt\client.c line 430
0x400d3ada: lwmqtt_subscribe_one at F:\Dokumente\Arduino\libraries\MQTT\src\lwmqtt\client.c line 458
0x400d373a: MQTTClient::subscribe(char const*, int) at F:\Dokumente\Arduino\libraries\MQTT\src\MQTTClient.cpp line 329
0x400d1842: setup() at F:\Dokumente\Arduino\libraries\MQTT\src/MQTTClient.h line 113
0x400d5173: loopTask(void*) at C:\Users\ds\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\cores\esp32\main.cpp line 14
0x40088b9d: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143
256dpi commented 3 years ago

You have to ensure that ledcSetup is called before any of the MQTT stuff. The crash is likely due to a ledcWrite triggered by a retained messaged before ledcSetup has been called.

D-ominik commented 3 years ago

Thanks Joel, you are absolutely right!

As this didn't happen if only one retained message arrives and it never happens with PubSubClient, I couldn't see the wood for the trees