Applying Robotics Learning in Unmanned Railway Crossing
Problems with unmanned railway crossing
In India, 61% of railway related fatalities are attributed to accidents at Unmanned Level Crossings as shown in fig.1.

Nearly two thirds of the total number of Level crossing accidents occur at unmanned Level Crossings and this proportion has been increasing ever since.
There are many ways to solve this problem. One solution could be to use manned crossing. Other one could be to use over bridges. But they have some drawbacks like making it manned will need more man power, cost, etc.
Moonpreneur students has created a passion project to solve this problem.
The project requires following items.
Required Items
- BBC Microbit and its cable
- 2 IR Sensors
- Servo Motor
- A toy train
(Any other object can also be used to mimic the action of train)
Age: 7-8 yrs
Let’s Start
Step1: Connecting IR Sensors
- Use a wire and connect one end to any pin of GND header in Microbit breakout board. Connect the other end with GND pin of IR sensor 1.

- Repeat the step for two more connections.
|
Microbit Breakout Board |
IR Sensor 1 |
|
3.3V |
VCC |
|
GND |
GND |
|
P0 |
OUT |
|
|
|

- Repeat the steps to connect another IR sensor.
|
Microbit Breakout Board |
IR Sensor 2 |
|
3.3V |
VCC |
|
GND |
GND |
|
P1 |
OUT |
|
|
|

NOTE: Calibrate the IR sensors by rotating the potentiometer such that it can sense the train/object from some appropriate distance.

Step2: Connecting Servo Motor
- Use a wire and connect one end to any pin of GND header in Microbit breakout board. Connect the other end with GND pin of servo motor.
- Repeat the step for two more connections.
|
Microbit Breakout Board |
Servo Motor |
|
3.3V |
VCC |
|
GND |
GND |
|
P2 |
Sig |
|
|
|

NOTE: Make sure that the arm of servo is mounted vertically (facing upwards) when the servo is at 0 degree position in order to get it horizontal when rotated to 90 degree.

Step3: Programming
The code monitors the passage of trains using infrared sensors. When a train enters the monitored area, it increments the count and closes the servo-controlled gate. When the train exits, it opens the gate.
Code
#*****************************
def __init__(self, pin, freq=50, min_us=600, max_us=2400, angle=180):
analog_period = round((1/self.freq) * 1000) # hertz to miliseconds
self.pin.set_analog_period(analog_period)
us = min(self.max_us, max(self.min_us, us))
duty = round(us * 1024 * self.freq // 1000000)
self.pin.write_analog(duty)
self.pin.write_digital(0) # turn the pin off
def write_angle(self, degrees=None):
degrees = math.degrees(radians)
total_range = self.max_us - self.min_us
us = self.min_us + total_range * degrees // self.angle
#***********************************
# Initialize servo motor on pin 2
sv1.write_angle(0) # Set initial angle of servo to 0 degrees
# Initialize variables to keep track of last state of IR sensors and train count
# Function to handle actions when train enters
IR2state = pin1.read_digital() # Read digital value from IR sensor 2
if IR2state != lastIR2state: # Check if state of IR sensor 2 has changed
if IR2state == 1: # If train exits (IR sensor detects no train)
sv1.write_angle(0) # Set angle of servo to 0 degrees (open position)
sleep(200) # Pause for 200 milliseconds
lastIR2state = IR2state # Update lastIR2state to current state
# Main loop to continuously check state of IR sensor 1
IR1state = pin0.read_digital() # Read digital value from IR sensor 1
if IR1state != lastIR1state: # Check if state of IR sensor 1 has changed
if IR1state == 0: # If train enters (IR sensor detects train)
sv1.write_angle(90) # Set angle of servo to 90 degrees (closed position)
sleep(200) # Pause for 200 milliseconds
count += 1 # Increment train count
lastIR1state = IR1state # Update lastIR1state to current state
display.show(count) # Display current train count on LED display
entered() # Call the entered function to handle train exit
# Imports go at the top
from microbit import *
#*****************************
class Servo:
def __init__(self, pin, freq=50, min_us=600, max_us=2400, angle=180):
self.min_us = min_us
self.max_us = max_us
self.us = 0
self.freq = freq
self.angle = angle
self.analog_period = 0
self.pin = pin
analog_period = round((1/self.freq) * 1000) # hertz to miliseconds
self.pin.set_analog_period(analog_period)
def write_us(self, us):
us = min(self.max_us, max(self.min_us, us))
duty = round(us * 1024 * self.freq // 1000000)
self.pin.write_analog(duty)
sleep(100)
self.pin.write_digital(0) # turn the pin off
def write_angle(self, degrees=None):
if degrees is None:
degrees = math.degrees(radians)
degrees = degrees % 360
total_range = self.max_us - self.min_us
us = self.min_us + total_range * degrees // self.angle
self.write_us(us)
#***********************************
# Initialize servo motor on pin 2
sv1 = Servo(pin2)
sv1.write_angle(0) # Set initial angle of servo to 0 degrees
# Initialize variables to keep track of last state of IR sensors and train count
lastIR1state = 1
lastIR2state = 1
count = 0
# Function to handle actions when train enters
def entered():
global lastIR2state
while True:
IR2state = pin1.read_digital() # Read digital value from IR sensor 2
if IR2state != lastIR2state: # Check if state of IR sensor 2 has changed
if IR2state == 1: # If train exits (IR sensor detects no train)
print("Train Exits")
sv1.write_angle(0) # Set angle of servo to 0 degrees (open position)
sleep(200) # Pause for 200 milliseconds
lastIR2state = IR2state # Update lastIR2state to current state
break # Exit the loop
# Main loop to continuously check state of IR sensor 1
while True:
IR1state = pin0.read_digital() # Read digital value from IR sensor 1
if IR1state != lastIR1state: # Check if state of IR sensor 1 has changed
if IR1state == 0: # If train enters (IR sensor detects train)
print("Train Entered")
sv1.write_angle(90) # Set angle of servo to 90 degrees (closed position)
sleep(200) # Pause for 200 milliseconds
count += 1 # Increment train count
lastIR1state = IR1state # Update lastIR1state to current state
display.show(count) # Display current train count on LED display
entered() # Call the entered function to handle train exit
# Imports go at the top
from microbit import *
#*****************************
class Servo:
def __init__(self, pin, freq=50, min_us=600, max_us=2400, angle=180):
self.min_us = min_us
self.max_us = max_us
self.us = 0
self.freq = freq
self.angle = angle
self.analog_period = 0
self.pin = pin
analog_period = round((1/self.freq) * 1000) # hertz to miliseconds
self.pin.set_analog_period(analog_period)
def write_us(self, us):
us = min(self.max_us, max(self.min_us, us))
duty = round(us * 1024 * self.freq // 1000000)
self.pin.write_analog(duty)
sleep(100)
self.pin.write_digital(0) # turn the pin off
def write_angle(self, degrees=None):
if degrees is None:
degrees = math.degrees(radians)
degrees = degrees % 360
total_range = self.max_us - self.min_us
us = self.min_us + total_range * degrees // self.angle
self.write_us(us)
#***********************************
# Initialize servo motor on pin 2
sv1 = Servo(pin2)
sv1.write_angle(0) # Set initial angle of servo to 0 degrees
# Initialize variables to keep track of last state of IR sensors and train count
lastIR1state = 1
lastIR2state = 1
count = 0
# Function to handle actions when train enters
def entered():
global lastIR2state
while True:
IR2state = pin1.read_digital() # Read digital value from IR sensor 2
if IR2state != lastIR2state: # Check if state of IR sensor 2 has changed
if IR2state == 1: # If train exits (IR sensor detects no train)
print("Train Exits")
sv1.write_angle(0) # Set angle of servo to 0 degrees (open position)
sleep(200) # Pause for 200 milliseconds
lastIR2state = IR2state # Update lastIR2state to current state
break # Exit the loop
# Main loop to continuously check state of IR sensor 1
while True:
IR1state = pin0.read_digital() # Read digital value from IR sensor 1
if IR1state != lastIR1state: # Check if state of IR sensor 1 has changed
if IR1state == 0: # If train enters (IR sensor detects train)
print("Train Entered")
sv1.write_angle(90) # Set angle of servo to 90 degrees (closed position)
sleep(200) # Pause for 200 milliseconds
count += 1 # Increment train count
lastIR1state = IR1state # Update lastIR1state to current state
display.show(count) # Display current train count on LED display
entered() # Call the entered function to handle train exit
Many pins of breakout board are available to add more features like a railway crossing sign.
References:
https://www.ispp.org.in/leveraging-technology-to-mitigate-traffic-congestion-at-manned-railway-crossings-in-india/
https://www.researchgate.net/figure/A-chart-showing-the-Loss-of-lives-in-train-accidents-in-percentage_fig1_306067468#:~:text=In%20India%2C%2061%25%20of%20railway,increasing%20ever%20since.%20