Variable overflowed into another variable (Particle.publish and Particle.variable issue)

The issue occurs with 4 variables.

Char* sensor_info_var (Stores sensor information in char) 
String sensor_info_str (Stores sensor information converted from char* to str)
Char* RGB_info_var (Stores LED RGB information in char) 
String RGB_info_str (Stores LED RGB converted from char* to str)

Somehow during publishing, the information in “RGB_info_var” is overflowed into “sensor_info_var”

NOTE: There’re way more code involved and it’s impractical to post all the code. It’s probably very unlikely to fully diagnose with partial code but It would be great if anyone could provide me with an insight on what could cause this issue!


const uint8_t NUM_OF_RGBS = 2;
const uint8_t NUM_OF_ULTRASONICS = 2;
const uint8_t NUM_OF_DHTS = 3;
const uint8_t NUM_OF_FANS = 6;
const uint8_t NUM_OF_NTCS = 7;
const uint8_t SENSOR_PUB_INTERVAL = 10-1;


time_t last_timer_checkin_time = 0;


uint8_t curr_bt[2][4];
uint8_t curr_rgb[NUM_OF_RGBS][3];
double curr_hsv[NUM_OF_RGBS][3];

uint8_t fan_spd[NUM_OF_FANS];
uint16_t fan_rpm[NUM_OF_FANS];
double dist_to_plant[NUM_OF_ULTRASONICS];
double ntc_temp[NUM_OF_NTCS]; //[front_LED, main_LED, rear_LED, water, peltier, pcb]
double dht_temp[NUM_OF_DHTS];
double dht_rh[NUM_OF_DHTS];  	//[ambient, chamber, chamber_exit]


double PCBTemp = 0, AcColdTemp = 0, AcHeatTemp = 0, mainLEDTemp = 0, frontLEDTemp = 0, rearLEDTemp = 0;
int ac_status = 0;
int pump_spd = 0;
int day_length = 0, target_bt = 0, bt_fade_time = 0;
int airflow = 0;
int sunriseUnix = 0, sunsetUnix = 0;
double pltHeight = -1, frontPltHeight = -1, rearPltHeight = -1, waterTemp = -1, waterLvl = -1;
double chbTemp = -1, chbRH = -1, ambTemp = -1, ambRH = -1;


char *sensor_info_var = new char[512];
char *RGB_info_var = new char[64];
char *phase_info_var = new char[256];
String sensor_info_str = "{\"Not Available\": \"N/A\"}";
String phase_info_str = "{\"Not Available\": \"N/A\"}";
String RGB_info_str = "{\"Not Available\": \"N/A\"}";

void setup(){

  Particle.variable("sensor_info_str", sensor_info_str);
  Particle.variable("phase_info_str", phase_info_str);
  Particle.variable("RGB_info_str", RGB_info_str);


}
void publishSensorInfo() {

    Particle.publish("sensor_info", sensor_info_var, PRIVATE);
}

void update_senser();
	// Updates all sesnor Info;
}

void loop(){
	curr_time = Time.now();
	update_senser();
	sprintf(sensor_info_var, "{ \"fBTw\": %d, \"mBTw\": %d, \"rBTw\": %d, \
                \"fBTc\": %d, \"mBTc\": %d, \"rBTc\": %d, \
                \"af\": %d,  \"wLvl\": %.1f, \"fHt\": %.1f, \"rHt\": %.1f,\
                \"fTemp\": %.1f, \"mTemp\": %.1f,\"rTemp\": %.1f,\
                \"wTemp\": %.1f, \"acHtTemp\": %.1f,\"acCdTemp\": %.1f,\"pcbTemp\": %.1f,\
                \"aTemp\": %.1f, \"cTemp\": %.1f,\"ceTemp\": %.1f,\
                \"aRH\": %.1f, \"cRH\": %.1f, \"ceRH\": %.1f,\
                \"inFanS\": %d, \"outFanS\": %d,\"acFanS\": %d,\"vFanS\": %d,\
                \"GlsClr\": %d, \"AcStat\": %d, \"pumpSpd\": %d}",
                curr_bt[WARM_LED][FRONT_LED], curr_bt[WARM_LED][MAIN_LED], curr_bt[WARM_LED][REAR_LED],
                curr_bt[COLD_LED][FRONT_LED], curr_bt[COLD_LED][MAIN_LED], curr_bt[COLD_LED][REAR_LED],
                airflow, waterLvl, dist_to_plant[0], dist_to_plant[1],
                ntc_temp[FRONT_LED_TEMP], ntc_temp[MAIN_LED_TEMP], ntc_temp[REAR_LED_TEMP],
                ntc_temp[WATER_TEMP], ntc_temp[AC_HEAT_TEMP], ntc_temp[AC_COLD_TEMP], ntc_temp[PCB_TEMP],
                dht_temp[0], dht_temp[1], dht_temp[2],
                dht_rh[0], dht_rh[1], dht_rh[2],
                fan_spd[ELEC_IN_FAN], fan_spd[ELEC_OUT_FAN], fan_spd[CHB_AC_FAN], fan_spd[VENT_FAN],
                eglass_tp, ac_status, pump_spd);
    sensor_info_str = String(sensor_info_var);
	
    sprintf(RGB_info_var, "{\"TRGB\": \"%02X%02X%02X\", \"FRGB\": \"%02X%02X%02X\",\
              \"THSV\": \"%.0f,%.2f,%.2f\", \"FHSV\": \"%.0f,%.2f,%.2f\"}",
              curr_rgb[TOP_RGB][0], curr_rgb[TOP_RGB][1], curr_rgb[TOP_RGB][2],
              curr_rgb[FRONT_RGB][0], curr_rgb[FRONT_RGB][1], curr_rgb[FRONT_RGB][2],
              curr_hsv[TOP_RGB][0], curr_hsv[TOP_RGB][1], curr_hsv[TOP_RGB][2],
              curr_hsv[FRONT_RGB][0], curr_hsv[FRONT_RGB][1], curr_hsv[FRONT_RGB][2]);
    RGB_info_str = String(RGB_info_var);

	if (curr_time - lastSensorInfoPub > SENSOR_PUB_INTERVAL){
      publishSensorInfo();
      lastSensorInfoPub = curr_time;
    }
}

Sound like you have variable boundary problems most likely the cause of your hard fault problems. Use snprintf (which takes the array length as an argument) in place of sprintf to be safer. Otherwise, you need to be absolutely sure that you never write more to the char array than you have length for (in your case 512 characters.)

1 Like

Thank you! It seems like it solved the problem.
I do have I more question on using methods such as sprintf();
Example:

    sprintf(sensor_info_var, "{ \"test1\": %d, \"test2\": %d, \
                                             \"test3\": %d, \"test4\": %d},
                                              1,                 2,               
                                              3,                 4);

printf("sensor_info_var");

I want to obtain the following result :
“test1”: 1, “test2”: %d, “test3”: 3, “test4”: 4

However what I get is:
“test1”: 1, “test2”: %d, (8 spaces) “test3”: 3, “test4”: 4

What is the appropriate format specifier that I should use to have a space instead of tab between “test2”: %d and “test3”: 3. Would like to keep the first and second lines separate for the ease of viewing.

Thank you!

You can use string concatenation in the preprocessor. So "ABC" "DEF" gets turned into"ABCDEF". This can allow you to break up your string into multiple shorter strings that will get pasted together and treated as one without weird embedded whitespace.

Thank you!

Could you be clearer about exactly what format of output you are after?
There appears to be a stray \ after the test2 %d? And a missing " after test4? I have added - suggest you look at the c format syntax to see how to format using the %flags.

snprintf(sensor_info_var, sizeof(sensor_info_var), "{ \"test1\": \"%d\",\"test2\":\"%d\",\"test3\":\"%d\", \"test4\": \"%d\"}",1,  2,  3,  4);

@armor, I think @roger_mary was after a way to break up a long format string over multiple lines.
And I think this is what @joel was trying to say (transformed into @roger_mary’s example)

     snprintf(sensor_info_var
             , sizeof(sensor_info_var)
             , "{ \"test1\": %d, \"test2\": %d"
               ", \"test3\": %d, \"test4\": %d}"
             ,          1,             2               
             ,          3,             4
             );

any two string literals that follow eachother will be “stitched together” as if they were written as one.
e.g.
"ABC" /*...some whitespace, comment or other non-C token...*/ "DEF"
will be treated by the compiler just the same as
"ABCDEF"

1 Like

WOW, Amazing explanation! That’s exactly what I meant.
Thank you!

1 Like