Wemos D1 - wifi plus MAX7219 64x16

Hi geeks,

I would like to create simple LED matrix build of 16(8x2) MAX7219 boards managed by MQTT over WiFi.
I've tried to build it on NodeMCU board. (edit: it is Wemos D1 mini)
If I use MAX7219 only, everything works good.
If I use wifi + MQTT only, everything works great.

But, when I try to combine it together, board is really unstable. It is resetting because of Soft WDT Reset. I suppose, that Wemos/ESP8266 has low power to run WiFi and MAX7219 together.
Is that thought right ?

I'm using MD_Parola library with 3 zones.
Maybe it is something wrong with my code, but as I wrote, when I run Wifi or MAX7219 separately, everything is OK.

Is it possible to power MAX7219 from different 5V power supply (instead of using 5V from Wemos)?
Which board (other than Wemos) should I use to satisfy my requirements ?

Thank you for your suggestions....

There is no such thing as "5V from NodeMCU".

Please provide a diagram - and well-taken photos in daylight - as well as an explanation of how you are attempting to power this project.

And cite exactly what MAX7219 matrix board or boards you are using. A weblink would be appropriate.

Well with no code to look at it is a bit hard to tell what is happening.

The ESP8266 is much more complex than an UNO. The fact that you can use the Arduino IDE gives a false sense that it is easy. The ESP8266 has a lot of code running in the background to get a wireless connection, handle the TCP/IP stack, handle asynchronous browser requests, maintain network communication, etc. It shares the processor with the user code, but the housekeeping code must be run on a regular basis (every 10’s of milliseconds). This is done by sharing the processor with the user code. At the start of each loop() iteration control is given to the esp8266 code, it does necessary housekeeping then continues with the user code. Some other function calls also call the housekeeping code before returning to the user. For example delay() (this is why adding a delay() sometimes “fixes” a crash). There is a watchdog timer set that causes an exception if it times out. This timer is reset by the background code. If the background code is not called often enough it times out and the system crashes.

If your combined code takes too long without the housekeeping getting control you will get the exception you are seeing. If you need a long loop you should call yield() occasionally to give the background code an opportunity to run.

aaaaaa
I'm Sorry, I'm using NodeMCU on different project. This one use Wemos D1 mini which has 5V output.
I've edited my question.
Wiring is simple, I2C from Wemos to MAX.
I'm powering it with USB port on notebook (consumption about 200mA).
But same issue occurs on 12W power source.

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

}