Wemos D1 - wifi plus MAX7219 64x16

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);
      }
    }
  }

}