Top 80+ Beginner-Friendly EEE/ECE Mini-Projects for Electronics Worth Trying

For students in Electronics and Communication Engineering (ECE), a mini-project is more than just a submission; it’s an opportunity to turn concepts like sensors, microcontrollers, embedded systems, communication, automation, digital electronics, and IoT into a working prototype.
That’s where Circuit Digest can be a practical resource for electronics students. Our project resources are available for free, with GitHub code, circuit schematics, and detailed project walkthroughs, including mini projects that cover the basics of electronics. We help students explore a wide range of electronics and communication topics through academic projects, experimentation, and hands-on learning.
Whether you’re looking for beginner-friendly ECE/EEE mini projects for Electronics, an Arduino project, an embedded systems idea, an IoT prototype, a communication project, or a more advanced electronics concept, Circuit Digest can help you explore your options, narrow down your choices, and find a project that fits your interests and goals.

Learn by Building: Hands-On Electronics Mini Projects to Turn Ideas into Reality 

The best way to learn electronics is to build something yourself. Each project includes a working circuit, source code, and a simple explanation of how everything works together. So, instead of just following the steps, you get to understand what’s happening in the circuit and why it works. These projects give you a practical way to take what you’ve learned in the classroom and turn it into a working prototype that you can test, improve, and confidently demonstrate.

Automatic Toll Gate System Using Arduino

Automatic Toll Gate System Using Arduino

The “automatic toll gate system project” shows how simple sensors and a microcontroller can automate a real-life process like toll collection, making it an ideal project for anyone just starting in electronics. 

Dual Axis Solar Tracker System

Dual Axis Solar Tracker System

This dual-axis solar tracking system uses Arduino to move the solar panel horizontally and vertically based on the sun's location. This project, using LDR and servo motors, can increase energy output by up to 40% compared to fixed solar installations. 

Arduino Location Tracker

Arduino Location Tracker

This comprehensive project creates a fully functional GPS tracking system using Arduino UNO R3, SIM800L GSM module, and NEO-6M GPS module, a perfect low-cost DIY combination for vehicle monitoring, asset protection, or personal safety applications. 

Gas Leakage Detector

Gas Leakage Detector 

In this project, you'll learn how to build a simple and budget-friendly gas leakage detector using Arduino. This LPG gas leak detector uses an Arduino Uno and MQ-5 gas sensor to detect gas levels in the air and activates a buzzer and LED to alert users when a leak is present.

Smoke and Fire Alarm System

Smoke and Fire Alarm System 

In this project, you will also learn how to build an Arduino smoke alarm that sends SMS Alerts without needing to rely on the GSM module.  A fire and smoke alarm system using Arduino UNO R4 that sends real-time SMS notifications.

Send SMS with Arduino UNO R4 via Internet

Send SMS with Arduino UNO R4 via the Internet 

In this tutorial, I’ll show you how to send SMS using Arduino UNO R4 and the free CircuitDigest Cloud SMS API. Whether it’s fire detection, motion sensing, or home automation, this setup has you covered.

Speed Sensor using Arduino

Speed Sensor using Arduino

In this article, we will learn how to calculate speed using Arduino and an IR sensor. By setting up the two IR sensors at a fixed distance from each other, we can track the time it takes for the object to travel between them. 

Detect the Direction of Sound

Detect the Direction of Sound

In this tutorial, let's learn how to find the direction of sound using Arduino and a few microphones. With the recorded time and the known distance between them, we can accurately calculate the object's speed using a formula.

RFID Door Lock System

 RFID Door Lock System

In this article, we will learn how to build an RFID door lock system using Arduino. It’s a fun and secure way to unlock the door. By integrating an RFID reader with an Arduino, this system will automatically open the door when an authorised RFID card or tag is scanned. 

Smart Home Using Arduino Uno R4 WiFi

Smart Home Using Arduino Uno R4 WiFi

Our Smart Home Using Arduino Uno R4 WiFi project is designed for home safety and convenience, integrating temperature, humidity, light, and gas monitoring. This project is perfect for anyone who wants to make their home or office a little smarter. 

Speaking Alarm Clock Using the XIAO ESP32-S3

 Speaking Alarm Clock Using the XIAO ESP32-S3

The ESP32 speaking alarm clock built in this tutorial replaces the beep at a scheduled time and expects the user to interpret the reason for the beep. This DIY Speaking Alarm Clock is developed using the XIAO ESP32-S3 microcontroller and a cloud-based Text-to-Speech (TTS) engine.

Noise Pollution Monitoring System

Noise Pollution Monitoring System

Noise Pollution Monitor tracks, analyses, and alerts on rising noise levels in real time. The noise pollution monitoring project continuously measures ambient sound and vibration, displays the readings locally, and pushes data to CircuitDigest Cloud to access the data from anywhere. 

Metal Detector System

Metal Detector System

This metal detector uses an affordable Wi-Fi-enabled microcontroller, a handful of available components, and a simple, hand-wound copper coil. We’ll guide you through winding the induction coil, assembling the pulse circuit, and flashing the code for this DIY PI metal detector.

Helmet Detection with Raspberry Pi

Helmet Detection with Raspberry Pi

This project is a compact, traffic monitoring device that uses a USB camera, Python, OpenCV, and the CircuitDigest Cloud API to automatically detect whether two-wheeler riders are wearing helmets in real time, without the need for on-device machine learning training or manual dataset labelling.

Raspberry Pi Waste Segregation System

Raspberry Pi Waste Segregation System

This project captures an image of waste using a USB camera and can be sent to an Image Processing API located in the Cloud for classification as either biodegradable or non-biodegradable. No trained machine learning model is required for classification, which is done using an API call. 

Raspberry Pi Parking Space Detection System

Raspberry Pi Parking Space Detection System

We have built a parking space detection system without any complex setup. We only need a Raspberry Pi board, a USB camera, and an account in CircuitDigest Cloud. The Requests library then sends the image to the CircuitDigest Cloud API using an HTTPS POST request with the API key.

T Flip-Flop

 T Flip-Flop

The flip-flop, aka latch, can also be understood as a bistable multivibrator with two stable states. Generally, these latch circuits can be either active-high or active-low, and they can be triggered by HIGH or LOW signals, respectively.

NAND Gate with Transistors

NAND Gate with Transistors

In this article, we will go over how to build a NAND gate circuit with transistors. Transistors serve as the building blocks of logic gates, such as AND gates, NAND gates, OR gates, XOR gates, and other gates that are integral to integrated circuits. 

XOR Gate with Transistors

XOR Gate with Transistors

In this article, we will explore the inner workings of the XOR gate, including its truth table, logical symbol representation, circuit diagram, and practical construction using transistors. The XOR gate an essential component in various applications, from binary arithmetic to complex data encryption algorithms.

Panic Alarm Button Circuit

Panic Alarm Button Circuit

A Panic Alarm Circuit is used to send an emergency signal immediately to people in nearby locations to call for help or to alert them. The indication of an emergency can either be in the form of a visible or audible signal, which can be fixed a few meters away through wire.

Fire Alarm Circuit

Fire Alarm Circuit

Building a simple fire alarm system using a 555 Timer IC that will sense a fire (temperature rise in the surrounding area) and trigger the alarm. The key component of the circuit is a thermistor, which has been used as a fire detector or a fire sensor

Rain Alarm

Rain Alarm

A rain alarm is an application which detects rainwater and blows an alarm. They are useful device and plays an important role in various industries such as automobile, irrigation, and wireless communication. 

Fridge Door Alarm Circuit

Fridge Door Alarm Circuit

This circuit triggers the alarm if the door of the fridge is left open for a long time. When the door of the refrigerator is left open, the temperature inside the cabin will increase. This rise in temperature will be sensed by the thermostat, which will try to cool down the cabin.

Doorbell using IC 555

Doorbell using IC 555

The main feature of this doorbell is that we can control the duration for which it keeps ringing upon pressing the switch. Also, we can control the oscillation frequency of the “doorbell sound” produced by the Doorbell (Here we are using a buzzer as a bell to illustrate).

Simple Flashing LED

Simple Flashing LED

An LED Flasher Circuit project is done with available electronic components and an easy-to-understand schematic. This tutorial will show you how to make an LED glow and fade at a certain interval

LED Dimmer Circuit

LED Dimmer Circuit

Building an LED ON and OFF circuit using a 555 timer IC and BC557 is very simple. In this circuit, the 555 timer IC is configured as an astable multivibrator, which means that it produces a continuous square wave output with a fixed frequency and duty cycle.

 DC-DC Boost Converter

DC-DC Boost Converter

In this article, we will learn about buck converters and design a very simple boost converter using a 555 timer and IRFZ44N, an N-channel MOSFET. A boost converter is a non-isolated type of switch-mode power supply that is used to step up the voltage.

 555 Timer-Based Buck Regulator

555 Timer-Based Buck Regulator

This circuit is basically a simple power electronics DC-DC Buck converter which can be used to step down voltage; its efficiency results in better battery life due to reduced heat generation, making it a lucrative option for smaller gadgets.

Positive and Negative Charge Pump Circuit

Positive and Negative Charge Pump Circuit

A charge pump is a type of circuit that is made out of diodes and capacitors configured in a specific configuration to get the output voltage higher than the input voltage or lower than the input voltage. By lower, I mean a negative voltage with respect to ground.

Simple Fading LED Light

 Simple Fading LED Light

The slow fade LED circuit is very simple; the 555 has been used in Astable mode, and a transistor is used to amplify the current. In Astable mode, the 555 IC oscillate at a particular frequency (depending on RC components), meaning the output at PIN 3 goes HIGH and LOW periodically.

Transistor Tester using 555 Timer IC

Transistor Tester using 555 Timer IC

In this tutorial, we will design a simple 555 TIMER-based circuit which will test the working of the transistor in seconds. This circuit is a convenient way to check the working of a transistor for newbies.

Audio Amplifier using 555 Timer IC

Audio Amplifier using 555 Timer IC

 In this tutorial, we are going to see how a 555 IC can be used as an audio amplifier. A low-power audio signal can be amplified using a 555 Timer IC.  We can test this circuit by blowing some air from the mouth towards the Mic; the speaker will generate sound.

Current Detector Circuit with 555 Timer

Current Detector Circuit with 555 Timer 

In this article, we build a simple current detector circuit with a 555 Timer and some passive components, which can help you to detect open live lines with ease. Before starting work on an electrical box and AC mains, one needs to verify that there is no AC leakage voltage.

Motion Detector Circuit using 555 Timer

Motion Detector Circuit using 555 Timer

In this tutorial, we are going to use an IR sensor with a NE555 Timer IC to detect motion and switch the AC load according to that. The 555 timer IC is used as a switch here. This circuit uses a digital timer IC; the operation of the circuit is fast and accurate, with even faster detection speeds. 

Simple LDR Circuit

Simple LDR Circuit

This dark detector circuit uses a 555 timer IC and an LDR (Light Dependent Resistor), which senses the light in the surroundings, and if it does not find light, it triggers the IC and turns on an LED attached to the circuit. 

Smart Dustbin Using Arduino

Smart Dustbin Using Arduino

This automatic smart dustbin is a decent gadget to make your home clean and attractive. Kids spread trash to a great extent with paper, wrappers, and numerous other things at home.  It opens automatically without touching to throw all trash and waste into this smart dustbin

Automatic Plant Watering System Using Arduino

Automatic Plant Watering System Using Arduino

This DIY automatic plant watering system project helps solve the common problem of forgetting to water plants while away from home. In this complete guide, we'll show you how to make an automatic plant watering system with soil moisture sensing and mobile app control capabilities.

ESP32 WLED Controller

ESP32 WLED Controller

 DIY tutorial is all about making our home lighting smart and fun without any complicated steps. We can connect a standard 12V LED strip to a tiny wi-fi chip and build our own ESP32 WLED controller.

Digital Keypad Security Door Lock

Digital Keypad Security Door Lock

In this project, I have built an Arduino Keypad Door Lock which can be mounted to any of your existing doors to secure them with a digital password. Of all the solutions, the low-cost one is to use a password- or PIN-based system.

Automatic Pet Feeder

Automatic Pet Feeder

Arduino automatic pet feeder that feeds your pet automatically at scheduled times. This project incorporates a DS3231 RTC (Real Time Clock) Module, allowing you to keep track of your pet's eating schedule and properly schedule feeding at specific times. 

3-Way Traffic Light Controller

3-Way Traffic Light Controller

This Arduino-based 3-Way Traffic Light Controller is a simple project which is useful for understanding how traffic lights work, which we see around us. It’s pretty simple and can be easily built on a breadboard 

Digital Thermometer Using Arduino

Digital Thermometer Using Arduino 

In this project, we have made an Arduino-based digital thermometer to display the current ambient temperature on a 16x2 LCD unit in real time. It can be deployed in houses, offices, industries, etc., to measure the temperature. 

Voice Controlled Home Automation

Voice Controlled Home Automation

 This is a model of a Modern Smart Home. These features demonstrate what a Smart Home would be like. It improves automation, control and monitoring of household devices and connects via standard means of communication for its operation.

Virtual Reality Interface with Gesture-Contro

Virtual Reality Interface with Gesture-Control 

This is a very interesting project in which we are going to learn how to implement virtual reality using Arduino and Processing. We will show you how you can simply wave your hand in front of a webcam and draw something on your computer. 

Arduino RFID Door Lock

Arduino RFID Door Lock

This RFID Door Lock can be made easily at home, and you can install it on any door. This door lock is just an electrically operated door lock which gets open when you apply some voltage (typically 12v) to it.

Automatic Street Light Controller

Automatic Street Light Controller

This Simple Automatic Street Light Circuit, using an LDR and a relay, will turn the light bulb on and off based on the light in the surroundings. This circuit is quite simple and can be built with Transistors and an LDR; you don’t need any op-amp or 555 IC to trigger the AC load. 

Clap Switch

Clap Switch

A clap switch, it can be turned ON by any sound of approximately the same pitch as a clap. Here, we are using an Electric Condenser Mic for sensing the sound, a transistor to trigger the 555 timer IC, and a 555 IC to turn ON the LED through a low-voltage trigger. 

Handheld Arduino Game Console

Handheld Arduino Game Console 

This Arduino handheld game console is lightweight, easy to carry, and simple to build, making it perfect for hobbyists, electronics engineers, and young tech enthusiasts alike. It’s beginner-friendly, and it is enough to spark creativity and deeper learning.

BLE-based Proximity Control

BLE-based Proximity Control 

In this article, I am going to show you how to make a simple BLE presence detector with the help of an ESP32 and Arduino, and in the end, we will test these devices using BLE on my smartphone and a smartwatch. 

ESP32-Based Webserver

ESP32-Based Webserver

An ESP32-based web server is used to display the temperature and humidity values from the DHT11 sensor. ESP32 board will read the temperature and humidity data from the DHT11 sensor and display it on the Webpage. Here, IFTTT is also used to send email notifications when the temperature goes beyond a particular limit.

Raspberry Pi Digital Code Lock

Raspberry Pi Digital Code Lock

Security is a major concern in our day-to-day life, and digital locks have become an important part of these security systems. Here, we are going to build this Digital Lock using a Raspberry Pi with a user-defined password. Once the password is set, the user can only access the door with the correct password.

16x2 LCD Interfacing with Raspberry Pi

16x2 LCD Interfacing with Raspberry Pi

In this tutorial, we will control a 16x2 LCD Display using a Raspberry Pi. We will connect the LCD to the GPIO (General Purpose Input/Output) pins of the Pi to display characters on it. We will write a program in PYTHON to send the appropriate commands to the LCD through GPIO and display the needed characters on its screen.

7 Segment Display

7 Segment Display

In this tutorial, we are going to do Raspberry Pi 7-segment display interfacing. Seven-segment displays are the cheapest display units. A couple of these segments stacked together could be used to display temperature, counter value, etc. We will connect the 7-segment display unit to the GPIO of the Pi and control it to display digits accordingly.

Room Temperature Measurement with Raspberry Pi

Room Temperature Measurement with Raspberry Pi

So here we are designing the first application based on the previous tutorials. The first basic application is reading room temperature with the Raspberry Pi. And you can monitor the Readings on a computer. There are no ADC channels provided internally in the Raspberry Pi. So, if we want to interface any analog sensors, we need an ADC conversion unit.

Arduino Ultrasonic Distance Measurement

Arduino Ultrasonic Distance Measurement

In this project, we have used the HC-SR04 Ultrasonic Sensor with Arduino to determine the distance of an obstacle from the sensor. The basic principle of ultrasonic distance measurement is based on the echo. When sound waves are transmitted in the environment, the waves return to the origin as an echo after striking the obstacle.

Arduino Soil Moisture Sensor

Arduino Soil Moisture Sensor

Whether you're a beginner learning how to connect a soil moisture sensor with Arduino, this step-by-step tutorial covers everything you need. We'll show you the exact Arduino soil moisture sensor wiring diagram, provide working Arduino soil moisture sensor code, and guide you through common troubleshooting scenarios that every maker encounters.

 

Temperature Controlled Fan using Arduino

Temperature Controlled Fan using Arduino

In today's fast-paced world, convenience is key. Dealing with the temperature fluctuations in your living space can be quite a hassle. In this temperature-controlled fan project, we'll guide you through the process of converting your temperature-controlled fan using an Arduino Uno, LM35 temperature sensor, and a relay.

Arduino Calculator using 4x4 Keypad

Arduino Calculator using 4x4 Keypad

In this tutorial, we will build our own calculator with Arduino. The values can be sent in through a keypad (4×4 keypad), and the result can be viewed on an LCD screen (16×2 dot matrix). This calculator could perform simple operations like Addition, Subtraction, Multiplication and Division with whole numbers.

Arduino Motion Detector

Arduino Motion Detector

In this project, we will learn how we can interface a PIR Sensor with a microcontroller like Arduino. We will interface an Arduino with a PIR module and blink an LED and beep a Buzzer whenever a movement is detected. The following components will be needed to build this project.

Arduino I2C Communication

Arduino I2C Communication

Today we will learn about another Serial Communication Protocol: I2C (Inter-Integrated Circuit). Comparing I2C with SPI, I2C has only two wires, while SPI uses four, and I2C can have Multiple masters and slaves, while SPI can have only one master and multiple slaves.

Audio Amplifier Circuit

Audio Amplifier Circuit

LM386 is a low-voltage audio amplifier and is frequently used in battery-powered music devices like radios, guitars, toys, etc. The gain range is 20 to 200; the gain is internally set to 20 (without using external components) but can be increased to 200 by using a resistor and capacitor between pins 1 and 8, or just with a capacitor.

Air Quality Monitoring

Air Quality Monitoring

Design a professional air quality monitoring system using Arduino to monitor the overall environmental conditions in real time. If you want to try your hand at building an air quality monitoring system project yourself, this detailed guide has step-by-step instructions all the way from choosing the electronic components to writing the software.

Arduino Data Logger

Arduino Data Logger

Here we are building Arduino Data Logger Project where we will learn how we can log data at a specific interval of time. We will use an Arduino board to read some data (here, temperature, humidity, date and time) and save it on an SD card and the computer simultaneously.

Peak Detector Circuit

Peak Detector Circuit

A peak detector circuit is used to find the peak amplitude in a rapidly changing waveform. Peak detectors are generally used in sound-measuring applications to find the maximum level of sound in a particular area or place, which helps in determining the maximum loudness level in that place.

Joule Thief Circuit

Joule Thief Circuit

The Joule Thief Circuit is a simple and clever electronic design that can power an LED using a nearly dead battery. The project demonstrates how basic components like a transistor, a toroidal coil, and a resistor can work together to boost a low input voltage to a usable output voltage.

Voice Controlled LEDs

Voice Controlled LEDs

Controlling LEDs with voice command seems to be a difficult task, but it’s easy and you can quickly build it. We just need an Arduino UNO to serially communicate with HC-06 Bluetooth module and a smartphone to send voice command to Bluetooth module HC-06.

Arduino Wirelessly over Bluetooth

Arduino Wirelessly over Bluetooth

Wireless programming or OTA (Over the Air) Programming can be done easily in ESP8266 and ESP32 as they have Wi-Fi support built in on board. But in Arduino, we have to use the Bluetooth module to program it wirelessly. So here we are going to learn how to program Arduino over Bluetooth.

Digital Clock using Arduino UNO

Digital Clock using Arduino UNO

In this project, we have the above-mentioned components, and the working is quite easy to understand. The user will input data through the matrix keypad. At first, we have to enter the hour and then the minutes. Then we have to insert the date, month and year in the correct format.

Arduino Countdown Timer

Arduino Countdown Timer

Here, in this tutorial, we will show you how to make a Countdown Timer using Arduino. Here, we are not using any Real Time Clock (RTC) module to get the time. The time duration is provided by the user with the help of a keypad and a 16x2 LCD.

What Makes a Good Mini Project for ECE/EEE?

A good project has to fit your budget, available components, semester timeline, technical skill level, and, most importantly, give you something meaningful to explain during a viva or interview.
Finding an electronics and communication engineering mini-project topic is often the first challenge. Finding a project that matches your skill level, syllabus, budget and available components is the harder part.
Before choosing a topic, consider five things:

» Technical relevance- Does the project demonstrate something you have learned?
» Buildability - Can you obtain the components and complete the prototype within your deadline?
» Budget - Can you build it without spending unnecessarily on specialised hardware?
» Demonstration value - Can you clearly show the input, processing and output?
» Learning value - Will you be able to explain the circuit, code, limitations and future improvements?

These factors are particularly important for a low-cost electronics engineering mini project. Existing engineering project resources frequently emphasise that cost, time and resource availability strongly influence project selection.

Why use Circuit Digest for Mini Projects for Electronics?

  • Ready-to-use code: Many projects include source code and GitHub resources that students can study, modify, and experiment with.
  • Practical orientation: Focus on projects that can help connect classroom concepts with working electronics.
  • Technology exploration: Compare traditional circuit approaches with modern microcontroller, wireless and IoT-based implementations.
  • Learning before building: Understanding the circuit and technology behind a project makes it easier to troubleshoot and explain.
  • Useful for academic work: Project ideas can help students move from topic selection to prototyping, documentation and demonstration.

Circuit Digest helps make your journey easier by bringing electronics engineering mini project ideas and practical technical knowledge together in one place.

Explore Related Project Hubs: Artificial Intelligence | Electronics | IoT | Robotics | ESP32 | Raspberry Pi | Arduino Projects | Drone Projects |  Electronic Circuit 

Get Help Along the Way

Circuit Digest’s community is active and always ready to help. If you get stuck while building a project or simply want feedback on your work, you can connect with us and get guidance from our community. Join us on our WhatsAppand Instagram channelto ask questions, share your projects, and get the support you need. 

Have any question related to this Article?

iHub Robotics, the Kerala Startup Building Almost Every Layer of Its Humanoids In-House

Submitted by Staff on

Athil said his interest in robotics began during his school years, inspired partly by the Tamil film Enthiran and partly by Iron Man. He said he wanted to build his own version of that kind of technology. During that period, Arduino boards were difficult to get, so he started building small robots from whatever components were available.

ESP32 Video Player: SD Card to TFT Display

Playing smooth, full-motion video on low-power microcontrollers has been challenging due to memory and processing limitations. But with the dual-core speed, high SPI clock rates and an optimized decoding library on the ESP32, you can turn a simple development board into a working video player. If you want to create custom animations or add dynamic visual UI elements to your hardware projects, building this video player is a great way to push your hardware to its limits.
    In this tutorial, we are building an ESP32 video player that streams Motion JPEG (.mjpeg) files directly from a MicroSD card and displays them on a TFT display. We’ll walk you through all the hardware setup, video file formatting and code implementation needed to get your video running smoothly. You can also check out similar ESP32 Projects done previously here at Circuit Digest.

How Does This ESP32 Video Player Work?

Below is the block diagram of the ESP32 video player

1. SD Card

Stores the video as a Motion JPEG (.mjpeg) file—a simple sequence of individual JPEG images packed back-to-back.
The ESP32 reads this raw file stream continuously over the SPI bus.

2. RAM Buffer

Reads data in 4KB chunks into memory instead of byte-by-byte to prevent lag.
Scans incoming data to locate frame boundary markers and assemble complete JPEG images in RAM.

3. JPEG Decoder

Uses the lightweight JPEGDEC library to decompress the JPEG image directly in memory.
Converts the JPEG data into a 16-bit RGB565 pixel format that the screen can render.

4. TFT Display

Receives pixel data over a high-speed 40MHz SPI bus to update the ILI9341 screen.
Applies small timing delays to keep playback smooth and locked at a steady 15 FPS. Here is another Arduino touch screen calculator using a TFT LCD project where we showcased how to make a calculator with a TFT display and Arduino.

Converting Video to MJPEG Format:

To prepare your video file for the ESP32, you need to convert standard formats like .mp4 into a .mjpeg (Motion JPEG) file using a free web-based converter tool.
Paste the converted video file to the MicroSD card root directory. The file name should be video, and the format should be mjpeg. If we want to change the file name, we need to change the name in the code too to match the file name we choose.
The table shows the video conversion settings.

SettingsValue
Resolution320x240
File FormatMJPEG
FPS15
QualityMedium

Components Required

Below is the list of components required to build this project

S.NoComponentsSpecificationQuantity
1.MicrocontrollerESP32 Dev Module    1
2.TFT Display2.4 TFT SPI 240*320
(TJCTM24024-SPI)
    1

Circuit Diagram

 The following is the circuit diagram of the ESP32 video player

Connect the circuit as per the table below

TFT Display pinsESP32 Dev Module Pins
VCC3.3V
GNDGND
CSGPIO 2 
RSTGPIO 4
D/CGPIO 5
MOSIGPIO 23
SCKGPIO 18
LED3.3V
MISOGPIO 19
SD_CSGPIO 15
SD_MOSIGPIO 23
SD_MISOGPIO 19
SD_SCKGPIO 18

Coding

#include <SPI.h>
#include <SD.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <JPEGDEC.h>
// --- TFT Display Pins ---
#define TFT_CS   2
#define TFT_DC   5
#define TFT_RST  4
// --- SD Card Pin ---
#define SD_CS    15
// --- Frame buffer for one JPEG frame ---
// Increase if your frames are larger than this; watch ESP32 RAM limits.
#define FRAME_BUF_SIZE (80 * 1024)
static uint8_t *frameBuf = nullptr;
// --- Target playback rate ---
#define TARGET_FPS 15
#define FRAME_INTERVAL_MS (1000 / TARGET_FPS)
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
JPEGDEC jpeg;
File videoFile;
// Drawing callback function
int JPEGDraw(JPEGDRAW *pDraw) {
 tft.drawRGBBitmap(pDraw->x, pDraw->y, pDraw->pPixels, pDraw->iWidth, pDraw->iHeight);
 return 1;
}
// Reads one JPEG frame (SOI 0xFFD8 ... EOI 0xFFD9) from videoFile into frameBuf.
// Returns frame size in bytes, or 0 if no more frames / error.
size_t readNextFrame() {
 // 1. Find SOI marker (0xFF 0xD8)
 int b1 = -1, b2 = -1;
 bool foundSOI = false;
 while (videoFile.available() >= 2) {
   b1 = videoFile.read();
   if (b1 == 0xFF) {
     b2 = videoFile.peek();
     if (b2 == 0xD8) {
       videoFile.read(); // consume the 0xD8
       foundSOI = true;
       break;
     }
   }
 }
 if (!foundSOI) return 0; // EOF reached without finding a new frame
 frameBuf[0] = 0xFF;
 frameBuf[1] = 0xD8;
 size_t idx = 2;
 // 2. Read bytes until EOI marker (0xFF 0xD9) is found
 int prevByte = 0;
 while (videoFile.available() && idx < FRAME_BUF_SIZE) {
   int curByte = videoFile.read();
   frameBuf[idx++] = (uint8_t)curByte;
   if (prevByte == 0xFF && curByte == 0xD9) {
     return idx; // complete frame captured
   }
   prevByte = curByte;
 }
 // Ran out of buffer space or file ended mid-frame
 Serial.print("WARN: frame incomplete or buffer too small, got ");
 Serial.print(idx);
 Serial.println(" bytes before running out of buffer/file");
 return 0;
}
void setup() {
 Serial.begin(115200);
 delay(1000);
 Serial.println("\n--- ESP32 Video Player Initializing ---");
 frameBuf = (uint8_t *)malloc(FRAME_BUF_SIZE);
 if (!frameBuf) {
   Serial.println("ERROR: Could not allocate frame buffer! Reduce FRAME_BUF_SIZE.");
   while (1) delay(1000);
 }
 Serial.print("Free heap after buffer alloc: ");
 Serial.println(ESP.getFreeHeap());
 tft.begin(27000000);
 tft.setRotation(1); // Landscape orientation
 tft.fillScreen(ILI9341_BLACK);
 Serial.println("Display Initialized.");
 if (!SD.begin(SD_CS)) {
   Serial.println("ERROR: SD Card initialization failed!");
   while (1) delay(1000);
 }
 Serial.println("SD Card initialized successfully!");
 if (!SD.exists("/video.mjpeg")) {
   Serial.println("ERROR: /video.mjpeg not found on SD card!");
   while (1) delay(1000);
 }
 videoFile = SD.open("/video.mjpeg", FILE_READ);
 if (!videoFile) {
   Serial.println("ERROR: Could not open /video.mjpeg!");
   while (1) delay(1000);
 }
 Serial.println("Found and opened /video.mjpeg on SD card!");
}
void loop() {
 unsigned long frameStart = millis();
 size_t frameSize = readNextFrame();
 if (frameSize == 0) {
   // End of file (or bad frame) — loop the video back to the start
   Serial.println("End of video, looping...");
   videoFile.seek(0);
   return;
 }
 if (jpeg.openRAM(frameBuf, frameSize, JPEGDraw)) {
   jpeg.decode(0, 0, 0);
   jpeg.close();
 } else {
   Serial.print("ERROR: jpeg.openRAM failed on this frame, size=");
   Serial.println(frameSize);
 }
 // Pace playback to target FPS
 unsigned long elapsed = millis() - frameStart;
 if (elapsed < FRAME_INTERVAL_MS) {
   delay(FRAME_INTERVAL_MS - elapsed);
 }
}
Have any question related to this Article?

Getting Started with the MAX32655 Feather Development Board

Submitted by Vishnu S on

Bluetooth Low Energy (BLE) has become one of the most widely adopted wireless technologies for battery-powered devices, offering reliable communication while consuming only a fraction of the power required by traditional wireless protocols. From wearable electronics and healthcare devices to wireless audio accessories and industrial sensors, BLE enables devices to remain connected for extended periods without sacrificing battery life.

Physical AI Tutorial: Train the SO-ARM101 Robot Arm with LeRobot and Jetson Orin NX

Submitted by Vedhathiri on

In this Physical AI tutorial, we will train a real robotic arm using Hugging Face LeRobot and imitation learning. The project uses the Seeed Studio SO-ARM101 leader–follower robotic arm and a reComputer J4012 powered by NVIDIA Jetson Orin NX.

We begin by configuring and calibrating the SO-ARM101, followed by teleoperation and dataset collection. We then record 150 human demonstrations, train an ACT policy using LeRobot and test whether the robotic arm can autonomously sort tomatoes and potatoes. This step-by-step LeRobot tutorial covers the complete workflow, including hardware setup, motor configuration, calibration, teleoperation, dataset recording, AI model training, troubleshooting and real-world evaluation. By the end, you will have everything needed to understand and reproduce the robotic learning pipeline used in this project. We have also worked on many projects related to robotics; you can check out our robotics projects for more ideas.

Both the SO-ARM101 robotic arm and the reComputer J4012 are Seeed Studio products. If you are planning to try a similar setup, you can use the links and promotional codes below: 

Check out SO-ARM101 Robotic Arm and use the promotional code KGYFKTZT to get $15 OFF

Check out reComputer J4012 and use the promotional code 90QQKB6Q to get 2% OFF.

Components Required for the Physical AI Robotic Arm Project

The following components are required to complete the robotic arm system. These include the mechanical, electronic, power, and communication components needed for operation. 

S.No                    ComponentQuantity                                            Purpose
1.Seeed Studio Leader Arm1Used by the human operator to teleoperate and demonstrate the required movements.
2.Seeed Studio Follower Arm1The actual working robotic arm that follows the leader arm and later runs the trained AI policy.
3.reComputer J4012-Edge AI Device with NVIDIA Jetson Orin NX1Main computing unit for training the AI model and running inference on the robot.
4.USB Camera1Captures visual observations of the workspace, objects, gripper, and bowls for vision-based learning and control.
5.12V Adapter2Powers the Follower arm motors and the Jetson Orin.
6.5V Adapter1Powers the Leader arm motors (7.4V / 5V motors).
7.Laptop1Used for initial setup, teleoperation, dataset recording, and development on Windows.
8.C-Type USB Cables2Connect the Leader arm, Follower arm, cameras, and Jetson to the Laptop.
9.Monitor, Mouse, and KeyboardOptionalProvides a display and input interface for the reComputer with Jetson Orin NX.

Essential Components for the project

Hardware and Software Understanding

This section provides an overview of the main hardware and software components used in the project, along with the reason for choosing them.

SO-101 Robotic Arm

The SO-101 is a low-cost, open-source 6-DOF robotic arm designed for research and learning applications. It consists of two arms: the Leader arm and the Follower arm. The Leader arm is operated by a human to demonstrate the required movements, while the Follower arm mimics those movements during teleoperation and later executes the trained AI policy independently. This Leader–Follower setup makes it easy to collect high-quality demonstration data for imitation learning.

Leader Arm

Unlike many industrial robotic arms, the SO-101 does not come with a separate external robot controller. Instead, it is supplied with two motor driver boards one for the Leader arm and one for the Follower arm and one for the Follower arm. These boards act mainly as a communication and power distribution interface between the computer and the motors.

Follower Arm

Motors: Feetech STS3215 Smart Servos

The SO-101 uses Feetech STS3215 smart bus servo motors. These are not ordinary DC motors. Each STS3215 motor has a built-in motor controller inside the servo itself. This internal controller handles position control, speed control, torque control, and feedback of the current joint position.

Smart Servo Motor

Because the intelligence is already inside the motor, the external driver board does not perform complex motion planning. It simply passes commands from the computer to the motors and supplies power. In simple terms, the motor contains the controller, the driver board acts as a communication bridge, and the computer (running LeRobot) sends the target positions.
Different gear ratios are used for different joints to balance torque and speed. The Leader arm typically uses lower-voltage (7.4V) motors so that it can be moved easily by hand, while the Follower arm is designed for actual task execution.

reComputer J4012 with NVIDIA Jetson Orin NX

The reComputer J4012 with NVIDIA Jetson Orin NX is a compact and powerful edge computing platform designed for AI workloads. In this project, it is used as the main system for training the imitation learning model and for running the trained policy on the robot.

reComputer J4012

Its GPU acceleration makes it suitable for training models such as ACT (Action Chunking with Transformers), which would be very slow or impractical on a normal laptop without a dedicated NVIDIA GPU.

Hugging Face and the LeRobot Framework

Hugging Face provides the ecosystem around LeRobot, including the LeRobot framework, model architectures, datasets and tools for sharing and managing robotics projects.

Hugging Face

In this project, the datasets and trained models were primarily stored locally during development, while the Hugging Face ecosystem provides the underlying framework and resources the project uses.

What is LeRobot?

LeRobot is an open-source robotics framework developed by Hugging Face. It provides a complete set of tools required for real-world robot learning, including hardware communication, teleoperation, dataset recording, model training, and policy evaluation. Without LeRobot, we would have to write most of this software pipeline from scratch.

Lerobot

Setting Up LeRobot on Windows

Installing Hugging Face LeRobot on Windows

In this project, we use the SO-ARM101 Low-Cost AI Arm Assembled Kit Pro (Leader + Follower) together with Hugging Face LeRobot. The goal of this phase on Windows is to complete motor setup and calibration, teleoperation, dataset recording, and dataset replay.
To begin the software setup, first install Miniconda. Visit the official Miniconda download page, download the Windows 64-bit installer, and run it. During installation, make sure to check the option “Add Miniconda3 to my PATH environment variable”. After the installation is complete, restart the computer. Next, open Command Prompt and create a dedicated environment for LeRobot by running the command below

conda --version
conda create -n lerobot python=3.10 -y
conda activate lerobot

If you get a Terms of Service error, run these commands first:

conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/main
conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/r
conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/msys2

After activating the environment, clone the official LeRobot repository and install it with Feetech motor support using the following commands:

git clone https://github.com/huggingface/lerobot.git
cd lerobot
pip install -e ".[feetech]"

Verify the Installation:

python -c "import lerobot; print(lerobot.__version__)"

A version number (such as 0.4.x or higher) should appear if the installation was successful.

Hardware Connection and Motor Setup

Before configuring the motors, it is recommended to clearly label them. Use F1 to F6 for the joints of the Follower arm and L1 to L6 for the Leader arm. The power supply must be connected carefully. The Leader arm always uses 7.4V motors and should be powered with a 5V adapter, while the Follower arm may use 12V motors depending on the configuration. Both the power supply and the USB cable must be connected, as the USB connection alone does not provide power to the motors.
Connect the 12V power adapter to the Follower arm driver board first, then connect the 5V power adapter to the Leader arm. After that, connect the USB cables from both driver boards to the laptop. To identify the correct COM ports for each arm, run the command below:

lerobot-find-port 

Then follow the on-screen instructions. Note down the port numbers for both the Follower and Leader arms.

Expected results:

Follower → COM(any number)
Leader → COM(any number)

Configuring SO-ARM101 Servo Motor IDs

Once the ports are identified, the motor IDs need to be configured. It is important to remove the daisy-chain connection before setting the ID of each motor; otherwise, errors may occur. Start with the leader arm and run the following command (replace the COM port with your actual port):

Setting up the Motor Id’s
lerobot-setup-motors --teleop.type=so101_leader --teleop.port=COM26

Follow the instructions carefully and connect one motor at a time. After completing the leader arm, repeat the same process for the follower arm using:

lerobot-setup-motors --robot.type=so101_follower --robot.port=COM23

Each motor must be assigned a unique ID from 1 to 6 so that the software can communicate with them individually.

Setting the Motor Id with Robotic Arm

Calibrating the SO-ARM101 Robot Arm

After setting the motor IDs, connect all the motors properly and proceed with calibration. When instructed, gently move each joint front and back and then move it to its minimum and maximum positions. You can also see the joint values changing on the screen. Then Press Enter to save the calibration values. First, calibrate the leader arm using the command:

lerobot-calibrate --teleop.type=so101_leader --teleop.port=COM26 --teleop.id=my_leader_arm
Calibrating Each Arm

Repeat the same process for the follower arm with the following command:

lerobot-calibrate --robot.type=so101_follower --robot.port=COM23 --robot.id=my_follower_arm

Calibration Working

Calibration Tips

  • Move joints slowly.

  • Do not force the mechanical limits.

  • Make sure the correct motor IDs are assigned.

  • Ensure the arm is properly powered.

  • If calibration produces unexpected values, stop and verify the motor ID and joint mapping.

  • Save the calibration only after verifying the joint movement.

Teleoperating the Robot Arm with LeRobot

Once both arms are calibrated, teleoperation can be tested. Run the following command:

lerobot-teleoperate --robot.type=so101_follower --robot.port=COM23 --robot.id=my_follower_arm --teleop.type=so101_leader --teleop.port=COM26 --teleop.id=my_leader_arm

When the Leader arm is moved, the Follower arm will follow the same movements in real time. Press Ctrl + C to stop teleoperation

Recording an Imitation Learning Dataset (Without Camera)

To record a dataset without using cameras, use the following command:

lerobot-record --robot.type=so101_follower --robot.port=COM23 --robot.id=my_follower_arm --teleop.type=so101_leader --teleop.port=COM26 --teleop.id=my_leader_arm --dataset.repo_id=semicon/arm_only_v1 --dataset.root="D:/lerobot_datasets/arm_only_v1" --dataset.num_episodes=3 --dataset.single_task="Pick and place small object" --dataset.push_to_hub=false --dataset.fps=30 --display_data=false

Make sure to change the COM port numbers and the dataset root path according to your system. This recording was performed without cameras.

Replaying a Recorded Dataset

To replay a recorded episode, use the command below:

lerobot-replay --robot.type=so101_follower --robot.port=COM23 --robot.id=my_follower_arm --dataset.repo_id=semicon/arm_only_v1 --dataset.root="D:/lerobot_datasets/arm_only_v1" --dataset.episode=0

This will make the Follower arm repeat the motion recorded in the selected episode.

Robotic Arm Playing Chess

Daily Startup Commands

Every time you start working, activate the environment and navigate to the LeRobot folder using:

conda activate lerobot
cd path\to\lerobot

After this, any of the above commands can be executed.

 Why Move to Jetson Orin NX for Training? 

Even though the robotic arm can perform basic operations such as teleoperation, recording, and replay on Windows, full model training is not practical on this platform. Dataset recording itself can still be done on Windows without major issues. However, training the AI model requires CUDA support for efficient GPU acceleration. If the computer does not have an NVIDIA GPU, or if it has limited RAM, the training process becomes extremely slow or may not run effectively at all. Considering these limitations, the model training process was moved to the reComputer J4012 with Jetson Orin NX. This is explained in more detail in the following section.

Setting Up LeRobot on NVIDIA Jetson Orin NX

Before starting the project on the reComputer J4012, it is important to understand a few key concepts related to AI model training and robot learning.

What is CUDA?

CUDA (Compute Unified Device Architecture) is a parallel computing platform developed by NVIDIA. It allows software to use the power of an NVIDIA GPU for general computing tasks, not just graphics.
A CPU usually processes tasks one after another, while a GPU can process thousands of smaller operations at the same time. CUDA is the technology that allows AI frameworks to use this GPU acceleration.

Cuda Definition

This is important because training a model like ACT involves a large number of mathematical calculations. These calculations are much faster on a GPU with CUDA. Since the Windows laptop used earlier did not have an NVIDIA GPU, training was impractical there. That is why the training process was moved to the reComputer J4012 with Jetson Orin NX

Different Types of Models Used in Robot Learning

In robot learning, different AI models can be used depending on the task:

  • ACT (Action Chunking with Transformers): This is the model used in this project. It learns from human demonstrations and predicts a sequence of robot actions. It is efficient and works well with smaller datasets.

  • Diffusion Policy: Generates actions step by step and is useful for complex or precise movements, but needs more computing power.

  • VLM (Vision-Language Model): Understands both images and text, useful when a robot must follow language instructions.

  • VLA (Vision-Language-Action Model): Combines vision, language, and actions for more general-purpose robot control. These models are larger and need more data.
    For this project, ACT was selected because it is suitable for imitation-learning tasks based on demonstration data and is practical for the relatively focused pick-and-place task used here.

Initial Setup on Jetson Orin NX

First, the Jetson Orin NX should be flashed with JetPack 6.1 or above for proper software compatibility and performance. To flash the Jetson Orin, follow the official document.
After that, the basic robot setup is done in the same way as on Windows:

  • Setting motor IDs

  • Calibration

  • Teleoperation

  • Record and replay testing

These steps follow the official Seeed Studio documentation. Checkcheck the document to get the full idea to setup in the linux. Once this basic setup is complete, the next stage is collecting data for the vegetable sorting task.

Dataset Collection and Training for Vegetable Sorting

To make the robotic arm learn the vegetable sorting task, we need to collect demonstration data. This data is recorded in the form of episodes.
What is an Episode?
An episode is one complete demonstration of the task.
For example:

  • Picking a tomato and placing it in the left bowl = 1 episode

  • Picking a potato and placing it in the right bowl = 1 episode

  • The AI model learns by studying many such examples. That is why multiple episodes are required.

Why around 120 episodes?
A single demonstration is not enough for the model to learn reliably. By collecting many episodes, the model sees different small variations in movement, timing, and object handling. In this project, around 120 episodes were collected in three groups:

  • Tomato only

  • Potato only

  • Both objects together

(picture of tomato, potato with the robotic arm)
This helps the model learn both individual object handling and combined sorting behaviour.

Recording the Vegetable Sorting Dataset

The following command is used to record the dataset using only the wrist camera:

Recording the dataset for the Tomato

conda activate lerobot
lerobot-record \
 --robot.type=so101_follower \
 --robot.port=/dev/ttyACM1 \
 --robot.id=my_follower_arm \
 --robot.cameras="{ wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30} }" \
 --teleop.type=so101_leader \
 --teleop.port=/dev/ttyACM0 \
 --teleop.id=my_leader_arm \
 --dataset.repo_id=local/tomato_potato_wrist_fixed \
 --dataset.push_to_hub=false \
 --dataset.num_episodes=120 \
 --dataset.single_task="Sort the tomato into the left bowl and the potato into the right bowl" \
 --dataset.episode_time_s=45 \
 --dataset.reset_time_s=15 \
 --display_data=true

If you need to record all the episodes in one go, use the above command. Instead, if you need to collect the datasets in stages, like tomato only first, potato only, then both, follow the commands below:

Tomato only

conda activate lerobot
lerobot-record \
 --robot.type=so101_follower \
 --robot.port=/dev/ttyACM1 \
 --robot.id=my_follower_arm \
 --robot.cameras="{ wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30} }" \
 --teleop.type=so101_leader \
 --teleop.port=/dev/ttyACM0 \
 --teleop.id=my_leader_arm \
 --dataset.repo_id=local/tomato_potato_wrist_fixed \
 --dataset.push_to_hub=false \
 --dataset.num_episodes=40 \
 --dataset.single_task="Sort the tomato into the left bowl and the potato into the right bowl" \
 --dataset.episode_time_s=45 \
 --dataset.reset_time_s=15 \
 --display_data=true

Recording the Dataset for each vegetable

Potato Only

lerobot-record \
 --robot.type=so101_follower \
 --robot.port=/dev/ttyACM1 \
 --robot.id=my_follower_arm \
 --robot.cameras="{ wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30} }" \
 --teleop.type=so101_leader \
 --teleop.port=/dev/ttyACM0 \
 --teleop.id=my_leader_arm \
 --dataset.repo_id=local/tomato_potato_wrist_fixed \
 --dataset.push_to_hub=false \
 --dataset.num_episodes=40 \
 --dataset.single_task="Sort the tomato into the left bowl and the potato into the right bowl" \
 --dataset.episode_time_s=45 \
 --dataset.reset_time_s=15 \
 --display_data=true \
 --resume=true

Recording the dataset for the potato

Both Objects Together(placing tomato and potato at the same time)

lerobot-record \
 --robot.type=so101_follower \
 --robot.port=/dev/ttyACM1 \
 --robot.id=my_follower_arm \
 --robot.cameras="{ wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30} }" \
 --teleop.type=so101_leader \
 --teleop.port=/dev/ttyACM0 \
 --teleop.id=my_leader_arm \
 --dataset.repo_id=local/tomato_potato_wrist_fixed \
 --dataset.push_to_hub=false \
 --dataset.num_episodes=40 \
 --dataset.single_task="Sort the tomato into the left bowl and the potato into the right bowl" \
 --dataset.episode_time_s=45 \
 --dataset.reset_time_s=15 \
 --display_data=true \
 --resume=true

Traning Potato

Training an ACT Policy with LeRobot:

After the dataset is collected, the ACT model is trained using the following command:

conda activate lerobot
lerobot-train \
 --dataset.repo_id=local/tomato_potato_wrist_fixed \
 --policy.type=act \
 --policy.repo_id=local/tomato_potato_wrist_fixed_act \
 --output_dir=outputs/train/tomato_potato_wrist_fixed_act \
 --job_name=tomato_potato_wrist_fixed_act \
 --policy.device=cuda \
 --batch_size=4 \
 --steps=100000 \
 --eval_freq=5000 \
 --save_freq=10000 \
 --log_freq=100 \
 --wandb.enable=false

Training the Model

Why these settings are used:

  • --policy.type=act → selects the ACT model

  • --policy.device=cuda → uses GPU acceleration

  • --steps=100000 → number of training steps

  • --save_freq=10000 → saves checkpoints regularly

If training is interrupted, it can be resumed from the last checkpoint:

conda activate lerobot
lerobot-train \
config_path=outputs/train/tomato_potato_wrist_fixed_act/checkpoints/last/pretrained_model/train_config.json \
 --resume=true

Testing the Physical AI Robot Arm

After training, the model is tested on the real robot using:


conda activate lerobot
lerobot-record \
 --robot.type=so101_follower \
 --robot.port=/dev/ttyACM1 \
 --robot.id=my_follower_arm \
 --robot.cameras="{ wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30} }" \
 --dataset.repo_id=local/eval_wrist_fixed \
 --dataset.push_to_hub=false \
 --dataset.num_episodes=1 \
 --dataset.single_task="Sort the tomato into the left bowl and the potato into the right bowl" \
 --dataset.episode_time_s=600 \
 --dataset.reset_time_s=15 \
 --display_data=true \
 --policy.path=outputs/train/tomato_potato_wrist_fixed_act/checkpoints/last/pretrained_model

In this step, the robot is no longer controlled by the leader arm. Instead, the trained model controls the follower arm based on the camera input and the learned behaviour. You can check out the model by placing the tomato and potato one by one.

Output of Sorting

Common SO-ARM101 and LeRobot Errors and Fixes

This section provides solutions to the most common problems encountered during the project, along with their possible causes and recommended fixes. Use it as a quick reference whenever an error occurs during setup, operation, or training.

S.NoProblemCauseSolution
1.Dataset already exists error while starting evaluationLeRobot does not overwrite an existing dataset folder by default. A previous evaluation dataset with the same name was already present.Deleted the existing dataset folder using rm -rf and then restarted the evaluation command.
2.Cameras disconnected during evaluationUSB bandwidth issues or an unstable camera connection caused the system to lose access to the camera devices mid-run.Reconnected the cameras, verified the indexes using lerobot-find-cameras opencv, and restarted the evaluation.
3.The training process got interrupted before completionLong training duration and system interruption stopped the process around intermediate checkpointsResumed training from the last saved checkpoint using the --resume=true option instead of restarting from zero.
4.Arm did not return to home position after evaluation episodesDuring policy evaluation without the leader arm, the reset phase has no active control input, so the arm stays in its final positionManually move the arm back to the starting/home position before each new episode
5.Magnitude/range error during calibrationJoint was not moved through its full range, or the motor moved too little / too much during calibrationRecalibrate the arm carefully by moving each joint slowly from minimum to maximum position as instructed
6.Motor ID setup failed / communication errorMotors were still connected in daisy-chain mode while assigning IDsDisconnect the daisy-chain, connect one motor at a time, set the ID, then reconnect

Future Improvements

While the current system successfully demonstrates imitation learning for tomato and potato sorting, there is still significant room for improvement. The present setup mainly relies on a wrist camera with fixed object positions, so introducing an additional external camera from the top or side can provide better visual understanding and help the robot handle objects placed in different locations more reliably. Beyond laboratory experiments, the same learning pipeline can be adapted for practical applications such as warehouse sorting, educational robotics platforms, and simple industrial pick-and-place tasks. The system can also be expanded to handle a wider range of objects by training it to sort multiple items like different fruits or colored blocks
Adding force or tactile sensing to the gripper would further improve grasp stability, especially when dealing with soft or irregular objects. In the longer term, mounting the arm on a mobile base could allow the robot to perform sorting tasks across different locations rather than remaining restricted to a fixed table setup, making the overall system more flexible and closer to real-world use.

 Conclusion

This project showed how a low-cost robotic arm can learn a real task by watching human demonstrations. Using the SO-101 arm and LeRobot, we completed the full process from hardware setup and teleoperation to data recording, model training, and final testing. The robot was trained to sort a tomato and a potato into different bowls. During the project, we worked on both Windows and the Jetson Orin NX, and this helped us understand which steps are easy on a normal laptop and which steps need stronger computing power.

We also faced practical problems such as camera disconnection, training interruptions, and limited performance when both objects were present. By solving these issues step by step, the system became more stable and useful. Overall, this project gives a clear and simple example of how imitation learning can be used to build practical robotic systems with affordable hardware, and it can be extended further for more complex tasks in the future.

Have any question related to this Article?

Component Selection Guide for AI Hardware: What to Check Before Finalizing MLCC, MCU, and CPU/GPU Peripheral BOMs

From June to July 2026, AI hardware demand affected more than just GPUs, CPUs, and high-bandwidth memory. TrendForce reported that DRAM contract prices would rise by 13%–18% in Q3 2026. NAND Flash contract prices would rise by 10%–15%. The main drivers are AI inference systems and large data center deployments.

The pressure also moved into passive components. Recent market reports show that ordinary MLCC spot prices increased by 15%–20% since late February. High-capacitance MLCCs used in AI servers, including 10µF and 22µF parts, saw average price increases of 50%–60%.

This changes the selection process for engineers and procurement teams. A component is not suitable just because its electrical parameters match the schematic. Before finalizing the BOM, teams also need to check availability, second-source options, validation effort, traceability, and long-term supply risk.

1. MLCC Selection: Look Beyond Capacitance and Package Size

Take Samsung Electro-Mechanics CL10A226MP8NUN# / CL10A226MP8NUNE as an example. This MLCC series is rated at 22µF, 10V, X5R, in a 0603 package. Engineers often use it for power decoupling, compact DC-DC output filtering, communication modules, and dense PCB layouts. But in AI edge devices, server accelerator boards, and industrial control modules, this type of high-capacitance, small-case MLCC should not be selected only by matching “22µF, 10V, 0603.” Engineers should check the following points:

  • Whether the effective capacitance after DC bias is still enough for rail stability
  • Whether the 10V rating leaves enough derating margin
  • Whether X5R or X7R temperature behaviour fits the operating environment
  • Whether 0603 can be changed to 0805 if supply becomes tight
  • Whether the application requires AEC-Q200 qualification for automotive or high-reliability industrial use

In June, Astute Group reported that demand from AI infrastructure is tightening global MLCC supply. Some lead times now exceed 20 weeks. These constraints are expected to continue into 2027. This means high-capacitance MLCCs should have approved alternatives early in the design stage. Teams should not wait until production demand has already started.

2. MCU Selection: Same Core Does Not Mean Drop-In Replacement

Take the STM32F103C8T6 as a common example for MCU-based control boards. According to STMicroelectronics, this MCU uses an Arm Cortex-M3 core. Its CPU runs at up to 72MHz. It has 64KB of Flash memory. Engineers often use it in motor control, USB, CAN, and general industrial control applications.

MCUs may face long lead times or price pressure. In that situation, it is risky to pick an alternative just because it has the same Arm Cortex-M3 core or a similar package. Engineers need to check several details. They should verify pin definitions and pin multiplexing functions. They should also check ADC channels, PWM outputs, CAN and USB interfaces, and external crystal pins. Flash and RAM capacity, boot mode, debug interface, and software library compatibility also matter.

Temperature grade is just as important. A commercial-grade MCU may work for a consumer device. But industrial and automotive designs often need a wider temperature range. They may also require AEC-Q100-related validation. For mature products, replacing an MCU is not a simple purchasing step. It may involve a schematic.

3. CPU/GPU Peripheral Components: Power and Interconnect Matter

CPUs and GPUs get the most attention in AI platforms. But the system's overall performance depends on many other components. NVIDIA's GB200 NVL72 is an example. It connects 36 Grace CPUs and 72 Blackwell GPUs. This system uses a rack-scale design with liquid cooling. Such a large platform needs more supporting parts. These include PMICs, MOSFETs, inductors, high-capacitance MLCCs, high-speed connectors, memory devices, PCB materials, thermal sensors, and cooling-control components.

When selecting CPU/GPU peripheral components, teams should check the following points:

  • Whether the PMIC or voltage regulator has a qualified second source
  • Whether MOSFETs meet voltage, current, RDS(on), switching loss, and thermal requirements
  • Whether inductors meet saturation current and temperature-rise limits
  • Whether high-speed connectors meet signal integrity, insertion loss, temperature rise, and mating-cycle requirements
  • Whether DRAM, NAND, or related memory devices are exposed to current price and allocation cycles
  •  Whether fan control, liquid-cooling control, or temperature‑monitoring components have long lead-time risk

One important point to note is that a project can still be delayed even when the main CPU or GPU is secured. A small power, connector, sensing, or memory component can become the actual delivery bottleneck if it has no approved alternative.

4. A Practical Selection Workflow for Engineering and Procurement Teams

Step 1: Re-rank the BOM by supply risk, not only by unit price. 
Low-cost MLCCs, small MCUs, connectors, or power components can become production blockers if they are hard to replace. AI hardware BOMs should mark MLCCs, MCUs, PMICs, memory devices, connectors, MOSFETs, inductors, and CPU/GPU power-rail components as priority review items.

Step 2: Build one shared alternative-part validation table.
The technical side should include package, pinout, electrical ratings, temperature grade, certification, lifecycle status, and software compatibility. The procurement side should include stock availability, lead time, date code, packaging condition, price validity, and manufacturer traceability. A part should move into validation only when both sides are acceptable.

Step 3: Move sourcing checks into the design stage.
ECIA’s June Industry Pulse report tracks sales expectations, product cancellations, product decommits, and component lead times across major categories and end markets. This shows why sourcing is now part of engineering decision-making. It is not only a purchasing task after design release.

Teams can use manufacturer data during design, pilot production, and mass production. They can also use official suppliers, other distributors, and the global spot market. They check if key parts are in stock. They check if these parts are traceable. They check if they have reliable replacements. In this workflow, WIN SOURCE can assist with BOM execution. We help procurement teams review supply availability. We help them review alternative options. We help them verify traceability. We help them assess delivery risks. We cover many component types. These include ICs, MLCCs, MCUs, memory chips, power devices, and connectors. Our support is especially useful for parts with long lead times. It also helps with parts in short supply. It helps with obsolete parts. It also helps with small-batch validation.

AI demand is changing how engineers and procurement teams select components. Parameter matching remains the foundation of component selection, but it is not sufficient to support a complete BOM decision. For MLCCs, MCUs, PMICs, memory devices, and CPU/GPU peripheral components, a more reliable selection process should include technical compatibility, supply stability, alternative validation time, and quality traceability before finalising the BOM.

 

 

© 2026 Win Source Electronics. All rights reserved. This content is protected by copyright and may not be reproduced, distributed, transmitted, cached or otherwise used, except with the prior written permission of Win Source Electronics.

Have any question related to this Article?

5 Hidden Features of the Arduino UNO R3 You Probably Didn’t Know

Submitted by Vedhathiri on

The Arduino UNO R3 is often the first board people use to learn electronics and programming. Connect an LED, read a sensor, control a motor, upload a sketch, and it can seem like you’ve already discovered everything the board can do.
But there is much more going on underneath.
At the heart of the UNO R3 is the ATmega328P microcontroller. That small chip contains hardware features that many Arduino users never directly use, including an internal temperature sensor, brown-out detection, multiple sleep modes, a watchdog timer, and pin-change interrupts. These are capabilities of the microcontroller that the UNO R3 is built around.
Here are five of the most interesting ones you can actually explore on an Arduino UNO R3.

1. Your Arduino Can Measure Its Own Temperature

When you want to measure temperature with an Arduino, you would normally connect an external sensor such as an LM35, TMP36, DHT11, or DS18B20.
But the ATmega328P already has a temperature-sensing circuit inside the microcontroller.
The sensor is internally connected to the ADC, allowing the chip to obtain a temperature-related reading without using an external temperature sensor. The ATmega328P datasheet specifically lists temperature measurement among its peripheral features.

The basic path is:
Internal temperature sensor → ADC → digital reading → Serial Monitor

How to Demonstrate It

Connect your UNO R3 to your computer and configure the ATmega328P's ADC to read its internal temperature channel.
Then print the ADC result to the Serial Monitor.
For a visually interesting demonstration, start with the reading on screen and gently warm the microcontroller. You should see the reading change.
You don't need:

  • An LM35
  • A DHT11
  • A TMP36
    Any other external temperature sensor
    The sensing circuit is already inside the microcontroller.

One Important Catch

This is not a precision thermometer. The internal sensor has significant variation between individual chips, so the reading should be treated as approximate rather than as an accurate measurement of room temperature. So the safest way to describe it is:
“Your Arduino has a temperature sensor inside its main chip.”
Rather than:
“Your Arduino can accurately measure room temperature.”

Video Reference

How to Read the Internal Temperature Sensor in Arduino - Electro Hijibiji
https://www.youtube.com/watch?v=43l6Ibk7Spw

2. Your Arduino Can Detect When Its Supply Voltage Gets Too Low

Another capability that doesn't require an external sensor is Brown-Out Detection, or BOD.
The ATmega328P can monitor its supply voltage. When brown-out detection is enabled and the voltage falls below the selected threshold, the microcontroller can be held in reset rather than continuing to operate under an insufficient supply voltage. The chip also provides a brown-out reset flag that allows software to determine that a brown-out reset occurred.
Think of it as a built-in low-voltage protection mechanism for the microcontroller:
Normal supply
↓
Supply voltage falls
↓
Brown-out threshold
↓
MCU reset/held in reset
This can be particularly useful in battery-powered embedded systems, where the supply voltage can change as the battery discharges.

How to Demonstrate It

For a controlled demonstration, use an appropriate adjustable power supply and a multimeter.
Gradually reduce the microcontroller's supply voltage while monitoring the system.
A simple visual sequence would be:
5 V → voltage decreases → threshold → reset

Safety

Don't experiment by randomly lowering the UNO's 5V rail while the board is simultaneously being powered through USB. Use a controlled setup and understand the board's power path before experimenting.

Video Reference

Arduino Project to Product – Part 4: Optimising Operating Voltage - Shawn Hymel / DigiKey
https://www.youtube.com/watch?v=7a4XYppZ6Bc

This is a useful engineering reference for ATmega328P operating voltage and brown-out detection.

3. Your Arduino Can Literally Go to Sleep

The ATmega328P doesn't have to keep its CPU fully active all the time.
It has six hardware sleep modes:

  • Idle
  • ADC Noise Reduction
  • Power-save
  • Power-down
  • Standby
  • Extended Standby

Each mode disables different parts of the chip to reduce power consumption.
The most interesting mode for low-power applications is Power-down.
Instead of keeping the microcontroller awake while it has nothing to do, you can design a system like this:

Do some work → sleep → wake → do some work → sleep again

This is extremely useful for battery-powered devices.
Imagine a sensor that only needs to collect data once every minute. There is little reason to keep the CPU fully active for the entire minute.

How to Demonstrate It

Use an Arduino UNO R3 with an LED and a wake-up source such as a push button.
Show:
Arduino running
↓
Arduino enters sleep
↓
Activity stops / current drops
↓
Wake-up event
↓
Arduino continues
For an even better demonstration, measure the current and show the difference between active and sleep states.

Why is this Useful?

Sleep modes are useful for:

  • Battery-powered sensors
  • Remote data loggers
  • Portable electronics
  • Environmental monitors
  • Low-power embedded systems

The basic idea is simple:
Don't spend power doing nothing.

Video Reference

Arduino Project to Product - Part 8: How to Put Arduino to Sleep - Shawn Hymel / DigiKey
https://www.youtube.com/watch?v=eQZf5pbEVxE

This is particularly useful because it demonstrates the relationship between sleep mode and power consumption.

4.  Your Arduino Can Restart Itself When Software Gets Stuck

This is one of the most useful features for real-world embedded projects.
The ATmega328P includes a hardware Watchdog Timer with a separate on-chip oscillator. The watchdog can be configured with a timeout, and if the software fails to service it before that timeout expires, it can trigger a system reset.
Imagine an unattended robot.
Everything is working:
Sensors → code → motors → communication
Then a software bug sends the program into an infinite loop.
Without a recovery mechanism, the system can remain frozen.
With the watchdog:
Program running
↓
Software gets stuck
↓
Watchdog isn't serviced
↓
Timeout
↓
Hardware reset
↓
Program starts again
The watchdog doesn't actually understand that the program “crashed.” It simply detects that it wasn't serviced in time.

How to Demonstrate It

You can deliberately create an infinite loop after enabling the watchdog:

#include <avr/wdt.h>
void setup() {
Serial.begin(9600);
Serial.println("Arduino STARTED");
wdt_enable(WDTO_2S);
}
void loop() {
Serial.println("Running...");
delay(500);
// Simulate a software freeze
while (true) {
}
}

The Serial Monitor will initially show:
Arduino STARTED
Running...
Running...
Running...
Then the program stops responding.
After the watchdog timeout, the ATmega328P resets and setup() runs again.
You should see:
Arduino STARTED
again.
That makes a great demonstration because it looks like the Arduino has recovered itself.

Where is this Useful?

Watchdog timers are especially useful in:

  • Robotics
  • IoT devices
  • Remote sensors
  • Industrial controllers
  • Security systems
  • Unattended embedded systems

If something is supposed to keep running for hours, days, or months without someone nearby to press RESET, a watchdog can provide an important recovery mechanism.

Video Reference

Tutorial: Using the Arduino Watchdog Timer - MAKE Course
https://www.youtube.com/watch?v=BDsu8YhYn8g
The video specifically covers the watchdog timer on the ATmega328P and its automatic timeout/reset behavior.

5. Your Arduino Can Wake Up When a Configured Pin Changes

This is where the sleep feature becomes even more interesting.
The ATmega328P provides Pin Change Interrupts, commonly called PCINT.
On the UNO R3, pin-change interrupt sources are spread across groups of GPIO pins. For example, the ATmega328P uses PCINT groups corresponding to:
D8 - D13
A0 - A5
D0 - D7
Electronoobs' detailed ATmega328P tutorial explains these groups, the corresponding interrupt vectors, and how to configure them.
But the really useful part is this:
Pin-change interrupts can be used to wake the ATmega328P from Power-down sleep.
So you can create this sequence:
Arduino running
↓
MCU enters sleep
↓
Button changes a configured pin
↓
Pin-change interrupt
↓
Arduino wakes
The microcontroller doesn't have to keep executing a loop asking:
“Is the button pressed?”
while it is sleeping.
The hardware can detect the configured change and use the interrupt as a wake-up event.

How to Demonstrate It

For example, connect a push button like this:
A0 ───── BUTTON ───── GND
Configure A0 with the internal pull-up resistor and enable the appropriate pin-change interrupt.
Then show:
Arduino awake
↓
Arduino enters sleep
↓
Current/activity drops
↓
Press button
↓
A0 changes state
↓
Pin-change interrupt
↓
Arduino wakes

Why is this Different from Normal Button Reading?

Normally, your program might repeatedly poll the pin:
Is the button pressed?
Is the button pressed?
Is the button pressed?
That means the CPU has to remain active.
With the sleep + interrupt approach, the CPU can sleep until the hardware detects the configured event.

Video Reference

Pin Change Interruptions ISR | PCINT | Arduino101- Electronoobs
https://www.youtube.com/watch?v=ZDtRWmBMCmw

This video demonstrates pin-change interrupts on the Arduino/ATmega328P and explains the PCINT groups and configuration.

 

Have any question related to this Article?

We Tested JBD, Daly & JK BMS After the E-Rickshaw Hack — The Vulnerability Is in the Hardware

Submitted by Dharagesh on

We recently came across reports covered by news outlets about electric vehicles, specifically e-rickshaws, being remotely hacked and stalled in the middle of busy roads. The attackers were using Android apps, some of which were available on the Google Play Store under names like BAT-BMS, Epoch Li-on and Overkill Solar. These apps were apparently able to connect to some specific brands of the Battery Management System (BMS) inside these vehicles over Bluetooth and shut down the power MOSFETs, effectively cutting power to the motor while the vehicle was in motion.

The Indian government responded by removing several of these apps from the Play Store. That seemed like a reasonable first step, but it immediately raised a question for us: does removing the app actually solve the problem, or is the real issue deeper than that?

We suspected the latter. If a third-party app, one not even made by the BMS manufacturer, could gain control over the battery's safety switches, then the vulnerability isn't in the app. It's in the BMS itself. Removing one app from the store doesn't stop anyone from writing another one, or from sending the same Bluetooth commands directly from a laptop or microcontroller.

So we decided to test it ourselves. We purchased three of the most widely used BMS brands in the consumer and light-EV market JBD (Jiabaida), Daly, and JK (Jikong) and set out to determine whether their Bluetooth Low Energy (BLE) interfaces had any meaningful security against unauthorized access. But what we found was more shocking! All three BMS platforms permitted unauthenticated remote control of their safety-critical MOSFETs. An attacker within BLE range can scan, connect, read live battery telemetry, and toggle the charge and discharge FETs without pairing, bonding, password verification, or any other form of firmware-level authentication.

To demonstrate the impact of these findings, we also built a proof-of-concept web application to visually demonstrate this vulnerability, and developed a hardware countermeasure that existing BMS owners can deploy right now to protect their systems. This article covers our complete journey through this investigation.

A Brief Primer on BLE

Before we examine the vulnerabilities identified during this research, it is useful to understand the Bluetooth Low Energy (BLE) concepts that make them possible. While BLE is designed for low-power, short-range wireless communication, it also includes a well-defined data model and several built-in security mechanisms. Understanding these fundamentals provides the context needed to see why the BMS devices we tested are vulnerable.
Bluetooth Low Energy (BLE), introduced as part of Bluetooth 4.0, differs significantly from Classic Bluetooth. Rather than exposing a continuous serial data stream through the Serial Port Profile (SPP), BLE organises communication using the Generic Attribute Profile (GATT). Under the GATT model, a device exposes its functionality through a hierarchy of Services, each identified by a unique UUID (Universally Unique Identifier). Each service contains one or more Characteristics, also identified by UUIDs, which represent individual pieces of data or control interfaces. A characteristic consists of the actual value along with a set of properties that define how it may be accessed.

BLE Data Model Services and Characteristics

In practice, a Service represents a logical grouping of related functionality, such as battery telemetry or configuration settings. Within that service, Characteristics expose specific values such as pack voltage, cell temperatures, state of charge, or control commands. BLE identifies these objects using UUIDs, which are 128-bit identifiers typically represented in hexadecimal. Standard BLE services use shortened 16-bit UUIDs; for example, 0x180F identifies the standard Battery Service, whereas vendor-specific implementations generally use custom 128-bit UUIDs.
Each characteristic also advertises one or more access properties that determine how a connected client may interact with it. The Read property allows a client such as a phone or laptop to retrieve the current value stored by the device. The Write property enables the client to send data or commands to the device, making it the mechanism through which configuration changes or control operations are typically performed. Some devices additionally support Write Without Response, which omits the acknowledgement normally returned by the device, improving throughput at the cost of reliability. The Notify property allows the device to asynchronously push updates to subscribed clients without requiring repeated polling, making it the standard mechanism for streaming live telemetry such as voltage, current, and temperature measurements.

BLE Data Interaction How Devices Communicate

BLE also includes a comprehensive security architecture designed to prevent unauthorized access. Pairing establishes a trusted relationship between two devices using methods such as Passkey Entry, Numeric Comparison, or Out-of-Band authentication. Once pairing has been completed, Bonding allows the generated security keys to be stored so that future connections can be established securely without repeating the pairing process. These keys are then used to enable Encryption, protecting all subsequent communication over the BLE link. At the application layer, Authorization provides an additional level of access control by allowing the device to determine whether a connected client is permitted to perform sensitive operations, such as modifying configuration parameters or issuing control commands.
The most important observation for this research is that BLE already provides the mechanisms necessary to secure sensitive devices such as Battery Management Systems. The vulnerabilities described in the following sections do not arise from weaknesses in the BLE protocol itself; rather, they resulted from manufacturers choosing not to implement pairing, encryption, authorization, or other available security controls, leaving critical functionality accessible to any nearby BLE client.

Our Investigation

Testing the Official Apps

We began our investigation not with code or protocol analysers, but with the official manufacturer of mobile apps. Our goal was simple: before we try to bypass anything, let's see what security the manufacturers themselves claim to provide.

JBD - "JBD BMS" and "XiaoXiang Electric"

JBD offers two apps that behave similarly. When a user connects to a JBD BMS as a guest, they can view battery information but cannot access control functions. To gain full control, the user must register a JBD account and bind the BMS device ID to that account. The binding is stored on JBD's cloud servers, and the app checks the cloud database for ownership before granting control access.

JBD BMS App Interface

Here's the problem: if a BMS owner purchases the unit and does not register and bind it to their account, anyone else can create their own JBD account and bind that BMS to theirs, at which point they get full control through the official app itself. More importantly, even this account-binding mechanism is only enforced by the app. The BMS hardware itself, the JBD DP04S007 we tested, accepts control commands from any connected BLE device without authenticating anything. JBD does not provide any on-device password authentication option on the models we tested.

Daly - "DALY BMS"

Daly's official app does not require account creation. Any user can connect directly to the BMS. To access control functions like FET toggling, the app prompts for a password. The default password is `123456`, and users can change it. The password is stored on the BMS hardware itself.

Daly BMS App Interface

However, our testing on the Daly 4S12V60A confirmed something important: the BMS firmware accepts control commands over BLE regardless of whether a password has been sent in the session. The password prompt exists only in the app's user interface. It is a client-side gate. If you bypass the app and send the control command directly to the BLE characteristic, the BMS executes it without question.

JK - "JK BMS"

JK's app follows a similar pattern to Daly. Users can connect and set a password to protect their BMS, and the password is stored on the BMS hardware. But once again, direct BLE command injection bypasses this password entirely. The JK-B2A8S20P we tested processes write commands to its control characteristics without checking any authentication state. The password is only verified by the official app, not by the firmware.

JK BMS App Interface

Going Deeper: Protocol-Level Analysis

After confirming that all three brands had either no app-level security or trivially bypassable security, we needed to verify whether the underlying BLE protocol itself enforced any restrictions.

Our approach involved connecting to each BMS and enumerating all GATT services and characteristics to identify which ones are used for data exchange. We analysed the properties of each characteristic to determine which support Write (for sending control commands) and Notify (for receiving telemetry). To characterise the BLE interface, we performed protocol analysis using publicly available resources and controlled experimentation. Once reliable communication had been established, we verified normal telemetry functionality before assessing the control operations.

BLE Protocol Level Analysis

For responsible disclosure reasons, we are deliberately not publishing the specific BLE service and characteristic UUIDs, the command byte sequences, or the frame structures used by any of the three brands. What we can say is that all three follow a broadly similar pattern: the client writes a binary command frame to the BMS's writable characteristic, and the BMS processes it and sends a response back via notifications. The command frame contains a header marker, a target address byte, a command ID, a data payload, and a checksum. Telemetry commands return pack voltage, current, cell voltages, temperatures, SOC, and MOSFET states. Control commands toggle the charge and discharge MOSFETs.

The fundamental finding is simple: the BMS firmware does not distinguish between a legitimate user and an attacker. Any device that can establish a BLE connection and write the correct bytes to the correct characteristic can issue control commands.

Comparative Vulnerability Analysis

The following table summarises our findings across all three BMS brands side by side.

Security DimensionJBD (DP04S007)Daly (4S12V60A)JK (B2A8S20P)
BLE Pairing RequiredNoNoNo
BLE Bonding / EncryptionNoneNoneNone
App Password ProtectionAccount binding (cloud)Yes (user-configurable)

Yes (user-configurable)

Password Stored OnJBD cloud serversBMS hardwareBMS hardware
Password Enforced by BMS FirmwareNoNoNo
Direct BLE Command AcceptedYes - unrestrictedYes - unrestrictedYes - unrestricted
Telemetry Readable Without AuthYesYesYes
FET Control Without AuthYesYesYes
Third-Party App ControlYes (Epoch Li-ion, Overkill Solar)So far, none (Official Only)So far, none (Official Only)
Firmware-Level Authentication MechanismNone detectedNone detectedNone detected

The bottom line is that all three brands fail at the most fundamental level. The BMS firmware itself has no mechanism to verify that the device issuing control commands is authorised to do so. The "security" offered by their official apps is entirely cosmetic; it exists only in the app UI and can be bypassed by anyone who communicates directly with the BLE interface.

Our Test Setup

Our BMS Test Setup

All testing was conducted in a controlled laboratory environment using our own equipment. We used a 4-cell (4S) 18650 lithium-ion battery pack connected to an Electronic Load Measurement Tool for safe, controlled discharge testing. The BLE host was a Windows PC with a Bluetooth adapter running Python with the `bleak` BLE library. The three BMS units under test were the JBD DP04S007, the Daly 4S12V60A, and the JK-B2A8S20P. We verified MOSFET state changes through both BLE telemetry readback and physical measurement of load current on the electronic load.

Demonstrating the Vulnerability: The BMS Analyser App

To make this vulnerability tangible and visually demonstrable, we built a proof-of-concept web application called BMS Analyser. The app runs as a local web server on a PC with Bluetooth capability, and any device on the same WiFi network (a phone, tablet, or another laptop) can open its browser and interact with the BMS in real time. This approach lets us demonstrate the vulnerability to the viewer by seeing live battery data and interactive MOSFET toggle switches on their phone screen.

Architecture

The backend is written in Python using Flask. Since BLE operations are inherently asynchronous (using the bleak library), we run a dedicated asyncio event loop in a background thread. Flask's synchronous request handlers submit BLE coroutines to this loop and block until the result is available. This bridge pattern lets us keep the simplicity of Flask's REST API while still performing non-blocking BLE operations under the hood.

BMS Analyzer Architecture

Driver Abstraction

We designed the BLE communication layer around a clean driver abstraction. An abstract BMSDriver base class defines the interface: scan, connect, disconnect, get_telemetry, set_charge_fet, and set_discharge_fet and three concrete implementations, JBDBLEDriver, DalyBLEDriver and JKBLEDriver, encapsulate all the brand-specific protocol details. Each driver handles BLE service discovery, command frame construction with proper headers, addresses, payloads and checksums, notification response parsing, and the protocol quirks unique to each brand. For instance, Daly streams cell voltages across multiple notification frames that need to be reassembled by frame number, while JK sends 300-byte cell info responses that arrive in BLE MTU-sized chunks and must be accumulated before parsing.

The User Interface

The frontend is a single-page HTML/CSS/JavaScript application that polls the backend every 1.5 seconds for telemetry data. It presents a BLE scanner panel where you select a brand and scan for nearby devices, with signal strength indicators and a scrollable device list. Once connected, a live telemetry dashboard shows pack voltage, current, power, SOC percentage with an animated progress bar, individual cell voltages rendered as a bar chart, and temperature readings. Below that sits the MOSFET control panel: two toggle switches for the charge and discharge FETs, with colour-coded status cards that update in real time.

BMS Analyzer Setup Interface

One practical challenge sometimes in the UI is toggle switch glitching. Because telemetry is polled every 1.5 seconds, there's a race condition: when a user toggles a FET, the command takes 1-2 seconds to propagate to the BMS hardware. If a telemetry poll completes during that window, it reads the old MOSFET state and overwrites the switch position back, causing it to visually bounce between states. 

BMS Remote Access Control Demo

The Solution: BMS Protector

Discovering a vulnerability without proposing a solution is only half the job. So we developed a hardware-based security shield that existing BMS owners can deploy immediately, without any modifications to their BMS itself.

The Core Insight

BLE peripherals like these BMS units typically support only one active GATT connection at a time. This is a fundamental limitation of most BLE peripheral firmware stacks; once a client is connected, the device stops advertising and rejects additional connection attempts. We realised we could exploit this limitation defensively: if a trusted device permanently occupies the BMS's only BLE connection slot, no attacker can connect.

How It Works

The ESP32 BMS Protector is a small, inexpensive microcontroller. We used the Seeed Studio XIAO ESP32-S3 for its tiny form factor that connects to your BMS via BLE and holds the connection 24/7. By maintaining the active BLE GATT session link, the protector keeps the connection slot occupied. Because the BMS's single connection slot is now permanently occupied by the ESP32, any external device, whether it's an attacker's phone or a malicious app that tries to scan and connect, will either not see the BMS at all or get a connection-refused error.

BMS Shield Setup Interface

When you legitimately need to use your phone app or the BMS Analyser to check battery status, you can temporarily release the lock by pressing the ESP32's built-in BOOT button or by using its built-in Wi-Fi web portal. The protector disconnects from the BMS, giving you a configurable window (default: 5 minutes) to connect with your normal tools. Once the timer expires, the ESP32 automatically reconnects and re-locks the BMS.

On first power-up, the ESP32 has no saved configuration, so it enters CONFIG mode and creates a Wi-Fi access point called BMS-Shield-Setup. You connect your phone to this AP, open a browser, and a captive portal lets you select your BMS brand (JBD, Daly, or JK), scan for nearby BLE devices, and select your BMS from the list. The ESP32 saves this to non-volatile storage and reboots into LOCKED mode. From then on, it automatically connects to your BMS on every boot and holds the connection.

BMS Shield State Machine

The onboard LED communicates the current state visually: a double-blink pulse in CONFIG mode, solid ON when locked and connected, slow blink when attempting to reconnect after a dropped connection, and fast blink during the temporary release window. A long press (5+ seconds) on the BOOT button triggers a factory reset, clearing the saved configuration and returning to CONFIG mode.

Limitations and Recommendations

The proposed solution is a mitigation rather than a permanent fix. It requires additional hardware for each BMS unit, and consumes a small amount of standby power. Additionally, a determined attacker with specialised radio equipment could potentially jam the BLE connection to force a disconnect. While these limitations make the workaround practical for many applications, they highlight that the underlying vulnerability remains within the BMS firmware itself.
The long-term solution must come from BMS manufacturers through the implementation of proper BLE security. At a minimum, devices should support BLE pairing with passkey entry, requiring a unique numeric passkey during the initial connection to prevent unauthenticated access. BLE bonding should be enabled so that only previously paired devices can reconnect, and all BLE communication should be encrypted using AES-CCM to protect against eavesdropping and packet injection.
At the firmware level, the most critical improvement is robust command authentication. Before executing any safety-critical command such as MOSFET control, parameter modification, or factory reset, the firmware should verify that the connected device has successfully authenticated using a secure challenge-response mechanism rather than relying on a plaintext password transmitted over BLE. Permission levels should also be separated, allowing unauthenticated users to read battery telemetry while restricting control functions exclusively to authenticated devices.

GitHub Repository

Code and SchematicsDownload Zip File

Conclusion

The BLE security vulnerability we discovered across JBD, Daly, and JK BMS units is not an edge case or an obscure protocol weakness. It is a systemic design failure, a conscious decision (or oversight) by manufacturers to ship thousands of units with no authentication on safety-critical control functions. The technology to fix this has existed for over a decade in the BLE specification itself. Pairing, bonding, encryption, and authorisation are all well-defined, well-supported standards. The missing ingredient is not capability; it is priority.

We hope this research serves as a signal to the BMS industry that security cannot be an afterthought. Until manufacturers respond with proper firmware-level security, the ESP32 BMS Protector offers a practical, deployable defence for the thousands of vulnerable units already in the field.

Have any question related to this Article?

Lessons from Building a Hardware Startup with Yatin, Nosh Robotics

Submitted by Staff on

Our recent Community Webinar featured Yatin Varachhia, Co-founder & CEO at Nosh Robotics, a company that makes a robot that cooks food. He previously worked as a design engineer at Analog Devices and has co-founded two companies. The session was held on a Sunday, with more than thirty people watching live, and included a question and answer segment.