Not getting 0 on EEPROM when I should. Why?

Greetings everyone,

I hope I am posting this question in the correct section, but here I go:

I am using an Arduino for the first time, the ATmega 2560 to be exact.
I currently need it to measure the current output of a servo drive (this can be done using the current monitor analog output of the servo drive itself). This should be a signal of ±5V.

Since I cannot read the values at a computer while I'm using the servo drive, I was thinking of writing them with EEPROM.write while I'm at the servo drive with the Arduino and then later plug it in my usb to open the Serial Monitor and use EEPROM.read without erasing the data. Not sure if that would work.

However I can't even get that far since it seems my code is misbehaving; when I run the program at the computer (thus without input) I should read only 0 as a value, since there is no input. However I read a bunch of variable values ! How is that so?

Here is my code below.

#include <EEPROM.h>

int var = 0; 
int addr = 0; 
int shock = 0; 
int current = 0; 

void setup() {
  Serial.begin(9600);
  var = 0; //Reset
  pinMode(2, OUTPUT); //Sets pin 2 as an output
  pinMode(A0, INPUT); //Sets pin A0 as an input
  
}

void loop() {
  
  while (var < 500) {

    var++; // Permet l'arrêt du loop lors de tests
    // Le servo drive a 15.9A/V. On vise 30.4 A. 255 = 5V. (255/5V = 51/V)
    analogWrite(2, 15.9 * 51 / 159); // Set pin 2 to generate needed voltage
    
    //This code is to record the Current Monitor Output (Pin 8 ) of the Servo Drive
    //La résolution de analogread est de 5V par 1024 unité. La convertion est donc unité/204.8
    //La mémoire EEPROM ne peut que tenir des valeures entre 0 et 255.

    shock = analogRead(A0) * 0.078;
    EEPROM.write(addr, shock);
    current = EEPROM.read(addr);
    Serial.println(current);
    addr = addr++;
    if (addr == EEPROM.length()) {
      addr = 0;
    }
  }

}

To explain the french part: The *0.078 comes from the servo drive's analog value being worth 15.9A for every volt it sends. Since the Arduino is at 5V for the value of 1024 in EEPROM, this gives *0.078.
This still doesn't explain why I don't get 0 when I should!

Anyway, I hope You can help Me.
Thanks.

Connect the analogue pin to ground if you want it to read zero.
An unconnected pin is floating. A floating pin is NOT the same as zero volts. In fact a floating pin can, and will, read any value it likes.

Excellent!

That part is now solved, but I'm wondering if I'm using the correct strategy to write a value in EEPROM and then read it later ?

Should I be using two different programs to avoid erasing the data ?

Thanks again

theoverlord:
Excellent!

That part is now solved, but I'm wondering if I'm using the correct strategy to write a value in EEPROM and then read it later ?

Should I be using two different programs to avoid erasing the data ?

Thanks again

I am not sure what the default is when you reprogram. Whether it preserves or erases the EPROM.

For ease of use and safety I would use the same program. Have a second pin as INPUT_PULLUP. Read the state f the pin to decide what to do. Ground the pin before start up to switch to the other mode.

Or dump the EPROM on power up, then wait for the pin to be grounded to start a recording. Lots of options.

Remember the EEPROM lifetime is limited to perhaps 100,000 cycles. So do not under any circumstances record continuously.

One obvious problem is that shock is an int, which is 2 bytes, but you are using EEPROM.write() and EEPROM.read() which only write and read 1 byte

Take a look at EEPROM.put() and EEPROM.get() which can be used with variables of any type/size but remember to allow for the length of the variable when choosing EEPROM addresses.

pcbbc:
I am not sure what the default is when you reprogram. Whether it preserves or erases the EPROM.

Writing a new sketch only affects flash memory and the fuses, EEPROM is untouched. This makes
sense if you realise that EEPROM is often used for identifying information of calibration values
particular to the hardware.

For this reason I have a sketch that just rewrites all EEPROM bytes to 0xFF (the factory state),
as some sketches use EEPROM and need that to do their initial configuration on a first run.

The short lifetime of EEPROM (100,000 writes typical) means its wise to always guard any write to
EEPROM with a check to see if the value would be unchanged - writing the same value to a location
is both unnecessary and stresses the EEPROM cell just as much as any write (high voltage is used
internal to the chip BTW, which is why writes cause gradual damage)

So is EEPROM even the right solution for what I'm trying to do ? (Take data from a servo drive's analog output, go into the next room, plug the arduino on a computer, read the data.)

How would You do it ?

Can't you write the data to an SD card and then read the SD card later?

No, I don't have an SD card available. Only the arduino.

You can easily add an SD module or some shield with SD on it. You never came back with any comments about the 100,000 write cycle limitation, or how often you need to write the EEPROM.

I don't have the time/budget to add new parts.

I only need write once! It's only to verify what the current output of the servo drive is so I can make sure my command actually works or not. (For some reason I cannot use my multimeter for this, probably too high current, thus wanting to use the current monitor to verify.)

I modified my code as follow:

....
 //La mémoire EEPROM ne peut que tenir des valeures entre 0 et 255.
    shock = analogRead(A0) * 0.078;

    if (shock != 0); {
      EEPROM.write(addr, shock);
      addr = addr++;
      if (addr == EEPROM.length()) {
        addr = 0;
      }
    }
    current = EEPROM.read(addr);
    Serial.println(current);
  }
....

there is no errors, but it also doesn't work. When I come back to the computer and check the Serial Monitor, it's all zeros.

Have you fixed the problem that I pointed out with saving an int ?

Please post your complete program as it is now

I think I did.
Here it is:

#include <EEPROM.h>

int var = 0; // Variable pour arrêter le loop lors de tests
int addr = 0; //Le byte où On commence à écrire
byte shock = 0; // Valeur initiale du courant
int current = 0; //Déclare la variable qui mémorise le courant

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  var = 0; //Reset
  pinMode(2, OUTPUT); //Sets pin 2 as an output
  pinMode(A0, INPUT); //Sets pin A0 as an input

}

void loop() {
  // put your main code here, to run repeatedly:
  while (var < 500) {

    //Serial.println("Testing"); //Display the current values
    var++; // Permet l'arrêt du loop lors de tests
    // Le servo drive a 15.9A/V. On vise 30.4 A. 255 = 5V. (255/5V = 51/V)
    analogWrite(2, 15.9 * 51 / 159); // Set pin 2 to generate needed voltage
    // delay(3); // Pause de 3 millisecondes


    // analogWrite(2, 0); // Set pin 2 to 0V
    //  delay(45); // Pause de 45 millisecondes

    //This code is to record the Current Monitor Output (Pin 8 ) of the Servo Drive
    //La résolution de analogread est de 5V par 1024 unité. La convertion est donc unité/204.8
    //La mémoire EEPROM ne peut que tenir des valeures entre 0 et 255.
    shock = analogRead(A0) * 0.078;

    if (shock != 0); {
      EEPROM.write(addr, shock);
      addr = addr++;
      if (addr == EEPROM.length()) {
        addr = 0;
      }
    }
    current = EEPROM.read(addr);
    Serial.println(current);
  }

}

Some parts are in comment on purpose since I'm testing the other parts right now.

byte shock = 0; // Valeur initiale du courant
      EEPROM.write(addr, shock);

Writes a byte to EEPROM

int current = 0; //Déclare la variable qui mémorise le courant
    current = EEPROM.read(addr);

Reads an int from EEPROM

Did you look at the .put() and .get() functions as I suggested ?
They would allow you to save and load an int but you must allow for the fact that an int takes 2 bytes of storage so the EEPROM address used must be incremented by 2 not 1 between saving the ints

Not yet, I'm trying not to get too exotic with my code. haha ^^'

So using EEPROM.put() and get() would require to have addr+2 at every loop instead ?

theoverlord:
Not yet, I'm trying not to get too exotic with my code. haha ^^'

So using EEPROM.put() and get() would require to have addr+2 at every loop instead ?

What do you mean by "Not, yet" ?
Using the correct functions for the task is vital

Yes, if you put() the first int at address zero the next one must be saved at address 2 (or higher) as each takes 2 storage locations. The same logic applies to reading the values back