Save errors to EEPROM deleting the last one

Hi everyone,
my Arduino controlled dishwasher project incorporates a self diagnosis feature. This means that if things should go wrong it will alert the user with an error code and, depending on the gravity of the situation, the cycle can't advance.
I'd like to take this to the next step and, as such, since I have already incorporated a service mode, it'd be cool to save all the different errors to EEPROM and be able to read them out. Here's where I need your help
I'd like to write a function that receives the latest error code (a single one) as an input and saves it to EEPROM (max. 3 error codes)
The way it should work is like this: when the very first error code (let's say F2) appears it should be saved to EEPROM in position 128. The next one (e.g. F1) will need to shift the previous to cell 129 and save F2 in position 128. The third one (e.g. F7) will shift the previous two in 130 and 129 respectively.
SO the EEPROM will look something like this:

128 -> F7
129 -> F1
130 -> F2

Then, when the very next error code appears (let's say F4) it should delete F2 and move the other by one, so that it would look something like this:

128 -> F4
129 -> F7
130 -> F1

How would you go writing something like this? I really can't seem to figure out how this could be done
Many thanks in advance

Why mess around moving the data about in EEPROM ?

Instead, keep a variable with a value of 0, 1 or 2 and use that as the index to the latest error code position used in EEPROM. Increment the index each time you save a code and once the index reaches 3 set it back to zero

yes, a circular buffer basically

just make it cyclic, make a variable that counts, for example, 0, 1 and 2, 0-> represents 128 in your memory, 1-> 129, 2->130.
When an error incomes, you add 1, for example if it starts in 0 and a error incomes, the variable would be 1. that means you should write in 1(128). When the value reaches to 2 and other error incomes, the variable returns to 0. So following this, always the variable that you are in
is the position of last error. the next value in memory is the first of the saved errors, and the next is the second.
for example if you are in 1:

     0        |                1             |          2
    128       |              129             |        130
second error  |        Last error            |   first error

Obviously there is no need to use 0,1,2 , its just to understand better the idea. You have to save the last number in memory before shut down or reset so you can know at any moment which error was the last and you can figure the order of the rest.

I get what you are saying, but I need to shift EVERYTHING by 1 to the right. How can I achieve that?

No. You don't shift anything in the EEPROM. You change then index to where the data is stored instead

Try this...

#include <EEPROM.h>

const uint8_t OFFSET = 127;
const uint8_t MAX    = 3;

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

  // Initialise the EEPROM.
  EEPROM.write(OFFSET, 0x00);
  for (uint8_t x = 0; x < MAX; x++)
    EEPROM.write(OFFSET + 1 + x, 0x00);  
  displayEEPROM();

  // Add some codes.
  addErrorCode(0xF7);
  addErrorCode(0xF1);
  addErrorCode(0xF2);
  displayEEPROM();

  // Add 1 more.
  addErrorCode(0xF4);
  displayEEPROM(); 

  // Add 1 more.
  addErrorCode(0xF5);
  displayEEPROM();
}

void loop()
{}


void addErrorCode(byte newCode)
{
  // Get the next index offset.
  byte x = EEPROM.read(OFFSET);

  Serial.print("Adding code ");
  Serial.print(newCode, HEX);
  Serial.print(" at ");
  Serial.println(x);
  
  // Add the new error code;
  EEPROM.write(OFFSET + 1 + x, newCode);

  // Increment the offset;
  x = (x + 1) % MAX;

  // Update the next index offset.
  EEPROM.write(OFFSET, x);
}


void displayEEPROM()
{  
  Serial.println(EEPROM.read(OFFSET), HEX);
  for (uint8_t x = 0; x < MAX; x++)
    Serial.println(EEPROM.read(OFFSET + 1 + x), HEX);
  Serial.println("---------------");
}

No you don't. You just change which value you interpret to be the first one. Here's an application note explaining the logic of how to use a circular buffer in EEPROM.

AVR101 - High Endurance EEPROM Storage.pdf (47.3 KB)

EEPROM has a certain number of times you can write on it, so you have to limit that at the minimum possible, thats why you shouldnt move everything in all the iterations, you have to just write 1 time per cycle, you should try the circular buffer.

Many thanks. I will try it out as soon as I have some free time

So I have tried using @red_car version of the code, but it doesn't work as I expected
First of all I have to correct one mistake I made, that is not having specified that F is a letter and not an hexadecimal value. So it should simply save 7 in case of F7 and I will print out the F afterwards by myself
However, in the case of red_car's code, what I'd like to get is something like this:

First call:
F2 (latest) in position 128
F1 (intermediate) in position 129
F7 (earliest) in position 130

Second call:
F4 (latest) in position 128
F2 (intermediate) in position 129
F1 (earliest) in position 130

Third time:
F5 (latest) in position 128
F4 (intermediate) in position 129
F2 (earliest) in position 130

Whereas this is what I get:

21:45:17.238 -> Adding code F7 at 0
21:45:17.238 -> Adding code F1 at 1
21:45:17.238 -> Adding code F2 at 2
21:45:17.278 -> 0
21:45:17.278 -> F7
21:45:17.278 -> F1
21:45:17.278 -> F2
21:45:17.278 -> ---------------
21:45:17.278 -> Adding code F4 at 0
21:45:17.278 -> 1
21:45:17.278 -> F4
21:45:17.278 -> F1
21:45:17.278 -> F2
21:45:17.278 -> ---------------
21:45:17.278 -> Adding code F5 at 1
21:45:17.278 -> 2
21:45:17.278 -> F4
21:45:17.278 -> F5
21:45:17.278 -> F2
21:45:17.278 -> ---------------

I think that you have missed the point (again). You do not move the values in the EEPROM, you change the index to the values instead, as has been previously explained

When you need to read the values out you use the same method but read the values using the index

Using a circular buffer, you don't move the data. You just start reading it from the appropriate place.

The following will read the EEPROM, and return the data in age order, newest first.

  
  Serial.println("Display in age order, newest first");

  byte address = OFFSET + EEPROM.read(OFFSET) + 1; // Next address to use.

  for (uint8_t x = 0; x < MAX; x++)                // Do MAX times.
  {
    address--;                                     // Get the previous address.
    if (address == OFFSET)                         // Gone passed the start of the buffer?
      address = OFFSET + MAX;                      // Loop to the end of the buffer.
         
    Serial.println(EEPROM.read(address), HEX);
  }

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