EEPROM Write (Arduino Uno)

Hello,

I am new to Arduino.

I have values from 31 to 4186 that I want to save into EEPROM. I read that when using EEPROM.write(address, value), the value needs to be from 0 to 255 (byte).

Does this mean I am unable to save my data into EEPROM?

Thank you in advance.

Look in the reference at the highByte and lowByte functions for splitting an int into 2 bytes.

An int is stored as two (consecutive) bytes in the memory of a 8-bit micro. The below code is an attempt to demonstrate this

char txBuffer[64];

void setup()
{
  Serial.begin(250000);

  // a variable
  int x = 4156;
  // a (byte) pointer to the varibale
  byte *ptr = (byte*)&x;

  // print where the variable x is located in memory
  sprintf(txBuffer, "address of x = %p", &x);
  Serial.println(txBuffer);
  // print the value of variable x in hexadecimal
  Serial.print("x = 0x"); Serial.println(x, HEX);
  // print the size of the variable x
  Serial.print("sizeof(x) = "); Serial.println(sizeof(x));
  // print the low byte of the variable x
  Serial.print("low byte = 0x"); Serial.println(lowByte(x), HEX);
  // print the high byte of the variable x
  Serial.print("high byte = 0x"); Serial.println(highByte(x), HEX);

  // print one of the bytes of the variable x using byte pointer
  sprintf(txBuffer, "content of location %p is 0x%02X", ptr, *ptr);
  Serial.println(txBuffer);

  // print the other byte of the variable x using byte pointer
  ptr++;
  sprintf(txBuffer, "content of location %p is 0x%02X", ptr, *ptr);
  Serial.println(txBuffer);
}

void loop()
{
}

I used hexadecimal representations to make it easier to see how the int is stored. The output on my system

address of x = 0x8f4
x = 0x103C
sizeof(x) = 2
low byte = 0x3C
high byte = 0x10
content of location 0x8f4 is 0x3C
content of location 0x8f5 is 0x10

From the above I've created a partial 'map':

variable | address | content | comment
---------+---------+---------+--------
 x       | 0x08f4  | 0x3C    | low byte
         | 0x08f5  | 0x10    | high byte

So using EEPROM.write, you need to write both bytes and when reading it back using EEPROM.read, you need to read two bytes back and recombine them.

Note: Alternative to using EEPROM.write is EEPROM.put which will write the int in one go. In that case you can use EEPROM.get (instead of EEPROM.read) to read the int back.

this is a example i made afther having the same question.

#include <EEPROM.h>
unsigned long inLong;
int inInt;

int outInt = 15;
unsigned long outLong = 4294967295;

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

  EEPROM.put(4, outInt);

  EEPROM.put(0, outLong);

  EEPROM.get(0, inLong);
  Serial.println(inLong);
  EEPROM.get(4, inInt);
  Serial.println(inInt);
}

void loop()
{
}

this is a link to the discustion then: https://forum.arduino.cc/index.php?topic=470454.15

So much grief - everyone spinning their wheels as the Arduino “core” code gets progressively more screwed up (as well as things that NEED fixing totally ignored).

THIS simple little bit of code solves all the problems:

/*
   Copyright (c) 2017 Roger A. Krupski
   All rights reserved.
 */

#ifndef _AVR_UNIVERSAL_EEPROM_H_
#define _AVR_UNIVERSAL_EEPROM_H_


// universal eeprom READ
template <typename T> T eepromRead (T *__address)
{
	T __value;
	uint8_t x = sizeof (__value);
	uint8_t *ptr = (uint8_t *)(&__value);

	while (x--) {
		*(ptr + x) = (eeprom_read_byte ((uint8_t *)(__address) + x));
	}

	return __value;
}

// universal eeprom WRITE
template <typename T> void eepromWrite (void *__address, T __value)
{
	uint8_t x = sizeof (__value);
	uint8_t *ptr = (uint8_t *)(&__value);

	while (x--) {
		eeprom_write_byte (((uint8_t *)(__address) + x), *(ptr + x));
	}
}

// universal eeprom UPDATE
template <typename T> void eepromUpdate (void *__address, T __value)
{
	uint8_t x = sizeof (__value);
	uint8_t *ptr = (uint8_t *)(&__value);

	while (x--) {
		eeprom_update_byte (((uint8_t *)(__address) + x), *(ptr + x));
	}
}

#endif

Stick this into the AVR toolchain under [b]avr/include/avr[/b] and give it a name (I named mine "
** **universal_eeprom.h** **
"), then in “[b]eeprom.h[/b]” add this line (at the bottom - shown in red):

[b]/*@}*/

#ifdef __cplusplus
}
#endif

/* modified RAK */
[color=red]#include "universal_eeprom.h"[/color]

#endif  /* !__ASSEMBLER__ */
#endif  /* E2END || defined(__DOXYGEN__) || defined(__COMPILING_AVR_LIBC__) */
#endif  /* !_AVR_EEPROM_H_ */

[/b]

Then in your sketches, simply include <avr/eeprom.h> instead of <EEPROM.h>, and use the eeprom variables as you would any other… example:

#include <avr/eeprom.h>

uint16_t ee_var EEMEM; // define the var, EEMEM places it in eeprom
uint16_t value = 1234; // value in SRAM

eepromWrite ((uint16_t *) ee_var, (uint16_t) value); // put "value" into "ee_var"

value = eepromRead ((uint16_t *) ee_var); // read eeprom "ee_var" into "value"

No matter what size variable you use, it works. Use floats or double. Use UINT64_t. No problem.

No need to go screwing around with splitting up variables that are larger than 8 bits (then what about read and write order? Big endian? Little endian? How many bytes does a double need? Where does the next var start?)

No need to worry about this BS. Just give the variables NAMES and reference them by NAME and all is taken care of.

Or… throw libraries/src/EEPROM.h into the trash can and replace it with the above, then add an "#include <avr/eeprom.h> at the top so that it can call the GCC code. You do lose “readblock”, “writeblock” and “updateblock”, but these are no faster than byte-for-byte copying and, worse, the syntax is backwards from what other similar functions use (for example, strncpy is strncpy (dest, src, count) whereas the writeblock and updateblock functions are backwards (src, dest, count) while readblock is correct! (yet ANOTHER source of confusion!)

Why not simply use EEPROM.put() and EEPROM.get() ?

UKHeliBob:
Why not simply use EEPROM.put() and EEPROM.get() ?

I could (in fact, those two functions are almost identical in function to what mine do).

I used to use “eepromReadByte” and “eepromReadDWord” etc… and the new library broke my old sketches. So that’s when I wrote “my own” universal code and updated my sketches to use them.

What I don’t like about the new get() and put() eeprom code is that “get” requires two parameters, the “idx” (index into the byte(s) making up the storage) and t (the value which is ONLY used to define the type T).

Again, this syntax is different than the old code.

If the new library also had readWord, DWord, QWord and float/double, and their write counterparts, it would be a lot better (and a lot more backward compatible).

It’s funny that in the code it says:

/*
 * EEPROMClass class.
 * This object represents the entire EEPROM space.
 * It wraps the functionality of EEPtr and EERef into a basic interface.
 * This class is also [color=red]100% backwards compatible[/color] with earlier Arduino core releases.
 */

…because it’s not!

I used to use “eepromReadByte” and “eepromReadDWord” etc…

Were they part of the

earlier Arduino core releases.

?

mirandamg: Hello,

I am new to Arduino.

I have values from 31 to 4186 that I want to save into EEPROM. I read that when using EEPROM.write(address, value), the value needs to be from 0 to 255 (byte).

Does this mean I am unable to save my data into EEPROM?

Thank you in advance.

use

EEPROM.put()

it can handle any object. The thing to keep in mind is keeping track of the locations so you are not writing over any of your other EEPROM data.

How many values are you saving?

I would indeed also prefer the .put() and .get() above a function where you have to cast the shit out of it to use it... ::)

Thanks so much for everyone's help! I really appreciate it.

I am also worried about writing and reading to/from EEPROM. I've read that "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."

My project is implementing an electronic piano with 8 tactile switch keys. I can play 8 different notes and 8 different octaves. I can also record (for a specified amount of time) and playback tunes.

When I record, I am implementing a loop that loops 900 times (specified time to record). I would like to write to EEPROM inside this loop.

If I want to store the different button presses (corresponding to different frequencies) into EEPROM, would this be too much for EEPROM to handle?

Thanks in advance.

When I record, I am implementing a loop that loops 900 times (specified time to record). I would like to write to EEPROM inside this loop.

OUCH !

Do you mean that you will write 900 values to the EEPROM ? What type of variables are you writing ? How many different locations will you write to ? Do the values change between writes to the same location ?

In my main code, I have a loop that is running up to a maximum of 900 loops. This specifies the length of the recording.

Inside this loop, each key is checked if it is high. If so, the specified frequency is played using the Tone function.

Do you mean that you will write 900 values to the EEPROM ?
I think it depends on the number of keys pressed by the user during the specified record time.

What type of variables are you writing ?
The values I want to store are integers ranging from 31 to 4186.

How many different locations will you write to ?
It depends on how many keys (different frequencies) are pressed during the record time.

Do the values change between writes to the same location ?
The values would change when I want to use the record function to rewrite what was already written.

So, you could potentially want to write 900 ints to the EEPROM each time you run the program

Problem 1 is that you need 1800 bytes to store 900 ints but the Uno only has 1024 bytes of EEPROM Problem 2 is that even if you could store the values you would exceed the number of write cycles after about 100 runs of the program.

mirandamg: In my main code, I have a loop that is running up to a maximum of 900 loops. This specifies the length of the recording.

Change all these 900 values each time or change only a few?

UKHeliBob: Problem 2 is that even if you could store the values you would exceed the number of write cycles after about 100 runs of the program.

It's 100,000 write cycles for an eeprom cell (byte).

sterretje:
It’s 100,000 write cycles per eeprom cell (byte).

Whoops, you are right of course. My mistake.

The record time is approximately 17 seconds. The user can press as many notes/keys as they want in 17 seconds.

I don't think they would be able to press 900 different notes within that timeframe?

The values are changed each time a person presses the record button.

Why did you choose 900 as the number of loops to run ?

900 loops approximately gives 17 seconds of recording time, so not too long and not too short for a user to play a little tune