Introduction
In this tutorial, we will learn how to use the 1) Ultrasonic Sensor 2) Servo and 3) LCD Screen with the Arduino Board to prototype a toll-gate for vehicles. This system is part of a larger train system I am working on with my group mates Leo and Neil, who each has also written wonderful tutorials on LED strip pattern response and peak weight detection using Arduino on this site – do check them out!
This system uses the Ultrasonic Sensor to detect nearby objects, and translates this information into motor motion in the Servo (the ‘toll gate’). Assuming the role of the serial monitor in Arduino, the LCD screen displays the distance between the Ultrasonic Sensor and the nearby object, and describes the action the ‘toll gate’ is about to take. The figure below illustrates this process.
You can also watch the following videos to better understand how this system performed!
The Toll-Gate response
The LCD Screen Response
The Components and Set-up
The components required for this tutorial’s set-up are listed below. Some components might not be available in your starter Arduino kit – highlighted are suggested links to sites where you can purchase those parts.
- Ultrasonic Sensor……………………………………………………Amazon
- Micro Servo Motor…………………………………………………Amazon
- LCD Screen………………………………………………………………Amazon
- Potentiometer…………………………………………………………from Arduino kit
- Arduino Board…………………………………………………………from Arduino kit
- Breadboard and Jumper Wires……………………………from Arduino kit
Because I love trains more than cars, my set-up closely mimics a train station system, with the ultrasonic sensor placed beneath the track to detect stationary trains at train stations:
(Feel free to come up with your own set-up design!)
(This was also a purely unintentional product placement. Really!)
A Note on How the Ultrasonic Sensor worked in this tutorial
The Ultrasonic Sensor comprises an emitter and a receiver. The emitter emits sounds ultrasound waves at 40 000 Hz that travels away from the sensor and through the air. If the sound waves hits an obstacle, they are reflected in an opposite direction back to the sensor, and received by the receiver. The time in microseconds between the emission and reception is recorded by the sensor.
This allows us to calculate the distance between the sensor and the object:
1 2 3 4 5 6 7 8 9 |
Speed of Ultrasound = 340m/second = 0.034cm/microsecond Distance travelled by Ultrasound = Time between emission and reception * Speed of Ultrasound Distance between object and sensor = Distance travelled by Ultrasound / 2 |
The sensitivity of the Ultrasonic Sensor may differ for different ranges of distances. When I was tinkering with the sensor, I realised that its accuracy in detecting very near objects (less than 2cm away) is highly inconsistent. My guess is that the Ultrasound is reflected too quickly back to the sensor, which then fails to register it as the reflected product of what was just emitted. Therefore, I set the minimum distance away from the sensor as 4cm, in order to produce a consistent response.
Wiring
As you have probably observed from the video, wiring for this project can get messy. Hopefully the Breadboard Diagram here helps:
Not pictured above is the power source – connecting this to your laptop or an external battery source works. Wires connecting to/from the 5V power source are red, while those connecting to/from the Ground are black.
As someone easily confused by too many bits and pieces, I found that wiring this section by section helps with managing the bundle of crisscrossing wires involved:
1. The Ultrasonic Sensor
The Ultrasonic Sensor I used (HC-SR04) has 4 pins in this order: Ground, Echo, Trig, and VCC.
Connect the Ground and VCC to the Ground and the 5V pins on the Arduino Board respectively. You can then connect the Echo and Trig pins to any of the Digital I/O pin on the Arduino Board. In this tutorial, I connected the Echo and Trig to 9 and 10 respectively.
2. The LCD Screen and its mate the Potentiometer
Wiring this part made me cross-eyed. Hopefully the figure below helps you avoid my pain:
As you can see, there are 16 pins on the LCD module. The last pair of pins (Anode and Cathode) completes the circuit that powers the backlight of the screen. This gives the LCD screen its constant blue background. Characters on the screen are displayed via contrasting white light. The first pair of pins completes the circuit that powers the contrast letters on the screen , and you should connect the third pin V0 to the middle pin of the potentiometer to adjust the contrast of these characters against the blue light. (I didn’t do this in the beginning and thought that I bought a dud when the letters failed to show up. Then I realised – I was the dud.)
The RS pin (Register Select) is used for selecting whether we will send commands or data to the LCD. When the RS pin is set on low state or zero volts, we are sending commands to the LCD . Such commands include setting the cursor to a specific location, clearing the display, turning off the display and so on. When RS pin is set on high state or 5 volts, we are sending data or characters to the LCD. These characters are what we ultimately read off the LCD screen. Here, I connected RS to Pin 1.
We use the RW (Read Write) pin to select whether we are reading from or writing to the LCD screen. This pin is connected to ground. Lastly, the E pin enables the writing to the registers – the next 8 data pins from D0 to D7. Here, I wired E, D4, D5, D6, D7 to Pin 2, 4, 5, 6, 7 respectively.
You may have noticed that I have only used the last 4 data pins from D4 to D7. This is because I am using the LCD in 4-bit mode. The Liquid Crystal library also allows the use of the LCD in 8-bit mode – this will fully utilise all 8 pins from D0 to D7 then.
If you are still interested to find out more on how this module work, Dejan on HowToMechatronics provided a really thorough description of what each pin on the LCD does, and I understood everything I described above from his site.
Connect the first and last pin of the potentiometer to Ground and 5V – the order does not matter!
3. The Servo Motor
The Servo Motor has 3 pins. Connect the yellow one to a pin on the Arduino board; in this tutorial my pin of choice was 13. Connect the red pin to 5V, and black pin to Ground.
Code
Coding is the simple part of this tutorial! First set up according to how you wired the pins – if you decide to use different pin combinations for your own purposes, do remember to change the numbers accordingly when defining the variables.
The purpose of each code line is also included below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
#include <LiquidCrystal.h> // includes the LiquidCrystal Library #include <Servo.h> //includes the Servo library LiquidCrystal lcd(1, 2, 4, 5, 6, 7); // Creates an LCD object. Parameters: (rs, enable, d4, d5, d6, d7) const int trigPin = 9; // Attaches pin 9 to the Trigger Pin const int echoPin = 10; //Attaches pin 10 to the Echo Pin long duration; //Set long variable duration as the time between Trigger and Echo int distanceCm; //Set distance variable Servo gateServo; //create servo object to control a servo int pos=0; //variable to store the servo position void setup() { lcd.begin(16,2); // Initializes the interface to the LCD screen, and specifies the dimensions (width and height) of the display pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); gateServo.attach(13); // Attaches pin 13 to the servo object } void loop() { digitalWrite(trigPin, LOW); //Send out a low pulse from Trigger Pin delayMicroseconds(2); //A sharp delay of 2 microseconds before... digitalWrite(trigPin, HIGH); //...sending out a high pulse from the Trigger Pin delayMicroseconds(10); //A longer delay of 10 microseconds before... digitalWrite(trigPin, LOW); //...sending out a low pulse again. duration = pulseIn(echoPin, HIGH); //duration is defined as the time at which the echopin detects a high pulse distanceCm= duration*0.034/2; //distance calculation based on known speed of pulse wave and the detected time lcd.setCursor(0,0); // Sets the location at which subsequent text written to the LCD will be displayed lcd.print("Distance: "); // Prints string "Distance" on the LCD lcd.print(distanceCm); // Prints the distance value from the sensor lcd.print(" cm"); delay(10); lcd.setCursor(0,1); delay(10); gateServo.write(pos); //set the servo to the position - on the first run it initializes to 0 if (distanceCm<4.00) //which means an object is detected above the Ultrasound Sensor { lcd.print("Gate is opening!"); //first describe the Gate action if (pos <90) //if the Servo is not already upright { delay(1500); //delay 1.5 seconds before reacting - this mimics the lagged response of toll gates in reality (for safety purposes). for(pos=0; pos<=90; pos++) //gradually moves through 90 degrees { gateServo.write(pos); delay(10); } } else //Servo is already upright - this accounts for when the train remains stationary before the gate { pos=90; //maintain the upright position delay(10); } } else //no object is detected above the Ultrasound Sensor { lcd.print("Gate is closed."); if (pos >0) //Gate is upright and needs to close { delay(1500); //delay 1.5 seconds before reacting for(pos=90; pos>=0; pos--) //gradually moves through 90 degrees { gateServo.write(pos); delay(10); } } else //Gate is already down { pos=0; //remain down delay(10); } |
I hope this tutorial was useful – let me know if you have any questions or ideas on how I can improve this!
4 replies on “How to make an Arduino toll-gate with Ultrasonic Sensor, Servo, and LCD Screen”
Nice work …. really want to know more about this
code is showing some error
Arduino: 1.8.16 (Windows 10), Board: “Arduino Uno”
C:\Users\Yash\OneDrive\Documents\Arduino\sketch_sep24c\sketch_sep24c.ino: In function ‘void loop()’:
sketch_sep24c:73:3: error: expected ‘}’ at end of input
}
^
sketch_sep24c:73:3: error: expected ‘}’ at end of input
exit status 1
expected ‘}’ at end of input
This report would have more information with
“Show verbose output during compilation”
option enabled in File -> Preferences.
C:\Users\Yash\OneDrive\Documents\Arduino\sketch_sep24c\sketch_sep24c.ino: In function ‘void loop()’:
sketch_sep24c:73:3: error: expected ‘}’ at end of input
}
^
sketch_sep24c:73:3: error: expected ‘}’ at end of input
exit status 1
expected ‘}’ at end of input
This report would have more information with
“Show verbose output during compilation”
option enabled in File -> Preferences.
Same…. Error expected
Thank you…its functional