Overview
This set of projects demonstrate how to build several smart transportation projects using the ACEBOTT QE027 Intelligent Transportation Educational Kit (Level 1) powered by the ESP32 microcontroller. The kit allows users—especially STEM teachers and students—to explore real-world traffic management and automation concepts through hands-on learning.
We created multiple projects to highlight different aspects of intelligent transportation, each focusing on a specific application:
Project 1: Smart Street Light
This project simulates an intelligent street lighting system that automatically turns lights on or off based on environmental conditions. By using light sensors to detect ambient brightness and optional motion sensors for pedestrian or vehicle movement, the system ensures illumination only when needed.
Project 2: Smart Traffic Light
A functional traffic light control system that manages vehicle flow at intersections with precision. The system can be programmed for fixed timing cycles or adaptive control based on sensor inputs, closely mirroring real-world traffic management. It demonstrates how automated traffic lights improve road safety, optimize traffic movement, and reduce congestion.
Project 3: Smart Crossing
This project showcases a pedestrian crossing system with automated signaling for improved safety. By integrating a button-activated signal and traffic light sequence, it allows pedestrians to cross the road safely while notifying drivers through visual cues. The system replicates the operation of modern pedestrian crossings and highlights how simple automation can protect pedestrians, especially in high-traffic urban environments or school zones.
Project 4: Smart Parking Lot
A fully functional parking management system designed to detect available parking spaces and indicate slot status through LED displays or signage. The system uses sensors to determine vehicle presence, updating availability in real time.
Project 5: Drag Racing Tree Light with Lap Detection
This specialized project replicates the classic drag racing “Christmas tree” light system, complete with integrated lap detection for accurate timing. The traffic light LEDs simulate pre-race countdown sequences, while sensors detect when a racer crosses the lap line. Real-time timing data and lap counts are displayed on an LCD screen, accompanied by buzzer alerts.
By working through these projects, students and makers will gain a deeper understanding of embedded systems, sensor integration, and IoT-based automation while building realistic prototypes of transportation technologies.
Hardware Used
- ACEBOTT QE027 Intelligent Transportation Educational Kit (Level 1)
Project 1: Smart Street LightProject 2: Smart Traffic Light
Project 3: Smart Crossing
Project 4: Smart Parking Lot
Project 5: Drag Racing Tree Light with Lap Detection
Software Used
-
Arduino IDE 2.3.6
Application Discussion
-
ESP32
Description: ESP32 is a low-power, highly integrated Wi-Fi and Bluetooth dual-mode microcontroller developed by Espressif Systems. The ESP32 development board is very popular due to its powerful features and abundant communication interfaces, making it suitable for various Internet of Things (IoT) applications, embedded system development, and project implementations.
Pinout:
Application: ESP32 serves as the main controller that connects and manages all components. It processes data from sensors, controls traffic lights, adjusts streetlight brightness, and operates safety devices like barriers and buzzers.
-
ESP32 Expansion Board
Description: The ESP32 expansion board is designed to make wiring connections easier and more reliable. It provides clearly labeled ports and a structured layout to reduce wiring errors, prevent short circuits, and simplify the assembly process when connecting sensors, modules, and other components.
Application: Used to expand the ESP32’s connectivity, allowing quick and safe attachment of multiple modules in the Intelligent Transportation Kit without complex wiring. -
White LED Module
Description:The White LED module integrates a high-brightness white LED with supporting circuitry, allowing simple connection and control. It turns ON when it receives a high-level signal and OFF when given a low-level signal. The module is designed for reliable, consistent illumination in small-scale projects.
Pinout:
Application: Provides focused light output for miniature streetlight simulations, status indicators, or as a visual output in smart lighting demonstrations within the transportation kit. -
Light Sensor Module
Description: The light sensor module (photoresistor-based) detects ambient light levels by changing its resistance in response to illumination. The module outputs an analog signal proportional to the detected brightness, allowing fine control over light-dependent behaviors.
Pinout:
Application: Enables automatic control of lighting systems in the kit, such as turning streetlights on when it’s dark and off when it’s bright, or adjusting brightness to save energy.Traffic Light Module
Description: A compact module that combines red, yellow, and green LEDs, each with independent control pins for flexible sequencing. The module is designed to replicate real-world traffic signal behavior in scaled-down systems.
Pinout:
Application: Simulates real-world traffic signals in projects, allowing the ESP32 to control light sequences for vehicle and pedestrian traffic management. -
Infrared Obstacle Avoidance Sensor Module
Description: Uses an infrared LED emitter and receiver to detect reflected IR light from nearby objects. When an obstacle is detected, the module outputs a LOW signal; otherwise, it outputs HIGH.
Application: Detects the presence or movement of vehicles in traffic light or parking lot projects, enabling adaptive control such as extending green lights for heavy traffic.
Pinout:
-
4-Digit Tube Display Module
Description: Features four 7-segment LED displays arranged for multi-digit readouts, controlled through I2C for minimal wiring. Capable of showing numbers and limited characters.
Pinout:
Application: Displays countdowns for traffic light changes, race timers, or numerical data in transportation projects for clear, real-time feedback. -
RGB Light Strip Module
Description: Contains multiple RGB LEDs with built-in drivers, allowing precise individual control of color and brightness via a single data line.
Pinout:
Application: Provides dynamic lighting effects such as ground-level pedestrian crossing lights, synchronized with main traffic signals for enhanced safety cues. -
Servo SG90
Description: A compact servo motor offering precise angular control (0°–180°) via PWM signals, ideal for lightweight mechanical movements.
Pinout:
Application: Operates gates or barriers in pedestrian crossings or parking systems, moving in sync with traffic signals or authentication systems. -
Button Module
Description: A simple push-button switch that completes a circuit when pressed, sending a digital signal to the microcontroller.
Pinout:
Application: Serves as a manual input for triggering pedestrian crossing lights, starting race timers, or initiating other user-controlled processes. -
Buzzer Module
Description: An audio device that produces sound when driven with electrical signals, using vibrations to generate tones or alarms.
Pinout:
Application: Emits alerts for pedestrian crossings, countdown timers, or warnings in intelligent transportation setups. -
MP3 Module
Description: A playback device capable of reading and playing MP3 files stored on a memory card, with serial communication for remote control.
Pinout:
Application: Broadcasts voice prompts, alerts, or background music for transportation systems, such as announcing traffic light changes or guiding parking lot drivers.Tips:
Before controlling the MP3 playback module to play music, you need to pre-store songs on the storage card of the MP3 module. Below are the steps to store songs on the MP3 playback module:1) Insert the memory card into the card slot of the MP3 module.
2) The back of the MP3 playback module has a USB interface. Connect the USB interface of the MP3 module to a computer using a Type-C data cable.
3) After connecting the MP3 module to the computer, the computer’s system disk will pop up a new folder. Place your MP3 files in this newly popped-up folder. If your MP3 files are located in the root directory of the storage card, the name of the MP3 files must start with four digits, such as 0001Hero.mp3, 0002Jingle bells.mp3.
4) If you want to create a folder at the root of your card, start the folder with a two-digit name and the MP3 files in the folder with a three-digit name.
-
LCD1602
Description: A 16-character by 2-line LCD display module for showing alphanumeric information. Often connected via an I2C adapter to reduce wiring.
Pinout:
Application: Displays system status messages, sensor readings, countdown timers, or other operational data in transportation projects. -
RFID Module
Description: Reads data from compatible RFID cards and transmits the stored unique identification code to the microcontroller.
Pinout:
Application: Used in access control and identification systems, such as managing vehicle entry in smart parking lots. -
IC Card
Description: The IC card is a contactless identification card used with the RFID module. It contains an embedded microchip that stores a unique identification code, which can be read wirelessly when the card is brought near the RFID reader.
Application: Used for identity verification in smart systems such as vehicle access control, parking lot entry, and other authentication features in the Intelligent Transportation Kit.
Hardware Setup
Project 1: Smart Street Light
Hardware Structure Diagram:
Assembly Instructions:
Step 1: Construct the Base.
Step 2: Install the ESP32 Control Board abd Expansion Board.
Note: First fix the copper column on the base, then install the ESP 32
Controller Board on the copper column,and finally install the expansion
board. When installing the expansion board, be sure to align the holes
with the ESP32 before installing it.
Step 3: Installing the battery holder.
Note: Use double sides tape to attach the battery holder to the
underside of the base, and do not cover the electric wire and pin holes of
the base.
Step 4: Install the street lamp bracket.
Step 5: Install LED modules.
Note: Before installing the LED module,please ensure to connect the
3-pin sensor cable in advance.
Step 6: Install a standing card on the base.
Step 7: Install the light sensor.
Note: Before installing the light sensor, connect the sensor's 3P cable in
advance and remove the screws from the LED module. Then, use the
removed screws to fix the LED module and the light sensor together.
Step 8: Install LUMI.
Hardware Wiring Diagram :
Wiring Instructions:
Note: Please make sure to strictly follow the wiring instructions when
connecting the module to the ESP32 controller board. Incorrect wiring may cause a short circuit and damage the ESP32 controller board.
Project 2: Smart Traffic Light
Hardware Structure Diagram:
Assembly Instructions:
Note: This project will adopt the base structure of the'Smart Street Light' (as shown in the diagram below). We will proceed directly to installing the traffic light module.
Step 1: Install the traffic light module.
Note: Before installing the traffic light module, please ensure to connect
the 4-pin sensor cable in advance.
Step 2: Secure the traffic light module onto the base.
Step 3: Install a standing sign on the base.
Step 4: Install the four-digit display module.
Note: Before installing the four-digit display module, make sure to connect the sensor's 4-pin connector in advance.
Step 5: Install the infrared obstacle avoidance sensor.
Note: Before fixing the infrared obstacle avoidance sensor, connect the
sensor's 3P cable in advance.
Step 6: Secure the infrared obstacle avoidance sensor.
Step 7: Construct the Base.
Hardware Wiring Diagram :
Wiring Instructions:
Note:
1). Before writing the program, you need to install the library file for
the 4-Digit Tube Display Module. Click here to get the library file "TM1650" for the 4-Digit Tube Display.
2). Please make sure to strictly follow the wiring instructions when connecting the module to the ESP32 controller board. Incorrect wiring may cause a short circuit and damage the ESP32 controller board.
Project 3: Smart Crossing
Hardware Structure Diagram:
Assembly Instructions:
Step 1: Construct the base.
Step 2: Installing the battery holder.
Note: Use double sides tape to attach the battery holder to the under side of the base, and do not cover the electric wire and pin holes of the base.
Step 3: Install the ESP32 Control Board and Expansion Board.
Note: First fix the copper column on the base, then install the ESP 32 Controller Board on the copper column,and finally install the expansion board.When installing the expansion board, be sure to align the holes with the ESP32 before installing it.
Step 4: Install the railing.
Step 5: Install the servo motor.Note: Assemble the servo box basswood boards in numerical order, and finally cover with the No.5 basswood board.
Step 6: Secure the railing structure.
Note:
1). Before installing this wheel onto the railing, adjust the servo
motor to the 90-degree position. After adjusting to the 90-degree position,
do not power off the servo motor.Then, install the railing according to
the diagram below.
2). Before writing the program,you need to install the libraryfile for the servo
Module. Click here to get the library file"ESP32_Servo"for the servo.
Step 7: Secure the servo motor box onto the base.Step 8: Install the traffic light module.
Note: Before installing the traffic light module, make sure to connect the
sensor's 4-pin connector in advance.
Step 9: Secure the traffic light module onto the base.
Step 10: Install the signboard on the base.Step 11: Install the RGB LED strip.
Attention: Peel off the adhesive film on the back of the LED strip,
then stick the strip onto the pedestrian walkway.Step 12: Install the buzzer.
Note: Before installing the buzzer, make sure to connect the sensor's
3-pin connector in advance.
Step 13: Assemble the button module.
Step 14: Install LUMI.
Hardware Wiring Diagram :
Wiring Instructions:
Note: Before writing the program, you need to install the library file for
the RGB strip Module. Click here to get the library file "Adafruit_NeoPiexl" for the RGB strip.
Project 4: Smart Parking Lot
Hardware Structure Diagram:
Assembly Instructions:
Step 1: Construct the base.
Step 2: Install the ESP32 Control Board and Expansion Board.
Note: First fix the copper column on the base, then install the ESP 32
Controller Board on the copper column,and finally install the expansion
board. When installing the expansion board, be sure to align the holes
with the ESP32 before installing it.
Step 3: Installing the battery holder.
Note: Use double sides tape to attach the battery holder to the
underside of the base, and do not cover the electric wire and pin holes of
the base.
Step 4: Assemble the RFID module.Step 5: Install the RFID module on the base.
Note: Before securing the RFID module, please ensure to connect the
4-pin sensor cable in advance.
Step 6: Install the railing.Step 7: Install LUMI.
Notice: Assemble the servo box basswood boards in numerical order, and finally cover with the No.6 basswood board. Note the orientation of the two holes on the No.6 basswood board, which should be installed in the opposite direction of the servo.
Step 8: Secure the railing structure.
Notice: Before installing this wheel onto the railing, first adjust the servo
to the 90-degree position. After adjusting to the 90-degree position, do
not power off the servo. Then, install the railing according to the diagram
below.
Click here to get the servo debugging program.
Step 9: Install the servo structure.
Step 10: Install the infrared obstacle avoidance sensor.
Step 11: Secure the infrared obstacle avoidance sensor to the
slope board.
Step 12: Install the intelligent parking lot signboard in the base.
Step 13: Install the LCD display screen.
Step 14: Secure the LCD display screen onto the base.
Step 15: Install the MP3 playback module.
Attention:Before installing the MP3 module, follow the instructions above to import the MP3 files that need to be played into the MP3 module's memory card. Click here to download the MP3 music files.
Step 16: Secure the MP3 playback module to the base.
Step 17: Install LUMI.
Hardware Wiring Diagram :
Wiring Instructions:
Note: Before writing the program, you need to install these library files.
Click here to get all the library files needed.
-
RFID Module
Click here to get the library file "MFRC522_I2C" for the RFID module.
-
LCD1602 Module
Click here to get the library file "hd44780" for the LCD1602 module.
-
MP3 Module
Click here to get the library file "ACB_MP3" for the MP3 module.
Project 5: Drag Racing Tree Light with Lap Detection
Schematic 1
Schematic 2
Software Setup
Arduino IDE
Description: Arduino IDE is a free, cross-platform programming tool used for writing, uploading, and debugging code for Arduino-compatible boards like the ESP32.
How to install the Arduino IDE Windows
A. Download and Install Arduino IDE
Go to the Official Website
-
Go to the Official Website
-
Select the correct version:
-
Windows 10 or above → Arduino IDE 2.x
-
Before Windows 10 → Arduino IDE 1.x
-
-
Click the download button and choose “Download Only” to get the
.exe
installer.
-
Install the Arduino IDE
-
Locate and double-click the downloaded installer file.
-
Click “I Agree” to accept the license agreement.
-
Click “Next”, then “Install”.
-
Wait for the installation to finish, then click “Close”.
-
-
Open Arduino IDE
-
Locate the Arduino IDE shortcut on your desktop or Start menu.
-
Double-click to launch it.
-
B. Install ESP32 Board Resources in Arduino IDE
-
Open Preferences
-
Go to File → Preferences in the Arduino IDE.
-
-
Add the Board Manager URL
-
In Additional Boards Manager URLs, paste:
arduino.esp8266.com/stable/package_esp8266com_index.json
-
-
Install ESP32 Package
-
Go to Tools → Board → Board Manager (or click the Boards icon in the left toolbar).
-
Search for ESP32, select Version 2.0.12, and click Install.
-
-
Verify Installation
-
Reopen Tools → Board and check if ESP32 Dev Module appears in the list.
-
C. Testing the ESP32 Setup
-
Connect the ESP32 Board
-
Use a Type-C data cable to connect the ESP32 to your computer.
-
Open Device Manager and check under Ports (COM & LPT) for
USB-SERIAL CH340 (COMx)
.-
If it shows as “Unknown Device,” install the CH340 driver (instructions are at the end of the kit manual).
-
-
-
Select Board and Port
-
In Arduino IDE, go to Tools → Board and choose ESP32 Dev Module.
-
Go to Tools → Port and select the COM port number matching your ESP32 in Device Manager.
-
-
Upload a Test Program
-
Open the Arduino IDE, write or paste a simple test code (e.g.,
Serial.println("Hello ESP32");
). -
Click the Verify button (check mark icon) to compile.
-
If there’s an error, review your code or board settings.
-
-
Click Upload (right arrow icon).
-
Wait until “Done uploading” appears in the status bar.
-
-
-
Check Serial Output
-
Open Tools → Serial Monitor.
-
Set the baud rate to match your code (e.g., 115200).
-
Confirm that your test message appears, verifying the board is working.
-
Code for Project 1: Smart Street Light
#define LED 19 //Declare the pins of the LED
#define PR 32 //Declare the pins of the light sensor
int brightness;
void setup() {
pinMode(LED, OUTPUT); //Set LED pins to output mode
pinMode(PR, INPUT); //Set the light sensor pins to input mode
}
void loop() {
int light_value = analogRead(PR); //get the light intensity value:
if(light_value < 1500){//check if value is less than 1500
analogWrite(LED,0);//turn off led
delay(100); //delay 0.1s
}
else{//check if value is more than 1500
//Convert the light value into an LED brightness value.
brightness = map(light_value, 1500, 4095, 0, 255);
analogWrite(LED, brightness); //set LED brightness
delay(100); //delay 0.1s
}
}
Code for Project 2: Smart Traffic Light
#include //Introducing libraries related to I2C communication
#include //Introducing 4-digit digital tube related libraries
#define R 14 //Define pins for red traffic lights
#define Y 2 //Define pins for yellow traffic lights
#define G 0 //Define pins for traffic lights and green lights
#define PE 23 //Define the pins of the photoelectric sensor
int carcount = 0;
int redtime = 5000, greentime = 3000, yellowtime = 2000; //Defining the Time of Traffic Lights
int lasttime = millis();//Defining the Time of Traffic Lights
int Traffic_volume;
int display_time;
char dis[4]; //Create a character array to store the displayed string
TM1650 d; //Create a TM1650 object
char light[3] = { 'g', 'y', 'r' };
char color;
void setup() {
Wire.begin(); //Enable I2C communication
d.init(); //Initialize TM1650 object
d.setBrightness(TM1650_MIN_BRIGHT); //Set the brightness of TM1650 display
d.displayOn(); //Turn on display function
pinMode(R, OUTPUT); //Set the red light pin to output mode
pinMode(Y, OUTPUT); //Set the yellow light pin to output mode
pinMode(G, OUTPUT); //Set the green light pin to output mode
pinMode(PE, INPUT); //Set the photoelectric sensor pins to input mode
Serial.begin(115200); //Initialize baud rate
}
void loop() {
lasttime = millis();
for (int i = 0; i < 3; i++) {
color = light[i];
trafficlight(color);
while (display_time >= 1) { //Countdown display
itoa(display_time, dis, 10); //Convert numbers into character arrays
d.displayString(dis); //Display countdown on digital display
for (int j = 0; j < 2; j++) {
if (digitalRead(PE) == 0) { // Does the infrared obstacle avoidance sensor detect the vehicle
carcount += 1;
}
delay(500);
}
display_time--; //Seconds minus 1
}
}
////Determine if the traffic flow within 15 seconds is greater than 5
if (carcount > 5 && millis() - lasttime < 15000) {
redtime = 3000;
greentime = 5000;
}else{
redtime = 5000;
greentime = 3000;
}
carcount = 0;
}
void trafficlight(char color) {
// Check if the traffic light is red
if (color == 'r') {
digitalWrite(R, HIGH);
digitalWrite(Y, LOW);
digitalWrite(G, LOW);
display_time = redtime / 1000;
}
// Check if the traffic light is green
if (color == 'g') {
digitalWrite(R, LOW);
digitalWrite(Y, LOW);
digitalWrite(G, HIGH);
display_time = greentime / 1000;
}
// Check if the traffic light is yellow
if (color == 'y') {
digitalWrite(R, LOW);
digitalWrite(Y, HIGH);
digitalWrite(G, LOW);
display_time = yellowtime / 1000;
}
}
Code for Project 3: Smart Crossing
#include <Adafruit_NeoPixel.h>
#include <ESP32Servo.h>
// Pin definitions
#define R 14 // Red traffic light pin
#define Y 2 // Yellow traffic light pin
#define G 0 // Green traffic light pin
#define Serve 4 // Servo motor pin
#define Button 25 // Button pin (assumed connected to GND)
#define LED_PIN 18 // RGB LED strip pin
#define LED_COUNT 9 // Number of LEDs in strip
#define BRIGHTNESS 50 // LED brightness (0-255)
#define buzzer 12 // Buzzer pin
Servo Myservo;
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN);
bool buttonPressed = false;
unsigned long lastButtonTime = 0;
const unsigned long debounceDelay = 50; // debounce button delay
void setup() {
strip.begin();
strip.setBrightness(BRIGHTNESS);
pinMode(R, OUTPUT);
pinMode(Y, OUTPUT);
pinMode(G, OUTPUT);
pinMode(Button, INPUT_PULLUP); // button connects to GND when pressed
pinMode(buzzer, OUTPUT);
Myservo.attach(Serve);
// Default mode setup
setDefaultMode();
}
void loop() {
// Check for button press with simple debounce
if (digitalRead(Button) == LOW) {
unsigned long currentMillis = millis();
if ((currentMillis - lastButtonTime) > debounceDelay) {
lastButtonTime = currentMillis;
if (!buttonPressed) { // only respond to first press until reset
buttonPressed = true;
runButtonSequence();
}
}
}
// Nothing to do continuously in default mode - it just stays there
}
// Set the system to default mode:
// servo 0 deg, green traffic light, red LED strip, no buzzer
void setDefaultMode() {
Myservo.write(0); // Servo up/open
Traffic_Light(0, 0, 1); // Traffic light green ON, others off
setStripColor(255, 0, 0); // LED strip RED
noTone(buzzer);
buttonPressed = false; // reset button flag to allow next press
}
// Helper: Control traffic light LEDs
void Traffic_Light(int r, int y, int g) {
digitalWrite(R, r);
digitalWrite(Y, y);
digitalWrite(G, g);
}
// Helper: Set all LEDs on strip to given color and show
void setStripColor(uint8_t red, uint8_t green, uint8_t blue) {
for (int i = 0; i < LED_COUNT; i++) {
strip.setPixelColor(i, strip.Color(red, green, blue));
}
strip.show();
}
// Runs the sequence triggered by button press
void runButtonSequence() {
// 1. Wait 5 seconds countdown (no buzzer)
delay(5000);
// 2. Turn traffic light yellow for 2 seconds
Traffic_Light(0, 1, 0); // Yellow ON
delay(2000);
// 3. Turn traffic light red, servo down (90 deg), LED strip green
Traffic_Light(1, 0, 0); // Red ON
Myservo.write(90); // Servo down/closed
setStripColor(0, 255, 0); // LED strip GREEN
// 4. Buzzer 8 seconds countdown with 0.5 second on/off intervals
unsigned long buzzerCountdown = 8000; // 8 seconds total
unsigned long interval = 500;
unsigned long startMillis = millis();
while (millis() - startMillis < buzzerCountdown) {
tone(buzzer, 1000); // Buzz ON at 1kHz
delay(interval);
noTone(buzzer); // Buzz OFF
delay(interval);
}
noTone(buzzer);
// 5. Return to default mode
setDefaultMode();
}
Code for Project 4: Smart Parking Lot
#include <ACB_MP3.h>
#include <Wire.h>
#include <MFRC522_I2C.h>
#include <ESP32Servo.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
#include <List.hpp>
#define SERVE 4
#define PE 23
#define RAILING_CLOSE 90
#define RAILING_OPEN 0
#define NUM_ROWS 2
#define NUM_COLS 16
const int TOTAL_PARKING = 5;
int parking_space = TOTAL_PARKING;
int cost = 0;
String rfid_str;
MFRC522_I2C mfrc522(0x28, -1);
Servo Myservo;
hd44780_I2Cexp lcd(0x27, NUM_ROWS, NUM_COLS);
ACB_MP3 MyMP3;
List<String> card_list;
List<int> time_list;
void setup() {
Wire.begin();
mfrc522.PCD_Init();
Myservo.attach(SERVE, 500, 2500);
Myservo.write(RAILING_CLOSE);
delay(500);
lcd.begin(NUM_COLS, NUM_ROWS);
lcd.backlight();
lcd.clear();
pinMode(PE, INPUT);
MyMP3.init(16, 17);
delay(500);
Serial.begin(115200);
}
void loop() {
spaceDisplay(parking_space);
if (digitalRead(PE) == 0) {
if (parking_space == 0) {
Myservo.write(RAILING_CLOSE);
} else {
Myservo.write(RAILING_OPEN);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Register IC Card");
while (!mfrc522.PICC_IsNewCardPresent() || !mfrc522.PICC_ReadCardSerial());
MyMP3.playInFolder(0x03);
delay(1000);
rfid_str = getCardUID();
int attempt = 0;
int index = indexOfList(rfid_str);
while (index >= 0 && attempt < 3) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Failed!");
lcd.setCursor(0, 1);
lcd.print("Use New Card!");
while (!mfrc522.PICC_IsNewCardPresent() || !mfrc522.PICC_ReadCardSerial());
MyMP3.playInFolder(0x03);
delay(1000);
rfid_str = getCardUID();
index = indexOfList(rfid_str);
attempt++;
}
if (index >= 0) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Card Exists");
lcd.setCursor(0, 1);
lcd.print("Try Again Later");
delay(2000);
Myservo.write(RAILING_CLOSE);
return;
}
card_list.add(rfid_str);
time_list.add(millis());
parking_space--;
MyMP3.playInFolder(0x01);
delay(2000);
Myservo.write(RAILING_CLOSE);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Successful!");
lcd.setCursor(0, 1);
lcd.print("Start Billing!");
delay(2000);
lcd.clear();
}
}
if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
rfid_str = getCardUID();
int index = indexOfList(rfid_str);
if (index == -1) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Unrecognized");
lcd.setCursor(0, 1);
lcd.print("IC Card!");
delay(2000);
lcd.clear();
return;
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Billing...");
delay(1000);
cost = ((millis() - time_list[index]) / 1000) * 2;
lcd.setCursor(0, 1);
lcd.print("Cost:");
lcd.setCursor(5, 1);
lcd.print(cost);
delay(2000);
Myservo.write(RAILING_OPEN);
MyMP3.playInFolder(0x02);
delay(2000);
Myservo.write(RAILING_CLOSE);
card_list.remove(index);
time_list.remove(index);
parking_space++;
lcd.clear();
}
}
String getCardUID() {
String uid = "";
for (byte i = 0; i < mfrc522.uid.size; i++) {
uid += String(mfrc522.uid.uidByte[i], HEX);
}
mfrc522.PICC_HaltA();
return uid;
}
int indexOfList(String s) {
for (int i = 0; i < card_list.getSize(); i++) {
if (s == card_list[i]) {
return i;
}
}
return -1;
}
void spaceDisplay(int space) {
lcd.setCursor(0, 0);
lcd.print("Parking Space");
lcd.setCursor(0, 1);
lcd.print("Total:");
lcd.setCursor(6, 1);
lcd.print(TOTAL_PARKING);
lcd.setCursor(8, 1);
lcd.print("Rest:");
lcd.setCursor(13, 1);
lcd.print(space);
delay(200);
}
Code for Project 5: Drag Racing Tree Light with Lap Detection
#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
// Pin definitions
#define R 14 // Red traffic light pin
#define Y 2 // Yellow traffic light pin
#define G 0 // Green traffic light pin
#define buzzer 12 // Buzzer pin
#define PE 23 // Photoelectric (IR) sensor pin
#define Button 25 // Button pin (connected to GND)
// Create LCD object
hd44780_I2Cexp lcd;
int laps = 3;
bool running = false;
// Button debounce variables
bool lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 50;
// IR sensor debounce variables
unsigned long lastIrTime = 0;
const unsigned long irDebounceDelay = 1000; // 1 second debounce
// Utility function to center print on LCD
void lcdPrintCenter(int row, const String &text) {
int startPos = (16 - text.length()) / 2;
lcd.setCursor(startPos, row);
lcd.print(text);
}
void setup() {
pinMode(R, OUTPUT);
pinMode(Y, OUTPUT);
pinMode(G, OUTPUT);
pinMode(buzzer, OUTPUT);
pinMode(PE, INPUT);
pinMode(Button, INPUT_PULLUP); // Button to GND uses internal pullup
// Start with all LEDs ON
digitalWrite(R, HIGH);
digitalWrite(Y, HIGH);
digitalWrite(G, HIGH);
noTone(buzzer);
lcd.begin(16, 2);
lcd.clear();
lcd.print("Push Button to");
lcd.setCursor(0, 1);
lcd.print("Start");
}
void loop() {
// Button reading with debounce
bool reading = digitalRead(Button);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading == LOW && !running) {
startSequence();
}
}
lastButtonState = reading;
// Lap counting using IR with debounce
if (running) {
int irValue = digitalRead(PE);
if (irValue == LOW) { // Detection assumed at LOW
if (millis() - lastIrTime > irDebounceDelay) {
lastIrTime = millis();
handleLapDetection();
}
}
}
}
void startSequence() {
running = true;
laps = 3;
// Turn off all LEDs initially
digitalWrite(R, LOW);
digitalWrite(Y, LOW);
digitalWrite(G, LOW);
delay(3000); // Wait 3 seconds after button press (countdown)
// Red LED blink 2 times with buzzer 500Hz, 1 sec interval (on 500ms, off 500ms)
for (int i = 0; i < 2; i++) {
digitalWrite(R, HIGH);
tone(buzzer, 500);
delay(500);
digitalWrite(R, LOW);
noTone(buzzer);
delay(500);
}
// Red to Yellow interval 0.25 sec
delay(250);
// Yellow LED on for 2 seconds, buzzer only on first 0.5 at 500 Hz
digitalWrite(Y, HIGH);
tone(buzzer, 500);
delay(500); // buzzer on 0.5 second
noTone(buzzer);
delay(1500); // yellow remains on additional 1.5 seconds without buzzer
digitalWrite(Y, LOW);
// Yellow to Green interval 0.25 sec
delay(250);
// Green LED on for 3 seconds, buzzer at 1 kHz for first 2 seconds
digitalWrite(G, HIGH);
tone(buzzer, 1000);
delay(2000); // buzzer on
noTone(buzzer);
delay(1000); // green remains on extra 1 second without buzzer
digitalWrite(G, LOW);
// Display centered "Laps Remaining:" on first row
lcd.clear();
lcdPrintCenter(0, "Laps Remaining:");
// Display centered laps number on second row
lcd.clear();
lcdPrintCenter(0, "Laps Remaining:");
String lapsStr = String(laps);
lcdPrintCenter(1, lapsStr);
}
void handleLapDetection() {
if (laps > 1) {
laps--;
String lapsStr = String(laps);
lcdPrintCenter(1, lapsStr);
} else if (laps == 1) {
laps = 0;
lcd.clear();
lcdPrintCenter(0, "FINISH!");
delay(3000);
resetSystem();
}
}
void resetSystem() {
running = false;
laps = 3;
lcd.clear();
lcd.print("Push Button to");
lcd.setCursor(0, 1);
lcd.print("Start");
// Turn all LEDs ON
digitalWrite(R, HIGH);
digitalWrite(Y, HIGH);
digitalWrite(G, HIGH);
noTone(buzzer);
}
Code Breakdown
Project 1: Smart Street Light
Pin Definitions:
#define LED 19
#define PR 32
- LED – Controls the street light brightness.
- PR – Reads input from the light sensor module.
Variables:
- int brightness; – Stores LED brightness level.
setup() Function:
- Configures LED pin as output.
- Configures light sensor pin as input.
loop() Function:
- Reads light intensity using analogRead(PR).
- If value < 1500 → LED OFF.
- Else → Maps sensor value (1500–4095) to brightness range (0–255) and sets LED brightness.
- Adds 0.1s delay for smooth transitions.
Project 2: Smart Traffic Light
Libraries Used:
#include <Wire.h> - Enables I2C communication
#include <TM1650.h> - Controls 4-digit LED display
Pin Definitions:
#define R 14
#define Y 2
#define G 0
#define PE 23
- R, Y, G – Traffic light LEDs.
- PE – Photoelectric sensor for vehicle detection.
Variables:
- carcount – Tracks detected cars.
- redtime, greentime, yellowtime – Light durations.
- display_time – Countdown timer display.
- char light[3] = {'g','y','r'} – Traffic light sequence.
setup() Function:
- Initializes I2C and TM1650 display.
- Sets light pins as outputs, sensor pin as input.
- Starts serial communication.
loop() Function:
- Cycles through green → yellow → red lights.
- Updates display countdown each second.
- Counts cars passing during green phase.
- Adjusts light durations if traffic volume > 5 in 15 seconds.
- trafficlight() Function:
- Activates correct light color.
- Sets display_time for countdown.
Project 3: Smart Crossing
Libraries Used:
#include <Adafruit_NeoPixel.h> - RGB LED strip control
#include <ESP32Servo.h> - Servo motor control
Pin Definitions:
#define R 14
#define Y 2
#define G 0
#define Serve 4
#define Button 25
#define LED_PIN 18
#define LED_COUNT 9
#define BRIGHTNESS 50
#define buzzer 12
- R, Y, G – Traffic light LEDs.
- Serve – Servo gate control.
- Button – Crossing activation.
- LED_PIN – RGB strip data pin.
- buzzer – Sound alert.
setup() Function:
- Initializes LED strip, servo, traffic lights, buzzer.
- Sets default crossing mode.
loop() Function:
- Waits for button press (debounced).
- Runs crossing sequence when pressed.
- runButtonSequence() Function:
- Wait 5 seconds.
- Yellow light for 2s.
- Red light ON, servo down, LED strip green.
- Buzzer beeps for 8 seconds.
- Return to default mode.
Project 4: Smart Parking Lot
Libraries Used:
#include <acb_mp3.h> - MP3 audio control
#include <Wire.h> - I2C communication
#include <MFRC522_I2C.h> - RFID reader via I2C
#include <ESP32Servo.h> - Servo control
#include <hd44780.h> - LCD control
#include <hd44780ioClass/hd44780_I2Cexp.h>
#include <List.hpp> - List handling for card IDs
Pin Definitions:
#define SERVE 4
#define PE 23
#define RAILING_CLOSE 90
#define RAILING_OPEN 0
- SERVE – Servo gate pin.
- PE – Photoelectric vehicle detection.
- RAILING_CLOSE/RAILING_OPEN – Servo angles.
Variables:
- TOTAL_PARKING – Maximum parking slots.
- parking_space – Tracks available slots.
- card_list – Stores active RFID card IDs.
- time_list – Stores parking start times.
setup() Function:
- Initializes RFID, servo, LCD, MP3 module.
- Sets initial gate position and displays default info.
loop() Function:
- If car detected at entry:
- Prompts for IC card registration.
- Stores new card, decreases available slots, starts billing.
- If IC card detected at exit:
- Calculates parking fee.
- Opens gate and removes card from list.
- Helper Functions:
- getCardUID() – Reads card UID.
- indexOfList() – Finds card in list.
- spaceDisplay() – Updates LCD display.
Project 5: Drag Racing Tree Light with Lap Detection
Libraries Used:
#include <Wire.h> - I2C communication
#include <hd44780.h> - LCD control
#include <hd44780ioClass/hd44780_I2Cexp.h>
Pin Definitions:
#define R 14
#define Y 2
#define G 0
#define buzzer 12
#define PE 23
#define Button 25
- R, Y, G – Traffic light LEDs.
- buzzer – Race start and alert sounds.
- PE – Infrared lap detection sensor.
- Button – Start race.
Variables:
- laps – Remaining laps (default 3).
- Debounce delays for button and IR sensor.
setup() Function:
- Initializes pins and LCD.
- Displays "Push Button to Start" message.
- Turns all lights ON initially.
loop() Function:
- Waits for button press to trigger race start.
- Detects laps using IR sensor with debounce.
- startSequence() Function:
- Red light blinks twice with buzzer.
- Yellow light for 2 seconds.
- Green light for 3 seconds with buzzer.
- LCD shows laps remaining.
- handleLapDetection() Function:
- Decreases lap count on each IR detection.
- Shows “FINISH!” when race ends.
- Resets system.
Video Demonstration
Project 1: Smart Street Light
Project 2: Smart Traffic Light
Project 3: Smart Crossing
Project 4: Smart Parking Lot
Project 5: Drag Racing Tree Light with Lap Detection
Conclusion
The ACEBOTT: Intelligent Transport Education Kit – Level 1 stands out as a powerful and practical tool for introducing STEM education in an engaging and hands-on way. Through a series of projects—including the Smart Street Light, Smart Traffic Light, Smart Crossing, Smart Parking Lot System, and an additional Drag Racing Tree Light with Lap Detection, we demonstrated real-world transportation concepts that students can build, program, and fully understand.
Instead of relying solely on visual coding platforms, we used the Arduino IDE to program each system, giving students a deeper insight into actual coding logic and embedded systems design. For younger students (elementary level), ACE Code or Scarth-based block programming is also available. This bridges the gap between theory and real-world application, allowing learners to build projects with a professional-level toolchain.
In summary, the ACEBOTT intelligent transportation kit is a well-rounded, beginner-friendly tool for teaching STEM concepts through hands-on, interactive projects. It helps students easily understand the fundamentals of electronics, automation, and intelligent transportation systems using real-world applications. With all essential components already included, it's a practical choice for schools, STEM educators, and workshops aiming to deliver meaningful tech learning experiences.
References
-
Arduino Documentation
- Acebott Official Website
-
ACEBOTT QE027 Intelligent Transportation L1 Documentation