Storing servo position on EEPROM

Hello, everybody.

I am trying to simulate protected railway gates using two servos and Arduino Uno.

Random PLC will be switching Arduino ON and OFF, thats why servos position in degrees has to be stored on EEPROM.

Procedure:

PLC turns Arduino ON: Servo horn turns 90° // from vertical(90°) to horizontal position(0°) // position at 0° is written to EEPROM
PLC turns Arduino OFF: Servo horn stays in horizontal position(0°)
PLC turns Arduino ON: Position is read from EEPROM // servo horn turns 90° // from horizontal(0°) to vertical position(90°)
PLC turns Arduino OFF: Servo horn stays in vertical position(90°)

The cycle repeats.

I am assuming only position at 0° needs to be stored on EEPROM in order to work properly but for the sake of timing accuracy when switching ON and OFF, and change in degrees, I would also like to store positions at 1°, 2°, and 3°. So if for example servos horn stops at 3° when PLC turns Arduino OFF, it doesn’t go on to 0° when turned ON again, instead it goes back to 90°.

Below I gathered some code that might be helpful. I tried to put it together to work properly but my programming knowledge is not that great.

Any kind of help is highly appreciated, especially if someone could write the appropriate code for this task.

// Servo Sweep (modified for my example)

#include <Servo.h>

Servo servo1;
Servo servo2;

int pos = 90;                            // variable to store the servo position

void setup() {
  servo1.attach(9);                      // attaches the servo on pin 9 to the servo object
  servo2.attach(10);                     // attaches the servo on pin 10 to the servo object
}

void loop() {
  for(pos = 0; pos <= 90; pos += 1) {    // goes from 0 degrees to 90 degrees in steps of 1 degree
    servo1.write(pos);                   // tells the servo to go to position in variable 'pos'
    servo2.write(pos);                   // tells the servo to go to position in variable 'pos'
    delay(15);                           // waits 15ms for the servo to reach the position
  }
  for(pos = 90; pos >= 0; pos -= 1) {    // goes from 90 degrees to 0 degrees in steps of 1 degree
    servo1.write(pos);                   // tells the servo to go to position in variable 'pos'
    servo2.write(pos);                   // tells the servo to go to position in variable 'pos'
    delay(15);                           // waits 15ms for the servo to reach the position
  }
}

----------------------------------------------------------------------------------------------

// Save Servo Position on EEPROM (forum topic http://forum.arduino.cc/index.php?topic=155924.0)

if(Serial.available() > 0) {
  data = Serial.read();
}

switch(data) {
case 'X':
case 'x':
  EEPROM.write( 1, servo1 position);
  EEPROM.write( 2, servo2 position);         
  break;
case 'Y':
case 'y':
  pos1 = EEPROM.read(1);
  servo1.write(pos1);
  pos2 = EEPROM.read(2);
  servo1.write(pos2);         
  break;
default:
  break;
}

----------------------------------------------------------------------------------------------

// Arduino EEPROM example - store led state (example from https://www.youtube.com/watch?v=P7s_VQhq4CY)

#include <EEPROM.h>

int ledpin1 = 10;
int ledpin2 = 11;
int ledpin3 = 12;
int val;
int val2;
int addr = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(ledpin1, OUTPUT);
  pinMode(ledpin2, OUTPUT);
  pinMode(ledpin3, OUTPUT);
  delay(200);
  Serial.println(EEPROM.read(addr));
    val2 = EEPROM.read(addr);
    switch (val2) {
    case 1:
    digitalWrite(ledpin1, HIGH);
    digitalWrite(ledpin2, LOW);
    digitalWrite(ledpin3, LOW);
      break;
    case 2:
    digitalWrite(ledpin2, HIGH);
    digitalWrite(ledpin1, LOW);
    digitalWrite(ledpin3, LOW);
      break;
    case 3:
    digitalWrite(ledpin3, HIGH);
    digitalWrite(ledpin1, LOW);
    digitalWrite(ledpin2, LOW);
      break; 
  }
}

void loop(){
  if (Serial.available()>0)
  {
  setLed();
  }
}

void setLed(){
    val = Serial.read();
    if(val == '1')               
  {
    digitalWrite(ledpin1, HIGH);
    digitalWrite(ledpin2, LOW);
    digitalWrite(ledpin3, LOW);
    EEPROM.write(addr, 1);
    Serial.println(EEPROM.read(addr));
  }
      if(val == '2')               
  {
    digitalWrite(ledpin2, HIGH);
    digitalWrite(ledpin1, LOW);
    digitalWrite(ledpin3, LOW);
    EEPROM.write(addr, 2);
    Serial.println(EEPROM.read(addr));
   }
     if(val == '3')               
  {
    digitalWrite(ledpin3, HIGH);
    digitalWrite(ledpin1, LOW);
    digitalWrite(ledpin2, LOW);
    EEPROM.write(addr, 3);
    Serial.println(EEPROM.read(addr));
   }
}

----------------------------------------------------------------------------------------------

// This example reads the byte value at address 28 in EEPROM
// memory every second, and sends it over the serial line.
// It then cyclically increments that value by one, and
// writes it to the same address in EEPROM memory.
// After removing the power from the i/o board, counting
// picks up where it left off, because values stored in
// EEPROM memory retain their value when power is lost.
// (example from http://liacs.leidenuniv.nl/~lamersmh/arduino/code/ard10_eeprom.txt)

#include <EEPROM.h>          // import eeprom functions

void setup() {
  Serial.begin(9600);        // start serial communication
  Serial.println("Powerup"); // show when the program restarts
}

void loop() {
  byte b = EEPROM.read(28);  // read byte value from eeprom address 28
  Serial.println(b, DEC);    // print that value via the serial port
  b = (b+1) % 256;           // cyclically increment the value
  EEPROM.write(28, b);       // write its new value to eeprom address 28
  delay(1000);               // waste one second
}

(deleted)

Aren't forums meant to give help for free? Though I know its not simple.

(deleted)

I agree, based on my example and request. I will keep you willingness to help in mind. I am going to try harder to make it work for the sake of my own appreciation later on. If I won't manage I will contact you in private. Thank you.

(deleted)

Any kind of help is highly appreciated, especially if someone could write the appropriate code for this task.

How much effort is it to call EEPROM.write() at the appropriate place, and EEPROM.read() at the appropriate place?

For you I guess 0. :)

Thank you spy. I will see what I can do.:)

Barko: For you I guess 0. :)

For you too. Do a little reading on EEPROM and Arduino. None of it is hard.

What part confuses you? Do you know how to read or write to EEPROM? Paul just gave you a big hint but reading up on those would be good. Do you need to know where to put those in code? I'd put them at the points you want the reads and writes to happen. Sounds like at the point where Arduino is turned on and off. Is it some other part that is confusing?

Thank you Delta_G for your willingness to help. :) I didn't see your post before and atm. its a bit late so I will answer to your questions in the morning, if you don't mind :) gn

if you code only does one thing then stops until next time it is rebooted, then you would put all the code in the setup() method:

void setup() {
  set up the pinModes
  read boolean value from eeprom
  if value
    move servo to 90
  else
    move servo to 0
  end if
  write boolean !value to eeprom
}

Normally, however, you would leave the arduino running, have the PLC send some sort of signal (ie: instead of +5v to power the arduino on, just put +5v on an input pin), and write a loop. This even allows the arduino to set an output pin for the PLC to read (if this PLC can do that), and also means that you aren't waiting for the arduino boot-up every time a train comes.

int pulse;
boolean gate;

setup() {
  set up the pinModes
  move the servo to 0
  digitalWrite(PLC out, LOW)
  pulse = digitalRead(PLC in)
  gate = false;
}

loop() {
  int prevPulse = pulse
  pulse = digitalRead(PLC in)
  if(prevPuls == LOW && pulse == HIGH) {
    // incoming! move the gate!
    gate = !gate;
    if(gate) {
      move the servo to 90
      digitalWrite(PLC out, HIGH)
    }
    else {
      move the servo to 0
      digitalWrite(PLC out, LOW)
    }
  }
}
[code]

Thank you PaulMurrayCbr for explaining your way of solving the problem.:)I will first try the easier method and maybe later your advanced method, though I doubt I can handle it:) Yes the PLC can read an output signal from Arduino. It could work.

Delta_G I am working on my code one more time, I will let you know what confuses me after testing.

Ok I’ve tried and tested my code multiple times and came to a dead end though this is the closest I ever came to a solution.

Change: Servos horn move/turn from 0° to 90° and not vice versa like written in procedure(though still from vertical to horizontal position).

The pos value of 90 is written to EEPROM, I can see that in serial communication but it doesn’t read that value after Arduino is reset or turned ON again, instead it “jumps” back to 0° like usual.

The pos value of 0 is also written to EEPROM but that’s not crucial, used just for testing.

I don’t have any idea of what might be missing or what might be wrong with my written code.

Any suggestions/corrections? Please feel free to answer.

#include <Servo.h>
#include <EEPROM.h>

Servo servo1;
Servo servo2;

int pos;

void setup(){
  Serial.begin(9600);
  Serial.println("Powerup");
  pos = EEPROM.read(pos);
  Serial.println(EEPROM.read(pos));
  servo1.attach(9);
  servo2.attach(10);
}

void loop(){
    for(pos = 0; pos <= 90; pos += 1){ // starting at 0° and not at 90° like written in procedure(forum)
      servo1.write(pos);
      servo2.write(pos);
      delay(60);
      if(pos >= 81){ // 10 degrees range for manual switching OFF i.e. testing EEPROM with reset button or plugged-out usb cable 
        pos = 90;
        EEPROM.write(pos, 90);
        Serial.println(EEPROM.read(pos));
      }
    }
    for(pos = 90; pos >= 0; pos -= 1){
      servo1.write(pos);
      servo2.write(pos);
      delay(60);
      if(pos <= 1){ // this if statement not necessary, used just for testing
        pos = 0;
        EEPROM.write(pos, 0);
        Serial.println(EEPROM.read(pos));
      }
    }
}
pos = EEPROM.read(pos);

At the this point you're telling it to read from EEPROM address 0.

But here:

pos = 90;
        EEPROM.write(pos, 90);

you wrote to address 90.

pos is the value you want to write. But you shouldn't use that for the address too. Set a constant to use the same address every time.

I see. So if I get this right. Const for example: int val?

val = EEPROM.read(pos)?

EEPROM.write(pos, 90); // Isn't pos the address and 90 the value for it?

Syntax

EEPROM.write(address, value)

Source: https://www.arduino.cc/en/Reference/EEPROMWrite

Barko: I see. So if I get this right. Const for example: int val?

val = EEPROM.read(pos)?

EEPROM.write(pos, 90); // Isn't pos the address and 90 the value for it?

OK sure. if you want pos to be the address then yes you have that second statment correct.

But in that case you should set pos to 90 at the very beginning when you create it and not change it. And definitely don't read the position back into it.

But in other places in your code you have:

servo1.write(pos);

which implies that pos is the servo position and not the EEPROM address. It can't be both is all I'm saying.

I see.

Delta_G: But in other places in your code you have:

servo1.write(pos);

which implies that pos is the servo position and not the EEPROM address. It can't be both is all I'm saying.

Didn't know this affects.

Well thank you for your time and help, have to change and try again.

(deleted)