EEPROM Storing more than 255

Hi to all. I’m in a middle of a project and i would appreciate your help. I’m trying to store a number to EEPROM starting from 0 and adding 1 every time a condition is met. The thing is that when it reaches number 255 in total then it goes back to the beggining. I’m lacking some basic knowledge about bytes so if there is any idea I would be gratefull

That is my code

#include <EEPROM.h>

int value; // for the coffees
int coffees = 0; // for the coffees


void setup() {
coffees = EEPROM.read(0);

}

void loop() {
// Read Coffees

if (digitalRead(switchReed) == HIGH & time == 1) {
  coffees++;
  int eeAddress = 0;   //Location we want the data to be put.

  EEPROM.put(eeAddress, coffees); //One simple call, with the address first and the object second.


  if (eeAddress == EEPROM.length()) {
    eeAddress = 0;
  }

  value = EEPROM.get(eeAddress, coffees);
  eeAddress = eeAddress + 1;
  EEPROM.update(eeAddress, coffees);
}
  eeAddress = eeAddress + 1;

What’s that for?

coffees = EEPROM.read(0); Oops

(Hint: print out sizeof(int) )

Please remember to use code tags when posting code

TheMemberFormerlyKnownAsAWOL:

  eeAddress = eeAddress + 1;

What's that for?

This is in order to write in the next available address. Is this wrong

coffees = EEPROM.read(0);

Oops

Sorry I didn't get my mistake

(Hint: print out sizeof(int) )

The size is 2

Please remember to use code tags when posting code

Thanks just correct it

If you look at the docs for EEPROM.read(), it says that it returns only 1 byte.

When you saved the value of 'coffees' using EEPROM.put(eeAddress, coffees), the code actually put 2 bytes into the EEPROM, because you defined coffees as an int (which is 16-bits). Note that these bytes were stored at eeAddress and eeAddress+1.

In order to easily retrieve the saved value of 'coffees' on startup, you need to use the EEPROM.get() function as it will correctly read out 2 bytes for you.

markd833:
If you look at the docs for EEPROM.read(), it says that it returns only 1 byte.

When you saved the value of 'coffees' using EEPROM.put(eeAddress, coffees), the code actually put 2 bytes into the EEPROM, because you defined coffees as an int (which is 16-bits). Note that these bytes were stored at eeAddress and eeAddress+1.

In order to easily retrieve the saved value of 'coffees' on startup, you need to use the EEPROM.get() function as it will correctly read out 2 bytes for you.

Thanks Mark, here is the thing. I want at startup to read the last saved number. with the EEPRO.get() I have to define both the last address and value that have been writen which I don't know how to write it.

The other thing is that it seems that the EEPROM.update () not working.

  if (eeAddress == EEPROM.length()) {
    eeAddress = 0;
  }

  value = EEPROM.get(eeAddress, coffees);
  eeAddress = eeAddress + 1;
  EEPROM.update(eeAddress, coffees);
}

I say that when the EEPROM reach the address limit which is 255 then set eeAddress = 0
and I'm asking to update the value with the new one with the EEPROM.update(eeAddress, coffees);
Am I thinkinh the wrong way?

I think I see what you are trying to do. So each time a coffee is "sold", you add 1 to the count of the number of coffees sold and write the count to the next address in the EEPROM, and then increment the EEPROM address. So your EEPROM is essentially being filled by an incrementing number until you reach the end of EEPROM space and then you start back at address 0 again with the number still incrementing.

Firstly, and I could be wrong here, but you need to increment your EEPROM address by 2 each time you use EEPROM.put() as you are writing a 16-bit value (i.e. 2 bytes), because coffees is defined as an int. The first value will be stored across addresses 0&1, the second value across addresses 2&3 etc.

Secondly, in order to locate the last saved number, you need to search the EEPROM from start to end to locate the biggest number stored. A simple loop in setup() would do this for you without getting into fancy algorithms. You need to use EEPROM.get() to read out the 16-bit value correctly.

The big question is what to do when you want to reset your coffee count back to zero. You could zero all of the EEPROM but that would involve additional writes. Another option is to "reserve" a location in the EEPROM to store the current count when you want to reset the count. Then you just subtract that value from your new count when you want to know how many coffees have been sold. That would work until you've sold 32767 coffees (or 65535 coffees if you used an unsigned int).

markd833:
I think I see what you are trying to do. So each time a coffee is "sold", you add 1 to the count of the number of coffees sold and write the count to the next address in the EEPROM, and then increment the EEPROM address. So your EEPROM is essentially being filled by an incrementing number until you reach the end of EEPROM space and then you start back at address 0 again with the number still incrementing.

Firstly, and I could be wrong here, but you need to increment your EEPROM address by 2 each time you use EEPROM.put() as you are writing a 16-bit value (i.e. 2 bytes), because coffees is defined as an int. The first value will be stored across addresses 0&1, the second value across addresses 2&3 etc.

Secondly, in order to locate the last saved number, you need to search the EEPROM from start to end to locate the biggest number stored. A simple loop in setup() would do this for you without getting into fancy algorithms. You need to use EEPROM.get() to read out the 16-bit value correctly.

The big question is what to do when you want to reset your coffee count back to zero. You could zero all of the EEPROM but that would involve additional writes. Another option is to "reserve" a location in the EEPROM to store the current count when you want to reset the count. Then you just subtract that value from your new count when you want to know how many coffees have been sold. That would work until you've sold 32767 coffees (or 65535 coffees if you used an unsigned int).

Ok now I think I'm getting it step by step. Let me explain exactly what I'm doing

As you correctly understanded I'm counting coffees

Firstly I'm using an int because when the time comes and I'm going to record the 256th coffee then I'll need 16bit numbers.

I have to use the EEPROM.get() in order to retrieve the info of 2 bytes for the int, and eeAdress + 2 in order not to rewrite the next but to write the one after next. I think I got it right.

There is no way of reseting. The counter will go on eternally.

So the only thing is to find the way to read always the last EEPROM record at start-up. Or as you say the biggest number

Good morning,

Why are you trying to complete the task in a very small program area? I don't understand why you don't apply the higher level systems that can handle your requests with greater efficient operations.

Ok, if you are not going to reset the counter (and you can't have a negative number of coffees!), then
I would suggest using an unsigned int so that you can count from 0 to 65535 coffees!

Yes, the EEPROM.put() and EEPROM.get() functions handle the size of the data type - in this case a 16-bit integer. So in order to avoid overwriting half of the previously stored value, you need to increment the address by 2 after each EEPROM.put().

In order to find the last coffee count written before reset/power-off, you would have a simple loop in start() that increments from start of EEPROM memory (i.e. address 0) in steps of 2 all the way to the top of EEPROM memory. Read each value and compare it to the value from the previous address. If the latest value is less than the previous value, then you've found the last place you wrote to.

There will be special cases - there always are!

The first time you try this on a brand new chip that has not had anything written to the EEPROM, then all the EEPROM memory will have the same value in it. I think it's 255 (0xFF). The above test will fail. You could check for this by an EEPROM.get() of location 0 and location 2. If they are the same value (something that will not happen in your application), or the value in location 2 is not 1 more than the value in location 0, then you can assume that this is the first time the program has run and start correctly with address 0.

Another special case will be if the count goes up to the top of EEPROM so that you've written to the last pair of locations, and then there's a power cut or reset. You would need to know that address 0 was the next address to be written to. If you reach the top of EEPROM memory always satisfying the test that the value in each pair of memory locations is 1 more than the previous pair, then that will tell you that you have to start back at location 0 again.

Hope some of that makes sense!

Gates:
Good morning,

Why are you trying to complete the task in a very small program area? I don't understand why you don't apply the higher level systems that can handle your requests with greater efficient operations.

What higher level system are those?

Gates:
Good morning,

Why are you trying to complete the task in a very small program area? I don't understand why you don't apply the higher level systems that can handle your requests with greater efficient operations.

Sorry my dear friend but I I'm not sure what are you talking about.. unless you're Bill then definately I'll never understand :slight_smile:

markd833:
Ok, if you are not going to reset the counter (and you can't have a negative number of coffees!), then
I would suggest using an unsigned int so that you can count from 0 to 65535 coffees!

Yes, the EEPROM.put() and EEPROM.get() functions handle the size of the data type - in this case a 16-bit integer. So in order to avoid overwriting half of the previously stored value, you need to increment the address by 2 after each EEPROM.put().

In order to find the last coffee count written before reset/power-off, you would have a simple loop in start() that increments from start of EEPROM memory (i.e. address 0) in steps of 2 all the way to the top of EEPROM memory. Read each value and compare it to the value from the previous address. If the latest value is less than the previous value, then you've found the last place you wrote to.

There will be special cases - there always are!

The first time you try this on a brand new chip that has not had anything written to the EEPROM, then all the EEPROM memory will have the same value in it. I think it's 255 (0xFF). The above test will fail. You could check for this by an EEPROM.get() of location 0 and location 2. If they are the same value (something that will not happen in your application), or the value in location 2 is not 1 more than the value in location 0, then you can assume that this is the first time the program has run and start correctly with address 0.

Another special case will be if the count goes up to the top of EEPROM so that you've written to the last pair of locations, and then there's a power cut or reset. You would need to know that address 0 was the next address to be written to. If you reach the top of EEPROM memory always satisfying the test that the value in each pair of memory locations is 1 more than the previous pair, then that will tell you that you have to start back at location 0 again.

Hope some of that makes sense!

Mark I'll give it a try. Please let me get back to you in any case

Whel yet another tricky thing is that when I deleted the delays, in order to have better results with a timer, every time the loop runs, instead of writing 1 value into EEPROM it writes 6!
Any clue? Everything comes back to normal when I put a delay (1000)!

We can’t see your code.

TheMemberFormerlyKnownAsAWOL:
We can’t see your code.

You’re right

#include <elapsedMillis.h>

#include "U8glib.h"

#include <EEPROM.h>

U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE);

const int numReadings = 10;
int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0.0;                // the average
int inputPin = A2;

const int hall = A2; // for the hall sensor
float rawValue = 0.0;               // Raw ADC Reading
float zeroLevel = 522;  // Adjust value as needed to get zero rawValue output with no magnetic field.

int LED = 7; // for the led strip

int value; // for the coffees
int value2; // for the coffees
int valuecof; // for the coffees
int coffees = 0; // for the coffees
int eeAddress = 0; // for the coffees


unsigned long time = 0; // for the timer
unsigned long time1; // for the timer
unsigned long time2; // for the timer
elapsedMillis timeElapsed; // for the timer



}
void setup(void) {

  //time1 = millis() + 1;
  //time2 = millis() + 1001;

  // sets the digital pin as output
  pinMode(LED, OUTPUT);

  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}


  void loop(void) {
    u8g.firstPage();

    //_________________________Reading magnetic field_______________________

    pinMode (hall, INPUT);
    Serial.begin(9600);
    rawValue = analogRead (hall) - zeroLevel; // Output normalized to '0' with no field present
    Serial.print ("Reading Raw: ");
    Serial.println (rawValue);
    Serial.print ("Average: ");
    Serial.println (average);
    Serial.print(value);
    Serial.print("\t");
    Serial.print(value, DEC);
    Serial.println();


    //____________________________Smoothing_____________________________________


    // subtract the last reading:
    total = total - readings[readIndex];
    // read from the sensor:
    readings[readIndex] = abs(analogRead(inputPin)); //convert negative reading to positive
    // add the reading to the total:
    total = total + abs(readings[readIndex]);
    // advance to the next position in the array:
    readIndex = readIndex + 1;

    // if we're at the end of the array...
    if (readIndex >= numReadings) {
      // ...wrap around to the beginning:
      readIndex = 0;
    }

    // calculate the average:
    average = total / numReadings - 521.5;
    // send it to the computer as ASCII digits




    //____________Timer___________________________________________________________________

    if (average > 1) {
      time = timeElapsed / 1000;
    }
    else {
      timeElapsed = 0;
    }
    do {
      draw();
    } while (u8g.nextPage() );


    //____________Enable LED___________________________________________________________________

    if (average > 1) {
      digitalWrite(LED, HIGH);
    }
    else {
      digitalWrite(LED, LOW);
    }



    //____________Read Coffees___________________________________________________________________
if (average > 1 & time == 2) {
    for (eeAddress = 0; eeAddress < 1024; eeAddress + 2)
  {
    if (EEPROM.get(eeAddress,coffees) != 0)
              ++coffees;

        EEPROM.put(eeAddress, coffees); //One simple call, with the address first and the object second.


        value = EEPROM.get(eeAddress, coffees);
        

        if (eeAddress == EEPROM.length()) {
          eeAddress = 0;

        }
      }
    }

  }

I want to sample 10 readings every millisecond so I can have a good average from my hall sensor
But then the EEPROM writes 6 values. When I set a delay(1000) the EEPROM works just fine but I’m loosing the average due to slow sampling

Any idea?

Please ignore the garbage coding. I will wrap it up at the end

Why do you keep starting the serial interface in loop ()?
Why the pinMode in loop ()?
Why are you taking abs of an analogRead?

Please use the IDE’s auto-format tool before posting code.

The code in reply #14 doesn’t compile. But you already knew that.

TheMemberFormerlyKnownAsAWOL:
Why do you keep starting the serial interface in loop ()?
Why the pinMode in loop ()?
Why are you taking abs of an analogRead?

Please use the IDE's auto-format tool before posting code.

The code in reply #14 doesn't compile. But you already knew that.

But I told you that it has a lot of garbage. It is a mixture of many sketches combined into one and I didn't have time for getting it pretty.

Also it was not all the code. I deliberately deleted some code that had to do the printing of results to an OLED. The original code compiles just fine.

I'm takinh abs of the analog read due to big fluctuation of the measurements on the magnetic field. I don't have a sensor with big resolution and I want the response from the measurements to trigger the actions immediately.

Did you manage to see why when I deleted the delays, in order to have better results with the timer, every time the loop runs, instead of writing 1 value into EEPROM it writes 6!
Everything comes back to normal when I put a delay (1000)!

If you need the original code I'll post it. Just have to take care of the garbage

I’m takinh abs of the analog read due to big fluctuation of the measurements

Fluctuations so big, analogRead returns negative values?
Slow down.
Stop and think.

TheMemberFormerlyKnownAsAWOL:
Fluctuations so big, analogRead returns negative values?
Slow down.
Stop and think.

Oh come on don't be so hard to me. I saw what you're saying. It's there by mistake
if you see I put it 2 lines below on the readings and forgot to delete it and I thought you're saying about that
I told you I'll clear the mess

Thank you but please don't pay attention to the coding but to the real problem.

Why it's writing 6 values instead of 1 when there's no delay?

The coding is the real problem.
Don’t be obtuse.

You wouldn’t say “my roof has collapsed, but ignore the fact that my house has no foundations and is built in an estuary”