Boron EEPROM Assertion Failure

Hi all,

below i have attached some code i have for a school project. i have a temp sensor actively reading and have hardcoded the measurements for now. If you want to try the code just comment out the sampling parts and hard code a temperature in. Anyways i am trying to use the EEPROM to store a sample from a time period then retrieve it and print it. once it prints my device has assertion failure. Not sure why… any help?
Thanks

int Temp = A2; // This is where your photoresistor is plugged in. The other side goes to the "power" pin (below).
float TempIn; // Here we are declaring the integer variable analogvalue, which we will use later to store the value of the photoresistor.
float CT1Average = 35.55;
float CT1Maximum = 45;
float CT2Average = 47.55;
float CT2Maximum = 55;
int numMarkedData = 0;
int count = 0;

class markedData {
   private:
   float CT1Average1, CT1Maximum1, CT2Average1, CT2Maximum1, TempIn1;
   String MeasTime;
   public:
   //Constructor for object 
   markedData(float CT1AverageIn, float CT1MaximumIn, float CT2AverageIn, float CT2MaximumIn, float TempIn, String MeasTimeIn){
       CT1Average1 = CT1AverageIn;
       CT1Maximum1 = CT1MaximumIn;
       CT2Average1 = CT2AverageIn;
       CT2Maximum1 = CT2MaximumIn;
       TempIn1 = TempIn;
       MeasTime = MeasTimeIn;
   }
   //get method for retrieving CT1 Average
   float getCT1A (){
       return CT1Average1;
   }  
   
   //get method for retrieving CT1 Maximum
   float getCT1M (){
       return CT1Maximum1;
   }  
   
   //get method for retrieving CT2 Average
   float getCT2A (){
       return CT2Average1;
   }  
   //get method for retrieving CT2 Maximum
   float getCT2M (){
       return CT2Maximum1;
   }  
   //get method for retrieving Temperature
   float getTemp (){
       return TempIn1;
   }  
       //get method for retrieving the time of measurement
   String getTime (){
       return MeasTime;
   }  
};

// Next we go into the setup function.
void setup() {
 pinMode(Temp, INPUT);
 Serial.begin(9600);
 Particle.subscribe("hook-response/Device Data", myHandler, MY_DEVICES);
 Time.zone(-4);
}

void loop() {
   TempIn = ((analogRead(Temp)*0.0008)*100)-273.15;
   Serial.printf("Temperature = %.2f \n \r", TempIn);
   String MeasTime = Time.timeStr();
   
   String Measurements = (String::format("%.2f,%.2f,%.2f,%.2f,%.2f", CT1Average, CT1Maximum, CT2Average, CT2Maximum, TempIn))+","+MeasTime;
   markedData Measurement (CT1Average, CT1Maximum, CT2Average, CT2Maximum, TempIn, MeasTime);
   
   size_t AvailableLength = EEPROM.length();
   
   Serial.println(Measurements);
   
   String MeasurementsObject = (String::format("%.2f,%.2f,%.2f,%.2f,%.2f", Measurement.getCT1A(), Measurement.getCT1M(), Measurement.getCT2A(), Measurement.getCT2M(), Measurement.getTemp()))+","+Measurement.getTime();
   Serial.println(MeasurementsObject);
   
   Serial.println(AvailableLength);
   
   while(numMarkedData<2){
       EEPROM.put(numMarkedData, Measurement);
       numMarkedData=numMarkedData + 1;;
   }
   markedData value(0,0,0,0,0,Time.timeStr());
   if (count ==0){
       EEPROM.get(1,value);
       count++;
   }
   Serial.println(value.getCT1A());
   Serial.println(value.getCT1M());
   Serial.println(value.getCT2A());
   Serial.println(value.getCT2M());
   Serial.println(value.getTemp());
   Serial.println(value.getTime());
   //delay 1 second every 1000
    delay(10000);
}

void myHandler(const char *event, const char *data) {
 // Handle the integration response
}

I also am printing everything to a PuTTy terminal!

From my troubleshooting so far i believe that once the main loop completes itself once, it will not restart.

That's not how the device OS works.
loop() will always iterate unless you actively prevent it from doing so (e.g. deadlocking or hard-blocking somewhere).

I also don't think your subscription is right (apart from being superfluous as the handler doesn't do anything).
Since an event that would trigger the webhook that you expect to give you the response should not contain blanks, I very much doubt that a response message would then contain a "disallowed" blank either.
https://docs.particle.io/reference/device-os/firmware/boron/#particle-publish-

I'd also advise against the use of String and rather use C-strings (aka character arrays).
e.g. EEPROM will not store content of a String object as that is not actually held in the object but on the heap and only referenced by a pointer in the object.
By the time you are getting the stored data back from EEPROM the original memory block on the heap must be considered invalid and any pointer to it (i.e. the one held in the previously stored String object) cannot be trusted.

You are also always reading from address 1 but putting the data into other locations - staring with 0.
Furthermore you are only incrementing by one byte each iteration but your stored data occupies more than one byte resuliting in corrupting previously stored data as you overwrite all but the first of these previously stored bytes.

BTW, if you regularly want to print the contents of your markedData objects it would be good practice to donate it a toString() method.
Additionally providing a default constructor (markedData()) makes constructing zero initialised objects easier and is also considered better practice.
I'd also not store MeasTime as string but as raw numeric value (int in this case), you can always convert it into the desired string representation in a dedicated getter function which can (should?) use Time.format(MeasTime). This way you hand the full authority over the desired format to the user of the class and don't impose your (creator of the class) preference on it.
Even if your are taking both roles it's a good habit to mentally separate these two roles when you lay out your code. This will help you in case you'd ever happen to work on a bigger project together with multiple developers for a third party customer.

BTW²: What are these trailing 1 on all your private variables for? That seems very redundant.

Hi ScruffR thanks for the very detailed response. Yes this code is far from correct i just created it quickly outside of my main program to get this EEPROM data storage working. I have since been able to get it working by using time as an integer.

In the main i will no doubt be using a tostring method and the trailing 1s yeah good question, no use.

Again Thanks

Good to know :+1:

You can have a look at this

1 Like