# Move a servo slowly between 2 positions based on input

I am trying to move model railroad crossing gates from a vertical position to a horizontal position when a train is detected. I have the electronics in for the sensing of train position but want the gates to go down and stay down while the train passed.

To do this, I am looking to be able to use an Arduino to slowly move a servo between two different positions based on a digital input (HIGH or LOW) to one of the digital input pins.

When this digital input goes HIGH, the servo needs to slowly move to the other end of travel and then stop. It must stay there until the digital input goes LOW, at which time it needs to slowly move back to the starting position and again await for a HIGH input.

I cannot figure out how to move the servo slowly to each position and keep it there.

Lacking information about the context of the servo action (ie, what needs to happen at the same time), I'll assume your paradigm uses a `loop()` function that executes fairly rapidly, and from time to time invokes any necessary actions.

Servo angles can be measured in degrees (typically 0 to 180) or microseconds (typically 1000 to 2000, corresponding to 0° to 180°). The servo library will accept numbers in either range, and act according to which range the numbers are in. Note that representing servo angles in microseconds instead of degrees gives about 5.55 times better resolution. The method outlined below doesn't care which you use.

Also assume the two servo angles mentioned in the question are A and B, with the servo at A if the input pin is low for a long time; and that the desired rate of swing is ±U units of angle every S milliseconds. Let P = current servo position; T = `millis()` value at most recent step, initially 0; and V = previous value of input pin.

In each pass through `loop()`:

• Test the input pin. If it isn't equal to V, toggle V and take a step. (See below.).
• If `millis()`-T > S, take a step. (See below.)
• Do any other brief per-loop actions

To take a step:
• Add (2*(V>0)-1) * U to P. The expression (V>0) equals 1 or 0, so (2*(V>0)-1) is 1 if V is true, and -1 if V is false.
• If (V) and P > B, set P = B
• If (!V) and P < A, set P = A
• Servo to position P
• Set T = `millis()`

Edit: You should create meaningful variable or constant names to represent the quantities A, B, P, S, T, U, V. Note that S and T should be declared as constants; and if A, B won't change, make them constants also. State-maintaining quantities P and T should be declared via file-scope variables or globals (outside `loop()`) or with static allocation (inside `loop()`), so that their values are maintained as `main()` repeatedly calls `loop()`.

• Thank you for your help. It should get me going on the project. I am trying to move model railroad crossing gates from a vertical position to a horizontal position when a train is detected. I have the electronics in for the sensing of train position but wanted the gates to go down and stay down while the train passed. Apr 17 '17 at 1:39
• I see how you are incrementally increasing or decreasing the servo position without going beyond the boundaries of the preset servo positions. I am not sure, however, how to get the servo to stay in the assigned positions since the variables are reinitialized each time it goes through the loop. Are some of these static variables? Sorry if stupid questions. New to Arduino programming. Apr 17 '17 at 3:03
• @BobPerry, see edit. Note, please upvote or accept answer if useful. Apr 17 '17 at 22:51
• Thanks. Setting up the variables as static didi the trick! Apr 20 '17 at 4:14