NODEMCU ESP8266 Crashes and Keep Restarting When Run "atof ()" or "atoi ()"

Hi, I’m trying to assign float and int variables independently from char array by us atof() and atoi().

I learn this from Robin2’s Serial Input Basics, somehow it crashes and keep restarting on my NODEMCU ESP8266.

Below is the code I run and the lower one is the error I got.

Is there other way to extract elements from char array?

// simple parse demo
char receivedChars[] = "This is a test, 1234, 45.3" ;

char messageFromPC[32] = {0};
int integerFromPC = 0;
float floatFromPC = 0.0;

char recvChar;
char endMarker = '>';
boolean newData = false;


void setup() {
 Serial.begin(9600);
 Serial.println("<Arduino is ready>");
 

}


void loop() {

 parseData();
 showParsedData();

}

 
void parseData() {

    // split the data into its parts
    
  char * strtokIndx; // this is used by strtok() as an index
  
  strtokIndx = strtok(receivedChars,",");      // get the first part - the string
  strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
  
  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  integerFromPC = atoi(strtokIndx);     // convert this part to an integer
  
  strtokIndx = strtok(NULL, ","); 
  floatFromPC = atof(strtokIndx);     // convert this part to a float

}


void showParsedData() {
 Serial.print("Message ");
 Serial.println(messageFromPC);
 Serial.print("Integer ");
 Serial.println(integerFromPC);
 Serial.print("Float ");
 Serial.println(floatFromPC);
}
⸮B⸮⸮⸮~<Arduino is ready>
Message This is a test
Integer 1234
Float 45.30

Exception (28):
epc1=0x402069fa epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000

>>>stack>>>

ctx: cont
sp: 3ffffd90 end: 3fffffc0 offset: 01a0
3fffff30:  00000000 3fdffec0 3ffe8020 3ffee3c4  
3fffff40:  40201194 3ffee35c 3ffe865e 402011a0  
3fffff50:  40201194 3ffee35c 3ffe865e 3ffee3c4  
3fffff60:  3fffdad0 00000000 3ffe8630 40206b54  
3fffff70:  00000000 00000000 3ffee35c 40204830  
3fffff80:  3fffdad0 00000000 3ffe8630 40201050  
3fffff90:  3fffdad0 00000000 3ffee384 40201121  
3fffffa0:  feefeffe feefeffe 3ffee384 40201cfc  
3fffffb0:  feefeffe feefeffe 3ffe8500 40100bd5  
<<<stack<<<

Good job with using code tags on your first post. :slight_smile:

strtok modifies the string passed to it by inserting nulls. The second time you try to parse it I think the esp is hanging as atoi() and atof() don't find anything to work on.

I ran your program on a WemosD1 and it showed the error. When I ran your program on a UNO, it rans without error, but the integer and float are reported as 0 after the first pass through loop(). I don't understand the difference between the two platforms.

Try to copy the message to a working string which gets modified. This change to parseData() does not hang on an the Wemos D1.

void parseData() {
  // split the data into its parts
  char copy_receivedChars[sizeof(receivedChars)] = "";
  strcpy(copy_receivedChars, receivedChars);
  char * strtokIndx; // this is used by strtok() as an index
  
  strtokIndx = strtok(copy_receivedChars,",");      // get the first part - the string
  strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
  
  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  integerFromPC = atoi(strtokIndx);     // convert this part to an integer
  
  strtokIndx = strtok(NULL, ",");
  floatFromPC = atof(strtokIndx);     // convert this part to a float

}

IMPRESSIVE!!! It Works!

Whats the differences between split the array(or string I don't know) directly and by passes to copy_receivedChars then split?

Why it's crashes on the ESP8266, when split it directly and it's ok on the UNO?

strtok() returns a pointer. If it is unable to find what you ask for, it will return NULL (i.e. - 0). You should ALWAYS verify it does NOT return NULL. You are not checking, so you pass those NULL pointers to atoi() and atof(), and they try to read from address 0, which, on the NODEMCU, is a memory access violation. On the Uno, it simply accesses address 0, which is NOT a memory access violation on the Uno, or any other AVR-based processor.

Regards,
Ray L.

Whats the differences between split the array(or string I don't know) directly and by passes to copy_receivedChars then split?

Good explanation here
https://wiki.sei.cmu.edu/confluence/display/c/STR06-C.+Do+not+assume+that+strtok()+leaves+the+parse+string+unchanged

The strtok() function parses the string up to the first instance of the delimiter character, replaces the character in place with a null byte ('\0'), and returns the address of the first character in the token.

Robin2 talks about this in his Serial input basics tutorial. and gives this code.

if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() used in parseData() replaces the commas with \0
        parseData();
        showParsedData();
        newData = false;
    }
"This is a test, 1234, 45.3"

Becomes

"This is a test\0 1234\0 45.3"

When you try and parse this again in loop() there are not comma delimiters to be found.

Why it's crashes on the ESP8266, when split it directly and it's ok on the UNO?

@RayLivingston has just explained it.

Your example is unusual in that you parse the same thing over and over in loop(). Typically you use strtok on a received message, and there is a new one each time.