It is weird. Yesterday I've tried to debug my code and now it works OK.
My approach was:
- Code with MD_Parola (3 zones), Wifi and MQTT did not work (soft WDT reset)
- I've tried to turn MD_Parola off - works OK
- I've tried to use MD_Parola without zones - works OK
- Then I've created 2 zones (instead of 3 planned) - works OK
- I've created 3 zones - works OK
So, now I don't know what happens.
I'm including stack trace from ESP Exception Decoder:
Decoding stack results
0x40207b25: String::invalidate() at C:\Users\<CENSORED>\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.6.3\cores\esp8266\WString.cpp line 140
0x40201528: setup() at C:\Users\CENSORED>\Documents\Arduino\libraries\MD_Parola\src/MD_Parola.h line 1670
0x402012e0: mqtt_callback(String, unsigned char*, unsigned int) at D:\matrix_display.ino/matrix_display.ino.ino line 105
0x40209d68: std::_Function_base::_Base_manager ::_M_manager(std::_Any_data&, std::_Any_data const&, std::_Manager_operation) at c:\users\CENSORED>\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\2.5.0-4-b40a506\xtensa-lx106-elf\include\c++\4.8.2/functional line 1934
0x40201014: std::_Function_handler ::_M_invoke(std::_Any_data const&, char*, unsigned char*, unsigned int) at c:\users\CENSORED>\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\2.5.0-4-b40a506\xtensa-lx106-elf\include\c++\4.8.2/functional line 2069
0x40208348: loop_wrapper() at C:\Users\CENSORED>AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.6.3\cores\esp8266\core_esp8266_main.cpp line 177
Also including my code (stack trace not match lines of this code):
#include "ESP8266WiFi.h"
#include "PubSubClient.h"
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#define BUILTINLED_LOW 1
#define BUILTINLED_HIGH 0
//Display
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 16
#define CS_PIN 15
#define SPEED_TIME 25
#define PAUSE_TIME 0
#define NUM_ZONES 3
#define MAX_MSG_CHAR 50
#define MAX_TIME_CHAR 50
#define MAX_ADD_CHAR 50
char msg_zone_char[MAX_MSG_CHAR+1] = "";
char time_zone_char[MAX_TIME_CHAR+1] = "";
char add_zone_char[MAX_ADD_CHAR+1] = "";
MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
//Wifi
const char* ssid = "SSID";
const char* password = "PASS";
IPAddress ip(192,168,22,205);
IPAddress gateway(192,168,22,1);
IPAddress subnet(255,255,255,0);
String static_ip;
unsigned long WifiStatusFreq = 10000;
int wifi_reconnects_count = 0;
unsigned long time_wo_wifi_s = 0;
unsigned long lastWifiMillis=0;
WiFiClient displayWifi;
//MQTT
const char* mqtt_server = "192.168.22.220";
const char* mqtt_username = "user";
const char* mqtt_password = "pass";
const char* mqtt_clientID = "MatrixDisplay";
PubSubClient client(displayWifi);
//Others
const int speakerPin = 5;
String boardStatusJSON = "{}";
unsigned long lastHBMillis=0;
unsigned long heartBeatFreq = 60000;
/**************************************
**** WiFi communication functions
*************************************/
void wifi_connect(bool board_start){
unsigned long connectstart_time = millis() / 1000;
unsigned long functionstart_time_s = connectstart_time;
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
WiFi.config(ip, gateway, subnet);
while (WiFi.status() != WL_CONNECTED) {
digitalWrite(LED_BUILTIN, BUILTINLED_HIGH);
delay(100);
digitalWrite(LED_BUILTIN, BUILTINLED_LOW);
delay(100);
if((millis() / 1000) > connectstart_time + 30){
Serial.println("Wifi has problem to connect, waiting 60s");
digitalWrite(LED_BUILTIN, BUILTINLED_HIGH);
delay(60000);
connectstart_time = millis() / 1000;
}
}
Serial.println("Wifi connected");
wifi_reconnects_count++;
time_wo_wifi_s += (millis() / 1000) - functionstart_time_s;
digitalWrite(LED_BUILTIN, BUILTINLED_LOW);
}
/**************************************
**** MQTT communication functions
*************************************/
void makeBoardStatusJSON()
{
boardStatusJSON = "{";
boardStatusJSON += "\"wifi_ip\":\""+static_ip+"\",";
boardStatusJSON += "\"wifi_rssi\":\""+(String)WiFi.RSSI()+"\",";
boardStatusJSON += "\"wifi_reconnects\":\""+(String)wifi_reconnects_count+"\",";
boardStatusJSON += "\"board_wo_wifi_s\":\""+(String)time_wo_wifi_s+"\",";
boardStatusJSON += "}";
}
// This functions is executed when some device publishes a message to a topic that your ESP8266 is subscribed to
void mqtt_callback(String topic, byte* message, unsigned int length) {
if( topic == "livingroom/display/command"){
if(!strncmp((char *)message, "MAKEDETAILEDSTATUS", length))
{
makeBoardStatusJSON();
client.publish("livingroom/display/detailedstatus",boardStatusJSON.c_str());
}
else if(!strncmp((char *)message, "SOMETHING", length))
{
}
}
if( topic == "livingroom/display/1/msg"){
//if(strlen((char *)message))
strcpy(msg_zone_char,(char *)message);
Serial.println((char *)message);
}
}
void mqtt_reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
// Serial.print("Attempting MQTT connection...");
if (client.connect(mqtt_clientID,mqtt_username,mqtt_password)) {
// Serial.println("mqtt connected");
// Subscribe or resubscribe to a topic
// You can subscribe to more topics (to control more LEDs in this example)
client.subscribe("livingroom/display/1/msg");
} else {
// Serial.print("failed, rc=");
// Serial.print(client.state());
// Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
/**************************************
**** Speaker functions
*************************************/
void play_start()
{
tone(speakerPin,1200);
delay(30);
pinMode(speakerPin, INPUT);
}
/******************************
**** RUN
*****************************/
void setup() {
//ESP.wdtDisable();
//ESP.wdtEnable(WDTO_8S);
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
play_start();
wifi_connect(1);
static_ip = (String)WiFi.localIP()[0]+"."+(String)WiFi.localIP()[1]+"."+(String)WiFi.localIP()[2]+"."+(String)WiFi.localIP()[3];
client.setServer(mqtt_server, 1883);
client.setCallback(mqtt_callback);
myDisplay.begin(NUM_ZONES);
myDisplay.setZone(0, 8, 15);
myDisplay.setZone(1, 4, 7);
myDisplay.setZone(2, 0, 3);
myDisplay.setIntensity(0);
myDisplay.displayZoneText(0, msg_zone_char, PA_LEFT, SPEED_TIME, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
myDisplay.displayZoneText(1, time_zone_char, PA_LEFT, SPEED_TIME, PAUSE_TIME, PA_PRINT, PA_NO_EFFECT);
myDisplay.displayZoneText(2, add_zone_char, PA_RIGHT, SPEED_TIME, PAUSE_TIME, PA_PRINT, PA_NO_EFFECT);
char msg_zone_char[MAX_MSG_CHAR+1] = "";
char time_zone_char[MAX_TIME_CHAR+1] = "";
char add_zone_char[MAX_ADD_CHAR+1] = "";
myDisplay.displayClear();
}
void loop() {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("Wifi reconnecting");
wifi_connect(0);
}
//MQTT reconnect pri vypadku spojenia s MQTT
if (!client.connected()) {
mqtt_reconnect();
}
client.loop();
// **** HEARTBEAT ****
if((millis() > lastHBMillis+heartBeatFreq) || (lastHBMillis == 0))
{
lastHBMillis = millis();
client.publish("livingroom/display/heartbeat","1");
}
// **** WiFi RSSI status ******
if(millis() > lastWifiMillis + WifiStatusFreq)
{
lastWifiMillis = millis();
Serial.print("Wifi RSSI: ");
Serial.println(WiFi.RSSI());
}
/*
if (myDisplay.displayAnimate())
myDisplay.displayText("Simon a Kubko do postele !!!", PA_LEFT, myDisplay.getSpeed(), myDisplay.getPause(), PA_SCROLL_LEFT, PA_SCROLL_LEFT);
*/
strcpy(msg_zone_char,"Simon a Kubko do postele !!!");
strcpy(time_zone_char,"23:59");
strcpy(add_zone_char,"-15 C");
if (myDisplay.displayAnimate()) // animates and returns true when an animation is completed
{
for (uint8_t i=0; i<NUM_ZONES; i++)
{
if (myDisplay.getZoneStatus(i))
{
// tell Parola we have a new animation
myDisplay.displayReset(i);
}
}
}
}