EEPROM working on Nano, but not on Uno

Dear forum,

I own a lot of Unos and Nanos. I want to write data (chars/bytes) via serial communication to the EEPROM.

Doing this with the Nano works pretty fine (connecting the board to USB, sending data, writing to EEPROM, disconnecting the USB-powered board from USB, reading the once written data when USB-cable is re-plugged).

With the Uno, the read only works until the board is powered off. When replugging it, the EEPROM only contains crap.

This applies to ALL my Unos and Nanos. And The EADR constant (the adress of the byte within the EEPROM) can be changed to any value; still the same behaviour.

Do you have any ideas? :slight_smile:

Thank you.

Here is my code (How to use? Any character but 'R' is written to the EEPROM; simply type 'R' after sending some other character, 9600 bps, no LF/CR):

#include <EEPROM.h>
#define EADR 5

void setup() {
  Serial.begin(9600);
}

void loop() {
  
  if (Serial.available() > 0) {
    unsigned char data = Serial.read();
    if (data == 'R') {
      Serial.print("Read last EEPROM value: ");
      Serial.print(char(EEPROM.read(EADR)));
      Serial.print("  (before cast: ");
      Serial.print(EEPROM.read(EADR));
      Serial.println(")");
    } else {
      Serial.println("Writing to EEPROM");
      EEPROM.write(EADR, data);
    }
  } 

}

Quick note:

The data saved to the EEPROM on the Uno survives when the reset-button is pressed (but USB stays plugged in).

The stored data only seems to be overwritten when serial communication is established.

Maybe this has to do with the DTR-stuff?

Anyway, the EEPROM is not erased (not 0xFF is read after re-plugging, but only some arbitrary "very high" value in the range > 0xFD is read).

The read value seems to be quite randomly, independent of the character/byte I really wrote to the EEPROM.

The boards are all Elegoo boards (-> china clones).

The Unos are Uno R3 with an 16u2 as USB-serial-converter, the Nanos are equipped with an FTDI.

One more observation ... ( :slight_smile: ):

Neither putting a 110 Ohm resistor between +5v and RESET nor putting a capacitor (100 uF) between GND and RESET does help. Somehwere I read on putting an 1k resistor between +3.3V and RESET, with no success, too.

One quick and ugly workaround I found:
Putting the 110 Ohm resistor between GND and RESET just before re-plugging helps. The Atmega328p is then put into reset-state and re-plugging USB does no harm: When I re-plug USB during the reset-state, I can read the written data correctly, after I the remove the resistor. :astonished:

I've tried both an original Uno and a Sparkfun Redboard and can't reproduce the issue. But I have seen at occasion rubbish coming in when using another computer; in that case a short delay at the end of setup() helped.

You can harden your code by adding the below to setup().

void setup()
{
  Serial.begin(9600);
  
  delay(500);
  // clear the serial buffer
  while(Serial.available() > 0)
  {
    Serial.read();
  }
}

This will clear the serial input buffer before entering loop().

Dear sterretje,

Thank you a lot for your reply!

I tried your suggestion, with no success. Anyway, cleaning the channel from any digital garbage levels was a reasonably very good idea! :slight_smile:

Would you please tell me what Version of the uno you where using?

I tried your idea in other places of the code posted above. Still, no success.

...

My solution for now, but highly interested in other ideas and eplainations:

Now I soldered a wire to the RESET-pin on the shield of my Uno. Before I re-plug and BEFORE I open the serial connection I put the wire into my GND rail. Then the AVR is in reset-state.

Then I open a serial monitor (with connection GND-RESET still present).

THEN I remove the wireconnection (so, GNX-RESET is cut).

Then everything works fine.

My eplaination for now:
The (at least all of mine) Arduino Uno R3 (with 16u2) does some strange things when serial communication is established. It's not simply resetting the AVR, but doing something more, like erasing the EEPROM. "Normal" reset of the Arduino does no harm to the EEPROM, so the serial communication reset routine seems a bit more tricky and agressive.

Do you out there have any other ideas?

Thank you all for any more answers.

Would you please tell me what Version of the uno you where using?

Tested with an arduino.org Uno R3

I'm afraid I can't help further.

Maybe "digital garbage on Serial" appears not only during power up but also on power down. Hard to say why this happens. Maybe some noise on partially connected USB lines? Or a brownout condition?

Hi Smajdalf,

Thank you for your thoughts! I think I have no bronout condition, since the data surely got written to the EEPROM. .oO(?) Anyway, on the garbage stuff. I added some Serial.flush(), with no effect again.

I will try Unos from another brand. (Edit: Just tried. Same results. ... ????)

Thank you guys! :slight_smile:

One more observation:

Tried an original Arduino Mega 2560. Same code as above, enriched with sterretje's hardening tipp.

Same results. ???

The boards (Uno/Nano/Mega) all are "bare", so no other electronics added.

I hardly believe it has to do with my USB-cables. :slight_smile:

Hmmmmmmmmmmmm.

On the Mega, USB-Serial-handling is done by a 8u2.

Maybe my code is buggy? I added some flushing and delays. No changes.

Only pulling RESET to GND before re-plugging and opening serial connection helps. Of course, GND-RESET needs to be cut then.

Yesterday I flashed the 16u2 of one of the Unos in hope the firmware was somehow altered by the manufacturer. Of course, this didn't work out (though the re-programming of the 16u2 was successful).

??? :slight_smile:

#include <EEPROM.h>
#define EADR 5

void setup() {
  Serial.begin(9600);
  delay(500);
  while(Serial.available() > 0) {
    Serial.read();
  }
  delay(500);
  Serial.println("Ready in 500 ms");
  Serial.flush();
  delay(500);
}

void loop() {
 
  if (Serial.available() > 0) {
    unsigned char data = Serial.read();
    if (data == 'R') {
      Serial.print("Read last EEPROM value: ");
      Serial.print(char(EEPROM.read(EADR)));
      Serial.print("  (before cast: ");
      Serial.print(EEPROM.read(EADR));
      Serial.println(")");
      Serial.flush();
    } else {
      Serial.println("Writing to EEPROM");
      Serial.flush();
      EEPROM.write(EADR, data);
      delay(100);
      Serial.println("Done");
      Serial.flush();
      delay(500);
    }
  }

}

Do you have the option to use another PC? It might be OS related.

Serial.flush has no effect on incoming data; that was changed long ago.

Hi sterretje, thank you! I know, as mentioned in the docs. :-)) My idea was that maybe something is on the stream to the outside that crumbled my data and mixed the crap on the fly. Anyway ....

Yeah, maybe OS-related. I always work with the same PC. Will try another one later, thank you for your suggestion.

This noon we have class and I wonder whether my students might find a solution. :slight_smile: Hope so.

BTW. All Debian, also in our lab. Hmhmhmhm.

DAMN IT WORKS!!!!!!

And WTF .... I was using Arduino 1.05 (very very old).

It's the version listed in the Debian repo (even in testing, I'm on buster ATM).

I downloaded the recent version from the project's webpage.

But I did not install it. Instead, I first executed the shell-script named "arduino-linux-setup.sh".

That script is responsible for a lot of udev-rules. Now in my /etc/udev/rules.d some new .rules-files are found, for example avrisp.rules, 99-arduino-101.rules, stuff like that.

I then was asked to reboot my system. Then I tested ... with old version 1.0.5.

And, yeah ... :smiley: :smiley: :smiley:

It worked out!

Obviously, there is something wrong with the old arduino package in the Debian repo.

ATM I can't explain further, but I will investigate and hopefully report back.

It works!! :-)))

Thank you all!

Could this be a fuse setting - EESAVE.

If you reflash the bootloader , it will probably clear this . ( you can flash a nano as “ gen UNO” if you want , it then appears as a UNO in the IDE)

Do not use the versions of the IDE supplied by linux package mangers. The versions are always out of date (partly arduino's fault - there's a longstanding issue with a license file that Arduino refuses to address), and are often modified from the "real" version by linux people who while very competent at linux software, I'm sure, but who have never used an Arduino and don't know which end of a soldering iron to pick up.