Runtime Crashed In Arduino Nano

This is an application ran on Arduino Nano(ATmega328p Version),target to receive user id and WiFi Info by HC-05 Bluetooth Controller and use to connect WiFi by ESP8266 WiFi Controller, then send data to my server. But when it comes to the code “Php_Connected();”(Line 607), the Serial printed abnormal string and the arduino crashed。I used the lib “MemoryFree.h” to monitor available SRAM,but it shows that 1300b available,I thought that it shouldn’t be caused by runtime data outing,please help me to deal with the problem, thank you very much!

test.ino (21.7 KB)

I've not read all the code but this struck me:

SoftwareSerial ESP8266(2,3); // RX, TX    
SoftwareSerial HC05(10,11); // RX, TX

I see you use the listen() method from Two Port Receive example but wonder if you are not just missing out on what happens in the other Serial line then and loose data. As you don't really control when the WiFi module will talk back to you this might be a challenge.

if you look at the documentation for SoftwareSerial they mention

If your project requires simultaneous data flows, see Paul Stoffregen's AltSoftSerial library. AltSoftSerial overcomes a number of other issues with the core SoftwareSerial, but has it's own limitations. Refer to the AltSoftSerial site for more information.

have you explored this?

My recommendation as handling Serial is critical in your setup would be to get a Mega so that you can use multiple hardware Serial ports.

I am sure that when I listen on HC-05, nothing from ESP8266 will be sent to Arduino, so maybe there won't be any conflict between the two softwareSerials. So now the most serious problem is the crash on the "Serial.println();" function, do you have any idea on this point?

J-M-L:
I’ve not read all the code but this struck me:

SoftwareSerial ESP8266(2,3); // RX, TX    

SoftwareSerial HC05(10,11); // RX, TX




I see you use the `listen()` method from [Two Port Receive example](https://www.arduino.cc/en/Tutorial/TwoPortReceive) but wonder if you are not just missing out on what happens in the other Serial line then and loose data. As you don't really control when the WiFi module will talk back to you this might be a challenge.

if you look at the [documentation for SoftwareSerial](https://www.arduino.cc/en/Reference/SoftwareSerial) they mention
have you explored this?

My recommendation as handling Serial is critical in your setup would be to get a Mega so that you can use multiple hardware Serial ports.

I am sure that when I listen on HC-05, nothing from ESP8266 will be sent to Arduino, so maybe there won’t be any conflict between the two softwareSerials. So now the most serious problem is the crash on the “Serial.println();” function, do you have any idea on this point?

liangyugz:
it comes to the code “Php_Connected();”

You have:

    String GET_REQUEST="GET ";
    GET_REQUEST.concat(WEBSITE_VERIFY_ID);

… but WEBSITE_VERIFY_ID is in PROGMEM.

Yours,
TonyWilk

TonyWilk:
You have:

    String GET_REQUEST="GET ";

GET_REQUEST.concat(WEBSITE_VERIFY_ID);




... but WEBSITE_VERIFY_ID is in PROGMEM.

Yours,
TonyWilk

Thank you for your help TonyWilk, but it still didn't work, the application were still crashed in the same line.

//ESP8266 sender and receiver(return values)
String ESP8266_MsgTx2Rx(String Msg,int Delay,const char* const SignList[],bool DebugSign)
{
  char*Temp_Buffer;
  ESP8266.println(Msg);
  if(DebugSign){
    Serial.println(Msg);
  }
  delay(Delay);
  String ReturnMsg="";
  char LastReturnChar=0;
  Temp_Buffer=new char[1];
  //Temp_Buffer=Num
  strcpy_P(Temp_Buffer, (char*)pgm_read_word(&(SignList[0])));
  int SignListLength=atoi(Temp_Buffer);
  delete(Temp_Buffer);

  ...
  ...

Code like that l highly suspicious to me. Temp_Buffer is an array with one element. I'm not quite sure what your copying, but I suspect that it's more than one byte. And hence you touch memory that's not 'yours'. Undefined behaviour is the result.

There might be more code like that.

This code indeed

char*Temp_Buffer;
...
Temp_Buffer=new char[1];
...
strcpy_P(Temp_Buffer, (char*)pgm_read_word(&(SignList[0])));

Is definitely a memory overflow

Strcpy adds a null char at the end of the buffer, so even if you were reading only one byte, the function would copy 2 bytes in the buffer but this is all the more suspicious as whatever SignList[0] is, i doubt it points to an address of a cstring in memory, does it??

liangyugz:
it still didn’t work, the application were still crashed in the same line.

Have you fixed ALL the references to strings that are declared PROGMEM ?
e.g. with something like:

#define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))

    String GET_REQUEST="GET ";
    GET_REQUEST.concat(FPSTR(WEBSITE_VERIFY_ID));

There appears to be loads of strings declared with PROGMEM which you cannot treat like ordinary char * strings.
It may make things easier if you do not put string pointer arrays (like AT_GET_REQUEST) in PROGMEM.

Yours,
TonyWilk

TonyWilk:
Have you fixed ALL the references to strings that are declared PROGMEM ?
e.g. with something like:

#define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))

String GET_REQUEST="GET ";
    GET_REQUEST.concat(FPSTR(WEBSITE_VERIFY_ID));



There appears to be loads of strings declared with PROGMEM which you cannot treat like ordinary char * strings.
It may make things easier if you do *not* put string pointer arrays (like AT_GET_REQUEST) in PROGMEM.

Yours,
TonyWilk

TonyWilk:
Have you fixed ALL the references to strings that are declared PROGMEM ?
e.g. with something like:

#define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))

String GET_REQUEST="GET ";
    GET_REQUEST.concat(FPSTR(WEBSITE_VERIFY_ID));



There appears to be loads of strings declared with PROGMEM which you cannot treat like ordinary char * strings.
It may make things easier if you do *not* put string pointer arrays (like AT_GET_REQUEST) in PROGMEM.

Yours,
TonyWilk

Thank you for your answer! Since I am not familiar with functions like "#define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper >(pstr_pointer))
", I would like to ask one more question, how could I read PROGMEM when it comes to const char
char but not const char?

", I would like to ask one more question, how could I read PROGMEM when it comes to const char* char but not const char?

the question does not mean anything... (or I don't get it)

when you have data in PROGMEM, you can use these functions and you should explore the PROGMEM documentation

liangyugz:
I am not familiar with functions like “#define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))”

Methods like Serial.print() have been written to handle a number of different types as parameters like int, long, float and char * for strings. It can also retrieve strings held in PROGMEM, but to do that it has to have some indication that it is a PROGMEM char array and not a RAM char array - that is where the cast to __FlashStringHelper comes in. This allows you to do:

Serial.print(F("Write something on the Serial Monitor that is stored in FLASH"));

// and using the macro:
const char mystring[] PROGMEM ="Some other string that is stored in FLASH")); 
Serial.print(FPSTR(mystring));

how could I read PROGMEM when it comes to const char* char but not const char?

Your program has:

const char AT_GET_REQUEST_0[] PROGMEM="3";    
const char AT_GET_REQUEST_1[] PROGMEM="SEND OK";    
const char AT_GET_REQUEST_2[] PROGMEM="SEND FAIL";    
const char AT_GET_REQUEST_3[] PROGMEM="CLOSED";    
const char* const AT_GET_REQUEST[] PROGMEM={AT_GET_REQUEST_0,AT_GET_REQUEST_1,AT_GET_REQUEST_2,AT_GET_REQUEST_3};//"OK"<->"SEND OK","FAIL"<->"SEND FAIL"

Here the strings AND the array of pointers to those strings are in PROGMEM, so your function:

ESP8266_MsgTx2Rx(GET_REQUEST,200,AT_GET_REQUEST,true);

has to use the PROGMEM access function to get the pointer and then get the string.
It can be a lot simpler if the relatively small pointer array is NOT in PROGMEM like this:

// strings in PROGMEM
const char AT_GET_REQUEST_0[] PROGMEM="3";    
const char AT_GET_REQUEST_1[] PROGMEM="SEND OK";    
const char AT_GET_REQUEST_2[] PROGMEM="SEND FAIL";    
const char AT_GET_REQUEST_3[] PROGMEM="CLOSED";    
// pointer array NOT in PROGMEM:
const char* const AT_GET_REQUEST[] ={AT_GET_REQUEST_0,AT_GET_REQUEST_1,AT_GET_REQUEST_2,AT_GET_REQUEST_3};//"OK"<->"SEND OK","FAIL"<->"SEND FAIL"

// then a function call like:    

ESP8266_MsgTx2Rx(GET_REQUEST,200,AT_GET_REQUEST,true);

// can be implemented like:

String ESP8266_MsgTx2Rx(String Msg,int Delay,const char* const SignList[],bool DebugSign)
{
  const char *sp= SignList[2];  // get pointer to PROGMEM string from non-PROGMEM char * array
  char mybuff[20];
  // just print the string
  Serial.println(FPSTR(sp));
  // or extract the PROGMEM string to local buffer
  strncpy_P( mybuff, sp, sizeof(mybuff) );
  ...

Yours,
TonyWilk

TonyWilk:
Methods like Serial.print() have been written to handle a number of different types as parameters like int, long, float and char * for strings. It can also retrieve strings held in PROGMEM, but to do that it has to have some indication that it is a PROGMEM char array and not a RAM char array - that is where the cast to __FlashStringHelper comes in. This allows you to do:

Serial.print(F("Write something on the Serial Monitor that is stored in FLASH"));

// and using the macro:
const char mystring PROGMEM =“Some other string that is stored in FLASH”));
Serial.print(FPSTR(mystring));




Your program has:


const char AT_GET_REQUEST_0 PROGMEM=“3”;   
const char AT_GET_REQUEST_1 PROGMEM=“SEND OK”;   
const char AT_GET_REQUEST_2 PROGMEM=“SEND FAIL”;   
const char AT_GET_REQUEST_3 PROGMEM=“CLOSED”;   
const char* const AT_GET_REQUEST PROGMEM={AT_GET_REQUEST_0,AT_GET_REQUEST_1,AT_GET_REQUEST_2,AT_GET_REQUEST_3};//“OK”<->“SEND OK”,“FAIL”<->“SEND FAIL”



Here the strings AND the array of pointers to those strings are in PROGMEM, so your function:


ESP8266_MsgTx2Rx(GET_REQUEST,200,AT_GET_REQUEST,true);



has to use the PROGMEM access function to get the pointer and then get the string.
It can be a lot simpler if the relatively small pointer array is NOT in PROGMEM like this:


// strings in PROGMEM
const char AT_GET_REQUEST_0 PROGMEM=“3”;   
const char AT_GET_REQUEST_1 PROGMEM=“SEND OK”;   
const char AT_GET_REQUEST_2 PROGMEM=“SEND FAIL”;   
const char AT_GET_REQUEST_3 PROGMEM=“CLOSED”;   
// pointer array NOT in PROGMEM:
const char* const AT_GET_REQUEST ={AT_GET_REQUEST_0,AT_GET_REQUEST_1,AT_GET_REQUEST_2,AT_GET_REQUEST_3};//“OK”<->“SEND OK”,“FAIL”<->“SEND FAIL”

// then a function call like:

ESP8266_MsgTx2Rx(GET_REQUEST,200,AT_GET_REQUEST,true);

// can be implemented like:

String ESP8266_MsgTx2Rx(String Msg,int Delay,const char* const SignList,bool DebugSign)
{
  const char *sp= SignList[2];  // get pointer to PROGMEM string from non-PROGMEM char * array
  char mybuff[20];
  // just print the string
  Serial.println(FPSTR(sp));
  // or extract the PROGMEM string to local buffer
  strncpy_P( mybuff, sp, sizeof(mybuff) );
  …



Yours,
TonyWilk

thank you very much! It helped me to resolve my problems.