Substring (after receiving RF signal) not working ANYMORE. Could you help me?

Hi friends,
I’m going nuts. Out of a blue the substring() stopped working for me!
I even tried another Arduino, with no success. It was working before, and it’s not working anymore.

The thing is: I recieve the date of some sensors by RF in a 26 characters string. So, I need to split this string into the INT and FLOAT variables. The string is being received CORRECTLY, and even the ToInt transmitter ID is being correctly converted.
Could you, please, for God’s sake, help me in that?
However, SOILH, SOILT and AIRT aren’t being converted at all! All that I got is the bellow on serial monitor:


Here’s the code.

#define receiverID  100001
int transmitterID;
int soilH;
float airT;
float soilT;

void setup(){
	Serial.begin(9600);
}

void loop(){

String str_humid; 
String str_soilT; 
String str_airT; 
String str_batteryCharge; // battery charge
String str_batteryStatus; // battery status
String str_tranID; //receptor module address

String str_out;


//583,21.15,19.79,99,1,10001   string style to receive


uint8_t buf[26];
    uint8_t buflen = sizeof(buf);
    // Check if received packet is correct size
    if (rf_driver.recv(buf, &buflen))
    {
      
      // Message received with valid checksum
      // Get values from string
      
      // Convert received data into string
  str_out = String((char*)buf);
  str_tranID = str_out.substring(21);
  }
    
    Serial.println(str_out);
  
  transmitterID = str_tranID.toInt();
  Serial.print("Transmitter ID    ");
  Serial.println(transmitterID); //PRINT SIGNAL RECEIVED
  
  if (transmitterID==receiverID){

      Serial.println("winner winner chicken dinner"); //TRANSMITTERID = RECEIVERID
      str_humid = str_out.substring(0, 3);
      str_soilT = str_out.substring(4,9);   
    str_airT = str_out.substring(10,15);
      str_batteryCharge = str_out.substring(16,18); 
    str_batteryStatus = str_out.substring(19,20); 


soilH = str_humid.toInt(); //NOT CONVERTING RIGHT
rawsoilH = soilH;


soilH = map(soilH,dryHvalueLimit, wetHvalueLimit, 0, 100); //converting SoilH to %
if (soilH>100) {soilH = 100;}
if (soilH<=1) {soilH = 0;}


soilT = str_soilT.toFloat(); //NOT CONVERTING RIGHT
rawsoilT = soilT; //for another use
airT = str_airT.toFloat(); //NOT CONVERTING RIGHT
rawairT = airT; //for another use
soilT = soilT + soilToffset;
airT = airT + airToffset; //for another use
batteryCharge = str_batteryCharge.toInt();
batteryStatus = str_batteryStatus.toInt();

// the bellow serial messages are for debug
lastrecievedSignal = millis();
Serial.print("SOILH    ");    
Serial.println(soilH);
Serial.print("SOILT    "); 
Serial.println(soilT);
Serial.print("AIRT    "); 
Serial.println(airT);
Serial.println(batteryCharge); 
Serial.println(batteryStatus);
Serial.println("---------------------------------------");  

  }      
	
	
}

Using the String class can cause problems with memory in the small memory systems on Arduinos. See the Evils of Strings.

Example #5 of the serial input basics tutorial shows how to receive serial data into a string and parse the string using the srttok() function.

Hey, thank you so much for your anwser. I'll consider this next time.

I've found the real villain!

wetHvalueLimit, dryHvalueLimit, airToffset and soilToffset were in EEPROM (in other part of code).
Since I compilated this code in a new Arduino board WITHOUT cleaning the EEPROM first, it was getting trash from EEPROM and couln't convert to INT and FLOAT properly.
I didn't post the entire source-code because it's 1500 lines long.

thanks so much!

Using the String class can cause problems with memory in the small memory systems on Arduinos

No problem using String class on UNO or Mega2560, they both work very reliably, but you may miss some text if you run out of memory.

Here are some guide lines for using Strings

  1. Declare long lived Strings as globals and reserve space in setup()
  2. Pass all Strings arguments to methods, as const String &. For results pass a String &result, that the method can update with the result. i.e. void strProcessing(const String &input1, const String &input2, , String &result) {…}

buf[26] one too short for your example data. Welcome to why Strings are safer to program with.

Here is your code with checks for out-of-memory.
Note if you go from Strings to char you will have to specify all the same numbers for the char, but they won’t be forgiving if you get them wrong and you won’t save much memory over using Strings. My SafeString library is a safe way to process char if you decide to go that way.

#include <StringReserveCheck.h>
const String receiverID = "10001";
//long transmitterID;
int soilH;
float airT;
float airToffset = 0.1;
float soilT;
int batteryStatus;
int batteryCharge;
unsigned long lastrecievedSignal =0;

String str_humid;
String str_soilT;
String rawsoilT;
String rawsoilH;
String str_airT;
String str_batteryCharge; // battery charge
String str_batteryStatus; // battery status
String str_tranID; //receptor module address
String str_out;
StringReserveCheck str_outCheck;

uint8_t buf[27] ="583,21.15,19.79,99,1,10001";
uint8_t buflen = sizeof(buf);

void stop() {
  Serial.println("out of memory");
  while (1) {}
}
void setup() {
  Serial.begin(9600);
  for (int i = 10; i > 0; i--) {
    Serial.print(i); Serial.print(' ');
    delay(500);
  }
  Serial.println();
  if (!str_humid.reserve(3)) { stop();}
  if (!str_soilT.reserve(5)) { stop();}
  if (!rawsoilH.reserve(5)) { stop();}
  if (!str_airT.reserve(5)) { stop();}
  if (!str_batteryCharge.reserve(2)) { stop();}
  if (!str_batteryStatus.reserve(1)) { stop();}
  if (!str_tranID.reserve(5)) { stop();}
  if (!str_out.reserve(25)) { stop();}
}

void printData() {
    Serial.println(str_humid);
    Serial.println(str_soilT);
    Serial.println(str_airT);
    Serial.println(str_batteryCharge);
    Serial.println(str_batteryStatus);
}

bool collectData(const String &str_out) {
  str_tranID = str_out.substring(21);
  Serial.print("Transmitter ID    ");
  Serial.println(str_tranID); //PRINT SIGNAL RECEIVED
  if (str_tranID == receiverID) {
    str_humid = str_out.substring(0, 3);
    str_soilT = str_out.substring(4, 9);
    str_airT = str_out.substring(10, 15);
    str_batteryCharge = str_out.substring(16, 18);
    str_batteryStatus = str_out.substring(19, 20);
    printData();
    return true;
  }
  return false;
}

bool haveData = true;
void loop() {
  //583,21.15,19.79,99,1,10001   string style to receive
  // Check if received packet is correct size
  //if (rf_driver.recv(buf, &buflen)) {
  if (haveData) {
    haveData = false; // do this only once
    // Convert received data into string
    str_out = String((char*)buf);
    Serial.println(str_out);
    if (collectData(str_out)) {
      Serial.println("Got new data");
      processData();
    }
  }
}


void processData() {
  soilH = str_humid.toInt(); //NOT CONVERTING RIGHT
  rawsoilH = soilH;
 // soilH = map(soilH, dryHvalueLimit, wetHvalueLimit, 0, 100); //converting SoilH to %
  if (soilH > 100) {
    soilH = 100;
  }
  if (soilH <= 1) {
    soilH = 0;
  }

  soilT = str_soilT.toFloat(); //NOT CONVERTING RIGHT
 // rawsoilT = soilT; //for another use
  airT = str_airT.toFloat(); //NOT CONVERTING RIGHT
//  rawairT = airT; //for another use
//  soilT = soilT + soilToffset;
  airT += airToffset; //for another use
  batteryCharge = str_batteryCharge.toInt();
  batteryStatus = str_batteryStatus.toInt();

  // the bellow serial messages are for debug
  lastrecievedSignal = millis();
  Serial.print("SOILH    ");
  Serial.println(soilH);
  Serial.print("SOILT    ");
  Serial.println(soilT);
  Serial.print("AIRT    ");
  Serial.println(airT);
  Serial.println(batteryCharge);
  Serial.println(batteryStatus);
  Serial.println("---------------------------------------");
}

output

583,21.15,19.79,99,1,10001
Transmitter ID    10001
583
21.15
19.79
99
1
Got new data
SOILH    100
SOILT    21.15
AIRT    19.89
99
1

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