I have an Electron that I am using as a datalogger but it keeps being unable to publish data to the cloud after about 4 days. It is running with system threading enabled.
Right now I am using a function to build and return the string that I want to publish, but I believe it may be causing a memory fragmentation issue when the Electron is run for more than 4 days continuously. I was under the impression that this would not result in memory fragmentation since all of the dynamically allocated strings that are implicitly created when String::format()
is called get released when the function exits. Sure there is a big memory gap in the heap that dataEntry
is sitting on top of at the end, but dataEntry
gets released in short order once the function returns and the built string gets written to the cloud.
Here is my function as it stands:
String getStringForCloud){
//Stores the line string to be published to the Cloud
String dataEntry;
dataEntry += String(Time.now()) + ','; //Add the UNIX time stamp
//Add pv system data points
dataEntry += String::format("%6.2f,", pvDat.avgVoltage);
dataEntry += String::format("%6.2f,", pvDat.avgCurrent);
dataEntry += String::format("%6.2f,", pvDat.avgPower);
dataEntry += String::format("%6.2f,", pvDat.energy);
//Add BESS system data points
dataEntry += String::format("%6.2f,", bessDat.avgVoltage);
dataEntry += String::format("%6.2f,", bessDat.avgCurrent);
dataEntry += String::format("%6.2f,", bessDat.avgPower);
dataEntry += String::format("%6.2f,", bessDat.energy);
//Add MPPT system data points
dataEntry += String::format("%6.2f,", mpptDat.avgPower);
dataEntry += String::format("%6.2f,", mpptDat.energy);
//Add JazaPack system data points
dataEntry += String::format("%6.2f,", inverterDat.avgPower);
dataEntry += String::format("%6.2f,", inverterDat.energy);
//Add 12 V Load system data points
dataEntry += String::format("%6.2f,", loads12vDat.avgPower);
dataEntry += String::format("%6.2f,", loads12vDat.energy);
//Add Controller Load system data points
dataEntry += String::format("%6.2f,", controllerDat.avgPower);
dataEntry += String::format("%6.2f,", controllerDat.energy);
return dataEntry;
}
-
Is there a better/safer way to build this string?
-
Would calling
dataEntry.reserve(200)
at the beginning of this function be a way to safeguard against heap fragmentation? -
What about all the little String objects that are allocated as I build up
dataEntry
? Since I have system threading enabled, is it possible that the system firmware will dynamically allocate heap memory on top of these short-lived string building blocks before this function exits and frees them back to the heap, thus causing fragmentation? If this is the case, would it be better to simply replace the above code with a singleString::format()
call? Like this:dataEntry += String::format("%6.2f,%6.2f,%6.2f,%6.2f,%6.2f,%6.2f,%6.2f,%6.2f,%6.2f,%6.2f,%6.2f,%6.2f,%6.2f,%6.2f,%6.2f,%6.2f,", pvDat.avgVoltage, pvDat.avgCurrent, pvDat.avgPower, pvDat.energy, bessDat.avgVoltage, bessDat.avgCurrent, bessDat.avgPower, bessDat.energy, mpptDat.avgPower, mpptDat.energy, inverterDat.avgPower, inverterDat.energy, loads12vDat.avgPower, loads12vDat.energy, controllerDat.avgPower, controllerDat.energy);