Go Down

Topic: Can I read EEPROM twice in one 'if' statement? (Read 319 times) previous topic - next topic

doublec4

Having some trouble here getting this bit of code to execute on my Arduino Pro Mini...


Code: [Select]

if(EEPROM.read(EEMEMORYCHECK1) != eevalues[EEMEMORYCHECK1] && EEPROM.read(EEMEMORYCHECK2) != eevalues[EEMEMORYCHECK2])          //checking to see if this is the very first time we will update the EEPROM to the default values
{
  for (int j = 0; j < EEPROM.length() ; j++)
  {
    EEPROM.write(j, 0);
  }
  for (int i = 0; i < EE_ARRAYSIZE; i++)
  {
    EEPROM.write(i, eevalues[i]);                                 //writes all of the default values to the eeprom memory
  }
}



Basically I'm storing my default values in the eevalues[] array that is initialized in my header.

What I'm trying to achieve is determine if this is the very first time I'm ever running this piece of code on my arduino. How I'm trying to do this is by comparing the first two bytes in the EEPROM to  two integers at positions EEMEMORYCHECK1 and EEMEMORYCHECK2 within the array.

The logic here is that it will be very statistically unlikely (I think) that 'out of the box' those first two bytes in EEPROM were randomly assigned the integer values I chose. Therefore, this piece of code should run the very first time the code ever runs. The first for loop basically clears all of the EEPROM, and the second for loop then puts my default values from my array into EEPROM memory. The next time this if statement is run, those memorycheck integers will match and I won't keep writing over EEPROM memory (to keep from wearing it out).

Sounds nice in theory but I can't get the if statement to run... if I remove the && and the second comparison then it works... but then I have a much greater chance that my new arduino will have a matching value in EEPROM!

Any help would be great! Thanks!


aarg

How I'm trying to do this is by comparing the first two bytes in the EEPROM to  two integers at positions EEMEMORYCHECK1 and EEMEMORYCHECK2 within the array.
You can only compare byte with int reliably if the int's value doesn't exceed 255. Please post the entire sketch so we can check for such hidden problems.
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

doublec4

#2
Oct 22, 2017, 11:22 pm Last Edit: Oct 22, 2017, 11:27 pm by doublec4
The entire sketch is huge but I've taken the parts that are applicable to this problem:

Code: [Select]


#include <EEPROM.h>

#define EEMEMORYCHECK1  0
#define EEMEMORYCHECK2  1
#define EEAUTOLOWER 2
#define EESPEEDLOCK 3
#define EEUPTIME    4
#define EEDOWNTIME  5
#define EEWINGUPTIME  6
#define EEWINGDOWNTIME  7
#define EESETSPEED 8
#define EEWINGMODE 9

#define EE_ARRAYSIZE 10

int eevalues[EE_ARRAYSIZE] = {0, 255, 1, 1, 5, 12, 5, 5, 100, 2};

void setup()
{

if(EEPROM.read(EEMEMORYCHECK1) != eevalues[EEMEMORYCHECK1] && EEPROM.read(EEMEMORYCHECK2) != eevalues[EEMEMORYCHECK2])          //checking to see if this is the very first time we will update the EEPROM to the default values
{
  for (int j = 0; j < EEPROM.length() ; j++)
  {
    EEPROM.write(j, 0);
  }
  for (int i = 0; i < EE_ARRAYSIZE; i++)
  {
    EEPROM.write(i, eevalues[i]);                                 //writes all of the default values to the eeprom memory
  }
}
else                                                              //else the program has been run before... load the eevalue array with the saved data in the eprom
{
  for (int i = 0; i < EE_ARRAYSIZE; i++)
  {
    eevalues[i] = EEPROM.read(i);                                 //sets the array entry at 'i' to the eeprom memory value at location 'i'
   
  }
}
}


None of the default values I put in the array are greater than 255... I'm sure there is probably a better way to achieve this but its the first thing I could think of.

I had some serial monitor output code in there to show me what the result was... basically it seems what was happening was that every EEPROM byte was set to 255... and then the first if statement was not being run although it should have been true, and it would skip to the else and run that. The result was that my eevalues[] array was filled with 255 in each entry.

Thanks!

cyberjupiter

#3
Oct 23, 2017, 02:49 am Last Edit: Oct 23, 2017, 03:00 am by cyberjupiter
Let's comment out unnecessary stuff in the code first to make sure we can write something on the eeprom.
We erase everything first by writing '0' and then check if the current value in eeprom is '0'.

I am modifying the code in #2
Code: [Select]
#include <EEPROM.h>

#define EEMEMORYCHECK1  0
#define EEMEMORYCHECK2  1

#define EE_ARRAYSIZE 10

int eevalues[EE_ARRAYSIZE] = {0, 255, 1, 1, 5, 12, 5, 5, 100, 2};

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

  /* clear every byte in eeprom */
  for (int j = 0; j < EEPROM.length() ; j++)
  {
    EEPROM.write(j, 0);
  }

  /* read eeprom to check if every byte in eeprom is 0 */
  for (int i = 0; i < EE_ARRAYSIZE; i++)
  {
    eevalues[i] = EEPROM.read(i);
    Serial.println(eevalues[i]);
  }
}

void loop()
{}


Now, at least you know that your eeprom contains NOTHING or all zeroes.

Start over by making sure that the 'if' will be executed.

Same as the code in #2 but we add another for loop outside the 'if-else' loop to read if we successfully written the values in eevalues[]. We add another array to store the read. We also add a Serial.println("some statements"); to make sure the if is executed.

Code: [Select]

#include <EEPROM.h>

#define EEMEMORYCHECK1  0
#define EEMEMORYCHECK2  1

#define EE_ARRAYSIZE 10

int eevalues[EE_ARRAYSIZE] = {0, 255, 1, 1, 5, 12, 5, 5, 100, 2};
int ee_ToCheck[EE_ARRAYSIZE];

void setup()
{
  Serial.begin(9600);
  if (EEPROM.read(EEMEMORYCHECK2) != eevalues[EEMEMORYCHECK2])         //checking to see if this is the very first time we will update the EEPROM to the default values
  {
    Serial.println("If succeeds, writing eevalues...");
    for (int i = 0; i < EE_ARRAYSIZE; i++)
    {
      EEPROM.write(i, eevalues[i]);
    }
  }
  else
  {
    Serial.println("the eeprom already been written, else will be executed...");
    for (int i = 0; i < EE_ARRAYSIZE; i++)
    {
      eevalues[i] = EEPROM.read(i);
    }
  }

  Serial.println("Reading eeprom back to check...");
  for (int i = 0; i < EE_ARRAYSIZE; i++) //our new for loop to read back the eeprom to confirm
  {
    ee_ToCheck[i] = EEPROM.read(i); //we store it in another array
    Serial.println(ee_ToCheck[i]); //print it
  }
}


void loop()
{}


However, I have to remove
Code: [Select]
if(EEPROM.read(EEMEMORYCHECK1) != eevalues[EEMEMORYCHECK1]

since our fresh eeprom contains all '0' and the value in evalues[EEMEMORYCHECK1] also contains '0'.

The 'if' will never get executed if you don't remove it.

EDIT: I edited the last code to add another Serial.println() so you can see whether if or else is run.




https://github.com/cyberjupiter
if you want to help me create (almost useless) libraries.

cyberjupiter

Now, assuming that your eeprom is virgin or has been erased to all zeroes, the if statement will always get executed if you run the code for the FIRST TIME.

Running it on the SECOND TIME and next time, will always execute else UNLESS EEPROM.read(EEMEMORYCHECK2) contains other value than 255.

https://github.com/cyberjupiter
if you want to help me create (almost useless) libraries.

PaulS

Code: [Select]
int eevalues[EE_ARRAYSIZE] = {0, 255, 1, 1, 5, 12, 5, 5, 100, 2};
The question was asked, and you tap-danced around not answering it. WHY is this array of type int? You are NOT storing ints in EEPROM.
The art of getting good answers lies in asking good questions.

cyberjupiter

Quote
Code: [Select]
int eevalues[EE_ARRAYSIZE] = {0, 255, 1, 1, 5, 12, 5, 5, 100, 2};
Well, his values in that example does not exceed 255, does it really matter in this case anyway?
https://github.com/cyberjupiter
if you want to help me create (almost useless) libraries.

BulldogLowell

Well, his values in that example does not exceed 255, does it really matter in this case anyway?
It is just 1) bad practice to mix the types and 2)wasteful of memory if indeed the values never exceed 0xFF.

cyberjupiter

Well, I just prefer solving the 'big' problem first, making OP get the desired result then start fixing those bad practice.
https://github.com/cyberjupiter
if you want to help me create (almost useless) libraries.

doublec4

Thanks for looking into this!

Your code will of course work because as you stated, you ran one program first to set all of the EEPROM values to 0. The next program you ran checked the EEPROM against MEMORYCHECK2 which is 255, so it will obviously be true and the if statement will execute.

However, a brand new Arduino out of the box could have all 0, all 255, or anything in between in the EEPROM memory, I believe.

So rather than write two programs - one to condition the EEPROM - and the next to write in the default values - I would like to do it all in one program.

It seemed that my EEPROM came out of the box with all values at 255. When I tried to read the first two bytes in my 'if' statement it would always come back false, despite the fact that one of the statements was true. As soon as I removed one of the memory check comparisons I could get the 'if' statement to be true.

Also, for those saying I shouldn't be using 'int' that is true. It was lazy of me to use int instead of byte.

PaulS

Quote
However, a brand new Arduino out of the box could have all 0, all 255, or anything in between in the EEPROM memory, I believe.
No. It will have all 255's. Of course, you could write a script that initialized all the addresses to some other value.

Quote
It seemed that my EEPROM came out of the box with all values at 255.
Well, it should have.
The art of getting good answers lies in asking good questions.

doublec4

Thanks Paul,

I was unaware that it will be 255 for each new arduino.

That makes my life much easier. I can just check it against the one value and set them all to 0 and proceed. (Also change my variable type to byte).


BulldogLowell

Thanks Paul,

I was unaware that it will be 255 for each new arduino.

That makes my life much easier. I can just check it against the one value and set them all to 0 and proceed. (Also change my variable type to byte).


you can also use the first few bytes to read/write an EEPROM key, for example:

Code: [Select]

#define EEPROM_KEY 0xDEADBEEFFEED

void setup()
{
  uint32_t eepromKey;
  EEPROM.get(0, eepromKey);
  if (eepromKey != EEPROM_KEY)
  {
    // initialize the eeprom
  }


then begin your EEPROM usage on location 4 of the EEPROM.

Go Up