I am writing a program to control door access to certain room. I am using a RobotGeek RFIDuino hat and antenna to scan new tags. The issue I am running isn't with the MQTT, WIFI, or even the RFIDuino library, but somewhere in between. After 2.5 to 3 minutes of running, the program is unable to properly store the incoming MQTT signal. It will still output the correct message, and it receives receives the response. However, it does not store this message, instead defaulting to it's most recent/previous value. I am thinking that this is due to possible memory fragmentation caused by use of strings, so I have converted everything I could think of to char arrays, but the issue persists. Seen below is the already char updated script. I can post the original string based one upon request.
NOTE: When broken, the MQTT response message isn't stored, but it can still store and recognize different tag values. Each tag scan renders the correct number values, even with multiple tags. Each tag value is 3 numbers anywhere from 1 to 999.
Here is the code:
//------------------------------------------------------------------// User Modified Code
int roomNumber = 224;
//------------------------------------------------------------------// Imports
#include <WiFiS3.h> //Includes the WiFiS2 Library
#include <ArduinoMqttClient.h> //Includes the MQTTClient Library
#include "wifi_bits.h" //Includes document for Wifi/Network data
//------------------------------------------------------------------// Variables
//Wifi Variables
char ssid[] = NET_SSID; // your network SSID (name)
char pass[] = NET_PASSWORD; // your network password (use for WPA, or use as key for WEP)
int status = WL_IDLE_STATUS; // the WiFi radio's status
WiFiClient wifiClient;
//MQTT Variable
MqttClient mqttClient(wifiClient);
//MQTT Broker Variables
const char broker[] = "local.host";
int port = 1883;
const char OPNRQST[] = "test/topic";
bool msgReceived = false;
char *message[6]; //Message to broadcast
char buffer[10];
//String door = ""; //Door Command applies to
//String OpnClse = ""; //Open or Close Command
char messageR[23]; //Recieved Message
//char messageRChar[] = messageR;
//RFIDuino Variables
byte tagData[5]; //Holds the ID numbers from the tag
int i = 0; //Counting variable for counter function
boolean goodScan = false; //true if tag scan and secondary(check) tag scan matches
boolean tagCheck = false; //true when a tag has been read, false otherwise
//RFIDuino Library Variables
int buzzer = 5;
int led1 = 3;
int led2 = 2;
int demodOut = 8;
int shd = 7;
int mod = 6;
int rdyClk = 4;
//------------------------------------------------------------------// Definitions
#define SERIAL_PORT Serial //Serial port definition for Geekduino, Arduino Uno, and most Arduino Boards
#define RELAY 9 //the relay PinOut
#define DELAYVAL 320 //384 //standard delay for manchster decode
#define TIMEOUT 1000 //standard timeout for manchester decode
//------------------------------------------------------------------// Setup() - Begin Program
void setup() { //Setup Code
//Begin Serial
SERIAL_PORT.begin(19200); //Declare Baud rate for Arduino at 19200
Serial.println("Begin");
itoa(roomNumber, buffer, 10);
message[0] = buffer;
//Pin Declarations
pinMode(RELAY, OUTPUT); //The relay must be manuualy initalized as an output
//set pin modes on RFID pins
pinMode(mod, OUTPUT);
pinMode(shd, OUTPUT);
pinMode(demodOut, INPUT);
pinMode(rdyClk, INPUT);
//set pins for User Acccessible Output
pinMode(buzzer, OUTPUT);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
//set user outputs to LOW
digitalWrite(buzzer, LOW);
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
//set shd and MOD low to prepare for reading
digitalWrite(shd, LOW);
digitalWrite(mod, LOW);
//Wifi Processes
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
//don't continue
while (true);
}
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
Serial.println("Please upgrade the firmware");
}
// attempt to connect to WiFi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network:
status = WiFi.begin(ssid, pass);
// wait 1 seconds for connection:
delay(50);
}
// you're connected now, so print out the data:
Serial.print("You're connected to the network ");
printCurrentNet();
printWifiData();
//MQTT Setup
Serial.println("Connecting to MQTT Broker");
while (!mqttClient.connect(broker, port)) {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());
delay(1000);
}
Serial.println("Connected to Broker");
//Signify Setup() is completed
beep(2, 2); //Beep the Arduino twice
}
//------------------------------------------------------------------// Loop() - Infinite Loop
void loop() {
goodScan = false;
msgReceived = false;
//tagCheck = decodeTag(tagData); //run the decodetag to check for the tag. If a tag is read then the function will return 'true' and load the data into 'tagData'
if(i > 10000){ //Counting function to possibly delay/prevent system breakdown
Serial.println("1K Reset");
i = 0;
}
if (tagCheck = decodeTag(tagData)) { //if a 'true' is returned from the decodetag function, a tag was succesffuly scanned
check(); //Transfer to Scan Function
tagCheck = false;
delay(500);
}
delay(2);
i++;
}
//------------------------------------------------------------------// Function - Check
void check() { // Compares tag vs valid tags
if (tagData[0] != 0) {
Serial.println(
String(message[0]) + "_" +
String(tagData[0]) + "_" +
String(tagData[1]) + "_" +
String(tagData[2]) + "_" +
String(tagData[3]) + "_" +
String(tagData[4]));
mqttClient.beginMessage(OPNRQST);
mqttClient.print(
String(message[0]) + "_" +
String(tagData[0]) + "_" +
String(tagData[1]) + "_" +
String(tagData[2]) + "_" +
String(tagData[3]) + "_" +
String(tagData[4]));
mqttClient.endMessage();
mqttClient.subscribe(OPNRQST); // Subscribe to the topic
int wait = 0;
beep(1, 2); // Beep the Arduino once
while (!msgReceived) {
int messageSize = mqttClient.parseMessage();
if (wait > 30) {
msgReceived = true;
}
if (messageSize) {
// Received a message
//messageR = "";
int n = 0;
while (mqttClient.available()) {
messageR[n] = ((char)mqttClient.read());
n++;
}
Serial.println(messageR[4]);
// Handle received message (e.g., checking if it matches criteria)
if ((String(messageR[4]) == "O" && String(messageR[5]) == "P")) {
goodScan = true;
msgReceived = true;
}else{
msgReceived = true;
}
}
wait++;
delay(1); // Short delay to avoid rapid looping
}
Serial.print(String(messageR[0]));
Serial.print(String(messageR[1]));
Serial.print(String(messageR[2]));
Serial.print(String(messageR[3]));
Serial.print(String(messageR[4]));
Serial.println(String(messageR[5]));
mqttClient.unsubscribe(OPNRQST); // Unsubscribe from the topic
if (goodScan) {
Serial.println("Open.");
beep(1, 1);
digitalWrite(RELAY, HIGH); // Turn the relay on
delay(1500); // Wait 1.5 seconds
digitalWrite(RELAY, LOW); // Turn the relay off
} else {
beep(1, 0);
}
}
}
//------------------------------------------------------------------// Function - Print Wifi Data
void printWifiData() {
// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
/*// print your MAC address:
byte mac[6];
WiFi.macAddress(mac);
Serial.print("MAC address: ");
printMacAddress(mac);
*/
}
//------------------------------------------------------------------// Function - Print Currect Network
void printCurrentNet() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
/*// print the MAC address of the router you're attached to:
byte bssid[6];
WiFi.BSSID(bssid);
Serial.print("BSSID: ");
printMacAddress(bssid);
*/
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.println(rssi);
/*// print the encryption type:
byte encryption = WiFi.encryptionType();
Serial.print("Encryption Type:");
Serial.println(encryption, HEX);
Serial.println();
*/
}
//------------------------------------------------------------------// Function - Beep
void beep(int bp, int gb) { //Makes it beep
int tkn = 0;
/*
if (gb == 1) {
successSound();
} else if (gb == 0) {
errorSound();
} else {
for (tkn; tkn < bp; tkn++) { //beeps inputed (bp) amount of time
digitalWrite(buzzer, HIGH);
delay(100);
digitalWrite(buzzer, LOW);
delay(100);
}
}
*/
}
//------------------------------------------------------------------// Function - Flash
void flash(int fls) { //Makes it Flash
int tkn = 0;
for (tkn; tkn < fls; tkn++) { //beeps inputed (bp) amount of time
digitalWrite(led2, HIGH);
delay(50);
digitalWrite(led2, LOW);
delay(50);
}
}
//------------------------------------------------------------------// RFIDuino Modified Library
bool decodeTag(unsigned char *buf) {
unsigned char i = 0;
unsigned short timeCount;
unsigned char timeOutFlag = 0;
unsigned char row, col;
unsigned char row_parity;
unsigned char col_parity[5];
unsigned char dat;
unsigned char searchCount = 0;
unsigned char j;
while (true) {
timeCount = 0;
if (0 == digitalRead(demodOut)) //watch for demodOut to go low
{
break;
}
if (timeCount >= 600) {
return false;
}
timeCount = 0;
delayMicroseconds(DELAYVAL);
if (digitalRead(demodOut)) {
for (i = 0; i < 8; i++) // 9 header bits
{
timeCount = 0; //restart counting
while (1 == digitalRead(demodOut)) //while DEMOD out is high
{
if (timeCount == TIMEOUT) {
timeOutFlag = 1;
break;
} else {
timeCount++;
}
}
if (timeOutFlag) {
break;
} else {
delayMicroseconds(DELAYVAL);
if (0 == digitalRead(demodOut)) {
break;
}
}
} //end for loop
if (timeOutFlag) {
timeOutFlag = 0;
return false;
}
if (i == 8) //Receive the data
{
timeOutFlag = 0;
timeCount = 0;
while (1 == digitalRead(demodOut)) {
if (timeCount == TIMEOUT) {
timeOutFlag = 1;
break;
} else {
timeCount++;
}
if (timeOutFlag) {
timeOutFlag = 0;
return false;
}
}
col_parity[0] = col_parity[1] = col_parity[2] = col_parity[3] = col_parity[4] = 0;
for (row = 0; row < 11; row++) {
row_parity = 0;
j = row >> 1;
for (col = 0, row_parity = 0; col < 5; col++) {
delayMicroseconds(DELAYVAL);
if (digitalRead(demodOut)) {
dat = 1;
} else {
dat = 0;
}
if (col < 4 && row < 10) {
buf[j] <<= 1;
buf[j] |= dat;
}
row_parity += dat;
col_parity[col] += dat;
timeCount = 0;
while (digitalRead(demodOut) == dat) {
if (timeCount == TIMEOUT) {
timeOutFlag = 1;
break;
} else {
timeCount++;
}
}
if (timeOutFlag) {
break;
}
}
if (row < 10) {
if ((row_parity & 0x01) || timeOutFlag) //Row parity
{
timeOutFlag = 1;
break;
}
}
}
if (timeOutFlag || (col_parity[0] & 0x01) || (col_parity[1] & 0x01) || (col_parity[2] & 0x01) || (col_parity[3] & 0x01)) //Column parity
{
timeOutFlag = 0;
return false;
} else {
return true;
}
} //end if(i==8)
return false;
} //if(digitalRead(demodOut))
} //while(1)
};
//use the tone() function to play an 'error' sound, a single tone repeated 3 times
void errorSound() {
tone(buzzer, 1300, 500);
delay(250);
noTone(buzzer);
delay(250);
tone(buzzer, 1300, 1000);
delay(250);
noTone(buzzer);
delay(250);
tone(buzzer, 1300, 1000);
delay(250);
noTone(buzzer);
delay(250);
};
//use the tone() function to play an 'success' sound, 3 ascending tones
void successSound() {
tone(buzzer, 3500, 1000);
delay(165);
noTone(buzzer);
tone(buzzer, 4000, 1000);
delay(165);
noTone(buzzer);
tone(buzzer, 4500, 1000);
delay(165);
noTone(buzzer);
delay(165);
};
//function to compare 2 byte arrays. Returns true if the two arrays match, false of any numbers do not match
bool compareTagData(byte *tagData1, byte *tagData2) {
for (int j = 0; j < 5; j++) {
if (tagData1[j] != tagData2[j]) {
return false; //if any of the ID numbers are not the same, return a false
}
}
return true; //all id numbers have been verified
}
//function to transfer one byte array to a secondary byte array.
//source -> tagData
//destination -> tagDataBuffer
void transferToBuffer(byte *tagData, byte *tagDataBuffer) {
for (int j = 0; j < 5; j++) {
tagDataBuffer[j] = tagData[j];
}
}
bool scanForTag(byte *tagData) {
static byte tagDataBuffer[5]; //A Buffer for verifying the tag data. 'static' so that the data is maintained the next time the loop is called
static int readCount = 0; //the number of times a tag has been read. 'static' so that the data is maintained the next time the loop is called
boolean verifyRead = false; //true when a tag's ID matches a previous read, false otherwise
boolean tagCheck = false; //true when a tag has been read, false otherwise
tagCheck = decodeTag(tagData); //run the decodetag to check for the tag
if (tagCheck == true) //if 'true' is returned from the decodetag function, a tag was succesfully scanned
{
readCount++; //increase count since we've seen a tag
if (readCount == 1) //if have read a tag only one time, proceed
{
transferToBuffer(tagData, tagDataBuffer); //place the data from the current tag read into the buffer for the next read
} else if (readCount == 2) //if we see a tag a second time, proceed
{
verifyRead = compareTagData(tagData, tagDataBuffer); //run the checkBuffer function to compare the data in the buffer (the last read) with the data from the current read
if (verifyRead == true) //if a 'true' is returned by compareTagData, the current read matches the last read
{
readCount = 0; //because a tag has been succesfully verified, reset the readCount to '0' for the next tag
return true;
}
}
} else {
return false;
}
}