ESP8266 / MRFC522 keeps crashing

Hi -

I am having trouble with ESP8266 connected to Arduino UNO and MFRC522 RFID. the ESP8266 connects successfully to WiFi and MQTT server whereafter the RFID successfully posts card reads to MQTT server. However, after a brief idle period, the data scanned by RFID is is no longer posted to the MQTT sever. The RX/TX light on the ESP is blinking with each card scan though.

To test sever connection and possible timeouts, I also subscribed to same topic via mobile phone which is consistently able to publish messages regardless of any idling time.

Can someone please assist, not sure of the error is in my code as I am fairly new to C+.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <WiFiClient.h>

const char* ssid = "";
const char
password = "
";
const char
mqttServer = “m15.cloudmqtt.com”;
const int mqttPort = 16897;
const char* mqttUser = "***";
const char
mqttPassword = "**J";
char
topic = “esp/Rhino_test”; //new
//const char
IncomingString = “”;

WiFiClient espClient;
PubSubClient client(mqttServer, mqttPort, espClient);

void callback(char* topic, byte* payload, unsigned int length) {
// handle message arrived
}

String macToStr(const uint8_t* mac)
{
String result;
for (int i = 0; i < 6; ++i) {
result += String(mac*, 16);*

  • if (i < 5)*
  • result += ‘:’;*
  • }*
  • return result;*
    }
    void setup() {
  • Serial.begin(115200);*
  • Serial.println(“Connecting to…”);*
  • Serial.println(ssid);*
  • WiFi.begin(ssid, password);*
  • while (WiFi.status() != WL_CONNECTED) {*
  • delay(500);*
  • }*
  • Serial.println(“Connected to”);*
  • Serial.println(ssid);*
  • Serial.println("IP address: ");*
  • Serial.println(WiFi.localIP());*
  • String clientName;*
  • clientName += “Rhino1-”;*
  • uint8_t mac[6];*
  • WiFi.macAddress(mac);*
  • clientName += macToStr(mac);*
  • clientName += “-”;*
  • clientName += String(micros() & 0xff, 16);*
  • client.setServer(mqttServer, mqttPort);*
  • client.setCallback(callback);*
  • while (!client.connected()) {*
  • Serial.print("Connecting to ");*
  • Serial.print(mqttServer);*
  • Serial.print(" as ");*
  • Serial.println(clientName);*
    if (client.connect((char*) clientName.c_str(), mqttUser, mqttPassword)) {
  • Serial.println(“Connected to MQTT broker”);*
  • Serial.print("Topic is: ");*
  • Serial.println(topic);*
  • } else {*
  • Serial.println(“MQTT connect failed”);*
  • Serial.println(“Will reset and try again…”);*
  • abort();*
  • }*
  • }*
    }
    void loop() {
  • char IncomingString[30];*
  • bool pubFlag = false;*
  • if (Serial.available() > 0)*
  • {*
  • int i = 0;*
  • while (Serial.available() > 0) {*
    _ IncomingString = Serial.read();_
    * i++;*
    * pubFlag = true;*
    * }*
    _ IncomingString = ‘\0’;
    * }
    if (pubFlag)
    {
    pubFlag = false;
    if (client.publish(topic, IncomingString)) {
    Serial.println(“Publish ok”);
    }
    else {
    Serial.println(“Publish failed”);
    }
    }
    yield();
    delay(100);
    }
    [/quote]*_
  if (Serial.available() > 0)
  {
    int i = 0;
    while (Serial.available() > 0) {
      IncomingString = Serial.read();
      i++;
      pubFlag = true;
    }
    IncomingString = '\0';
  }

If you use a char * and add a character to it and up the index counter then you should use that index likeIncomingString[i] =

Hi Deva -

Thank you for your response. Will allocating the string differently cause the comms between RFID and UNO not crash? Presuming that is the problem. What is baffling me is the fact that the ESP is still transmitting some data on each card read as I can clearly see the RX/TX LED on both UNO and ESP flashing with each read.

Regards, Friedl

Post your current code, using code tags (the </> icon), not quote tags. As posted, your code will not compile.

  char IncomingString[30];
  bool pubFlag = false;


  if (Serial.available() > 0)
  {
    int i = 0;
    while (Serial.available() > 0) {
      IncomingString = Serial.read();

You can NOT assign data to an array that way.

Hi Paul -

Thank you for the response, posted code as per your request.

Thanks for letting me know. Not sure what happened to i in IncomingString = ‘\0’; in first post, but as you can see it is in the actual code below.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <WiFiClient.h>

const char* ssid = "***";
const char* password =  "***";
const char* mqttServer = "m15.cloudmqtt.com";
const int mqttPort = ***;
const char* mqttUser = "***";
const char* mqttPassword = "***";
char* topic = "esp/Rhino_test"; //new


WiFiClient espClient;
PubSubClient client(mqttServer, mqttPort, espClient);

void callback(char* topic, byte* payload, unsigned int length) {
  // handle message arrived
}

String macToStr(const uint8_t* mac)
{
  String result;
  for (int i = 0; i < 6; ++i) {
    result += String(mac[i], 16);
    if (i < 5)
      result += ':';
  }
  return result;
}

void setup() {


  Serial.begin(115200);

  Serial.println("Connecting to..");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);

  }
  Serial.println("Connected to");
  Serial.println(ssid);
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  String clientName;
  clientName += "Rhino1-";
  uint8_t mac[6];
  WiFi.macAddress(mac);
  clientName += macToStr(mac);
  clientName += "-";
  clientName += String(micros() & 0xff, 16);


  client.setServer(mqttServer, mqttPort);
  client.setCallback(callback);

  while (!client.connected()) {
    Serial.print("Connecting to ");
    Serial.print(mqttServer);
    Serial.print(" as ");
    Serial.println(clientName);

    if (client.connect((char*) clientName.c_str(), mqttUser, mqttPassword)) {

      Serial.println("Connected to MQTT broker");
      Serial.print("Topic is: ");
      Serial.println(topic);

    } else {
      Serial.println("MQTT connect failed");
      Serial.println("Will reset and try again...");
      abort();
    }
  }
}
void loop() {

  char IncomingString[30];
  bool pubFlag = false;


  if (Serial.available() > 0)
  {
    int i = 0;
    while (Serial.available() > 0) {
      IncomingString[i] = Serial.read();
      i++;
      pubFlag = true;
    }
    IncomingString[i] = '\0';
  }

  if (pubFlag)
  {
    pubFlag = false;
    if (client.publish(topic, IncomingString)) {
      Serial.println("Publish ok");
    }
    else {
      Serial.println("Publish failed");

    }
  }
  yield();
  delay(100);
}

friedlbasson: Will allocating the string differently cause the comms between RFID and UNO not crash? Presuming that is the problem. What is baffling me is the fact that the ESP is still transmitting some data on each card read as I can clearly see the RX/TX LED on both UNO and ESP flashing with each read.

i don't think it was ever crashing, unless you would write data beyond the size of the character array. (which wasn't possible before, but you should make sure that can't happen !!) but it was just sending the Array, with it's NULL terminator as it's first character (but still sending the whole Array) If you are using 'Strings' anyway (as you do in setup) you may as well create a function that reads the Serial and creates a String and sends it. Also you should make sure that all Serial data actually get's read. Atm the delay(100) at the end of loop() probably ensures that (though not 100% fail safe)

Not sure what happened to i in IncomingString = ‘\0’; in first post

Since you didn’t use code tags, the forum software saw the sequence of characters ‘[’, ‘i’, and ‘]’ and said "Hey, that means show the text, up to the “[/i]” in italics, so it did. It was doing what it was supposed to do.

If you had done what you were suppose to (read the stickies, post code correctly), that wouldn’t have happened.

String macToStr(const uint8_t* mac)
{
  String result;
  for (int i = 0; i < 6; ++i) {
    result += String(mac[i], 16);
    if (i < 5)
      result += ':';
  }
  return result;
}

There is NO reason to use a String here. The maximum number of characters is KNOWN, so it is trivial to allocate a char array (static, so you CAN return a pointer to it) of the right size. sprintf() could then populate the array with no for loop or if statements needed. Far easier to understand that code, too.

 String clientName;
  clientName += "Rhino1-";

Why do you need to append this value to a String instance that you KNOW is empty? Why do you need to use two statements to declare a variable and assign a value to it?

  String clientName = "Rhino1-";

If you are going to use Strings, at least try to minimize the number of calls to the constructor, copy operator, and destructor.

}
void loop() {

  char IncomingString[30];

The ONLY excuse for putting the { on the same line as the function statement is to save real-estate. You look pretty stupid following that with a blank line, wasting real-estate.

 if (Serial.available() > 0)
  {
    int i = 0;
    while (Serial.available() > 0) {
      IncomingString[i] = Serial.read();
      i++;
      pubFlag = true;
    }
    IncomingString[i] = '\0';
  }

You’ve captured all of the data that was in the buffer. But, you haven’t a clue whether that represents a complete packet, part of a single packet, or parts of two or more packets. So, you can’t meaningfully use the data in IncomingString.

   if (client.publish(topic, IncomingString)) {

But, you try anyway…

Do you even KNOW what is in that array? Not that I can see…

What is connected to the serial port? You mention a MFRC522 RFID and an ESP8266 in your initial post, but I can’t tell which one, if either one, is connected to the serial port. If neither one is, I don’t see where you are getting data from/sending data to either one. If either one is, I don’t understand what some of the (less than useful) Serial.print() data is supposed to mean to it.

Hi Paul -

I am new at this, please have patience with my ‘stupid’ mistakes. We all had to learn at some stage. I do appreciate your help though.

Connected to hardware serial pins (RX/TX) is the ESP module. I use SoftwareSerial (9,10) to communicate with the RFID reader. From what I understood in other forums on programming the ESP module was that it has to be on hardware serial with pins swopped around in order to load code on it. So after this stuck with ESP on (0,1) obviously just swopping the pins around again for normal operation.

All the code in previous post runs on the ESP module. The code below is running on the UNO.

#include <SPI.h>
#include <MFRC522.h>
//#include <SoftwareSerial.h>

#define SS_PIN 10
#define RST_PIN 9

char Data [6];
int uid = 0;
String str;

MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class
MFRC522::MIFARE_Key key;

byte nuidPICC[4];

void setup()
{
  Serial.begin(115200);

  SPI.begin(); // Init SPI bus
  rfid.PCD_Init(); // Init MFRC522

  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }
}

void loop()
{

  // Look for new cards
  if ( ! rfid.PICC_IsNewCardPresent())
    return;

  // Verify if the NUID has been read
  if ( ! rfid.PICC_ReadCardSerial())
    return;


  for (byte i = 0; i < 4; i++) {
    nuidPICC[i] = rfid.uid.uidByte[i];
  }

  printHex(rfid.uid.uidByte, rfid.uid.size);

  delay(1000);

  rfid.PICC_HaltA();
  rfid.PCD_StopCrypto1();
}

void printHex(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
}

Thank you again for you advice and patience.

that is what i thought as well, but where do you expect the Serial.print statements from the ESP code to end up, do you still have the USB of the Uno connected ? (Paul’s main valid point imo)

All the code in previous post runs on the ESP module. The code below is running on the UNO.

So, which code do you think is causing the problem?

What is the ESP supposed to do with this data?

 Serial.println("Connecting to..");
  Serial.println(ssid);
  Serial.println("Connected to");
  Serial.println(ssid);
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
    Serial.print("Connecting to ");
    Serial.print(mqttServer);
    Serial.print(" as ");
    Serial.println(clientName);
      Serial.println("Connected to MQTT broker");
      Serial.print("Topic is: ");
      Serial.println(topic);
      Serial.println("MQTT connect failed");
      Serial.println("Will reset and try again...");

Deva_Rishi: that is what i thought as well, but where do you expect the Serial.print statements from the ESP code to end up, do you still have the USB of the Uno connected ? (Paul's main valid point imo)

Serial.print was just to monitor on Serial Monitor what was happening whilst it was still connected to USB yes. Did not think it would harm to leave it there?

PaulS:
So, which code do you think is causing the problem?

What is the ESP supposed to do with this data?

 Serial.println("Connecting to..");

Serial.println(ssid);
 Serial.println(“Connected to”);
 Serial.println(ssid);
 Serial.println("IP address: ");
 Serial.println(WiFi.localIP());
   Serial.print("Connecting to “);
   Serial.print(mqttServer);
   Serial.print(” as ");
   Serial.println(clientName);
     Serial.println(“Connected to MQTT broker”);
     Serial.print("Topic is: ");
     Serial.println(topic);
     Serial.println(“MQTT connect failed”);
     Serial.println(“Will reset and try again…”);

Hi Paul. it was just to print to Serail Monitor for me to see that it actually connects to Wifi and MQTT server. Had no use beyond that. Spend days with Arduino uno with onboard WiFi just to realise later it was never connecting to WiFi at all and read that many people where complaining about the same model board. Plan is to clean up all this before the final prototype.

friedlbasson: Serial.print was just to monitor on Serial Monitor what was happening whilst it was still connected to USB yes. Did not think it would harm to leave it there?

No it doesn't, as long as it is disconnected from the moment that the UNO is doing all the communicating (in fact you can't upload the ESP via the UNO once it is doing Serial communication on the same bus anyhow)

Deva_Rishi: No it doesn't, as long as it is disconnected from the moment that the UNO is doing all the communicating (in fact you can't upload the ESP via the UNO once it is doing Serial communication on the same bus anyhow)

Hi Deva -

I was initially powering the UNO from my laptop, but when troubleshooting I did switch it to external power supply but still via USB. No Serial monitoring running at the time. Only used the Serial Monitor to make sure the ESP connects to WiFi and MQTT. Separately then used Serial Monitor to make sure RFID is reading and sending Unique ID's only.

I get the uploading to the ESP... think I mastered it by now as I probably did it a thousand times :D

Well disconnect the UNO from USB if you want the program to run. do not have more than 2 devices on the same bus at one time.

@Paul

}
void loop() {

  char IncomingString[30];

This can even be a 'style' separating the start of a function from other sections of conditional code, mind you the closing brace of the previous function does deserve a blank line afterwards in that case also.

How are you powering the ESP ?

Deva_Rishi: How are you powering the ESP ?

Hi, both ESP and RFID is powered from 3.3V pin.

Powering the ESP from the UNO 3.3v pin is pushing it as it is.... you should put a separate regulator, (preferably with a little extra heatsink) and 1uF cap per unit on the 3.3v rail and an extra cap on the 5v rail i don't know what the RFID draws, but the ESP has peaks during wifi-setup and transmission going up above 200mA

Hi -

Thank you, I will try this. I know the RFID is very light weight. I assumed as I was able to upload code successfully there should be no problem sending smaller packets of data. I will switch to external power supply simulating the 3.7V li-op battery I will use to power this unit.

Deva_Rishi:
Powering the ESP from the UNO 3.3v pin is pushing it as it is… you should put a separate regulator, (preferably with a little extra heatsink) and 1uF cap per unit on the 3.3v rail and an extra cap on the 5v rail i don’t know what the RFID draws, but the ESP has peaks during wifi-setup and transmission going up above 200mA

Hi Deva -

I did some hardware troubleshooting like you suggested. I disconnected from my laptop and provided external power supply through battery bank. 12V 2A. Then, I connected RFID to 3.3V pin and ESD to 5V pin but through step down converter but problem persists. I narrowed down the problem to when there is inactivity for 20s or more. I put static value on the Uno that is published every couple of seconds. In addition to this I can scan the RFID cards. If this delay is set to more than 20s, the Uno stops posting the ‘test value’ to the MQTT server or simply stops posting card reads. See my ‘debug code’ below.

#include <SPI.h>
#include <MFRC522.h>
//#include <SoftwareSerial.h>

#define SS_PIN 10
#define RST_PIN 9

char Data [6];
int uid = 0;
String str;

MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class
MFRC522::MIFARE_Key key;

long wait_tick = 0;

byte nuidPICC[4];

void setup()
{
  Serial.begin(115200);

  SPI.begin(); // Init SPI bus
  rfid.PCD_Init(); // Init MFRC522

  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }
}

void loop()
{
  if (wait_tick < (millis() - 20000))
  {
    Serial.print("00 00 00 00");
    wait_tick = millis();
  }

  // Look for new cards
  if ( ! rfid.PICC_IsNewCardPresent())
    return;

  // Verify if the NUID has been read
  if ( ! rfid.PICC_ReadCardSerial())
    return;

  wait_tick = millis();
  
  for (byte i = 0; i < 4; i++) {
    nuidPICC[i] = rfid.uid.uidByte[i];
  }

  printHex(rfid.uid.uidByte, rfid.uid.size);

  delay(500);

  rfid.PICC_HaltA();
  rfid.PCD_StopCrypto1();
}

void printHex(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
}