EEPROM Countdown timer

Hello there!

I made a countdown timer (the elapse time can be changed via 4 push buttons). But every time it is powered, I have to set the time interval. I saw that the arduino have internal memory (the EEPROM).
Can i save the last settings of the timer? Can I save a number in that memory? And how to do so? Because all of the tutorials I saw, the were for saving the readings from analog input. Or is it the same in my case?

I have no experience in that area. Any help will be appreciated.

Can i save the last settings of the timer?

Permission granted.

Can I save a number in that memory?

Yes.

And how to do so?

EEPROM.write(addr, valu);

Or is it the same in my case?

Where the value to be stored came from is irrelevant.

Study the examples in the EEPROM library included with the IDE. File>examples>EEPROM

In particular study EEPROM.put() and EEPROM.get()

This is what happened.
First I put some data in the EEPROM like this:

#include <EEPROM.h>
struct MyObject{
  int field1;
};

void setup(){

  Serial.begin(9600);
  }

  int a = 10;
  int b = 20;
  int eeAddress = 0;
  int eeAddress1 = 1;

  EEPROM.put( eeAddress, a );
  EEPROM.put( eeAddress1, b );
  
  
  Serial.println("Written float data type!");

  Serial.print( "Written custom data type! \n\nView the example sketch eeprom_get to see how you can retrieve the values!" );
}

void loop(){ /* Empty loop */ }

Then I get the data, like this:

#include <EEPROM.h>

void setup(){
  
  int a;
  int b;
  int eeAddress = 0;
  int eeAddress1 = 1;
  Serial.begin( 9600 );
  Serial.print( "Read float from EEPROM: " );
  EEPROM.get( eeAddress, a );
  Serial.println(a,1);
  EEPROM.get( eeAddress1, b );
  Serial.println(b);
}
void loop(){ /* Empty loop */ }

And in the serial monitor I get:

"Read float from EEPROM: 5130
20"

Where is the problem?

void setup(){

  Serial.begin(9600);
  }//<<<<< Hey, what are you doing here?

Still the same problem appeared.

You didn't store a float in EEPROM, so the message about reading one is nonsense.

The variable that you stored the data read from EEPROM in is an int, so what do you suppose that the second argument is doing, when the first is not a float?

How many bytes does an int take? How many are you allowing for?

Well the message is leftover from the example sketch.
I want to store two (or more) different numbers (secs. and mins. for the countdown timer). Obviously this is not the way.

How many bytes does an int take? How many are you allowing for?

I don't know.

I want to store two (or more) different numbers (secs. and mins. for the countdown timer).

How big will your numbers be? If they are always less than 255, they will fit into a byte and you can store them using eeprom.write() and eeprom.read() which write one byte to one address location.

If your numbers are bigger and are typed as ints, then you will need the eeprom put and get functions which can handle multi byte read and writes. When you do this, you need to think about address management.

Quote
How many bytes does an int take? How many are you allowing for?
I don't know.

If you are going to advance in your programming, you need to learn about data types and their size in bits and bytes.
Review the section called Data Types on the reference page http://www.arduino.cc/en/Reference/HomePage

There will be two timers, and I need to store the minutes for TMR1 (max 30 min.) and TMR2 (max 5 mins.), also the seconds for the two timers (max 60 secs. for both timers). Also I need to store the time that the countdown timer has been working in hours, max to 1500h.

If all of my numbers for mins and secs. are "bytes", do I need to transfer them into decimal format? Or can I just make all of them "ints"? For the time that the countdown timer has been working, I think I must go with "int". Am I wrong?

For the time that the countdown timer has been working, I think I must go with "int". Am I wrong?

You are correct, the time that the countdown timer has been working will need to be stored as an int.(two bytes) The other times can be stored as single bytes.

If all of my numbers for mins and secs. are "bytes", do I need to transfer them into decimal format?

I don't know what you mean by this.

Each eeprom address can hold one byte (8 bits). A byte is just an 8 bit unsigned number with a value between 0-255. The number can be expressed in binary (base 2), decimal (base 10) or hexidecimal (base 16). These are just human readable forms of the same value.

The int will be stored in two addresses, one containing the high byte and the other the low byte. eeprom.put and eeprom.get will know how to read and write the two addresses but you will need to manage the starting address parameter for the function.

The int will be stored in two addresses,

So, if Iwant to store two integers (int1 and int2), it must be likethis:?

eeAddress_int1 = 0
eeAddress_int2 = 2

not like this

eeAddress_int1 = 0
eeAddress_int2 = 1

Am I correct?

Stan_be:
Am I correct?

You started with EEPROM.h which allows you to save a struct object, so go with that. this example allows you to save the hour, minute and second to a single EEPROM address, so you don't have to worry about the size of the object.

I've added in an overloaded operator so that you can also easily compare two TimeVar objects for equality.

Try this, looking at the Serial monitor and let the program run for 20 seconds. after that, the EEPROM will be updated for a new time. then re-start your arduino and look at the output again.

#include <EEPROM.h>

struct TimeVar {
  byte hour;
  byte minute;
  byte second;
  bool operator == (const TimeVar& t)
  {
    return (hour == t.hour && minute == t.minute && second == t.second);
  }
  bool operator != (const TimeVar& t)
  {
    return (hour != t.hour || minute != t.minute || second != t.second);
  }
};

TimeVar remainingTime;
const TimeVar defaultTime = {0, 10, 30};  // program default time is 00:10:30 , zero hours, ten minutes and thirty seconds

unsigned long startTime = 0;
bool updated = false;

void setup()
{
  Serial.begin(9600);
  TimeVar storedTime;
  EEPROM.get(0, storedTime);
  if (storedTime != defaultTime)
  {
    remainingTime = storedTime;
  }
  else
  {
    remainingTime = defaultTime;
  }
  Serial.print("Countdown Time:");
  char buffer[15] = "";
  snprintf(buffer, sizeof(buffer), "%2d:%2d:%2d, ", remainingTime.hour, remainingTime.minute, remainingTime.second);
  Serial.print(buffer);
  Serial.println(remainingTime == defaultTime? "the default time." : "the stored time");
}

void loop()
{
  if(millis() -  startTime > 20000UL && !updated)
  {
    TimeVar newTime = {1,20,30};
    EEPROM.put(0,newTime);
    Serial.println("stored time updated");
    updated = true;
  }
}

So, if Iwant to store two integers (int1 and int2), it must be likethis:?

eeAddress_int1 = 0
eeAddress_int2 = 2

not like this

eeAddress_int1 = 0
eeAddress_int2 = 1

Am I correct?

Yes.

You started with EEPROM.h which allows you to save a struct object, so go with that.

What happens to the size of that struct when you start adding code to it? Does that code get saved in EEPROM?

PaulS:
What happens to the size of that struct when you start adding code to it? Does that code get saved in EEPROM?

If I understand you correctly, no, only the data members are saved (non static). The code, if used, will reside in flash with all the other code.

Storing data like this: a=10; b=20;

#include <EEPROM.h>

int a = 10;
int b = 20;
int eeAddress1 = 0;
int eeAddress2 = 3;
void setup(){

  Serial.begin(9600);
  
  EEPROM.put( eeAddress1, a );
  EEPROM.put( eeAddress2, b );
  
  Serial.println("Written float data type!");
}

void loop(){ /* Empty loop */ }

Retrieving data:

#include <EEPROM.h>

void setup(){
  
  int a;
  int eeAddress1=0;
  int b;
  int eeAddress2=3;
  
  
  Serial.begin( 9600 );
  Serial.print( "Read float from EEPROM: " );
  EEPROM.get( eeAddress1, a );
  Serial.println( a );
  EEPROM.get(eeAddress1, b);
  Serial.println(b);
}
void loop(){ /* Empty loop */ }

And the result is not what i have stored:

"Read float from EEPROM: 10
10"

Where is the problem?

Using the same address variable here is your problem:

EEPROM.get( eeAddress[color=red][b]1[/b][/color], a );
Serial.println( a );
EEPROM.get(eeAddress[color=red][b]1[/b][/color], b);

Also, if you are using an Uno, or Mega, or AVR type Arduino, an int is two bytes. You can change your addresses slightly:

int eeAddress1 = 0;
int eeAddress2 = [color=red][b]2[/b][/color]; // Not 3
  EEPROM.get( eeAddress1, a );
  Serial.println( a );
  EEPROM.get(eeAddress1, b);
  Serial.println(b);

Shouldn't the second get use address2 rather than address1 ?