Low memory available Stability problems may occur.. Help Please!!!

I'm getting low memory error. Please help me to optimize my code. Here is my code:

namespace {
  const char * USER_AGENT = "UbidotsESP8266"; // Assgin the user agent
  const char * VERSION =  "1.0"; // Assign the version 
  const char * METHOD = "POST"; // Set the method
  const char * TOKEN = "assign_your_ubidots_token"; // Assign your Ubidots TOKEN
  const char * DEVICE_NAME = "telemetry"; // Assign the desire device name 
  const char * DEVICE_LABEL = "ESP8266"; // Assign the device label 
  const char * VARIABLE_LABEL_1 = "temperature"; // Assign the variable label 
  const char * VARIABLE_LABEL_2 = "heartrate"; // Assign the variable label
  const char * VARIABLE_LABEL_3 = "bloodpressure"; // Assign the variable label

}

char first_command[700]; // command
char second_command[700];
char telemetry_unit[100]; // response of the telemetry unit

/* Space to store values to send */
char str_sensor1[10];
char str_sensor2[10];
char str_sensor3[10];

/****************************************
 * Main Functions
 ****************************************/ 
void setup() {
  Serial.begin(115200);
  Serial1.begin(115200);
}

void loop() {

  /* Analog reading */ 
  float sensor1 = analogRead(A0);
  float sensor2 = analogRead(A1);
  float sensor3 = analogRead(A2);
  
  /* 4 is mininum width, 2 is precision; float value is copied onto str_sensor*/
  dtostrf(sensor1, 4, 2, str_sensor1);
  dtostrf(sensor2, 4, 2, str_sensor2);
  dtostrf(sensor3, 4, 2, str_sensor3);

  /* Building first the logger command */ 
  sprintf(first_command, "init#");
  sprintf(first_command, "%s%s/%s|%s|%s|", first_command, USER_AGENT, VERSION, METHOD, TOKEN);
  sprintf(first_command, "%s%s:%s=>", first_command, DEVICE_NAME, DEVICE_LABEL);
  sprintf(first_command, "%s%s:%s", first_command, VARIABLE_LABEL_1, str_sensor1);
  sprintf(first_command, "%s,%s:%s", first_command, VARIABLE_LABEL_2, str_sensor2); // uncomment this line to send sensor 2 values
  sprintf(first_command, "%s|end#final", first_command);

  /* Prints the command sent */
  //Serial.println(first_command);// uncomment this line to print the command
  
  /* Sends the command to the telemetry unit */
  Serial1.print(first_command);

  /* Reading the telemetry unit */
  int i = 0;
  while (Serial1.available() > 0) {
    telemetry_unit[i++] = (char)Serial1.read(); 
  }
  Serial.println(telemetry_unit);
  i = 0;
  
  delay(1000);
  
  /* Building the second logger command */ 
  sprintf(second_command, "init#");
  sprintf(second_command, "%s%s/%s|%s|%s|", second_command, USER_AGENT, VERSION, METHOD, TOKEN);
  sprintf(second_command, "%s%s:%s=>", second_command, DEVICE_NAME, DEVICE_LABEL);
  sprintf(second_command, "%s%s:%s", second_command, VARIABLE_LABEL_3, str_sensor3);
  sprintf(second_command, "%s|end#final", second_command);

  /* Prints the command sent */
  //Serial.println(second_command);// uncomment this line to print the command
  
  /* Sends the command to the telemetry unit */
  Serial1.print(second_command);

  /* Reading the telemetry unit */
  while (Serial1.available() > 0) {
    telemetry_unit[i++] = (char)Serial1.read(); 
  }
  Serial.println(telemetry_unit);
  i = 0;

  delay(5000);
}

Please help me to optimize it is just testing code i have other variables too that i haven't used in this sketch (like lm35 code, heart rate code and their variables) please help me out

Two things pop out at me right off for saving RAM in your sketch.

  1. all constant strings should be stored in and printed from flash ram.

  2. your use of sprintf() to create full-size strings that you then feed to serial... just don't!

As for 1), Key word is PROGMEM. You can store many KB there if your sketch, including libraries, isn't huge.

For 2).........

Serial even at 115200 baud (11520 chars/sec, 868 micros, almost 14000 cpu cycles to send 1 char) is not nearly so fast that you have to assemble your whole data before sending. Your text goes into a 64 byte buffer fast enough to fill it in less than 100 micros.

  sprintf(first_command, "init#");
  sprintf(first_command, "%s%s/%s|%s|%s|", first_command, USER_AGENT, VERSION, METHOD, TOKEN);
  sprintf(first_command, "%s%s:%s=>", first_command, DEVICE_NAME, DEVICE_LABEL);
  sprintf(first_command, "%s%s:%s", first_command, VARIABLE_LABEL_1, str_sensor1);
  sprintf(first_command, "%s,%s:%s", first_command, VARIABLE_LABEL_2, str_sensor2); // uncomment this line to send sensor 2 values
  sprintf(first_command, "%s|end#final", first_command);

If you break this up into pieces and print those, it will look exactly the same at the receiving end. Exactly the same chars sent at the same speed.

Print the PROGMEM text in separate lines using the print from PROGMEM methods provided or code all of that text as print lines that use the F() macro and you won't need to make PROGMEM lines since F() does it.

Don't buffer what you don't have to. You don't have room for such conveniences.

And apart from that, congrats on not using String! It would crash even sooner!

Lastly, take some time to learn to code without delay() and other blocking code. Once you do learn, you will regret the time spent putting it off!

Just breaking up the transmission printing and getting rid of those buffers should get you running.

GoForSmoke:
Two things pop out at me right off for saving RAM in your sketch.

  1. all constant strings should be stored in and printed from flash ram.

  2. your use of sprintf() to create full-size strings that you then feed to serial... just don't!

As for 1), Key word is PROGMEM. You can store many KB there if your sketch, including libraries, isn't huge.

For 2).........

Serial even at 115200 baud (11520 chars/sec, 868 micros, almost 14000 cpu cycles to send 1 char) is not nearly so fast that you have to assemble your whole data before sending. Your text goes into a 64 byte buffer fast enough to fill it in less than 100 micros.

  sprintf(first_command, "init#");

sprintf(first_command, "%s%s/%s|%s|%s|", first_command, USER_AGENT, VERSION, METHOD, TOKEN);
  sprintf(first_command, "%s%s:%s=>", first_command, DEVICE_NAME, DEVICE_LABEL);
  sprintf(first_command, "%s%s:%s", first_command, VARIABLE_LABEL_1, str_sensor1);
  sprintf(first_command, "%s,%s:%s", first_command, VARIABLE_LABEL_2, str_sensor2); // uncomment this line to send sensor 2 values
  sprintf(first_command, "%s|end#final", first_command);




If you break this up into pieces and print those, it will look exactly the same at the receiving end. Exactly the same chars sent at the same speed.

Print the PROGMEM text in separate lines using the print from PROGMEM methods provided or code all of that text as print lines that use the F() macro and you won't need to make PROGMEM lines since F() does it.

Don't buffer what you don't have to. You don't have room for such conveniences.

And apart from that, congrats on not using String! It would crash even sooner!

Lastly, take some time to learn to code without delay() and other blocking code. Once you do learn, you will regret the time spent putting it off!

I'm using Ubidots Library and the code that i have posted was the example posted by Ubidots. Would you please share some edited code that can help me out?

Please share some edited code so that i can better understand what you are saying.

What do you understand about the code you grabbed?

What board are you using? Ubidots is for ESP8266 that has over 64K RAM, that sketch wouldn't have low memory in 64K.

I can't test anything I'd give you and I'd only do that first block I showed, could you take it from there or just be puzzled?
I might be back in a short while but it's getting late here, no long explanations.

GoForSmoke:
What do you understand about the code you grabbed?

What board are you using? Ubidots is for ESP8266 that has over 64K RAM, that sketch wouldn't have low memory in 64K.

I can't test anything I'd give you and I'd only do that first block I showed, could you take it from there or just be puzzled?
I might be back in a short while but it's getting late here, no long explanations.

Yes ubidots is for ESP8266 but i'm using their serial library. I don't know how to optimize my code i didn't got you because i'm new on Arduino

Anyone else knows please help me here.. sprintf commands are taking too much space i think so because when i removed second_command logger it uploaded and it was using 67% of dynamic memory when i uncomment the second_command then it gives error..
Anyone here to help me out?

So, as asked, which board are you actually using?

To reduce memory footprint, reduce the size of your buffers; do you really need 700 bytes for each?

It also does not look like you use first_command and second_command at the same time, so you can get rid of one if I'm right.

sterretje:
So, as asked, which board are you actually using?

To reduce memory footprint, reduce the size of your buffers; do you really need 700 bytes for each?

It also does not look like you use first_command and second_command at the same time, so you can get rid of one if I'm right.

I'm using Arduino UNO and ESP8266-01 is attached with arduino UNO.. UNO is getting values from sensors and sending it to ESP8266-01 via software serial and then ESP8266-01 sends data to UBIDOTS. I can send only 2 variables at a time so that's why i created 2 commands first command will send 2 variables values and the 2nd command wil send the 3rd variable value

Remove the second_command variable; change all references in the code to it to first_command. Compile and you have gained 700 bytes; it's sufficient to get rid of the warning.

Also count the maximum size of the data that you want to send and adjust first_command accordingly.

You also don't have to put everything in a single buffer; you can send half of it followed by the second half; or whatever suits you, divide by 3 or 4 or ...

As indicated by @GoForSmoke, move everything in the namespace to PROGMEM and you can again gain.

sterretje:
You also don't have to put everything in a single buffer; you can send half of it followed by the second half; or whatever suits you, divide by 3 or 4 or ...

What does it mean? Would you please highlight the code where change is required??

You can change

  sprintf(first_command, "init#");
  sprintf(first_command, "%s%s/%s|%s|%s|", first_command, USER_AGENT, VERSION, METHOD, TOKEN);
  sprintf(first_command, "%s%s:%s=>", first_command, DEVICE_NAME, DEVICE_LABEL);
  sprintf(first_command, "%s%s:%s", first_command, VARIABLE_LABEL_1, str_sensor1);
  sprintf(first_command, "%s,%s:%s", first_command, VARIABLE_LABEL_2, str_sensor2); // uncomment this line to send sensor 2 values
  sprintf(first_command, "%s|end#final", first_command);

  Serial1.print(first_command);

to

Serial1.print(F("init#")); // F macro places "init#" in PROGMEM
Serial1.print(USER_AGENT);
Serial1.print(VERSION)
Serial1.print(METHOD)
...
...

I will type this slowly to help

I could spend an hour breaking down that first command build up into a series of print statements but you would just come back with "I don't understand" that after a few times posted here gets read as "do it for me".

You're not dishonest, you just grabbed code that you have no clue about and want help to get it working where your part is "don't understand" rather than "where can I learn this stuff?".

Maybe there's an Ubidot forum where this very issue already has working, tested answers.

I am not going to walk anyone through changes to their code when they can't walk through the code as it is.
The reason is simple. I KNOW how long debugging it all can take and I KNOW that I will have to do 100% of it alone.

If you have a close deadline then get someone to do it for you.
If you don't then work on learning the code you grabbed starting with every bit you don't recognize.

I see that sterretje has done a partial of what I might have. Can't wait to see the reply!

Yes!! I'm new on arduino platform and i have few days left till deadline of my project that is why i was asking for help because i wasn't able to get idea how i can modify the commands that are built in by Ubidots. I have also posted a question but i got no help from there. I will try to put my command in Serial.pint and will check it works or not

"A few days before the deadline" is not the right time to start trying to understand and modify a complex sketch like this when you don't have the first clue about how it works. Even for me, I would want a couple of weeks to allow for study, testing, and debugging. If you think you can finish it quickly, the 90-90 rule* will bite you on the ass.

First of all, you can't be using an Arduino Uno because this will not compile for it. An Uno does not have Serial1. You've got something else, probably a Leonardo or Micro.

Second:

  sprintf(first_command, "init#");
  sprintf(first_command, "%s%s/%s|%s|%s|", first_command, USER_AGENT, VERSION, METHOD, TOKEN);
  sprintf(first_command, "%s%s:%s=>", first_command, DEVICE_NAME, DEVICE_LABEL);
  sprintf(first_command, "%s%s:%s", first_command, VARIABLE_LABEL_1, str_sensor1);
  sprintf(first_command, "%s,%s:%s", first_command, VARIABLE_LABEL_2, str_sensor2); // uncomment this line to send sensor 2 values
  sprintf(first_command, "%s|end#final", first_command);

  Serial1.print(first_command);

Will this even work the way you want it too? I think it might in this case, but a self-referential print command like that just doesn't sit right with me. Since you're just appending each part of the command piecemeal and sending it all out at once, just send out each individual portion of the command as you make it. Then your buffer doesn't need to be so big. Reducing the size of the first_command and second_command buffers will greatly reduce your memory usage.

Why do you even have two buffers anyway? You don't use the command again after you send it, so just use a single command buffer.

  • The first 90% of code takes 90% of the development time. The remaining 10% of code also takes 90% of the development time. Also consider Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.

Instead of building the text and then printing, simply print the parts in order and get rid of those 700 char arrays.

Or if that's too hard then just cut the waste in half:

namespace {
  const char * USER_AGENT = "UbidotsESP8266"; // Assgin the user agent
  const char * VERSION =  "1.0"; // Assign the version
  const char * METHOD = "POST"; // Set the method
  const char * TOKEN = "assign_your_ubidots_token"; // Assign your Ubidots TOKEN
  const char * DEVICE_NAME = "telemetry"; // Assign the desire device name
  const char * DEVICE_LABEL = "ESP8266"; // Assign the device label
  const char * VARIABLE_LABEL_1 = "temperature"; // Assign the variable label
  const char * VARIABLE_LABEL_2 = "heartrate"; // Assign the variable label
  const char * VARIABLE_LABEL_3 = "bloodpressure"; // Assign the variable label

}

char first_command[700]; // command <----------- a waste, really. it looks like PC IT code
//  char second_command[700];   <<============= this is wasted RAM doubled
char telemetry_unit[100]; // response of the telemetry unit

/* Space to store values to send */
char str_sensor1[10];
char str_sensor2[10];
char str_sensor3[10];

/****************************************
 * Main Functions
 ****************************************/
void setup() {
  Serial.begin(115200);
  Serial1.begin(115200);
}

void loop() {

  /* Analog reading */
  float sensor1 = analogRead(A0);
  float sensor2 = analogRead(A1);
  float sensor3 = analogRead(A2);
 
  /* 4 is mininum width, 2 is precision; float value is copied onto str_sensor*/
  dtostrf(sensor1, 4, 2, str_sensor1);
  dtostrf(sensor2, 4, 2, str_sensor2);
  dtostrf(sensor3, 4, 2, str_sensor3);

  /* Building first the logger command */
  sprintf(first_command, "init#");
  sprintf(first_command, "%s%s/%s|%s|%s|", first_command, USER_AGENT, VERSION, METHOD, TOKEN);
  sprintf(first_command, "%s%s:%s=>", first_command, DEVICE_NAME, DEVICE_LABEL);
  sprintf(first_command, "%s%s:%s", first_command, VARIABLE_LABEL_1, str_sensor1);
  sprintf(first_command, "%s,%s:%s", first_command, VARIABLE_LABEL_2, str_sensor2); // uncomment this line to send sensor 2 values
  sprintf(first_command, "%s|end#final", first_command);

  /* Prints the command sent */
  //Serial.println(first_command);// uncomment this line to print the command
 
  /* Sends the command to the telemetry unit */
  Serial1.print(first_command);

  /* Reading the telemetry unit */
  int i = 0;
  while (Serial1.available() > 0) {
    telemetry_unit[i++] = (char)Serial1.read();
  }
  Serial.println(telemetry_unit);
 
  for ( i = 0; i < 700; i++ )
  {
    first_command[ i ] = 0;
  }

  i = 0;

  delay(1000);
 
  /* Building the second logger command */
  sprintf(first_command, "init#");
  sprintf(first_command, "%s%s/%s|%s|%s|", first_command, USER_AGENT, VERSION, METHOD, TOKEN);
  sprintf(first_command, "%s%s:%s=>", first_command, DEVICE_NAME, DEVICE_LABEL);
  sprintf(first_command, "%s%s:%s", first_command, VARIABLE_LABEL_3, str_sensor3);
  sprintf(first_command, "%s|end#final", first_command);

  /* Prints the command sent */
  //Serial.println(first_command);// uncomment this line to print the command
 
  /* Sends the command to the telemetry unit */
  Serial1.print(first_command);

  /* Reading the telemetry unit */
  while (Serial1.available() > 0) {
    telemetry_unit[i++] = (char)Serial1.read();
  }
  Serial.println(telemetry_unit);
  i = 0;

  delay(5000);
}

If this saves you and you don't get down to learning then it will only be a hole you don't climb out of, future assignments will build on concepts you won't have a clue about. It is not a save, only a short reprieve.

Jiggy-Ninja:
"A few days before the deadline" is not the right time to start trying to understand and modify a complex sketch like this when you don't have the first clue about how it works. Even for me, I would want a couple of weeks to allow for study, testing, and debugging. If you think you can finish it quickly, the 90-90 rule* will bite you on the ass.

First of all, you can't be using an Arduino Uno because this will not compile for it. An Uno does not have Serial1. You've got something else, probably a Leonardo or Micro.

Second:

  sprintf(first_command, "init#");

sprintf(first_command, "%s%s/%s|%s|%s|", first_command, USER_AGENT, VERSION, METHOD, TOKEN);
  sprintf(first_command, "%s%s:%s=>", first_command, DEVICE_NAME, DEVICE_LABEL);
  sprintf(first_command, "%s%s:%s", first_command, VARIABLE_LABEL_1, str_sensor1);
  sprintf(first_command, "%s,%s:%s", first_command, VARIABLE_LABEL_2, str_sensor2); // uncomment this line to send sensor 2 values
  sprintf(first_command, "%s|end#final", first_command);

Serial1.print(first_command);



Will this even work the way you want it too? I think it might in this case, but a self-referential print command like that just doesn't sit right with me. Since you're just appending each part of the command piecemeal and sending it all out at once, just send out each individual portion of the command as you make it. Then your buffer doesn't need to be so big. Reducing the size of the first_command and second_command buffers will greatly reduce your memory usage.

Why do you even have two buffers anyway? You don't use the command again after you send it, so just use a single command buffer.

* The first 90% of code takes 90% of the development time. The remaining 10% of code also takes 90% of the development time. Also consider Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.

It's code for the ESP8266 lifted from Ubidots and I expect is missing some #includes to begin with.
The OP is clueless and days from a deadline. I wonder if the teacher won't notice, I'd laugh but I've seen many as bad.

It compiles as-is when I set the board to Mega or Leonardo. It has the memory stability message with the Leonardo.