Temerature controller stops after 1-3 month

Right, So im using the below code, which seems to work fine for 1-2 month and then it can freeze.

This lead me to believe its down to the millis overflow, but when i run my test code ising micros it will run fine for a hour and half, and the micros shows it has gone back to start, so ruled this out

So the only other difference in test code is i dont run the DS18B20 temp probes, but instead generate a random number between the temps that would be returned

The code has definetly stopped or crashed, the OLED goes static, and relays stay on for what there controlling at time.

unsigned long lastTempMillis = 0;
unsigned long currentMillis = 0;

void loop(void)
{
currentMillis = millis();
if ((currentMillis - lastTempMillis) > 1000) {
lastTempMillis = currentMillis;
getTemps();
if (sensors.getDeviceCount() != 2){
stopcode();
}else{
setRelays();
}
logTemps();
if (Debounce == true){
CountDown = CountDown -1;
if (CountDown == 0){
CountDown = 0;
}
}
updateDisplay();
}
}

I can only presume its this section that stops

Please post your complete sketch following the advice on posting a programming question given in Read this before posting a programming question

In particular note the advice to Auto format code in the IDE and to use code tags when posting code here as it prevents some combinations of characters in code being interpreted as HTML commands such as italics, bold or a smiley character, all of which render the code useless

it wont let me post code in here as its over 9000 characters

Temp_Controller.txt (20.6 KB)

What board are you using ?

You are using the String class:

displayString = " P1=" + to1DP(temp[0]) + " P2=" + to1DP(temp[1]);

which can cause instability by fragmenting the heap storage.

You can reserve space for Strings to minimise this effect.

Also, you may, as a work around, configure the watchdog timer to force a restart if it get stuck somewhere.

I dont the the wdt is available on the arduino nano EVERY?

How would you sort the string, i thought, it replaced the string on each loop? so wouldnt affect space

If i could replicate it on a test system, but i cant really leave it running connected to laptop for days,

So ive done code to replicate 6months worth of data in a few hours and nothing seems to stop the code, which is why i looked at the millis to micros, and that runs :expressionless:

How would you sort the string, i

You mean "How would you sort the String". Note the capital S

Use C style strings (lowercase s) instead. They are zero terminated arrays of chars of a fixed length so do not fragment memory like Strings. As a stopgap, don't concatenate Strings on the fly as in

displayString = " P1=" + to1DP(temp[0]) + "    P2=" + to1DP(temp[1]);

instead print each element separately

However, the first option is still the best solution to stability of the system

This illustrates one of the nastier aspects of using String objects - you are never sure that you have done enough testing.

A Freemem function will help, but there's still the risk that your heap only leaks in some rarely used error handler or other edge case.

Well, the data sheet for the Atmega4809 is here :

http://ww1.microchip.com/downloads/en/DeviceDoc/megaAVR0-series-Family-Data-Sheet-DS40002015B.pdf (see Chapter 18 for the watchdog timer)

In principle, you set a timeout and regularly reset the watchdog timer (say in the loop() ). If it gets stuck and fails to do the reset within the timeout period, it forces a system reset.

Ideally, though, this should not be used simply as a substitute for robust programming.

global defined Strings with capital "S" eat up all memora over time
The Evils of Arduino Strings

You should use something like the PString-library.

You can use PStrings almost the same as Strings. In some aspects it's even more comfortable as adding integers or floats can be done very easy by just coding

myPString = "My Test Text ";
int myInt = 1234;
myPString += myInt;

Serial.println(myPString);

result in the serial monitor
My Test Text 1234

or you could use the SafeString-library.

You are using Strings as the returntype for several functions.
Maybe the experts can say something about if this is eating up memory too or not.
As far as I know it global defined Strings eat up memory

best regards Stefan

As far as I know it global defined Strings eat up memory

Only if you misuse them

Cheers all

So i have updated all refs from displayString to displayPString

I thought clearing it like the below would mean the string is emptied

String displayString = “”;

I was using WDT in the original code on a normal nano, but had to switch to a EVERY as the program got too large, but as the EVERY was new i couldnt find this wdt_enable(WDT_PERIOD_4KCLK_gc); as the below wouldnt compile

wdt_enable(WDTO_4S);

So ive now added
#include <avr/wdt.h>

This in setup
wdt_enable(WDT_PERIOD_4KCLK_gc);

this at top of main loop
wdt_reset();

I would like to get to bottom of what causes the hang up, but I just cant seem to replicate the error in the testing. and obviously running the code for 2 hours with no issues, simulates 60 days, think i went upto 6 month one day and the code was still running

UKHeliBob:
Only if you misuse them

void loop() {
myString = "";
//......so eother code

myString = DateStr;
myString += TimeStr;
}

@CAH: that was just a short line

So i have updated all refs from displayString to displayPString

PStrings are based on array of char and need a definition like this

char displayPString_AoC[64];
PString displayPString(displayPString_AoC, sizeof (displayPString_AoC) );

So you changed your code to use PStrings?
best regards Stefan

Hi,
I am not familiar with the Nano 33, does it have a LED on board connected to an I/O pin like pin13 in Nano and UNO?

If do, then using "blink without delay" make the LED blink, it will be the "heartbeat" of your code, if you have a code stall the heartbeat will stop.

Tom... :slight_smile:

StefanL38:

void loop() {

myString = "";
//......so eother code

myString = DateStr;
myString += TimeStr;
}



@CAH: that was just a short linePStrings are based on array of char and need a definition like this


char displayPString_AoC[64];
PString displayPString(displayPString_AoC, sizeof (displayPString_AoC) );




So you changed your code to use PStrings?
best regards Stefan

Hi no sorry i think ive just chnged its name, how would i determine size?

Yeah i think it does have LED, but my OLED updates the stats every5 seconds, so i know code has stalled, each relay also has a LED, so if there on and screens not updated, when i reset arduino, temp jumps from 25.4 uptp 27 etc

It is nt clear to me what you mean with "determine size"
how many bytes the array of char should have?

I'm pretty sure that you can do at least a rough estimation how many characters get stored in your displayString.
Add some additional bytes and it will work.

The advantage of PStrings is whenever you try to store more characters than the PString can hold the too much characters just get truncated and that's all what is happening.

PString is not just a single variable-type like int float etc. it canbe used the same way but not as a variabletype that is used as a return-value from functions

best regards Stefan

I have also run into issues using the String class so what has been said here is really good advice.

Rather than adding strings etc, you can simply just use the sprintf() function. It works great. I use it with my OLED. Here is an example of how I display a date as e.g. 2020-12-27 using a sprintf() call:

   t = now();
   char dateArray[11]; //2020-12-27 = 10 chars and \0
   sprintf(dateArray,"%04d-%02d-%02d",year(t),month(t),day(t));
   display.println(dateArray);

I modified the BareMinimum.ino to my needs.
BareMinimum.ino is used as template for new files

So some useful functions are always already there if I start a new sketch
it includes a heart-beat-function based on millis89

//#include 
void PrintFileNameDateTime()
{
  Serial.println("Code running comes from file ");
  Serial.println(__FILE__);
  Serial.print("  compiled ");
  Serial.print(__DATE__);
  Serial.print(" ");
  Serial.println(__TIME__);  
}


boolean TimePeriodIsOver (unsigned long &expireTime, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();  
  if ( currentMillis - expireTime >= TimePeriod )
  {
    expireTime = currentMillis; // set new expireTime
    return true;                // more time than TimePeriod) has elapsed since last time if-condition was true
  } 
  else return false;            // not expired
}

unsigned long MyTestTimer = 0;                   // variables MUST be of type unsigned long
const byte    OnBoard_LED = 13;


void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
  static unsigned long MyBlinkTimer;
  pinMode(IO_Pin, OUTPUT);
  
  if ( TimePeriodIsOver(MyBlinkTimer,BlinkPeriod) ) {
    digitalWrite(IO_Pin,!digitalRead(IO_Pin) ); 
  }
}



void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
  PrintFileNameDateTime();

}


void loop() {
  BlinkHeartBeatLED(OnBoard_LED,100);

  if ( TimePeriodIsOver(MyTestTimer,1000) ) {

  }  

}

best regards Stefan

yeah on my first project, i used the on board LED and a external one as blinking, that project has been running for 2 years now never failed

I have another project been running 6-8 month now no issues and this has a oled with time contantly updating, but all code revolves around numbers

So theres only thins with strings, wich tbh a mate off a aqaurium forum wrote. I`ll look into changing the strings as theres only 5 stats pages so should be easy to work out whats needed.

It would have been nice to see it flop over on serial monitor so ive something to go off to make sure its fixed, wdt is enabled now so least it wont leave a relay on or not turn them on