Serial Advice with intermittent dissconnects

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.

I cannot say that is the problem but conversely I cannot say it is not the problem without more information. Most MOS logic is fast and definitely edge sensitive. Keeping your leads (they are antennas) connected to the processor less then 10"/25cm which is is about 750 Mhz without accounting for reflections etc is very important. Receivers follow the same as transmitters, the bigger the antenna the greater the gain the further it will go the more it will receive. Keep It Short & Simple.

The data that you receive in processSerialData() is a character array, not a String (capital S). So passing a character array to processInput() does not make sense.

You seem to do the same thing in all the codes that your presented.

Yes you’re correct, I’ve only just noticed that.

Is changing string to char all that’s needed? My code works but this could be one of the reasons it fails after a certain amount of time.

Unfortunately I have lots of wires of much greater lengths going to the ds18b20s and lots of internal working hooking it all up, I think my problem is most likely code to be honest as it’s runs very well sometimes for weeks before the serials data stops flowing which then stops my node red flow working

the use of the String class is not recommended on low power low memory processors such as the UNO and Mega
Use can fragment memory leading to unpredictable behaviour and program crashes

I will look into fixing that, node red was has been sending command via serial etc and for that last 8 hours and then all serial data stopped and my program stopped working.

I need to figure it out, I’m not even sending data fast as I have staggered the messages and have delays between

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.