The Problem:
Arduino Mega 2560 randomly stops sending information to my server after 1-3 days of functioning
The Situation:
- Board is Arduino Mega 2560 w/ Ethernet Shield
- This Arduino has 6x DHT-22 sensors which gathers temperature and humidity data which are compiled into a JSON which is sent over MQTT (using ethernet) to my nodejs server (stores it to a database, displays it to Grafana, etc)
- The Arduino is currently being powered by a AC to DC 9V 1A Plug
- Operating in temperatures around 24-30 degrees Celsius
- Pressing the "reset" button on the board will make it reconnect and return to normal without having to unpower the board. So I can just toggle reset every day but that isn't a viable long-term solution.
What I've tried:
Hardware
- I've tried 3 different Arduino Mega 2560 boards
- I've tried a different power supply (current one is specified above in "The Situation", and the first one overheated the 1st Arduino board after about a month of use... lol)
- Thought it could be the network cutting out, but I've tried directly unplugging the Ethernet from the board, waiting an hour, and reconnecting it. And it will reconnect to the server fine.
Software
- I thought it was a memory issue/leak, but testing shows that's not the case. The
stackAvailable()function on line 269 outputs how many bytes are free in memory, and I've been including that in the payload JSON to log it to the DB/Grafana. The amount of memory available stays consistent all the way until it stops sending data. - Replaced all Strings with char[] (did this over a month ago)
- Tried both strcpy vs strncpy (scraping the bottom of the barrel for solutions)
- Bit unrelated, but the ArduinoMqttClient library has a limit to the payload size (it cuts off anything exceeding it), to fix that you must directly change the source code of the library (I did this a while ago, so I've since forgotten where/how exactly)
Schematic
Code
// Program Libraries
#include <SPI.h> // Serial Peripheral Interface
#include <Ethernet.h> // Ethernet
#include <ArduinoJson.h> // JSON
#include <ArduinoMqttClient.h> // MQTT
// Sensor Libraries
#include <DHT.h> // DHT Sensors
bool debug = true; // Print debug logs
bool readings = true; // Print data logs
//
// PROGRAM VARIABLES
//
int loopDelay = 3000; // MUST BE GREATER THAN 2000 (2 seconds) - Due to limitation of sensors
char payload[500] = {}; // JSON Payload variable
char recievedMessage[500] = ""; // Inbound MQTT Payload variable
//
// NETWORK VARIABLES
//
byte mac[] = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }; // This Device's Mac Address
IPAddress server(192, 168, 1, X); // Server's IP Address
int port = 1883; // Server's MQTT Port
IPAddress ip(192, 168, 1, X); // This Device's IP Address
IPAddress gateway(127, 0, 0, 1); // Default Gateway
EthernetClient eclient; // Ethernet Client
MqttClient client(eclient); // MQTT Client using the EthernetClient, 256byte payload size limit
char mqttAuthUser[] = "USERNAME"; // MQTT USER
char mqttAuthPass[] = "PASSWORD"; // MQTT PASSWORD
char listenTopic[] = "topic/subtopic";
char postTopic[] = "topic/subtopic";
char deviceID[] = "DEVICE_ID";
//
// SENSOR VARIABLES
//
// TEMPERATURE+HUMIDITY SENSORS
#define PIN_DHT_F1 8
#define PIN_DHT_F2 3
#define PIN_DHT_F3 2
#define PIN_DHT_B1 7
#define PIN_DHT_B2 6
#define PIN_DHT_B3 5
#define DHT_TYPE DHT22
DHT dhtF1(PIN_DHT_F1, DHT_TYPE); // Front-1 Temperature Sensor (top)
DHT dhtF2(PIN_DHT_F2, DHT_TYPE); // Front-2 Temperature Sensor (middle)
DHT dhtF3(PIN_DHT_F3, DHT_TYPE); // Front-3 Temperature Sensor (bottom)
DHT dhtB1(PIN_DHT_B1, DHT_TYPE); // Back-1 Temperature Sensor (top)
DHT dhtB2(PIN_DHT_B2, DHT_TYPE); // Back-2 Temperature Sensor (middle)
DHT dhtB3(PIN_DHT_B3, DHT_TYPE); // Back-3 Temperature Sensor (bottom)
// Sensors: dhtF1, dhtF2, dhtF3
float lastFrontHumidity[3] = { 999.999, 999.999, 999.999 };
float lastFrontTemp[3] = { 999.999, 999.999, 999.999 };
// NOTE: 999.999 is used as a "filter" on the server's backend which are ignored
// Sensors: dhtB1, dhtB2, dhtB3
float lastBackHumidity[3] = { 999.999, 999.999, 999.999 };
float lastBackTemp[3] = { 999.999, 999.999, 999.999 };
void SetupNetwork() {
Ethernet.begin(mac, ip, gateway); // Begin Ethernet connection
Ethernet.setDnsServerIP(ip); // Set Ethernet IP
client.setClient(eclient); // Set MQTT Client as the EthernetClient
// client.setUsernamePassword(mqttAuthUser, mqttAuthPass); // Set Username & Password for MQTT Connection
client.onMessage(NewMqttMessage); // MQTT Messages are passed through the RecievedMessage Function
client.connect(server, port); // Connect to MQTT Broker
client.subscribe(listenTopic); // Set MQTT subscribed topic
delay(1000);
if (debug) {
// Display this Device's IP Address
Serial.print("\nArduino's IP --> ");
Serial.println(Ethernet.localIP());
Serial.println();
// Display this Device is attempting to connect to the MQTT Server & Port
Serial.print("connecting to ");
Serial.print(server);
Serial.print(":");
Serial.print(port);
Serial.println("...");
}
// If MQTT Server is connected, print the Server IP and TOPIC it is set to publish to
if (client.connect(server, port)) {
Serial.print("connected to ");
Serial.print(eclient.remoteIP());
Serial.print(":");
Serial.println(port);
Serial.print("Publishing to: ");
Serial.println(postTopic);
Serial.print("Subscribing to: ");
Serial.println(listenTopic);
Serial.println('\n');
}
else {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(client.connectError());
}
}
void MaintainNetwork() {
Ethernet.maintain();
if (!client.connected()) // Checks if this Device is not connected to Server
{
if (debug)
Serial.println("---Disconnected! Attempting to Reconnect---");
SetupNetwork();
}
}
// Incoming MQTT Message Handler
void NewMqttMessage(int messageSize) {
Serial.println("NEW MESSAGE!");
/*strcpy*/ strncpy(recievedMessage, "", 500);
while (client.available()) {
//recievedMessage = recievedMessage + ((char)client.read());
/*strcpy*/ strncpy(recievedMessage, (recievedMessage + ((char)client.read())), 500);
}
if (debug) {
Serial.println("");
Serial.print("Received a message with topic '");
Serial.print(client.messageTopic());
Serial.print("', length ");
Serial.print(messageSize);
Serial.println(" bytes:");
Serial.println(recievedMessage);
Serial.println();
}
//MessageHandler(recievedMessage); // Function does not exist yet - code just here for when I implement it in the future
}
void SetupTemperatureSensors() {
dhtF1.begin();
dhtF2.begin();
dhtF3.begin();
dhtB1.begin();
dhtB2.begin();
dhtB3.begin();
}
void CheckDHT(DHT sen, int i) {
float h = sen.readHumidity(); // Get humidity %
float t = sen.readTemperature(); // Get temperature (celcius)
delay(100);
// IF h AND t BOTH HAVE VALUE:
if (!isnan(h) && !isnan(t)) {
if (i >= 3) { // if index >= 3 then it is a back sensor
i -= 3;
lastBackHumidity[i] = h;
lastBackTemp[i] = t;
} else { // if not, use normal index as its a front sensor
lastFrontHumidity[i] = h;
lastFrontTemp[i] = t;
}
} else { // Yes im aware i can remove the else statement and make t and h just = 999.999 if invalid, but... "dont fix what isnt broken"
if (i >= 3) { // if index >= 3 then it is a back sensor
i -= 3;
lastBackHumidity[i] = 999.999;
lastBackTemp[i] = 999.999;
} else { // if not, use normal index as its a front sensor
lastFrontHumidity[i] = 999.999;
lastFrontTemp[i] = 999.999;
}
}
}
void UpdateTemperatureHumidityData() {
for (int dhtSenIndex = 0; dhtSenIndex < 6; dhtSenIndex++) { // Loop and update all DHT sensors
switch (dhtSenIndex) {
case 0:
CheckDHT(dhtF1, dhtSenIndex);
break;
case 1:
CheckDHT(dhtF2, dhtSenIndex);
break;
case 2:
CheckDHT(dhtF3, dhtSenIndex);
break;
case 3:
CheckDHT(dhtB1, dhtSenIndex);
break;
case 4:
CheckDHT(dhtB2, dhtSenIndex);
break;
case 5:
CheckDHT(dhtB3, dhtSenIndex);
break;
default:
Serial.println("Function UpdateTemperatureHumidityData() switch statement hit default somehow?!");
break;
}
}
}
void SetupSensors() {
SetupTemperatureSensors();
// More functions would be here for other sensors (not implemented yet)
}
void UpdateSensorData() {
UpdateTemperatureHumidityData();
// More functions would be here for other sensors (not implemented yet)
}
void CompilePayload() {
/*strcpy*/ strncpy(payload, "", 500); // Not sure what is better to use (strcpy vs strncpy)
JsonDocument doc;
doc["type"] = "new_data";
doc["device"] = deviceID;
JsonObject data = doc.createNestedObject("data");
JsonObject temperature_sensors = data.createNestedObject("temperature_sensors"); //dht
JsonObject humidity_sensors = data.createNestedObject("humiditiy_sensors"); //dht
if (debug) { doc["free_ram"] = stackAvailable(); } // Used for debugging (shows remaining memory)
// TEMPERATURE
temperature_sensors["F1"] = lastFrontTemp[0];
temperature_sensors["F2"] = lastFrontTemp[1];
temperature_sensors["F3"] = lastFrontTemp[2];
temperature_sensors["B1"] = lastBackTemp[0];
temperature_sensors["B2"] = lastBackTemp[1];
temperature_sensors["B3"] = lastBackTemp[2];
// HUMIDITY
humidity_sensors["F1"] = lastFrontHumidity[0];
humidity_sensors["F2"] = lastFrontHumidity[1];
humidity_sensors["F3"] = lastFrontHumidity[2];
humidity_sensors["B1"] = lastBackHumidity[0];
humidity_sensors["B2"] = lastBackHumidity[1];
humidity_sensors["B3"] = lastBackHumidity[2];
serializeJson(doc, payload); // Set JSON data to payload variable
if (readings) {
Serial.println(payload);
}
}
void SendData() {
client.subscribe(postTopic); // Subscribe to the PostTopic
// Send the payload to the Server
client.beginMessage(postTopic);
client.print(payload);
client.print("");
client.endMessage();
client.subscribe(listenTopic);
}
unsigned int stackAvailable() // FOR DEBUGGING - TESTING RETURNS 7948 (in empty sketch) THIS PROGRAM RETURNS ~5219 bytes
{
extern int __heap_start, *__brkval;
unsigned int v;
return (unsigned int)&v - (__brkval == 0 ? (unsigned int)&__heap_start : (unsigned int)__brkval);
}
void setup() {
Serial.begin(9600);
if (debug) readings = true;
SetupNetwork();
SetupSensors();
}
void loop() {
// The loop will run every 2 seconds (due to hardware limitations of sensor read-time)
// During each loop all data will be collected, compiled into a JSON, and sent over MQTT
MaintainNetwork();
UpdateSensorData();
CompilePayload();
SendData();
delay(loopDelay);
}
I've been trying to solve this problem for around around 2 months now, I can't figure out what is causing it to stop sending data, and if it is something with the network or MQTT, or if its the arduino board, or code.
This is my first post on the forums, but I've gone through here enough by now that I know what you guys like to see (ALL the code, schematics, etc) so hopefully I've captured all the information you need.
It's a bit of a big post so a massive thanks to those willing to help
![]()


