Hi guys,
i built a lamp which can be controlled over a webserver (using ESPAsyncWebserver).
The client is communicating with the server through a websocket.
My code uploads without any errors and works fine for some time.
However, when pushing some buttons etc. on the webpage, the program crashes, throwing me Exception 3 (LoadStoreErrorCause) and the stack trace. It crashes at random times, between 6s and 1min, and only when in active usage (interacting with the website).
Why is this happening and how can I fix this?
I found out online that it may have something to do with the chip running out of heap memory...
Is it because of the Strings instead of char arrays?
EDIT 1: I found out during testing, that it has nothing to do with the FastLED library (simplified my code in the question accordingly) and the crash almost never happens if i wait 2s between every input. As soon as I start clicking faster, it crashes again.
Below is my code (I'm sorry it is rather long, I wasn't able to recreate the problem with less code) and the decoded exception code.
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include "webpage_hexalamp.h";
#include <Arduino_JSON.h>
const char* ssid = "M MAIN";
const char* password = "21832040298146194648";
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
// Create a WebSocket object
AsyncWebSocket ws("/ws");
JSONVar values;
int colorValues[3];
int brightness = 50;
double speed = 1;
String activeLightmode = "none";
bool powerOn = false;
void brightnessUpdate() {
// Do something
}
void powerButton(){
// Do something
}
// Websocket Handling ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
String getValues(){
values["brightness"] = String(brightness);
values["speed"] = String(speed);
values["activeLightmode"] = String(activeLightmode);
values["powerOn"] = powerOn ? "true" : "false";
String jsonString = JSON.stringify(values);
return jsonString;
}
//Send all active clients current values
void notifyClients(String values) {
ws.textAll(values);
}
//Websocket Communication: New message from client
void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {
AwsFrameInfo *info = (AwsFrameInfo*)arg;
if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
String message = "";
data[len] = 0;
message = (char*)data;
// Brightness and Speed Slider
if (message.indexOf("slider") >= 0) {
if(message.startsWith("brightness")){
brightness = message.substring(22).toInt();
brightnessUpdate();
} else{
speed = message.substring(17).toDouble();
}
if(message.indexOf("Send") >= 0) {
notifyClients(getValues());
}
}
// Lightmodes
else if (message.indexOf("lightmodeI") >= 0) {
activeLightmode = message.substring(10);
notifyClients(getValues());
}
// Power Button
else if (message.indexOf("powerI") >= 0) {
if(message.substring(6) == "On"){
powerOn = true;
} else {
powerOn = false;
}
powerButton();
notifyClients(getValues());
//RGB Color Picker
} else if (message.indexOf("TTT") >= 0) {
char* charMessage = const_cast<char*>(message.c_str());
colorValues[0] = atoi(strtok(charMessage, "T"));
colorValues[1] = atoi(strtok(NULL, "T"));
colorValues[2] = atoi(strtok(NULL, "T"));
}
else{
Serial.println(message);
}
if (strcmp((char*)data, "getValues") == 0) {
notifyClients(getValues());
}
}
}
// Eventhandler for Websocket Events
void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
switch (type) {
case WS_EVT_CONNECT:
Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
break;
case WS_EVT_DISCONNECT:
Serial.printf("WebSocket client #%u disconnected\n", client->id());
break;
case WS_EVT_DATA:
handleWebSocketMessage(arg, data, len);
break;
case WS_EVT_PONG:
case WS_EVT_ERROR:
break;
}
}
void setup() {
Serial.begin(115200);
initWiFi();
initWebSocket();
// Web Server Root URL
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/html", webpage_hexalamp);
});
server.begin();
void initWebSocket() {
ws.onEvent(onEvent);
server.addHandler(&ws);
}
void initWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi ..");
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(1000);
}
Serial.println(WiFi.localIP());
}
void loop() {
ws.cleanupClients();
}
Decoded Error Message in Serial Monitor:
Exception 3: LoadStoreError: Processor internal physical address or data error during load or store
PC: 0x401067f3: is in umm_disconnect_from_free_list(umm_heap_context_t*, uint16_t) (C:\Users\leosp\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\umm_malloc\umm_malloc.cpp:395).
EXCVADDR: 0x4004439e
Decoding stack results
0x401007fa: is in umm_free_core(umm_heap_context_t*, void*) (C:\Users\leosp\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\umm_malloc\umm_malloc.cpp:642).
0x402040b6: AsyncWebSocketClient::_queueMessage(AsyncWebSocketMessage*) at c:\Users\leosp\Documents\Arduino\libraries\ESPAsyncWebServer\src\StringArray.h:32
0x40100b48: free(void*) at C:\Users\leosp\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\umm_malloc\umm_malloc.cpp:688
0x4020330c: is in std::_Function_handler<void(AsyncWebSocketMessageBuffer* const&), AsyncWebSocket::AsyncWebSocket(const String&)::<lambda(AsyncWebSocketMessageBuffer*)> >::_M_invoke(const std::_Any_data &, AsyncWebSocketMessageBuffer * const&) (c:\Users\leosp\Documents\Arduino\libraries\ESPAsyncWebServer\src\AsyncWebSocket.cpp:853).
0x40203481: AsyncWebSocket::_cleanBuffers() at c:\Users\leosp\Documents\Arduino\libraries\ESPAsyncWebServer\src\StringArray.h:33
0x40202675: is in handleWebSocketMessage(void*, unsigned char*, unsigned int) (C:\Users\leosp\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266/WString.h:115).
0x4020dd94: is in AsyncWebSocket::_handleEvent(AsyncWebSocketClient*, AwsEventType, void*, unsigned char*, unsigned int) (c:\users\leosp\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.1.0-gcc10.3-e5f9fec\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h:617).
0x40100b48: free(void*) at C:\Users\leosp\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\umm_malloc\umm_malloc.cpp:688
0x40203ef8: is in AsyncWebSocketClient::_onData(void*, unsigned int) (c:\Users\leosp\Documents\Arduino\libraries\ESPAsyncWebServer\src\AsyncWebSocket.cpp:691).
0x40208888: is in AsyncClient::_recv(std::shared_ptr<ACErrorTracker>&, tcp_pcb*, pbuf*, int) (c:\Users\leosp\Documents\Arduino\libraries\ESPAsyncTCP\src/ESPAsyncTCP.h:103).
0x402088e8: is in AsyncClient::_s_recv(void*, tcp_pcb*, pbuf*, int) (c:\users\leosp\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.1.0-gcc10.3-e5f9fec\xtensa-lx106-elf\include\c++\10.3.0\bits/shared_ptr_base.h:1324).
0x4020b020: loop_wrapper() at C:\Users\leosp\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp:252
0x4021af69: tcp_input at core\tcp_in.c:501
0x4021fec9: ip4_input at core/ipv4\ip4.c:1467
0x40217bc1: mem_malloc at core\mem.c:210
0x401007fa: is in umm_free_core(umm_heap_context_t*, void*) (C:\Users\leosp\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\umm_malloc\umm_malloc.cpp:642).
0x40217285: ethernet_input_LWIP2 at netif\ethernet.c:188
0x40217098: esp2glue_ethernet_input at glue-lwip\lwip-git.c:118
0x4023fb5d: ethernet_input at glue-esp\lwip-esp.c:365
0x4023fb6f: ethernet_input at glue-esp\lwip-esp.c:373
0x401000ab: app_entry_redefinable() at C:\Users\leosp\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp:386
0x40100274: is in ets_post(uint8, ETSSignal, ETSParam) (C:\Users\leosp\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp:238).
0x40100274: is in ets_post(uint8, ETSSignal, ETSParam) (C:\Users\leosp\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp:238).
0x40100274: is in ets_post(uint8, ETSSignal, ETSParam) (C:\Users\leosp\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp:238).
0x4020ca44: run_scheduled_recurrent_functions() at C:\Users\leosp\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_features.h:64
0x40100274: is in ets_post(uint8, ETSSignal, ETSParam) (C:\Users\leosp\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp:238).
0x40100274: is in ets_post(uint8, ETSSignal, ETSParam) (C:\Users\leosp\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp:238).
0x40100274: is in ets_post(uint8, ETSSignal, ETSParam) (C:\Users\leosp\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp:238).
0x40204398: is in AsyncWebSocket::count() const (c:\Users\leosp\Documents\Arduino\libraries\ESPAsyncWebServer\src/StringArray.h:35).
0x402043d8: is in AsyncWebSocket::cleanupClients(unsigned short) (c:\Users\leosp\Documents\Arduino\libraries\ESPAsyncWebServer\src\AsyncWebSocket.cpp:922).
0x402043c4: is in AsyncWebSocket::cleanupClients(unsigned short) (c:\Users\leosp\Documents\Arduino\libraries\ESPAsyncWebServer\src\AsyncWebSocket.cpp:922).
0x40202314: is in CPixelLEDController<(EOrder)66, 1, 4294967295u>::show(CRGB const*, int, CRGB) (c:\Users\leosp\Documents\Arduino\libraries\FastLED\src/controller.h:289).
0x4021899a: tcp_listen_with_backlog_and_err at core\tcp.c:916
0x40208ff4: is in CFastLED::show(unsigned char) (c:\Users\leosp\Documents\Arduino\libraries\FastLED\src/controller.h:183).
0x402090a5: is in CFastLED::addLeds(CLEDController*, CRGB*, int, int) (c:\Users\leosp\Documents\Arduino\libraries\FastLED\src\FastLED.cpp:51).
0x4020439e: is in AsyncWebSocket::count() const (c:\Users\leosp\Documents\Arduino\libraries\ESPAsyncWebServer\src/StringArray.h:35).
0x4020dd48: is in std::_Function_handler<bool(AsyncWebSocketClient* const&), AsyncWebSocket::count() const::<lambda(AsyncWebSocketClient*)> >::_M_manager(std::_Any_data &, const std::_Any_data &, std::_Manager_operation) (c:\users\leosp\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.1.0-gcc10.3-e5f9fec\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h:268).
Would be great if anyone is able to help, I already spent hours working on this problem.
If I should modify my question and provide more data, please just tell me!
Thanks in advance!