I currently have an Mega2560, this has multiple DS18B20s 3 per digital pin, all is working somewhat in this regard although I seem to have lost a few but I need to track that down when I get on site with the setup, my main issue at the moment is serial communication stopping after sometime and the raspberry pi running node red needs to be rebooted.
I have tried to tidy my code with advice I got last year on this forum and I will post it below but my question at the moment, is it better to call each pin and get a response send to node red for processing or call all the pins and build a long string of temperatures and return that, I'm trying to judge if I had a memory leak or I'm clogging up the buffer.
Original code that stalls after some time
#include <OneWire.h>
#include <DallasTemperature.h>
const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;
#define RELAY_OFF 0
#define RELAY_ON 1
void ProcessSerialData()
{
static boolean recieveInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while(Serial.available() > 0 && newData == false)
{
rc = Serial.read();
if(recieveInProgress == true)
{
if(rc != endMarker)
{
receivedChars[ndx] = rc;
ndx++;
if(ndx >= numChars)
{
ndx = numChars - 1;
}
}
else
{
receivedChars[ndx] = '\0';
recieveInProgress = false;
ndx = 0;
newData = true;
}
}
else if(rc == startMarker)
{
recieveInProgress = true;
}
}
}
void ShowNewData()
{
if(newData == true)
{
ProcessSerialInput(receivedChars);
//Serial.println(receivedChars);
newData = false;
}
}
void ProcessSerialInput(String data)
{
if(data.substring(0, 5) == "relay")
{
if(data.substring(7, 9) == "on")
{
int p = data.substring(5, 7).toInt();
RelayControl(p, RELAY_ON);
}
else if(data.substring(7, 9) == "of")
{
int p = data.substring(5, 7).toInt();
RelayControl(p, RELAY_OFF);
}
}
else if(data.substring(0, 5) == "tstat")
{
if(data.substring(7, 9) == "aa")
{
int p = data.substring(5, 7).toInt();
ProcessTemperature(p);
}
}
}
void RelayControl(int Pin, unsigned char Status)
{
pinMode(Pin, OUTPUT);
digitalWrite(Pin, Status);
Serial.println("RELAY,PIN," + String(Pin) + "," + String(Status));
}
String GetSensorAddress(DeviceAddress device)
{
String address;
address += "[";
for(uint8_t i = 0; i < 8; i++)
{
address += String("0x");
if(device[i] < 0x10)
{
address += String("0");
}
address += String(device[i], HEX);
if(i < 7)
{
address += String(", ");
}
}
address += String("]");
return address;
}
void ProcessTemperature(int Pin)
{
String serialDataTemp = "";
String address = "";
float tempC;
OneWire OneWireBus(Pin);
DallasTemperature Sensor(&OneWireBus);
Sensor.begin();
Sensor.requestTemperatures();
for(int i = 0; i < Sensor.getDeviceCount(); i++)
{
tempC = Sensor.getTempCByIndex(i);
Serial.println("TEMP,PIN," + String(Pin) + "," + String(tempC));
}
}
void setup()
{
Serial.begin(115200);
}
void loop()
{
ProcessSerialData();
ShowNewData();
}
My new code including some edits from a previous question post
#include <OneWire.h>
#include <DallasTemperature.h>
#define RELAY_OFF 0
#define RELAY_ON 1
void relayControl(
int pin,
unsigned char state) {
pinMode(pin, OUTPUT);
digitalWrite(pin, state);
Serial.println("RELAY,PIN," + String(pin) + "," + String(state));
}
void processTemperature(
int pin) {
float temperature = 0.0;
int deviceCount = 0;
OneWire OneWireBus(pin);
DallasTemperature Sensor(&OneWireBus);
Sensor.begin();
Sensor.requestTemperatures();
deviceCount = Sensor.getDeviceCount();
if (deviceCount > 0) {
for (int i = 0; i < deviceCount; i++) {
temperature = Sensor.getTempCByIndex(i);
Serial.println("TEMP," + String(pin) + "," + String(temperature));
}
} else {
Serial.println("TEMP," + String(pin) + ",NO_DATA");
}
}
const int cylPin = 52;
void cylStatState() {
pinMode(cylPin, INPUT_PULLUP);
int pinState = digitalRead(cylPin);
Serial.println("CYLSTAT," + String(pinState));
}
void processInput(
String data) {
String cmd = data.substring(0, 5);
int pin = data.substring(5, 7).toInt();
String opt = data.substring(7, 9);
if (cmd == "relay") {
if (opt == "on") {
relayControl(pin, RELAY_ON);
} else {
relayControl(pin, RELAY_OFF);
}
} else if (cmd == "temps") {
processTemperature(pin);
} else if (cmd == "cstat") {
cylStatState();
}
}
char receivedChars[80];
void processSerialData() {
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
if (!Serial.available()) {
return;
}
char c = Serial.read();
if (c == startMarker) {
ndx = 0;
} else if (c == endMarker) {
receivedChars[ndx] = '\0';
processInput(receivedChars);
} else {
receivedChars[ndx++] = c;
if (sizeof(receivedChars) <= ndx) {
ndx = 0;
}
}
}
void setup() {
Serial.begin(115200);
}
void loop() {
processSerialData();
}
My current test code which returns a long serial message such as
null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,
rather than
TEMP,22,NO_DATA
in the hopes of keeping the serial lines clear, also added reserve to the string
#include <OneWire.h>
#include <DallasTemperature.h>
#define RELAY_OFF 0
#define RELAY_ON 1
const int temperaturePinArray[] = {23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53};
String temperatureMessage = "";
void relayControl(
int pin,
unsigned char state) {
pinMode(pin, OUTPUT);
digitalWrite(pin, state);
Serial.println("RELAY,PIN," + String(pin) + "," + String(state));
}
void processTemperature() {
temperatureMessage = "";
for (int element : temperaturePinArray) {
OneWire OneWireBus(element);
DallasTemperature Sensor(&OneWireBus);
Sensor.begin();
Sensor.requestTemperatures();
delay(5);
if (Sensor.getDeviceCount() > 0) {
for (int i = 0; i < Sensor.getDeviceCount(); i++) {
temperatureMessage += Sensor.getTempCByIndex(i);
temperatureMessage += ",";
}
} else {
temperatureMessage += "null,";
}
}
Serial.println(temperatureMessage);
}
const int cylPin = 52;
void cylStatState() {
pinMode(cylPin, INPUT_PULLUP);
int pinState = digitalRead(cylPin);
Serial.println("CYLSTAT," + String(pinState));
}
void processInput(
String data) {
String cmd = data.substring(0, 5);
int pin = data.substring(5, 7).toInt();
String opt = data.substring(7, 9);
if (cmd == "relay") {
if (opt == "on") {
relayControl(pin, RELAY_ON);
} else {
relayControl(pin, RELAY_OFF);
}
} else if (cmd == "temps") {
processTemperature();
} else if (cmd == "cstat") {
cylStatState();
}
}
char receivedChars[80];
void processSerialData() {
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
if (!Serial.available()) {
return;
}
char c = Serial.read();
if (c == startMarker) {
ndx = 0;
} else if (c == endMarker) {
receivedChars[ndx] = '\0';
processInput(receivedChars);
} else {
receivedChars[ndx++] = c;
if (sizeof(receivedChars) <= ndx) {
ndx = 0;
}
}
}
void setup() {
Serial.begin(115200);
temperatureMessage.reserve(256);
}
void loop() {
processSerialData();
}
I'm at a loss really, I think personally I will upload the middle code section and see how it goes, node red sends a request to Arduino such as and Arduino responds with the result and this does work fairly well. I have staggered my calls to try and keep the traffic low but something in my first code share above kills the Arduino after some time, then again it could be something else like noise on the system, there is a rather large 63a water heater that kicks in a few times a day and I'm considering if that could be causing issues with the local main voltage instability during start and stop cycles.