Mqtt does not work in combination with software serial

There was a similar conversation about this here where someone claimed to have fixed the wifiClient library but it has not solved the problem thread

Similar to this earlier person who posted this issue, I am experienced occasional disconnects that unfortunately cause the entire device to malfunction - no functions will work not even the watchdog reset. One of two things will occur: Sometimes readouts on the serial monitor will suddenly stop, with no error messages printed. All functionality of the device also stops. Other times, it appears the device gets stuck in a loop where it says “[INFO] Create socket successfully” and then “[ERROR] Connect to server failed” then [INFO] [ard_socket.c][send_data] err = 0" “failed, rc = 4” and repeats this cycle infinitely. When I remove the mqtt functionality OR the software serial functionality, the problem goes away. It only occurs when I combine the two. I have posted the simplest form of my code that demonstrates the problem:

#include <WiFi.h>
#include <PubSubClient.h>

#include <SoftwareSerial.h>

SoftwareSerial mySerial(PB2, PB1); // RX, TX

char c;
String dataIn;


char ssid[] = "xxxxxx";      
char pass[] = "xxxxxx";  


int status = WL_IDLE_STATUS;        


char mqttServer[]     = "test.mosquitto.org";
char clientId[]       = "amebaClient";
char publishTopic[]   = "Server";
char publishPayload[] = "initialize";
char subscribeTopic[] = "INPUT";

char key[10] = {0};


void callback(char* topic, byte* payload, unsigned int length) {
    Serial.print("Message arrived [");
    Serial.print(topic);
    Serial.print("] ");
    for (unsigned int i = 0; i < length; i++) {
        Serial.print((char)(payload[i]));
    }
    Serial.println();
}

WiFiClient wifiClient;
PubSubClient client(wifiClient);

void reconnect() {
    // Loop until we're reconnected
    while (!(client.connected())) {
        Serial.print("\r\nAttempting MQTT connection...");
        // Attempt to connect
        if (client.connect(clientId)) {
            Serial.println("connected");
            //Once connected, publish an announcement and resubscribe
            client.publish(publishTopic, publishPayload);
            client.subscribe(subscribeTopic);
        } else {
            Serial.println("failed, rc=");
            Serial.print(client.state());
            Serial.println(" try again in 5 seconds");
            //Wait 5 seconds before retrying
            delay(5000);
        }
    }
}



void setup() {
    //Initialize serial and wait for port to open:
    Serial.begin(115200);
    mySerial.begin(115200);
    //Attempt to connect to WiFi network
    while (status != WL_CONNECTED) {
        Serial.print("\r\nAttempting to connect to SSID: ");
        Serial.println(ssid);
        // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
        status = WiFi.begin(ssid, pass);
        // wait 10 seconds for connection:
        delay(10000);   
    }
    client.setServer(mqttServer, 1883);
    client.setCallback(callback);
    
    //Allow Hardware to sort itself out
    delay(1500);
    
}

void loop() 
{

  while (mySerial.available()>0) 
  {
    c = mySerial.read();

    if (c == '\n') {break;}
    else {dataIn+=c;}
  }

  if (c=='\n')
  {
    Serial.println(dataIn);
    int str_len = dataIn.length() + 1;
    dataIn.toCharArray(key, str_len);     
    if (client.connect(clientId)) 
    {
      client.publish(publishTopic, key);
    }
            
    c=0;
    dataIn="";
  }

   
  if (!(client.connected())) 
  {
    reconnect();
  }
  client.loop();
   
  
}


Hi @microPC ,

I tried to replicate your set up to look for the issue. However, I was able to perform MQTT and software serial functionality simultaneously (i.e. receives message via UART from an external device [AMB26] and publish to a MQTT topic). I have tested it overnight and did not encounter the sudden stop error.

This is the code that I had been running on BW16:

#include "sys_api.h"

#include <WiFi.h>
#include <PubSubClient.h>

#include <SoftwareSerial.h>

SoftwareSerial mySerial(PB2, PB1); // RX, TX

char c;
String dataIn;
unsigned int dataIn_len;


char ssid[] = "Network_SSID5";      
char pass[] = "Password";  
int status = WL_IDLE_STATUS;        

char mqttServer[]     = "test.mosquitto.org";
char clientId[]       = "amebaClient";
char publishTopic[]   = "sd3outTopic";
char publishPayload[] = "Hello from Ameba";
char subscribeTopic[] = "sd3inTopic";
char key[10] = {0};

void callback(char* topic, byte* payload, unsigned int length) {
    Serial.print("Message arrived [");
    Serial.print(topic);
    Serial.print("] ");
    for (unsigned int i = 0; i < length; i++) {
        Serial.print((char)(payload[i]));
    }
    Serial.println();
}

WiFiClient wifiClient;
PubSubClient client(wifiClient);
void reconnect() {
    // Loop until we're reconnected
    while (!(client.connected())) {
        Serial.print("\r\nAttempting MQTT connection...");
        // Attempt to connect
        if (client.connect(clientId)) {
            Serial.println("connected");
            //Once connected, publish an announcement and resubscribe
            client.publish(publishTopic, publishPayload);
            client.subscribe(subscribeTopic);
        } else {
            Serial.println("failed, rc=");
            Serial.print(client.state());
            Serial.println(" wait 5 seconds");
            delay(5000);
        }
    }
    
}



void setup() {
    //Initialize serial and wait for port to open:
    Serial.begin(115200);
    mySerial.begin(115200);
    mySerial.println("Hello");
    //Attempt to connect to WiFi network
    while (status != WL_CONNECTED) {
        //Serial.print("\r\nAttempting to connect to SSID: ");
        //Serial.println(ssid);
        // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
        status = WiFi.begin(ssid, pass);

        // wait 10 seconds for connection:
        delay(10000);
        
    }

    client.setServer(mqttServer, 1883);
    client.setCallback(callback);
    
    //Allow Hardware to sort itself out
    delay(1500);
    
}


void loop() 
{

    if (mySerial.available()) {
      c = mySerial.read();

      if (c == '\n'){
        Serial.println(dataIn);
        // Serial.println(dataIn.length());
        dataIn_len = dataIn.length()+1;
        // Serial.println(dataIn_len);
        char dataIn_arr[dataIn_len];
        dataIn.toCharArray(dataIn_arr, dataIn_len);
        // Serial.println(dataIn_arr);
        client.publish(publishTopic, dataIn_arr);
        client.subscribe(subscribeTopic);
        c=0;
        dataIn="";
      }
      else{
        dataIn+=c;
      }
    }

   
  if (!(client.connected())) 
  {
    //reconnect();
    reconnect();
  }
  client.loop();
   
  
}

This is the code for my external device AMB26 to send UART messages every 5 seconds to BW16:

#include <SoftwareSerial.h>

SoftwareSerial mySerial(PB18, PB19); // RX, TX

void setup() {
    // Open serial communications and wait for port to open:
    Serial.begin(115200);
    while (!Serial) {
        ; // wait for serial port to connect. Needed for native USB port only
    }

    Serial.println("Hello!");

    // set the data rate for the SoftwareSerial port
    mySerial.begin(115200);
    mySerial.println("Hi there!");
}

void loop() { // run over and over

    mySerial.write("Good morning\n");
    delay(5000);
    mySerial.write("Good afternoon\n");
    delay(5000);
    mySerial.write("Good evening\n");
    delay(5000);
    mySerial.write("Good night\n");
    delay(5000);

}

I used MQTT Explorer to view the published messages:

Hope it helps.
Thanks.

Have you tried disconnecting the internet while it is running and turning it back on? I suspect the hang may occur when the connection is unreliable. In either case, there should never occur hangups that prevent a software reset, which I am mist certainly experiencing when testing multiple bw16 devices. I can post videos to show the problem occuring

Hi @microPC ,

I would suggest you to use a watchdog timer to perform software reset if there is an unstable network connection.

Here is the code that I have tested on my set up:

#include <WiFi.h>
#include <PubSubClient.h>
#include "WDT.h"
#include <SoftwareSerial.h>


#define RUN_CALLBACK_IF_WATCHDOG_BARKS (0)
WDT wdt;


SoftwareSerial mySerial(PB2, PB1); // RX, TX

char c;
String dataIn;
unsigned int dataIn_len;


char ssid[] = "sd3win11";      
char pass[] = "Password";  
int status = WL_IDLE_STATUS;        

char mqttServer[]     = "test.mosquitto.org";
char clientId[]       = "amebaClient";
char publishTopic[]   = "sd3outTopic";
char publishPayload[] = "Hello from Ameba";
char subscribeTopic[] = "sd3inTopic";
char key[10] = {0};

void callback(char* topic, byte* payload, unsigned int length) {
    Serial.print("Message arrived [");
    Serial.print(topic);
    Serial.print("] ");
    for (unsigned int i = 0; i < length; i++) {
        Serial.print((char)(payload[i]));
    }
    Serial.println();
}

WiFiClient wifiClient;
PubSubClient client(wifiClient);
void reconnect() {
    // Loop until we're reconnected
    while (!(client.connected())) {
        Serial.print("\r\nAttempting MQTT connection...");
        // Attempt to connect
        if (client.connect(clientId)) {
            Serial.println("connected");
            //Once connected, publish an announcement and resubscribe
            client.publish(publishTopic, publishPayload);
            client.subscribe(subscribeTopic);
        } else {
            Serial.println("failed, rc=");
            Serial.print(client.state());
            Serial.println(" wait 5 seconds");
            delay(5000);
        }
    }
    
}



void setup() {
    //Initialize serial and wait for port to open:
    Serial.begin(115200);
    mySerial.begin(115200);
    mySerial.println("Hello");
    //Attempt to connect to WiFi network
    while (status != WL_CONNECTED) {
        Serial.print("\r\nAttempting to connect to SSID: ");
        Serial.println(ssid);
        // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
        status = WiFi.begin(ssid, pass);

        // wait 10 seconds for connection:
        delay(10000);
        
    }

    client.setServer(mqttServer, 1883);
    client.setCallback(callback);
    
    //Allow Hardware to sort itself out
    delay(1500);

    wdt.InitWatchdog(10000);  // setup 10s watchdog

  #if RUN_CALLBACK_IF_WATCHDOG_BARKS
      wdt.InitWatchdogIRQ(my_watchdog_irq_handler, 0);
  #else
      // system would restart in default when watchdog barks
  #endif

      wdt.StartWatchdog();  // enable watchdog timer
      Small_Task();
    
}


void loop() 
{

    if (mySerial.available()) {
      c = mySerial.read();

      if (c == '\n'){
        Serial.println(dataIn);
        // Serial.println(dataIn.length());
        dataIn_len = dataIn.length()+1;
        // Serial.println(dataIn_len);
        char dataIn_arr[dataIn_len];
        dataIn.toCharArray(dataIn_arr, dataIn_len);
        // Serial.println(dataIn_arr);
        client.publish(publishTopic, dataIn_arr);
        client.subscribe(subscribeTopic);
        c=0;
        dataIn="";
      }
      else{
        dataIn+=c;
      }
    }
    Small_Task();
    // delay(2000);
    if (!(client.connected())) {
      reconnect();
    }
    client.loop();
    
  
}

void Small_Task(void) {
    // Serial.println("......checking WiFi......");
    // for (int i = 0; i < 50000000; i++) {  // dummy task
    //     asm(" nop");
    // }
    long rssi = WiFi.RSSI(); // received WiFi signal strength
    if (rssi != 0){
      // Serial.println("WiFi Connection Stable.");
      wdt.RefreshWatchdog();
    }
    else{
      Serial.println("No WiFi Connection!!");
    }
}

BW16 will reboot itself if the received WiFi signal strength is 0 for more than 10 seconds.

Thank you.