EEPROM not returning values correctly

Disclamer: I am new to using this forum, so if there is anything I've done improperly, I'd love to know. Thanks.

Hi. I am having a problem trying to write some values to my arduino's EEPROM, and then get last few values to print on the serial monitor when I unplug the arduino, and plug it back in (the last 200 values before unplugging are to be printed when plugged back in). However, my code is not returning the values that I am intending to have returned.

The variable I'm doing this with is called accelMag, and the values that are printed to the serial monitor when I print the accelMag are right around 1.00 or 0.99. However, this is what I'm getting from the EEPROM:

Screen Shot 2023-03-06 at 3.44.27 PM

This is the part of my code that is using the EEPROM:

void rememberData() { // goal is to write last 200 accelMag values to the EEPROM, adress 0-199
  if (adress < 200) { // adress starts at zero, add one for each time
    EEPROM.put(adress, accelMag); // accelMag should be a float
    ++adress;
  }
  else { // if have already written to 200 adresses, go back and update 
   adress2 = adress%200; // if adress is above 200, I want to update the adress 200 below it with the current value (only writing to first 200 adresses)
    EEPROM.put(adress2, accelMag); // accelMag should be a float
    ++adress;
  }
}

void readEEPROM() { // printing past values of EEPROM before starting to record new values
  while (number < 200) { // only for adresses that were written to
    EEPROM.get(number, adressValue); // adressValue is the value (float) written at the adress "number" (adress 0-199)
    Serial.println(adressValue); // print each value from written adresses
    ++number;
 }
}

If there is anything you need to know about the entire code, here is an explanation of the project and the full code compiled.

I am using an arduino uno to make a project where a MPU-6050 is being used to work with values from its accelerometer. I am trying to get the total magnitude vector of the linear acceleration, and store it to the EEPROM of the board, so that if I use the board with a battery, when I plug it back into my computer, I can see the last 200 magnitudes of the total linear accelerations.

If there are any areas in this code that could be improved, or you have a better idea of how to remember the last 200 accelMag values and print them when the board is plugged back in, please let me know. I am new to coding arduino.

Full Code:

#include <Wire.h>
#include <EEPROM.h>

long accelX, accelY, accelZ;
float gForceX, gForceY, gForceZ;

float accelMag; //maxAccel

int adress = 0, adress2;
int number = 0;
float adressValue;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  setupMPU();
  readEEPROM();
}


void loop() {
  recordAccelRegisters();
  calcMag();
  rememberData();
  printData();
  delay(50);
}

void setupMPU(){
  Wire.beginTransmission(0b1101000); //This is the I2C address of the MPU (b1101000/b1101001 for AC0 low/high datasheet sec. 9.2)
  Wire.write(0x6B); //Accessing the register 6B - Power Management (Sec. 4.28)
  Wire.write(0b00000000); //Setting SLEEP register to 0. (Required; see Note on p. 9)
  Wire.endTransmission();  
  Wire.beginTransmission(0b1101000); //I2C address of the MPU
  Wire.write(0x1B); //Accessing the register 1B - Gyroscope Configuration (Sec. 4.4) 
  Wire.write(0x00000000); //Setting the gyro to full scale +/- 250deg./s 
  Wire.endTransmission(); 
  Wire.beginTransmission(0b1101000); //I2C address of the MPU
  Wire.write(0x1C); //Accessing the register 1C - Acccelerometer Configuration (Sec. 4.5) 
  Wire.write(0b00000000); //Setting the accel to +/- 2g
  Wire.endTransmission(); 
}

void recordAccelRegisters() {
  Wire.beginTransmission(0b1101000); //I2C address of the MPU
  Wire.write(0x3B); //Starting register for Accel Readings
  Wire.endTransmission();
  Wire.requestFrom(0b1101000,6); //Request Accel Registers (3B - 40)
  while(Wire.available() < 6);
  accelX = Wire.read()<<8|Wire.read(); //Store first two bytes into accelX
  accelY = Wire.read()<<8|Wire.read(); //Store middle two bytes into accelY
  accelZ = Wire.read()<<8|Wire.read(); //Store last two bytes into accelZ
  processAccelData();
}

void processAccelData(){
  gForceX = accelX / 15074.0;
  gForceY = accelY / 15074.0; 
  gForceZ = accelZ / 15074.0;
}

void calcMag() {
  accelMag = sqrt(sq(gForceX)+sq(gForceY)+sq(gForceZ));
}

void printData() {
  Serial.print(accelMag);
}

void rememberData() { // goal is to write last 200 accelMag values to the EEPROM, adress 0-199
  if (adress < 200) { // adress starts at zero, add one for each time
    EEPROM.put(adress, accelMag); // accelMag should be a float
    ++adress;
  }
  else { // if have already written to 200 adresses, go back and update 
   adress2 = adress%200; // if adress is above 200, I want to update the adress 200 below it with the current value (only writing to first 200 adresses)
    EEPROM.put(adress2, accelMag); // accelMag should be a float
    ++adress;
  }
}

void readEEPROM() { // printing past values of EEPROM before starting to record new values
  while (number < 200) { // only for adresses that were written to
    EEPROM.get(number, adressValue); // adressValue is the value (float) written at the adress "number" (adress 0-199)
    Serial.println(adressValue); // print each value from written adresses
    ++number;
 }
}

Thanks in advance

1 Like
  ++adress;

That advances the address you write to in EEPROM by a single byte

but

    EEPROM.put(adress, accelMag); // accelMag should be a float

how many bytes are you actually writing ?

Oh, I think that the the values are floats, so 4 bytes?
The values do not exceed around 5.00

Here is what they normally look like.
Screen Shot 2023-03-06 at 4.05.19 PM

Do you think I should then advance the adress by 4 each time?

Also, do you know if this approach to recording the values is okay? I've read that using the EEPROM of the board too much can mess it up. Is there a better way to record the last 200 values than using EEPROM.put and EEPROM.get? Sorry for all the questions

What did the EEPROM library documentation say about the size of EEPROM on the Uno? I don't think it's 4 x 200 = 1,600.
https://docs.arduino.cc/learn/built-in-libraries/eeprom

I've read that using the EEPROM of the board too much can mess it up.

Don't rely on second hand, hearsay advice. Read the documentation.

Ahem. 4x200 = 800.

Oops.

1 Like

Calculate how often you write any given location. How long will it take to write the number of cycles to a location that is specified?

As for address++, try address = address + sizeof(your float name here).

The safe way to do it is to advance the address by sizeof(float). You are using computer so let it do the work for you

... but to follow that logic, you also then need to compute the maximum number of floats the EEPROM can hold.

Code tags!   :people_hugging:

@tim268 Don't be confused by @dougp , he's just overjoyed a new member actually followed the guidance and used code tags in his FIRST POST! BRAVO! C'mon, everyone, a round of applause for Tim!

The EEPROM memory has a specified life of 100,000 write/erase cycles, so you may need to be careful about how often you write to it.

100.000 * 50 msec is more than 1 hour of testing.
The Arduino should still be usable for non-EEPROM fun afterwards. :boom:

Classic usage of EEPROM includes storing of manually entered and rarely changed settings, or storing values just before a power outage (big capacitor and diode in power supply line required).

But he's writing 200 locations sequentially, so he should be over the 200 hour mark before any chance the EEPROM gets flaky. Of course, we don't know how many hours this device has already been writing to the EEPROM, so there's that.

This discussion comes up repeatedly. If you can execute a power down sequence, you don't need to keep updating all the time. But it requires a power loss detection circuit that trips with sufficient time to perform a save before the processor stops running. Typically that would be a backup source like a capacitor.

Hi michael,
Thanks for the heads up. I am only using the EEPROM to determine certain thresholds I will be using in the program, so I think I'll be more than okay.

Thank you for the help.

Ok, thank you for the help. The code is working normally now.

Thanks for the advice. The serial monitor is reading normal values now.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.