Nano on blocking

Hello,

I am using Arduino NANO v3.

The project is a little automation where

Arduino --> serial to esp-01 (to send and receive commands from the web)
Arduino --> I/O to Relay (5 relay)
Arduino --> I/O from input (4 input)
Arduino --> I/O from DS18B20 (5 input)
Arduino --> LCD to report some information

The code is quite simple, even a little long.
From time to time the Arduino stop to work without any advice.
I was thinking about the problem with the powering (some disturbance), but it happens by powering by USB also... so I think it could be because of RAM issues.

Is there any possibility by any software to check the code, if RAM can saturated?
I am worried it can be caused by an error during reading the temperature DS18B20 that time to time fault.

Any suggestion?

If it is useful I can post the code also.

Hi, @AlessandroLecce

It would be good if we saw your code.
It would be good if we saw a schematic.
It would be good if we saw some pictures of your project.

Thanks... Tom.. :grinning: :+1: :coffee: :australia:

1 Like

Start by posting the full sketch, using code tags when you do

Posting your complete sketch is the minimum of information that you should provide

If you are able change from an arduino to an ESP32 you will have a much easier time than hassling around with an Arduino and serial connected ESP01.

The ESP32 could do do the internetconnection and all the IO-stuff standalone

Sorry, to don't be complete on the first post.
Here code and schematic.

#include <SoftwareSerial.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>


//RELAY
#define OUT_L0 6 //Relay0  D6
#define OUT_L1 5 //Relay1  D5
#define OUT_L2 4 //Relay2  D4
#define OUT_L3 3 //Relay3  D3
#define OUT_L4 2 //Relay4  D2
//RELAYEND


//TEMPERATURES
#define ONE_WIRE_BUS_L0 A0  //T0
#define ONE_WIRE_BUS_L1 A1  //T1
#define ONE_WIRE_BUS_L2 A2  //T2
#define ONE_WIRE_BUS_L3 A3  //T3
#define ONE_WIRE_BUS_L4 12  //T4

OneWire oneWire_L0(ONE_WIRE_BUS_L0);
OneWire oneWire_L1(ONE_WIRE_BUS_L1);
OneWire oneWire_L2(ONE_WIRE_BUS_L2);
OneWire oneWire_L3(ONE_WIRE_BUS_L3);
OneWire oneWire_L4(ONE_WIRE_BUS_L4);

DallasTemperature sensors_L0(&oneWire_L0);
DallasTemperature sensors_L1(&oneWire_L1);
DallasTemperature sensors_L2(&oneWire_L2);
DallasTemperature sensors_L3(&oneWire_L3);
DallasTemperature sensors_L4(&oneWire_L4);
//END TEMPERATURES
//STORAGE TEMPERATURS
String Stemp0 = "ERR";
String Stemp1 = "ERR";
String Stemp2 = "ERR";
String Stemp3 = "ERR";
String Stemp4 = "ERR";
float Ftemp0 = 0;
float Ftemp1 = 0;
float Ftemp2 = 0;
float Ftemp3 = 0;
float Ftemp4 = 0;

//END STORAGE TEMPERATURS

//INPUT
#define IN_L0 7 //INPUT0  //avvia pompa pressione se 1
#define IN_L1 8 //INPUT1 
#define IN_L2 10 //INPUT2 
#define IN_L3 11 //INPUT3  
//INPUTEND

//VARIABLE
int var0 = 10; //differnza di temperatura di avvio pannelli
int var1 = 5; //differnza di temperatura di stop pompa pannelli
int var2 = 50; //temperatura avvio caldaia
int var3 = 55; //temperatura avvio stop caldaio
int var4 = 5; //temperatura di sicurezza al di sotto della quale si avvio la pompa pannelli
int var5 = 60; //minuti avvio pompa pressione
int var6 = 0; //se 1 non avviare pompa pressione
int var7 = 0; //se 1 non essettuare il loop
int var8 = 0;
int var9 = 0;
//VARIABLE END

///LCD
LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display
String textL0_1 =""; //testoLinea0 1^
String textL0_2 =""; //testoLinea0 2^
String textL0_3 =""; //testoLinea0 3^
String textL1_1 =""; //testoLinea1 1^
String textL1_2 =""; //testoLinea2 2^
String textL1_3 =""; //testoLinea3 3^



//CYCLE OR WEB
bool cycle = true;
int currentTimeCycle;
int previousTimeCycle;
int LCDTimeCycle;
  
SoftwareSerial SerialSoft(13, 9);//RX, TX

void setup() 
{
  Serial.begin(9600);
  // Initialize the output serial to pilot the relay
  SerialSoft.begin(9600);

  //LCD
  lcd.init();                      // initialize the lcd 
  // Print a message to the LCD.
  lcd.backlight();
  lcd.setCursor(0,0);//colonna - riga
  lcd.print("Welcome in:");
  lcd.setCursor(0,1);
  lcd.print("Enere SOLAR CONTROLL");

  //Relays
  pinMode(OUT_L0, OUTPUT);
  pinMode(OUT_L1, OUTPUT);
  pinMode(OUT_L2, OUTPUT);
  pinMode(OUT_L3, OUTPUT);
  pinMode(OUT_L4, OUTPUT);
    
  digitalWrite(OUT_L0, LOW);
  digitalWrite(OUT_L1, LOW);
  digitalWrite(OUT_L2, LOW);
  digitalWrite(OUT_L3, LOW);
  digitalWrite(OUT_L4, LOW);

  //Temperatures
  sensors_L0.begin();
  sensors_L1.begin();
  sensors_L2.begin();
  sensors_L3.begin();
  sensors_L4.begin();

  //Input
  pinMode(IN_L0, INPUT);
  pinMode(IN_L1, INPUT);
  pinMode(IN_L2, INPUT);
  pinMode(IN_L3, INPUT);
}

String command = "";
bool start_reading_command = false;

void loop()
{
  currentTimeCycle = millis();
  
  if(SerialSoft.available() > 0) 
  {
      previousTimeCycle = millis();
      cycle=false;   
      char c = SerialSoft.read();
      Serial.write(c);
      
      if(start_reading_command) //it's true in the end if '_'
      {
        command = command + c;
        if (c == ';')
        {
          start_reading_command = false;
          
          Serial.print("#");
          for(int i=0; i<command.length(); i++)
          {
            Serial.print(command[i]);
          }
          Serial.println("#");
          //relay
          if(command[0] == 'R')
          {
            //write
            if(command[2] == 'W')
            {
              if(command[3] == '0' && command[5] == '0')
              {
                digitalWrite(OUT_L0, LOW);
              }
              else if(command[3] == '0' && command[5] == '1')
              {
                digitalWrite(OUT_L0, HIGH);
              }
              else if(command[3] == '0' && command[5] == '2')
              {
                digitalWrite(OUT_L0, HIGH);
                delay(2000);
                digitalWrite(OUT_L0, LOW);
              }
              else if(command[3] == '1' && command[5] == '0')
              {
                digitalWrite(OUT_L1, LOW);
              }
              else if(command[3] == '1' && command[5] == '1')
              {
                digitalWrite(OUT_L1, HIGH);
              }
              else if(command[3] == '1' && command[5] == '2')
              {
                digitalWrite(OUT_L1, HIGH);
                delay(2000);
                digitalWrite(OUT_L1, LOW);
              }
              else if(command[3] == '2' && command[5] == '0')
              {
                digitalWrite(OUT_L2, LOW);
              }
              else if(command[3] == '2' && command[5] == '1')
              {
                digitalWrite(OUT_L2, HIGH);
              }
              else if(command[3] == '2' && command[5] == '2')
              {
                digitalWrite(OUT_L2, HIGH);
                delay(2000);
                digitalWrite(OUT_L2, LOW);
              }
              else if(command[3] == '3' && command[5] == '0')
              {
                digitalWrite(OUT_L3, LOW);
              }
              else if(command[3] == '3' && command[5] == '1')
              {
                digitalWrite(OUT_L3, HIGH);
              }
              else if(command[3] == '3' && command[5] == '2')
              {
                digitalWrite(OUT_L3, HIGH);
                delay(2000);
                digitalWrite(OUT_L3, LOW);
              }
              else if(command[3] == '4' && command[5] == '0')
              {
                digitalWrite(OUT_L4, LOW);
              }
              else if(command[3] == '4' && command[5] == '1')
              {
                digitalWrite(OUT_L4, HIGH);
              }
              else if(command[3] == '4' && command[5] == '2')
              {
                digitalWrite(OUT_L4, HIGH);
                delay(2000);
                digitalWrite(OUT_L4, LOW);
              }
              SerialSoft.print("ok;");
            }
            //read
            else if(command[2] == 'R')
            {
              if(command[3] == '0')
              {
                SerialSoft.print("_" + String(digitalRead(OUT_L0)) + ";");
              }
              else if(command[3] == '1')
              {
               SerialSoft.print("_" + String(digitalRead(OUT_L1)) + ";");
              }
              else if(command[3] == '2')
              {               
               SerialSoft.print("_" + String(digitalRead(OUT_L2)) + ";");
              }
              else if(command[3] == '3')
              {
               SerialSoft.print("_" + String(digitalRead(OUT_L3)) + ";");
              }
              else if(command[3] == '4')
              {
               SerialSoft.print("_" + String(digitalRead(OUT_L4)) + ";");
              }
            }
          }
          else if(command[0] == 'T')
          {
            
            if(command[2] == '0')
            {
              SerialSoft.print("_" + Stemp0  +";");
              Serial.println("T0");
              Serial.println("_" + String(Ftemp0)  +";");
            }
            else if(command[2] == '1')
            {
              SerialSoft.print("_" + Stemp1  +";");
              Serial.println("T1");
              Serial.println("_" + String(Ftemp1)  +";");
            }
            else if(command[2] == '2')
            {
              SerialSoft.print("_" + Stemp2  +";");
              Serial.println("T2");
              Serial.println("_" + String(Ftemp2)  +";");
            }
            else if(command[2] == '3')
            {
              SerialSoft.print("_" + Stemp3  +";");
              Serial.println("T3");
              Serial.println("_" + String(Ftemp3)  +";");
            }
            else if(command[2] == '4')
            {
              SerialSoft.print("_" + Stemp4  +";");
              Serial.println("T4");
              Serial.println("_" + String(Ftemp4)  +";");
            } 
          }
          else if(command[0] == 'I') //Reading input
          {
            if(command[2] == '0')
            {
              SerialSoft.print("_" + String(digitalRead(IN_L0)) + ";");
            }
            else if(command[2] == '1')
            {
              SerialSoft.print("_" + String(digitalRead(IN_L1)) + ";");
            }
            else if(command[2] == '2')
            {
              SerialSoft.print("_" + String(digitalRead(IN_L2)) + ";");
            }
            else if(command[2] == '3')
            {
              SerialSoft.print("_" + String(digitalRead(IN_L3)) + ";");
            }
          }
          else if(command[0] == 'V') //Variable
          {
            //write
            if(command[2] == 'W') //write/set the value
            {
              if(command[3] == '0')
              {
                  var0 = variableValue(command);
              }
              else if(command[3] == '1')
              {
                  var1 = variableValue(command);
              }
              else if(command[3] == '2')
              {
                  var2 = variableValue(command);
              }
              else if(command[3] == '3')
              {
                  var3 = variableValue(command);
              }
              else if(command[3] == '4')
              {
                  var4 = variableValue(command);
              }
              else if(command[3] == '5')
              {
                  var5 = variableValue(command);
              }
              else if(command[3] == '6')
              {
                  var6 = variableValue(command);
              }
              else if(command[3] == '7')
              {
                  var7 = variableValue(command);
              }
              else if(command[3] == '8')
              {
                  var8 = variableValue(command);
              }
              else if(command[3] == '9')
              {
                  var9 = variableValue(command);
              }
            }
            else if(command[2] == 'R') //read the value
            {
              if(command[3] == '0')
              {
                SerialSoft.print("_" + String(var0) + ";");
              }
              else if(command[3] == '1')
              {
                SerialSoft.print("_" + String(var1) + ";");
              }
              else if(command[3] == '2')
              {
                SerialSoft.print("_" + String(var2) + ";");
              }
              else if(command[3] == '3')
              {
                SerialSoft.print("_" + String(var3) + ";");
              }
              else if(command[3] == '4')
              {
                SerialSoft.print("_" + String(var4) + ";");
              }
              else if(command[3] == '5')
              {
                SerialSoft.print("_" + String(var5) + ";");
              }
              else if(command[3] == '6')
              {
                SerialSoft.print("_" + String(var6) + ";");
              }
              else if(command[3] == '7')
              {
                SerialSoft.print("_" + String(var7) + ";");
              }
              else if(command[3] == '8')
              {
                SerialSoft.print("_" + String(var8) + ";");
              }
              else if(command[3] == '9')
              {
                SerialSoft.print("_" + String(var9) + ";");
              }
            }
          }
          command = "";
        }
      }  
      if(c == '_')
      {
        start_reading_command = true;
      }   
  }
  if (Serial.available() > 0) 
  {
    //write back
       SerialSoft.write(Serial.read());
  }

  //after 3 second without serial command from ESP8266
  if((currentTimeCycle - previousTimeCycle)>3000) 
  {
    cycle = true;
  }

  //every 30-35 second in any case execute 1 time
  if((currentTimeCycle - previousTimeCycle)>30000 && (currentTimeCycle - previousTimeCycle)< 35000) 
  {
    previousTimeCycle = millis();
    cycle = true;
  }

  if(cycle == true) //update temperature if cycle is working - if serial no!
  {
    Read_T0();
    Read_T1();
    Read_T2();
    Read_T3();
    Read_T4();
  }

//HERE THE LOOP 
  if(cycle && var7==0)
  {  
        //TEMP PANNELLI T0
        float temp_pannelli = Ftemp0;
                    
        //TEMP BASSA T1
        float temp_bassa = Ftemp1;
        
        //TEMP ALTA T2
        float temp_alta = Ftemp2;
      
        bool execute = true;
        
        if(Stemp0 == "ERR")
        {
          lcd.clear();
          lcd.setCursor(0,1);
          lcd.print("ERROR-SONDA PANNELLI");
          previousTimeCycle = millis(); //stop the cyle 3 sec
          cycle = false;
          execute = false;
        }
      
        if(Stemp1 == "ERR")
        {
          lcd.clear();
          lcd.setCursor(0,1);
          lcd.print("ERROR-SONDA BASSA");
          previousTimeCycle = millis(); //stop the cyle 3 sec
          cycle = false;
          execute = false;
        }
      
        if(Stemp2 == "ERR"){
          lcd.clear();
          lcd.setCursor(0,1);
          lcd.print("ERROR-SONDA ALTA");
          previousTimeCycle = millis(); //stop the cyle 3 sec
          cycle = false;
          execute = false;
        }
      
        
      /*
      int var0 = 10; //differnza di temperatura di avvio pannelli
      int var1 = 5; //differnza di temperatura di stop pompa pannelli
      int var2 = 50; //temperatura avvio caldaia
      int var3 = 55; //temperatura avvio stop caldaia
      int var4 = 5; //temperatura di sicurezza al di sotto della quale si avvio la pompa pannelli
      int var5 = 60; //minuti avvio pompa pressione
      int var6 = 0; //se 1 non avviare pompa pressione
      int var7 = 0; //se 1 non avviare Caldaia
      */
      //RELAY POMPA CIRC L0
      //RELAY POMPA CALD L1
      //RELAY POMPA PRESSIONE L2
        if(execute)
        {
            
             
            if(temp_pannelli<var4)//PANNELLI SICUREZZA LOW TEMPERATURE
            {
                digitalWrite(OUT_L4, HIGH);
            }
            else
            {
              if((temp_pannelli-temp_bassa)>var0) //PANNELLI riscaldamento
              {
                digitalWrite(OUT_L4, HIGH);
              }
              if((temp_pannelli-temp_bassa)<var1)
              {
                digitalWrite(OUT_L4, LOW);
              }
            }
           
            
            //CALDAIA
            if(temp_alta<var2)
            {
              digitalWrite(OUT_L3, HIGH);
            }
            if(temp_alta>var3)
            {
              digitalWrite(OUT_L3, LOW);
            }
          
          
            //POMPA
            unsigned long tempo = millis();
            unsigned long sec = tempo/1000;
            int res = sec % (60*var5);
          
            if(res>0 && res<60)
            {
               digitalWrite(OUT_L2, HIGH);
            }
            else
            {
              digitalWrite(OUT_L2, LOW); 
            }
      
      
            //WRITE ON SCREEN:
            String stat = "OFF";
            if(digitalRead(OUT_L4))
            {
              stat = "ON";
            }

            textL0_1 = "POMPA PANNEL:" + stat;
            textL1_1 = "TEMP PANNEL:" + String(temp_pannelli);
      
            stat = "OFF";
            if( digitalRead(OUT_L3))
            {
              stat = "ON";
            }

            textL0_2 = "CALDAIA:" + stat;
            textL1_2 = "TEMP ALTA:" + String(temp_alta);
      
            stat = "OFF";
            if( digitalRead(OUT_L2))
            {
              stat = "ON";
            }
            textL0_3 = "POMPA PRES:" + stat;
            textL1_3 = "TEMP BASSA:" + String(temp_bassa);

            
            if((currentTimeCycle - LCDTimeCycle)>1500) 
            {
              LCDTimeCycle = millis();
              writeLCD();
            }
        }
    }
    
}

int sequenza = 0;

void writeLCD()
{
  lcd.clear();
  if(sequenza == 0)
  {
    lcd.setCursor(0,0);
    lcd.print(textL0_1);
    lcd.setCursor(0,1);
    lcd.print(textL1_1);
    sequenza++;    
  }
  else if(sequenza == 1)
  {
    lcd.setCursor(0,0);
    lcd.print(textL0_2);
    lcd.setCursor(0,1);
    lcd.print(textL1_2);
    sequenza++;    
  }
  else if(sequenza == 2)
  {
    lcd.setCursor(0,0);
    lcd.print(textL0_3);
    lcd.setCursor(0,1);
    lcd.print(textL1_3);
    sequenza = 0;
  }
}




int variableValue(String command)
{
  int start_value_pos = command.indexOf("=")+1;
  int end_value_pos = command.indexOf(";");
  String valueS = command.substring(start_value_pos,end_value_pos);
  int value = valueS.toInt();
  return value;
}

int tentativiT0 = 0;
void Read_T0()
{
  sensors_L0.requestTemperatures();
  float temp = sensors_L0.getTempCByIndex(0);
  if(String(temp) == "-127.00" || String(temp) == "85.00")
  {
    tentativiT0++;
  }
  else
  {
    tentativiT0 = 0;
    Stemp0 = String(temp);
    Ftemp0 = temp;
  }
  if(tentativiT0 > 100)
  {
    Stemp0 = "ERR";
  }
}

int tentativiT1 = 0;
void Read_T1()
{
  sensors_L1.requestTemperatures();
  float temp = sensors_L1.getTempCByIndex(0);
  if(String(temp) == "-127.00" || String(temp) == "85.00")
  {
    tentativiT1++;
  }
  else
  {
    tentativiT1 = 0;
    Stemp1 = String(temp);
    Ftemp1 = temp;
  }
  if(tentativiT1 > 100)
  {
    Stemp1 = "ERR";
  }
}

int tentativiT2 = 0;
void Read_T2()
{
  sensors_L2.requestTemperatures();
  float temp = sensors_L2.getTempCByIndex(0);
  if(String(temp) == "-127.00" || String(temp) == "85.00")
  {
    tentativiT2++;
  }
  else
  {
    tentativiT2 = 0;
    Stemp2 = String(temp);
    Ftemp2 = temp;
  }
  if(tentativiT2 > 100)
  {
    Stemp2 = "ERR";
  }
}


int tentativiT3 = 0;
void Read_T3()
{
  sensors_L3.requestTemperatures();
  float temp = sensors_L3.getTempCByIndex(0);
  if(String(temp) == "-127.00" || String(temp) == "85.00")
  {
    tentativiT3++;
  }
  else
  {
    tentativiT3 = 0;
    Stemp3 = String(temp);
    Ftemp3 = temp;
  }
  if(tentativiT3 > 100)
  {
    Stemp3 = "ERR";
  }
}

int tentativiT4 = 0;
void Read_T4()
{
  sensors_L4.requestTemperatures();
  float temp = sensors_L4.getTempCByIndex(0);
  if(String(temp) == "-127.00" || String(temp) == "85.00")
  {
    tentativiT4++;
  }
  else
  {
    tentativiT4 = 0;
    Stemp4 = String(temp);
    Ftemp4 = temp;
  }
  if(tentativiT4 > 100)
  {
    Stemp4 = "ERR";
  }
}

ESP-01 is connected by a 5V adapter

Do not use the String class with a nano, particularly String concatenation. It is very likely causing your problem. See this thread for more information on exactly why. Use c-style strings instead. You cannot increase the size of the c-style string dynamically, so you will need to declare your string as large as you will need it to be in the beginning. This will save you from the memory fragmentation that is very likely causing the problem for you.

  //every 30-35 second in any case execute 1 time
  if((currentTimeCycle - previousTimeCycle)>30000 && (currentTimeCycle - previousTimeCycle)< 35000)

It's probably not related to your stated problem, but the compiler warns:

sketch_feb22a.ino:424:92: warning: comparison is always true due to limited range of data type [-Wtype-limits]

In preferences, set compiler warnings to "all", and enable verbose output for both compilation and uploading.

As for the use of Strings, more information than you likely want given the preponderance of Strings in your code:

Hello AlessandroLecce

Post an overview of commands used in your project.

These should be unsigned long integers as that is what millis() returns.

The condition is not true at 3 seconds but at 3 seconds and 1 millisecond. Also parentheses and braces not necessary. Also also, format correctly so stuff isn't all jammed up together.

if (currentTimeCycle - previousTimeCycle >= 3000) cycle = true;

or

cycle = (currentTimeCycle - previousTimeCycle >= 3000) ? true: false;

As stated by @camsysca, the max value for a signed int is 32767, so it will ALWAYS be < 35000.
This second half isn't really necessary and seems redundant to the conditional before it. This may be a result of trying to figure out why you're freezing, which is very likely related to the String class and memory fragmentation from you use of concatenation of Strings. Consider replacing both conditionals with the following lines.

if (currentTimeCycle - previousTimeCycle >= 30000) 
  {
    previousTimeCycle = currentTimeCycle;
    cycle = true;
  }

The parenthesis and brackets aren't strictly necessary, but there are a bunch of folks who won't attempt to read your code without them. So when you need help from other people, it's nice to format your code in a way that makes it easier for them to read.

1 Like

I'll concede on the braces, but maintain contention on the extra set of parentheses.

Oh yeah, those can go. I just meant to say the braces.

1 Like

@Delta_G
I wholly agree on the bracing style for use on the forum.

In my own use, when the conditional is simple and the function is singular, when reviewing my own code, it makes it easier for me to see it as a complete thought.

When the conditional is short and the function list long, I put the open brace on the conditional line.

When the conditional is complex, I place the open brace on the next line, and often comment on my condition...

I know this breaks all style guides in existence...

The inner pair or parentheses may not be necessary but they are still useful. I like to be able to read code as much like an English sentence as possible and if a couple of braces helps that then why not use them ?

Not jamming the elements of the test expression together also helps with readability

2 Likes

It might be lost in my previous response, but millis() returns an unsigned long integer (unsigned long or uint32_t) which has a value from 0 to 4294967295. This value is truncated when you assign (=) it to a signed integer (int), which has a value from -32,768 to 32,767 on the Nano. I am foggy on the exact conversion, but it can mean your conditional math is evaluated incorrectly, and maybe your conditions isn't true every 30 seconds, but maybe sometimes every 53 or 81 or 176 seconds when previousTimeCycle is a number close to 30000. I don't see it in the code you have presented, but these millis() statements can create a situation where the condition stops ever being true if not handled correctly.

Thanks... I am trying to fix all little by little (unfortunately I am using C#, I could never image problem with Strings"

Now, I am getting warming

char Stemp0[7] = "ERR4567";

warming remove if:

char Stemp0[7] = "ERR456";

Can I get and explanation of the warming??

warning: initializer-string for array of chars is too long [-fpermissive]

7 chars are ERR4567 not ERR456 ???

char Stemp0[7] = "ERR4567";

The string that you are trying to put into the array has 8 characters, not 7. The 7 visible characters are followed by a '\0' character that marks the end of the string

If you use

char Stemp0[] = "ERR4567";

then the compiler will work out for itself how many bytes to allocate to the array

It's horrible working without String ( :tired_face:)

use the SafeString-library which can be installed from the library manager
offers almost the same comfort as String but is safe to use.
You have to define the maximum length of the string at compiletime
and this memory is always reserved for this string

If you try to assign more characters than the SafeString can hold the too much characters just get truncated and that's all

Demo-code

/*
  SafeString substring()
  Examples of SafeString substring

  by Matthew Ford
  Copyright(c)2020 Forward Computing and Control Pty. Ltd.
  This example code is in the public domain.

  www.forward.com.au/pfod/ArduinoProgramming/SafeString/index.html
*/

#include "SafeString.h"
createSafeString(MyReadString, 60, "<state><datapoint ise_id='2634' value='59.000000'/></state>");
//createSafeString(MyReadString, 30, "Content-Type: text/html");
createSafeString(substr, 60);
size_t BeginOfSubStr;
size_t EndOfSubStr;

void setup() {
  // Open serial communications and wait a few seconds
  Serial.begin(115200);
  Serial.println();

  SafeString::setOutput(Serial); // enable full debugging error msgs
  Serial.println();
                                 //          10        20        30        40        50
  MyReadString.debug();          //012345678901234567890123456789012345678901234567890123456789
  Serial.println();              //<state><datapoint ise_id='2634' value='59.000000'/></state>
  
                                     // 12345678
  BeginOfSubStr = MyReadString.indexOf("ise_id=") + 8;
  EndOfSubStr   = MyReadString.indexOf("value=")  - 3;
  
  MyReadString.substring(substr, BeginOfSubStr,EndOfSubStr);
  Serial.print("substr#");
  Serial.print(substr);
  Serial.println("#");  
  Serial.println();
                                     // 1234567
  BeginOfSubStr = MyReadString.indexOf("value=") + 7;
  EndOfSubStr   = MyReadString.indexOf("/>")  - 3;

  MyReadString.substring(substr, BeginOfSubStr,EndOfSubStr);
  Serial.print("substr#");
  Serial.print(substr);
  Serial.println("#");  
  Serial.println();

}

void loop() {
}

another demo

// SafeStrings are based on array of chars
// SafeStrings offer almost the same comfort as Strings
// but avoid some dis-advantages of varable-type String
// the name SafeString is PROGRAM They are safe to use

// with the alternatives "String" must not awlays but CAN 
// eat up memory over time which will make the code crash

// with zero-terminated array of chars (c_string)
// you have to take care of boundary checking yourself 
// otherwise your code will start to behave weird and this kind of bug is very hard to find
// you can read more about this here https://www.forward.com.au/pfod/ArduinoProgramming/ArduinoStrings/index.html#safestring
// and here https://hackingmajenkoblog.wordpress.com/2016/02/04/the-evils-of-arduino-strings/

// very basic demo-code to show how to declare a SafeString-variable
// and how to assign text to them

// as a personal convention I use the suffix "_SS" to indicate 
// THIS IS A SAFESTRING-VARIABLE
// but you can name it whatever you like

#include "SafeString.h"
createSafeString(myTitle_SS, 64);  // reserve 64 bytes for the SafeString-variable
createSafeString(myString_SS, 32); // reserve 32 bytes for the SafeString-variable

int myInteger = -1234;
float myFloat = -987.009;


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

  myString_SS = F("fixed text directly assigned");
  Serial.print( F(" #") ); // leading double-cross "#" to show where the string starts
  Serial.print(myString_SS); 
  Serial.println(F("#") ); // trailing double-cross "#" to show where the string REALLY ends


  myTitle_SS = F("content of an integer:");
  myString_SS = myInteger;

  Serial.println(myTitle_SS);
  Serial.print( F(" #" )); // leading double-cross "#" to show where the string starts
  Serial.print(myString_SS); 
  Serial.println( F("#") ); // trailing double-cross "#" to show where the string REALLY ends



  myTitle_SS = F("content of a float:");
  myString_SS = myFloat;

  Serial.println(myTitle_SS);
  Serial.print( F(" #" )); // leading double-cross "#" to show where the string starts
  Serial.print(myString_SS); 
  Serial.println( F("#") ); // trailing double-cross "#" to show where the string REALLY ends

  myTitle_SS = F("you can append more text with the +=-operator ");
  myString_SS = F("text ");
  myString_SS += myInteger;
  myString_SS += F(" ,");
  myString_SS += myFloat;

  Serial.println(myTitle_SS);
  Serial.print( F(" #" )); // leading double-cross "#" to show where the string starts
  Serial.print(myString_SS); 
  Serial.println( F("#") ); // trailing double-cross "#" to show where the string REALLY ends  
}


void loop() {

}