Integrating EEPROM into Code for Linear Actuator Position retention on UNO

I was wondering if someone could please assist me with adding the EEPROM function into the following Code for a Linear Actuator Project that I'm working on with my Arduino UNO. I got everything running but would like to retain the 3 Memory positions when the Power is turned off or lost and not familiar with the EEPROM function.

#include <Encoder.h>
#include <Button.h>

const int RELAY[] = {6,7}; //RELAY[0] and RELAY[1] to access the pins
const int BTN_EXTEND = 4;
const int BTN_RETRACT = 5;
const uint8_t MANUAL = 1; //a constant to indicate manual mode
const uint8_t AUTOMATIC = 2; //a constant to indicate automatic mode
const int BTN_MEM_PIN[] = {8,9,10};
const int BTN_SET_MEM = 11;

//Set up the linear actuator encoder
//On many of the Arduino boards pins 2 and 3 are interrupt pins
// which provide the best performance of the encoder data.
Encoder myEnc(2, 3);
long oldPosition = -999;
long targetPosition = 0;
#define ACCURACY 10 //How close to your target position is close enough. Higher accuracy may result in
// a bit of jitter as the actuator nears the position
#define DEBOUNCE_MS 20 //A debounce time of 20 milliseconds usually works well for tactile button switches.
#define PULLUP true //To keep things simple, we use the Arduino's internal pullup resistor.
#define INVERT true //Since the pullup resistor will keep the pin high unless the
//switch is closed, this is negative logic, i.e. a high state
//means the button is NOT pressed. (Assuming a normally open switch.)
uint8_t MODE = MANUAL;

Button btnExtend(BTN_EXTEND, PULLUP, INVERT, DEBOUNCE_MS);
Button btnRetract(BTN_RETRACT, PULLUP, INVERT, DEBOUNCE_MS);
Button btnSetPos(BTN_SET_MEM, PULLUP, INVERT, DEBOUNCE_MS);
Button btnPos1(BTN_MEM_PIN[0], PULLUP, INVERT, DEBOUNCE_MS);
Button btnPos2(BTN_MEM_PIN[1], PULLUP, INVERT, DEBOUNCE_MS);
Button btnPos3(BTN_MEM_PIN[2], PULLUP, INVERT, DEBOUNCE_MS);

long memPosition[] = {0,0,0};

void setup() {
pinMode(RELAY[0], OUTPUT);
pinMode(RELAY[1], OUTPUT);

Serial.begin(9600);
}

void loop() {

btnExtend.read();
btnRetract.read();
btnSetPos.read();
btnPos1.read();
btnPos2.read();
btnPos3.read();

if (btnExtend.isPressed()) {
extendActuator();
MODE = MANUAL;
}

if (btnRetract.isPressed()) {
retractActuator();
MODE = MANUAL;
}

if (!btnExtend.isPressed() && !btnRetract.isPressed() && MODE == MANUAL) {
stopActuator();
MODE = MANUAL;
}

if(btnPos1.wasReleased()) {
Serial.println("btnPos1");
MODE = AUTOMATIC;
targetPosition = memPosition[0];
}
if(btnPos2.wasReleased()) {
Serial.println("btnPos2");
MODE = AUTOMATIC;
targetPosition = memPosition[1];
}
if(btnPos3.wasReleased()) {
Serial.println("btnPos3");
MODE = AUTOMATIC;
targetPosition = memPosition[2];
}

//check the encoder to see if the position has changed
long newPosition = myEnc.read();
if (newPosition != oldPosition) {
oldPosition = newPosition;
Serial.println(newPosition);
}

if(MODE == AUTOMATIC && newPosition != targetPosition) {
Serial.print("Target/Actual:");Serial.print(targetPosition);Serial.print(" / ");Serial.print(newPosition);Serial.print(" [");Serial.print(abs(targetPosition - newPosition));Serial.println("]");
if(targetPosition < newPosition) {
Serial.println("AUTO RETRACT");
retractActuator();
MODE = AUTOMATIC;
}
if(targetPosition > newPosition) {
Serial.println("AUTO EXTEND");
extendActuator();
MODE = AUTOMATIC;
}
if( (targetPosition == newPosition) || abs(targetPosition - newPosition) <= ACCURACY) {
Serial.println("AUTO STOP");
stopActuator();
MODE = MANUAL;
}
}

if(btnSetPos.isPressed()) {
if(btnPos1.isPressed())
memPosition[0] = newPosition;
if(btnPos2.isPressed())
memPosition[1] = newPosition;
if(btnPos3.isPressed())
memPosition[2] = newPosition;

}
}

void extendActuator() {
//Serial.println("extendActuator");
digitalWrite(RELAY[0], HIGH);
digitalWrite(RELAY[1], LOW);
}

void retractActuator() {
//Serial.println("retractActuator");
digitalWrite(RELAY[0], LOW);
digitalWrite(RELAY[1], HIGH);
}

void stopActuator() {
//Serial.println("stopActuator");
digitalWrite(RELAY[0], HIGH);
digitalWrite(RELAY[1], HIGH);

}

Please follow the advice on posting code given in posting code

In particular note the advice to Auto format code in the IDE and to use code tags when posting code here as it prevents some combinations of characters in code being interpreted as HTML commands such as italics, bold or a smiley character, all of which render the code useless

What have you tried so far ?
There are examples for the EEPROM library available in the IDE

would like to retain the 3 Memory positions when the Power is turned off or lost

How frequently do you envisage saving the values, bearing in mind that the EEPROM has a limited number of write cycles ?

Sorry about the Code being posted improperly. The writes wouldn't be often maybe 100 Power Cycles per Year I just need the Memory to retain the programmed positions since all 3 are specific. I checked out the EEPROM Code but was unable to figure out the integration into the Code provided so I'm reaching out for help if there is another way please let me know

I presume that it is the memPosition array that you want to save and reload on power up or reset. There may be only 100 power cycles per year, but how often will the array values change and will the power cycles be controlled so that the values can be saved before they occur or will they be unplanned events ?

Depending on your answers the solutions will be very different

I checked out the EEPROM Code but was unable to figure out the integration into the Code provided so I'm reaching out for help

long memPosition[] = {0,0,0};

You will use the eeprom.h library with the .put() and .get() functions. Work some test examples with storing and retrieving a long integers.

A long integer will take 4 bytes of eeprom memory, so be sure you space the starting locations at least 4 addresses apart.

You will .get() the values in setup() which indeed runs after a power cycle.

I would use the .put() in the place where you change the values. For example

if(btnSetPos.isPressed()) {
   if(btnPos1.isPressed())
{
     memPosition[0] = newPosition;
     //store the changed value with .put() in the chosen memory location
}

The writes wouldn't be often maybe 100 Power Cycles per Year

Deciding when the power cycles and writing before the Arduino shuts down is an entirely different issue from writing the values when they change and retrieving them from memory at start up.
The spec if for 100K writes. How often do you change the target position?

Thank you for your reply cattledog. The 3 Positions will not change they should stay the same during the whole duration of use

UKHeliBob:
I presume that it is the memPosition array that you want to save and reload on power up or reset. There may be only 100 power cycles per year, but how often will the array values change and will the power cycles be controlled so that the values can be saved before they occur or will they be unplanned events ?

Depending on your answers the solutions will be very different

Yes the power cycles will be controlled and the array values shouldn't change since there is 3 specific Positions the Actuator needs to go to. Thank you for taking out your time and replying to my question

LooneyG:
Thank you for your reply cattledog. The 3 Positions will not change they should stay the same during the whole duration of use

If the positions do not change then why do you need to save and reload them

I note that your code has provision to change the values

if(btnSetPos.isPressed()) {
   if(btnPos1.isPressed())
     memPosition[0] = newPosition;
   if(btnPos2.isPressed())
     memPosition[1] = newPosition;
   if(btnPos3.isPressed())
     memPosition[2] = newPosition;

I was going to program the Positions as they were applied then save them. The Actuator will be in a somewhat enclosed space so measuring the actual Positions will be rather difficult but as I stated before "if there is another way please let me know" so I'm open to changes if possible :slight_smile:

I can envisage a system whereby there are buttons to adjust the 3 positions and a button to save the values to EEPROM. You might want to arrange that saving the value requires a particular sequence or combination of button presses to avoid the positions being accidentally saved

How will the project be powered and are you stuck with using a Uno or could you consider using an ESP8266 or ESP32 on which you could run a web server and communicate with it wirelessly ?

Power Source is a 12V Lithium Battery and the Arduino is the only thing I could find with a Project as shown. Currently to set a position the 1st Button has to be pushed and held to program any of the 3 Position Buttons that are available so the accidental reprogram shouldn't happen. I'm not too familiar with ESP8266 programming but I'm sure a Web Server would probably make this request somewhat easier

From what you say it sounds like there should not be a problem with wearing out the EEPROM so maybe your decisions are relly about how you will control and monitor the project

Using an ESP board running a web server would remove the need for physical buttons and the system could be access by any web browser. Other alternatives would be using wireless in some other way, such as Bluetooth or RF24, both of which could be done using a Uno and an add on module. The ESP32 has built in Bluetooth functionality and would require no extra hardware.

Once set up, Bluetooth provides a serial interface to your project and is, therefore, easy to program and test. A web server, on the other hand , can seem intimidating if you have never used HTML

The ESP32 has built in Bluetooth functionality and would require no extra hardware.

Once set up, Bluetooth provides a serial interface to your project and is, therefore, easy to program and test. A web server, on the other hand , can seem intimidating if you have never used HTML

Agreed. The ESP32 supports classic bluetooth and the serial interface programing is very simple. If you think you can control your project with a phone within 10 meters of the MCU its worth considering.

It's a cleaner configuration than an UNO with an HC05 BT module, and likely not much different in cost.

The ESP32 development modules, like this one, are inexpensive, powerful, and programable with the Arduino IDE. There are quadrature encoder libraries for the board.

Thank you for the suggestions UKHeliBob and cattledog I will look into possibly switching this Project over to a ESP32 Controlled System

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