Fun with Arduino 18 Railway Crossing Servo Motor to Operate the Gate

Servo_SG90We can use a servo motor to operate the gate. Servo’s can be had in different sizes, strengths and qualities, like fitted with plastic or with metal gears. For our purpose a cheap SG90 type servo will do fine. They can be had for under €2,-, but even at that price we get quite some amazing technology with multiple components all packed inside the tiny housing:

  • servo_internala DC motor
  • a control circuit, partly digital, partly analog
  • a potentiometer for angle measurement feedback
  • a gearbox

Servo_Control

The servo uses a closed loop feedback control system. The shaft angle is measured and a motor current is generated when the measured angle differs from the target angle. When it has reached the target angle, it wants to stay there. Any force that tries to change the angle will be counteracted by sending a current to the motor. This is why you can sometimes hear them rumble a bit.

Servo_WiringBy the way, tiny as they are, they can be quite hungry for current. One or maybe two SG90 servos can safely be powered from the Arduino on board 5V, but if you have more, then connect them to a separate 5V power supply. Take care that the GND of that supply is connected to the GND of the Arduino.

The control signal to be sent to the servo looks much like a pwm signal. We do not have to generate this signal ourselves, it is taken care of by servo functions that come available once we’ve included the servo library. A maximum of 12 servo’s can be controlled by an Arduino UNO and we have to give every servo a name. Let’s name ours gate_servo. Now we can use an instruction like gate_servo.write(35) to rotate the servo to a 35 degrees angle.

A standard SG90 servo has a range of 0-180 degrees. If we don’t take measures, the servo moves at maximum speed. We want it to rotate at a controlled speed however and we can do that with a similar technique as we did with LED fade: we increment or decrement the angle step by step with an interval time.

Read on below the video …

Enough theory … let’s connect a servo and play with it. The code is almost similar to the LED fade code we used in video 16, with a few additions for the servo:

  • The servo library is loaded: #include
  • A servo object is created: Servo gate_servo;
  • The servo is connected to a pin: gate_servo.attach(SERVO_PIN);
  • An angle is sent to the servo with: gate_servo.write(angle);

The servo moves from angle A to angle B when we toggle the switch. Angle B can be changed with the potentiometer. The speed is determined by the SERVO_SPEED interval time in ms. In the code the word ‘setpoint’ is used in stead of ‘target’ because this is more custom in control systems.

#define SWITCH_PIN    2
#define SERVO_PIN     3
#define GATE_SPEED   50 // [ms] lower number is higher speed
#define GATE_OPEN    45 // angle
#define GATE_CLOSED 135 // angle
#define POTM_PIN     A0

#include 
Servo gate_servo; // creates a Servo with the name 'gate_servo'

byte angle    = GATE_OPEN;
byte setpoint = GATE_OPEN;
unsigned long time_for_servo;

void setup() {
  pinMode(SWITCH_PIN,INPUT_PULLUP);
  gate_servo.attach(SERVO_PIN);
  Serial.begin(9600);
}

void loop() {

  if(digitalRead(SWITCH_PIN) == LOW)
    setpoint = map(analogRead(POTM_PIN), 0, 1024, 2 , 179);
// alternative: setpoint = GATE_CLOSED; 
  else
    setpoint = GATE_OPEN;

  if (millis() > time_for_servo) {
    time_for_servo = millis() + GATE_SPEED;
    if (angle < setpoint) angle++;     if (angle > setpoint) angle--;
    gate_servo.write(angle);
    Serial.print(setpoint);
    Serial.print("  ");
    Serial.println(angle);
  }
}

Let’s test this … yes … the servo moves when we toggle the switch and we can change the angle with the potentiomenter.

With our railway crossing we will use fixed angles for the gate servo, approximately 90 degrees apart. We can use this sketch to find the correct angles and later put them in the code.

Optical_SensorOn to the next challenge … we need to detect a train. We’ll use optical sensors for that … like this one. (Click to enlarge.)

— 0 —

12 thoughts on “Fun with Arduino 18 Railway Crossing Servo Motor to Operate the Gate

  1. The servo library seems to be missing? #include I think?
    In the UnoArduSim, the sketch fails to compile at the ‘if’ statement but I’ve no idea why – help!!

    Like

    • The servo library is included by default, it doesn’t have to be explicitly included.
      What happens if you compile the file in the standard Arduino IDE?

      Like

      • Rudy,
        Yes, it sees the simulator is not 100% as the IDE! I have got a sketch from a guy in Canada via the TrainBoard forum. I had a problem with his code on the simulator as well, but all this adds to my very basic abilities with Arduino. My next task will be to use your turntable sketch to automate my turntable, but I have to alter it for a 60:1 ratio between the motor and bridge shafts. I will need to wait for warmer weather as my shed is a bit too cold at present! Cheers, Keith

        Like

  2. Hi Rudy,
    very nice project, congratulation. My question is, how can I increase the servo speed? I modified the value here: #define GATE_SPEED 50 // [ms] lower number is higher speed. I swap value 50 to 1 but the servo is still too slow. Any idea? I look forward to your answer. Thanks, Matt

    Like

    • I have no idea … this is the instruction (at the bottom of the code) where the new time to move the servo is set:
      time_for_servo = millis() + GATE_SPEED;
      I see no reason why it shouldn’t work, although 1 ms seems like a very short time to me. Why not first try 20? If the speed doesn’t change, try putting the number directly in the code, like this:
      time_for_servo = millis() + 20;

      Like

  3. Hello Rudy!
    I want to add servo.attach() and detach() commands to avoid buzzing the servo in the rest positions. Can you help me where I need to add? Thanks in advance! Szabolcs

    Like

    • There’s a line of code where the servo angle is compared with the setpoint and if it’s not equal one degree is added or subtracted. Here you can add to attach the servo and if angle = setpoint then detach,

      Like

      • Thanks for the quick reply, Rudy! Did you mean this one:

        if (millis() > time_for_servo) {
        time_for_servo = millis() + GATE_SPEED;
        if (angle setpoint) pos–;
        servo.attach(8);
        servo.write(setpoint);
        if (angle = setpoint) servo.detach();
        }

        Like

  4. With havin so much written content do you ever run into any problems of plagorism or copyright violation? My site has a lot of exclusive content I’ve either written myself or outsourced but it seems a lot of it is popping it up all over the internet without my authorization. Do you know any techniques to help stop content from being stolen? I’d truly appreciate it.|

    Like

Leave a comment