Intelligent Transport System using ACEBOTT QE027 Education Kit (ESP32 – Level 1)
ACEBOTT QE027 Intelligent Transportation Educational Kit (Level 1): 5 Smart Transportation Projects

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.

Smart Street Light project

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.

Smart Traffic Light project

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.

Smart Crossing project

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.

Smart Parking Lot project

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.

Drag Racing Tree Light project

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)
Note: Library download links are provided by ACEBOTT via Google Drive folders — see the Software Setup section for each project's specific library requirements.

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.

ESP32 board

Pinout:

ESP32 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.

ESP32 expansion board

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.

White LED module

Pinout:

White LED module 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.

Light sensor module

Pinout:

Light sensor module 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.

Traffic light module

Pinout:

Traffic light module 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.

Infrared obstacle avoidance sensor

Pinout:

Infrared sensor 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.

4-digit tube display module

Pinout:

4-digit tube display 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.

RGB light strip module

Pinout:

RGB light strip 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.

Servo SG90

Pinout:

Servo SG90 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.

Button module

Pinout:

Button module 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.

Buzzer module

Pinout:

Buzzer module 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.

MP3 module

Pinout:

MP3 module pinout

Application: Broadcasts voice prompts, alerts, or background music for transportation systems, such as announcing traffic light changes or guiding parking lot drivers.

Tip: Before controlling the MP3 playback module, pre-load songs onto its memory card. Insert the memory card into the module, connect the module's USB port to a computer with a Type-C cable, then copy your MP3 files onto the drive that appears. Files placed in the root directory must start with four digits (e.g. 0001Hero.mp3). To use folders, name the folder with two digits and the files inside with three digits.
Inserting memory card into MP3 module Connecting MP3 module to computer MP3 file naming example MP3 folder naming example

LCD1602

Description: A 16-character by 2-line LCD display module for showing alphanumeric information. Often connected via an I2C adapter to reduce wiring.

LCD1602 module

Pinout:

LCD1602 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.

RFID module

Pinout:

RFID module 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.

IC card

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:

Smart Street Light hardware structure

Assembly Instructions:

  1. Construct the base.
    Street light base
  2. Install the ESP32 Control Board and Expansion Board.
    Installing ESP32 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.
  3. Install the battery holder.
    Installing 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.
    Battery holder placement
  4. Install the street lamp bracket.
    Street lamp bracket
  5. Install the LED module.
    Note: Before installing the LED module, connect the 3-pin sensor cable in advance.
    LED module install step 1 LED module install step 2 LED module install step 3
  6. Install a standing card on the base.
    Standing card step 1Standing card step 2
  7. 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.
    Light sensor install step 1 Light sensor install step 2 Light sensor install step 3
  8. Install LUMI.
    Installing LUMI step 1Installing LUMI step 2

Hardware Wiring Diagram:

Smart Street Light wiring diagram

Wiring Instructions:

Smart Street Light wiring instructions
Note: Please 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:

Smart Traffic Light hardware structure

Assembly Instructions:

Note: This project uses the same base structure as the Smart Street Light project. Proceed directly to installing the traffic light module.
Smart Traffic Light base
  1. Install the traffic light module.
    Note: Before installing the traffic light module, connect the 4-pin sensor cable in advance.
    Traffic light module install
  2. Secure the traffic light module onto the base.
    Securing traffic light module
  3. Install a standing sign on the base.
    Standing sign step 1Standing sign step 2
  4. Install the four-digit display module.
    Note: Before installing the four-digit display module, connect its 4-pin connector in advance.
    Four-digit display step 1 Four-digit display step 2 Four-digit display step 3
  5. Install the infrared obstacle avoidance sensor.
    Note: Before fixing the sensor, connect its 3-pin cable in advance.
    IR sensor install
  6. Secure the infrared obstacle avoidance sensor.
    Securing IR sensor step 1Securing IR sensor step 2
  7. Construct the base.
    Base step 1Base step 2

Hardware Wiring Diagram:

Smart Traffic Light wiring diagram

Wiring Instructions:

Smart Traffic Light wiring instructions
Note: Before writing the program, install the library file "TM1650" for the 4-Digit Tube Display Module (see Software Setup). Please strictly follow the wiring instructions when connecting modules to the ESP32 controller board — incorrect wiring may cause a short circuit and damage the board.

Project 3: Smart Crossing

Hardware Structure Diagram:

Smart Crossing hardware structure

Assembly Instructions:

  1. Construct the base.
    Smart Crossing base step 1Smart Crossing base step 2
  2. Install the battery holder.
    Battery holder install
    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.
  3. Install the ESP32 Control Board and Expansion Board.
    ESP32 and expansion board install
    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.
  4. Install the railing.
    Railing install step 1Railing install step 2
  5. Install the servo motor.
    Servo motor install step 1Servo motor install step 2
    Note: Assemble the servo box basswood boards in numerical order, and finally cover with the No.5 basswood board.
    Servo box assembly
  6. 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.
    Railing structure secured
  7. Secure the servo motor box onto the base.
    Servo motor box step 1Servo motor box step 2
  8. Install the traffic light module.
    Note: Before installing the traffic light module, connect its 4-pin connector in advance.
    Traffic light module install
  9. Secure the traffic light module onto the base.
    Traffic light module secured
  10. Install the signboard on the base.
    Signboard step 1Signboard step 2
  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.
    RGB LED strip install step 1 RGB LED strip install step 2
  12. Install the buzzer.
    Note: Before installing the buzzer, connect its 3-pin connector in advance.
    Buzzer install step 1 Buzzer install step 2
  13. Assemble the button module.
    Button module step 1Button module step 2
  14. Install LUMI.
    LUMI install step 1LUMI install step 2

Hardware Wiring Diagram:

Smart Crossing wiring diagram

Wiring Instructions:

Smart Crossing wiring instructions
Note: Before writing the program, install the library file "Adafruit_NeoPixel" for the RGB strip module (see Software Setup).

Project 4: Smart Parking Lot

Hardware Structure Diagram:

Smart Parking Lot hardware structure

Assembly Instructions:

  1. Construct the base.
    Parking lot base step 1Parking lot base step 2
  2. Install the ESP32 Control Board and Expansion Board.
    ESP32 install
    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.
  3. Install the battery holder.
    Battery holder install
    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.
    Battery holder placement
  4. Assemble the RFID module.
    RFID module assembly
  5. Install the RFID module on the base.
    Note: Before securing the RFID module, connect the 4-pin sensor cable in advance.
    RFID module install step 1 RFID module install step 2
  6. Install the railing.
    Railing install
  7. Install LUMI.
    LUMI install step 1LUMI install step 2
    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.
    Servo box detail 1 Servo box detail 2 Servo box detail 3
  8. 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.
    Railing structure secured
  9. Install the servo structure.
    Servo structure step 1Servo structure step 2
  10. Install the infrared obstacle avoidance sensor.
    IR sensor install
  11. Secure the infrared obstacle avoidance sensor to the slope board.
    IR sensor slope 1IR sensor slope 2IR sensor slope 3IR sensor slope 4IR sensor slope 5
  12. Install the intelligent parking lot signboard in the base.
    Signboard install step 1Signboard install step 2
  13. Install the LCD display screen.
    LCD install
  14. Secure the LCD display screen onto the base.
    LCD secured step 1LCD secured step 2
  15. 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).
    MP3 module install step 1 MP3 module install step 2
  16. Secure the MP3 playback module to the base.
    MP3 module secured step 1MP3 module secured step 2
  17. Install LUMI.
    LUMI final install

Hardware Wiring Diagram:

Smart Parking Lot wiring diagram

Wiring Instructions:

Smart Parking Lot wiring instructions
Note: Before writing the program, install the library files "MFRC522_I2C" (RFID), "hd44780" (LCD1602), and "ACB_MP3" (MP3 module).

Project 5: Drag Racing Tree Light with Lap Detection

Schematic 1:

Drag Racing schematic 1

Schematic 2:

Drag Racing 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

  1. Go to arduino.cc/en/Main/Software.
  2. Select the correct version: Windows 10 or above → Arduino IDE 2.x. Before Windows 10 → Arduino IDE 1.x.
  3. Click the download button and choose "Download Only" to get the .exe installer.
  4. Locate and double-click the downloaded installer file.
  5. Click "I Agree" to accept the license agreement.
  6. Click "Next", then "Install".
  7. Wait for the installation to finish, then click "Close".
  8. Locate the Arduino IDE shortcut on your desktop or Start menu and double-click to launch it.
    Arduino IDE shortcut

Step 2 — Install ESP32 Board Resources

  1. Go to File → Preferences in the Arduino IDE.
    Arduino IDE preferences
  2. In Additional Boards Manager URLs, paste:
    url
    arduino.esp8266.com/stable/package_esp8266com_index.json
    Boards manager URL field
  3. Go to Tools → Board → Board Manager (or click the Boards icon in the left toolbar).
  4. Search for ESP32, select Version 2.0.12, and click Install.
    Installing ESP32 board package
  5. 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)
Note: Library files for this kit are distributed by ACEBOTT via Google Drive rather than the Arduino Library Manager. Download the correct library folder for your project before compiling.

Step 4 — Select Board and Port

  1. Use a Type-C data cable to connect the ESP32 to your computer.
  2. Open Device Manager and check under Ports (COM & LPT) for USB-SERIAL CH340 (COMx). If it shows as "Unknown Device," install the CH340 driver.
  3. In Arduino IDE, go to Tools → Board and choose ESP32 Dev Module.
    Selecting ESP32 Dev ModuleESP32 board selection detail
  4. Go to Tools → Port and select the COM port number matching your ESP32 in Device Manager.

Step 5 — Upload the Code

  1. Open the Arduino IDE and paste in the code for your chosen project from the Code section below.
  2. Click the Verify button (check mark icon) to compile. If there's an error, review your code or board settings.
  3. 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

Arduino / C++
#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

Arduino / C++
#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

Arduino / C++
#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

Arduino / C++
#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

Arduino / C++
#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).

Common Issue: If it shows as "Unknown Device," install the CH340 driver before continuing.

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.

Common Issue: A compile error usually points to a missing library or an incorrect board selection under Tools → Board.

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
Quality Checked by
  • Lemuel Jess Azaria
  • Kyla Jade Entorum
ACEBOTT QE027 Intelligent Transportation Educational Kit (Level 1) – CreateLabz
Acebott intelligent transportation kit, Arduino ide, Drag racing tree light, Educational robotics kit, Esp32, Pedestrian crossing project, Smart city projects, Smart parking system, Smart street light, Stem education

Leave a comment

All comments are moderated before being published