ACEBOTT QE027 Intelligent Transportation Educational Kit (Level 1): 5 Smart Transportation Projects
01 Overview
This set of projects demonstrates 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 Use Case
This kit is designed for STEM educators, students, and makers who want a hands-on introduction to embedded systems, sensor integration, and IoT-based automation. It is well suited for classroom demonstrations, robotics clubs, and workshops focused on real-world transportation technologies.
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.
02 Hardware and Software Components
Gather everything below before you start. This is your checklist — names, models, and versions only.
Hardware Components
| Component | Description |
|---|---|
| ACEBOTT QE027 Kit | Intelligent Transportation Educational Kit (Level 1) |
| ESP32 | Main controller board (Wi-Fi/Bluetooth dual-mode microcontroller) |
| ESP32 Expansion Board | Simplifies wiring connections between ESP32 and modules |
| White LED Module | High-brightness white LED with control circuitry |
| Light Sensor Module | Photoresistor-based ambient light detector |
| Traffic Light Module | Combined red, yellow, green LEDs with independent control pins |
| Infrared Obstacle Avoidance Sensor | IR emitter/receiver for detecting nearby objects |
| 4-Digit Tube Display Module | Four 7-segment LED displays, I2C controlled |
| RGB Light Strip Module | Individually addressable RGB LEDs |
| Servo SG90 | Compact servo motor, 0°–180° angular control |
| Button Module | Push-button switch for manual input |
| Buzzer Module | Audio device for alerts and tones |
| MP3 Module | Plays MP3 files from a memory card via serial control |
| LCD1602 | 16x2 character LCD display with I2C adapter |
| RFID Module | Reads compatible RFID cards |
| IC Card | Contactless identification card used with the RFID module |
Software Tools
| Software | Version / Details |
|---|---|
| Arduino IDE | 2.3.6 (use 1.x if on a Windows version before Windows 10) |
| ESP32 Board Package | Version 2.0.12, installed via Arduino Boards Manager |
Required Libraries
Install these libraries before uploading any of the project code below.
| Library | Used For |
|---|---|
| TM1650 | 4-Digit Tube Display Module (Project 2) |
| ESP32_Servo | Servo motor control (Projects 3 and 4) |
| Adafruit_NeoPixel | RGB Light Strip Module (Project 3) |
| MFRC522_I2C | RFID Module (Project 4) |
| hd44780 | LCD1602 Module (Projects 4 and 5) |
| ACB_MP3 | MP3 Module (Project 4) |
03 Application Discussion
Here is what each component does and why it is part of this project.
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.
Pinout:
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.
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.
0001Hero.mp3). To use folders, name the folder with two digits and the files inside with three digits.
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.
04 Hardware Setup
Wire the components to the board for each project using the diagrams and steps below.
Project 1: Smart Street Light
Hardware Structure Diagram:
Assembly Instructions:
- Construct the base.
- Install the ESP32 Control Board and Expansion Board.
Note: First fix the copper column on the base, then install the ESP32 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. - Install the battery holder.
Note: Use double-sided 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.
- Install the street lamp bracket.
- Install the LED module.
Note: Before installing the LED module, connect the 3-pin sensor cable in advance.
- Install a standing card on the base.

- Install the light sensor.
Note: Before installing the light sensor, connect its 3-pin 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.
- Install LUMI.

Hardware Wiring Diagram:
Wiring Instructions:
Project 2: Smart Traffic Light
Hardware Structure Diagram:
Assembly Instructions:
- Install the traffic light module.
Note: Before installing the traffic light module, connect the 4-pin sensor cable in advance.
- Secure the traffic light module onto the base.
- Install a standing sign on the base.

- Install the four-digit display module.
Note: Before installing the four-digit display module, connect its 4-pin connector in advance.
- Install the infrared obstacle avoidance sensor.
Note: Before fixing the sensor, connect its 3-pin cable in advance.
- Secure the infrared obstacle avoidance sensor.

- Construct the base.

Hardware Wiring Diagram:
Wiring Instructions:
Project 3: Smart Crossing
Hardware Structure Diagram:
Assembly Instructions:
- Construct the base.

- Install the battery holder.
Note: Use double-sided 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. - Install the ESP32 Control Board and Expansion Board.
Note: First fix the copper column on the base, then install the ESP32 Controller Board on the copper column, and finally install the expansion board. Align the holes with the ESP32 before installing it. - Install the railing.

- Install the servo motor.

Note: Assemble the servo box basswood boards in numerical order, and finally cover with the No.5 basswood board.
- Secure the railing structure.
Note: Before installing the wheel onto the railing, adjust the servo motor to the 90-degree position and keep it powered. Then install the railing. Before writing the program, install the library file "ESP32_Servo" for the servo.
- Secure the servo motor box onto the base.

- Install the traffic light module.
Note: Before installing the traffic light module, connect its 4-pin connector in advance.
- Secure the traffic light module onto the base.
- Install the signboard on the base.

- 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.
- Install the buzzer.
Note: Before installing the buzzer, connect its 3-pin connector in advance.
- Assemble the button module.

- Install LUMI.

Hardware Wiring Diagram:
Wiring Instructions:
Project 4: Smart Parking Lot
Hardware Structure Diagram:
Assembly Instructions:
- Construct the base.

- Install the ESP32 Control Board and Expansion Board.
Note: First fix the copper column on the base, then install the ESP32 Controller Board, then the expansion board, aligning the holes with the ESP32. - Install the battery holder.
Note: Use double-sided tape to attach the battery holder to the underside of the base, and do not cover the electric wire and pin holes.
- Assemble the RFID module.
- Install the RFID module on the base.
Note: Before securing the RFID module, connect the 4-pin sensor cable in advance.
- Install the railing.
- Install LUMI.

Note: Assemble the servo box basswood boards in numerical order, finishing with the No.6 basswood board. Note the orientation of the two holes on the No.6 board, which should face opposite the servo.
- Secure the railing structure.
Note: Before installing the wheel onto the railing, adjust the servo to the 90-degree position and keep it powered. Then install the railing.
- Install the servo structure.

- Install the infrared obstacle avoidance sensor.
- Secure the infrared obstacle avoidance sensor to the slope board.




- Install the intelligent parking lot signboard in the base.

- Install the LCD display screen.
- Secure the LCD display screen onto the base.

- Install the MP3 playback module.
Attention: Before installing the MP3 module, import the required MP3 files onto the module's memory card (see the MP3 Module tip in Application Discussion).
- Secure the MP3 playback module to the base.

- Install LUMI.
Hardware Wiring Diagram:
Wiring Instructions:
Project 5: Drag Racing Tree Light with Lap Detection
Schematic 1:
Schematic 2:
05 Software Setup
Follow these steps in order. Do not skip any step.
Step 1 — Install the Arduino IDE (Windows)
Description: Arduino IDE is a free, cross-platform programming tool used for writing, uploading, and debugging code for Arduino-compatible boards like the ESP32.
Download and Install
- Go to arduino.cc/en/Main/Software.
- 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
.exeinstaller. - 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".
- Locate the Arduino IDE shortcut on your desktop or Start menu and double-click to launch it.
Step 2 — Install ESP32 Board Resources
- Go to File → Preferences in the Arduino IDE.
- In Additional Boards Manager URLs, paste:
url
arduino.esp8266.com/stable/package_esp8266com_index.json
- 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.
- Reopen Tools → Board and check that ESP32 Dev Module appears in the list.
Step 3 — Install Libraries
Install the following libraries via the Library Manager, based on which project(s) you are building:
- TM1650 — for the 4-Digit Tube Display Module (Project 2)
- ESP32_Servo — for the servo motor (Projects 3 and 4)
- Adafruit_NeoPixel — for the RGB Light Strip Module (Project 3)
- MFRC522_I2C — for the RFID Module (Project 4)
- hd44780 — for the LCD1602 Module (Projects 4 and 5)
- ACB_MP3 — for the MP3 Module (Project 4)
Step 4 — Select Board and Port
- 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. - 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.
Step 5 — Upload the Code
- Open the Arduino IDE and paste in the code for your chosen project from the Code section below.
- 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) and wait until "Done uploading" appears in the status bar.
06 Code
Copy each file below into the Arduino IDE as described in the Software Setup section. Read the Code Breakdown section to understand what each part does.
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
}
}
Project 2: Smart Traffic Light
#include <Wire.h> //Introducing libraries related to I2C communication
#include <TM1650.h> //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;
}
}
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();
}
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);
}
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);
}
07 Code Breakdown
Here is what each part of the code does. Read this after uploading.
Project 1: Smart Street Light
Pin Definitions
-
LED (19)— Controls the street light brightness. -
PR (32)— Reads input from the light sensor module.
setup()
Configures the LED pin as output and the light sensor pin as input.
loop()
Reads light intensity using analogRead(PR). If the value is below 1500, the LED turns off. Otherwise, the sensor value (1500–4095) is mapped to a brightness range (0–255) and applied to the LED, with a 0.1s delay for smooth transitions.
Project 2: Smart Traffic Light
Libraries Used
-
Wire.h— Enables I2C communication. -
TM1650.h— Controls the 4-digit LED display.
Pin Definitions
-
R (14), Y (2), G (0)— Traffic light LEDs. -
PE (23)— Photoelectric sensor for vehicle detection.
Variables
-
carcount— Tracks detected cars. -
redtime, greentime, yellowtime— Light durations. -
display_time— Countdown timer display. -
light[3] = {'g','y','r'}— Traffic light sequence.
setup()
Initializes I2C and the TM1650 display, sets light pins as outputs and the sensor pin as input, and starts serial communication.
loop()
Cycles through green → yellow → red lights, updating the display countdown each second. Counts cars passing during the green phase and adjusts light durations if traffic volume exceeds 5 vehicles in 15 seconds.
trafficlight()
Activates the correct light color and sets display_time for the countdown.
Project 3: Smart Crossing
Libraries Used
-
Adafruit_NeoPixel.h— RGB LED strip control. -
ESP32Servo.h— Servo motor control.
Pin Definitions
-
R (14), Y (2), G (0)— Traffic light LEDs. -
Serve (4)— Servo gate control. -
Button (25)— Crossing activation. -
LED_PIN (18)— RGB strip data pin. -
buzzer (12)— Sound alert.
setup()
Initializes the LED strip, servo, traffic lights, and buzzer, then sets the default crossing mode.
loop()
Waits for a debounced button press, then runs the crossing sequence.
runButtonSequence()
Waits 5 seconds, shows a yellow light for 2 seconds, turns red with the servo down and the LED strip green, beeps the buzzer for 8 seconds, then returns to default mode.
Project 4: Smart Parking Lot
Libraries Used
-
ACB_MP3.h— MP3 audio control. -
Wire.h— I2C communication. -
MFRC522_I2C.h— RFID reader via I2C. -
ESP32Servo.h— Servo control. -
hd44780.h/hd44780ioClass/hd44780_I2Cexp.h— LCD control. -
List.hpp— List handling for card IDs.
Pin Definitions
-
SERVE (4)— Servo gate pin. -
PE (23)— Photoelectric vehicle detection. -
RAILING_CLOSE (90) / RAILING_OPEN (0)— 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()
Initializes the RFID reader, servo, LCD, and MP3 module, and sets the initial gate position and default display.
loop()
On car detection at entry, prompts for IC card registration, stores the new card, decreases available slots, and starts billing. On IC card detection at exit, calculates the parking fee, opens the gate, and removes the card from the list.
Helper Functions
-
getCardUID()— Reads the card UID. -
indexOfList()— Finds a card in the list. -
spaceDisplay()— Updates the LCD display.
Project 5: Drag Racing Tree Light with Lap Detection
Libraries Used
-
Wire.h— I2C communication. -
hd44780.h/hd44780ioClass/hd44780_I2Cexp.h— LCD control.
Pin Definitions
-
R (14), Y (2), G (0)— Traffic light LEDs. -
buzzer (12)— Race start and alert sounds. -
PE (23)— Infrared lap detection sensor. -
Button (25)— Starts the race.
Variables
-
laps— Remaining laps (default 3). - Debounce delay variables for the button and IR sensor.
setup()
Initializes pins and the LCD, displays "Push Button to Start," and turns all lights on initially.
loop()
Waits for a button press to trigger race start, and detects laps using the IR sensor with debounce.
startSequence()
Blinks the red light twice with the buzzer, shows yellow for 2 seconds, then green for 3 seconds with the buzzer, and displays laps remaining on the LCD.
handleLapDetection()
Decreases the lap count on each IR detection and shows "FINISH!" when the race ends, then resets the system.
08 Testing and Calibration
After uploading, verify each of the following to confirm the ESP32 setup is working correctly before building out a full project.
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).
Upload a Test Program
Open the Arduino IDE, write or paste a simple test sketch (e.g. Serial.println("Hello ESP32");), click Verify to compile, then click Upload. 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), and confirm that your test message appears — this verifies the board is working correctly.
09 System Demonstration
Video demonstrations of each completed project are below.
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
10 Conclusion
The ACEBOTT Intelligent Transportation Education Kit – Level 1 stands out as a powerful and practical tool for introducing STEM education in an engaging, hands-on way. Through a series of projects — the Smart Street Light, Smart Traffic Light, Smart Crossing, Smart Parking Lot System, and a 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 Scratch-based block programming is also available, bridging the gap between theory and real-world application 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 understand the fundamentals of electronics, automation, and intelligent transportation systems using real-world applications. With all essential components included, it's a practical choice for schools, STEM educators, and workshops aiming to deliver meaningful tech learning experiences.
Possible Improvements and Future Enhancements
- Add Wi-Fi connectivity so traffic and parking data can be monitored remotely from a phone or dashboard.
- Log sensor and traffic data over time to analyze patterns and optimize light timing further.
- Combine multiple projects (e.g. Smart Crossing and Smart Traffic Light) into a single connected intersection model.
11 References
- Arduino Documentation
- Acebott Official Website
- ACEBOTT QE027 Intelligent Transportation L1 Documentation
12 Project Authors
- Francesca Rose Bejenia
- Lemuel Jess Azaria
- Kyla Jade Entorum
