Micro SD Express 3-in-1 Solution
Unlock 985 MB/s storage with Amphenol's microSD Express, perfect for high-res content and IoT
Unlock 985 MB/s storage with Amphenol's microSD Express, perfect for high-res content and IoT
Redefining Connectivity: AIROC™ CYW55913 modules for IoT, Smart Home, Industrial
Experience low power, high security, and reliable performance with PolarFire® Core & SoC FPGAs.
Voice control has become an integral part of modern smart home automation. In this tutorial, we build a voice-controlled LED system using the ESP32-S3-BOX-3 development board, combining wake word detection, speech recognition, touch interface, and audio feedback to create an intelligent control system. The code will be based on the factory example provided by Espressif and we will do the needed modifications to make it apt for our project.
The ESP32-S3-BOX-3 is a powerful development platform from Espressif that integrates a 320×240 touchscreen display, dual microphones for voice input, stereo speakers, and WiFi/Bluetooth connectivity. This project demonstrates how to leverage these features using the ESP-IDF (Espressif IoT Development Framework) and ESP-SR (Speech Recognition) library.

For a detailed hands-on review and getting-started walkthrough of the ESP32-S3-BOX-3 board, check out our previous articles on the same
Getting Started with ESP32-S3-BOX-3 - CircuitDigest Review
Programming ESP32-S3-BOX-3 with Arduino IDE - RGB LED Control
| S.No | Component | Quantity |
| 1 | ESP32-S3-BOX-3 Development Board | 1 |
| 2 | RGB LED Module | 1 |
| 3 | Jumper Wires | As needed |
| 4 | USB-C Cable (for programming and power) | 1 |
The circuit connection is straightforward. We connect an external LED to GPIO 40 of the ESP32-S3-BOX-3 board through a current-limiting resistor. For the ease of demonstration, we have used the RGB LED module that came with the ESP32-S3-BOX-3. We will be using the DOCK accessory to connect the LED. Insert the ESP32S3-Box-3 into the dock. Connect the GND pin of the RGB Module to any of the ground points in the dock and any one of the anode pins to the G40 port in the dock. As already mentioned, if you are using a single external LED, connect the cathode of the LED to ground and the anode to the G40 through a current-limiting resistor. The image below shows the connection.

Here is the ESP32S3-Box-3 with the LED attached.
This project requires ESP-IDF v5.5.2. For full installation and configuration instructions, refer to the official Espressif Getting Started Guide:
ESP-IDF Getting Started Guide (Official)
Then make sure to get our project file from our repo using git clone or manually downloading and extracting it to your preferred location.
git clone https://github.com/Circuit-Digest/Voice-Activated-LED-Controller-with-Touch-Interface-Using-ESP32S3-Box-31. Set up the ESP-IDF environment: Once you have properly installed and set up the ESP-IDF following Espressif's guide, on Mac or Linux systems, open a terminal and run the following command to set up the ESP-IDF environment. Make sure not to close the terminal once done, and any upcoming idf command has to be executed through the same terminal or command prompt. If you ever close the terminal, or when opening the project later, run this command first to set up the environment. This has to be done in each new section.
. $HOME/esp/esp-idf/export.shOn Windows PCs, you can directly run the ESP-IDF command prompt shortcut in the Start menu, created by the ESP-IDF installer.
2. Navigate to the project directory. The path you provide must be to the root folder of your project directory.
cd /path_to_your_project_directory3. Configure the project: The menu config option is used to change or reconfigure the project parameters. It is completely optional since all required properties are already configured. But if you need, you can use the following command to access the menuconfig options.
idf.py menuconfig4. Build the project: You can use the following script to build the project. When it's executed, the IDF will copy any required managed components to the project folder and build the project. If any error occurs, other than related to code, it is highly recommended to do a full clean and then build.
idf.py build5. Flash and monitor: the following command is used to flash the code to the ESp32S3-Box-3 and monitor the serial log. Make sure to connect the board to the computer before running the command. If the board is not detected, even after connecting to the computer, Press and hold the boot button and then press the reset button. Later, release the boot button and try to upload the code. Once uploaded with this method, make sure to reset the board manually once the code is uploaded.
idf.py flash monitorFor your reference, this is the file structure of our project. The Main folder contains all the source code, while the components folder contains unmanaged component libraries, and the spiffs folder contains all the image or audio files.
Wake word detection uses ESP-SR WakeNet, a low-power neural network engine that runs continuously in the background. The Audio Front-End (AFE), preprocesses audio from the microphone array. Sample rate: 16 kHz, 16-bit signed, 2 channels (stereo). Then the WakeNet Engine does the CNN-based wake word detection. The Wakenet framework continuously monitors the audio stream with low power consumption. It supports up to 5 wake words simultaneously. The wake word detection flow is as given below.
Microphone -> I2S -> AFE -> WakeNet -> Wake Detection Event
Detection Events
The following key functions are used for the wakeword detection and are called from main/app/app_sr.c.
The project supports multiple pre-trained wake words. Configure them via idf.py menuconfig.
Navigation: idf.py menuconfig -> ESP Speech Recognition -> Load Multiple Wake Words
| Wake Word | Language | Config Key |
| Hi ESP | English | |
| Hi Lexin | Chinese | |
| Alexa | English | |
| Xiao Ai Tong Xue | Chinese | |
| Ni Hao Xiao Zhi | Chinese | |
Method 1 - Using menuconfig
1.Run idf.py menuconfig
2.Navigate to: ESP Speech Recognition -> Load Multiple Wake Words
3.Enable or disable desired wake words.
4.Save and rebuild: idf.py build flash
Method 2 - Modify Code
Wake word selection happens in app_sr.c:
// In app_sr_set_language() function (line ~235)
char *wn_name = esp_srmodel_filter(models, ESP_WN_PREFIX,
(SR_LANG_EN == g_sr_data->lang ? "hiesp" : "hilexin"));To switch the English wake word to "Alexa":
char *wn_name = esp_srmodel_filter(models, ESP_WN_PREFIX,
(SR_LANG_EN == g_sr_data->lang ? "alexa" : "hilexin"));Requirements: A custom wake word model trained with ESP-SR tools, in ESP-SR compatible format, with sufficient model partition space.
1. Train a custom wake word using ESP-SR training tools (see ESP-SR documentation).
2. Place the generated model file (.bin) in spiffs/ or the model partition.
3. Enable the custom word in menuconfig: For eg, ESP Speech Recognition -> CONFIG_SR_WN_WN9_CUSTOMWORD
4 .Update code in app_sr.c:
char *wn_name = esp_srmodel_filter(models, ESP_WN_PREFIX, "customword");5. Rebuild and flash: idf.py build flash
Speech recognition uses ESP-SR MultiNet, an offline command recognition engine that supports up to 200 commands without requiring cloud connectivity. Both English and Chinese are supported in the ESP-SR engine.
Wake Word Detected -> AFE Processing -> MultiNet -> Command ID -> Handler Action
Recognition States
Key Components
// Command definition array (app_sr.c)
static const sr_cmd_t g_default_cmd_info[] = {
{SR_CMD_LIGHT_ON, SR_LANG_EN, 0, "turn on light", "TkN nN LiT", {NULL}},
{SR_CMD_LIGHT_OFF, SR_LANG_EN, 0, "turn off light", "TkN eF LiT", {NULL}},
};
⇒ Step 1 - Add Command Enum (app_sr.h)
typedef enum {
SR_CMD_LIGHT_ON,
SR_CMD_LIGHT_OFF,
SR_CMD_MY_NEW_CMD, // Add your command enum
SR_CMD_MAX,
} sr_user_cmd_t;⇒ Step 2 - Add Command Definition (app_sr.c)
static const sr_cmd_t g_default_cmd_info[] = {
{SR_CMD_LIGHT_ON, SR_LANG_EN, 0, "turn on light", "TkN nN LiT", {NULL}},
{SR_CMD_LIGHT_OFF, SR_LANG_EN, 0, "turn off light", "TkN eF LiT", {NULL}},
{SR_CMD_MY_NEW_CMD, SR_LANG_EN, 2, "my new command", "mI nU kMnd", {NULL}}, // Add
};⇒ Step 3 - Add Handler Action (app_sr_handler.c)
case SR_CMD_MY_NEW_CMD: // Add your handler
ESP_LOGI(TAG, "My new command executed!");
// Your action here
break;⇒ Step 4 - Rebuild and Flash
idf.py build flash monitor// app_sr.h - enum
SR_CMD_FAN_ON,
SR_CMD_FAN_OFF,
SR_CMD_SET_BRIGHTNESS_HIGH,
SR_CMD_SET_BRIGHTNESS_LOW,
// app_sr.c - command definitions
{SR_CMD_FAN_ON, SR_LANG_EN, 2, "turn on fan", "TkN nN fN", {NULL}},
{SR_CMD_FAN_OFF, SR_LANG_EN, 3, "turn off fan", "TkN eF fN", {NULL}},
{SR_CMD_SET_BRIGHTNESS_HIGH, SR_LANG_EN, 4, "brightness high", "brItns hI", {NULL}},
{SR_CMD_SET_BRIGHTNESS_LOW, SR_LANG_EN, 5, "brightness low", "brItns lO", {NULL}},Dynamic Command Addition (Runtime)
sr_cmd_t new_cmd = {
.cmd = SR_CMD_MY_NEW_CMD,
.lang = SR_LANG_EN,
.id = 10,
.str = "my command",
.phoneme = "mI kMnd"
};
app_sr_add_cmd(&new_cmd);
app_sr_update_cmds(); // Update MultiNet command listAPI Functions (app_sr.h)
The project uses LVGL (Light and Versatile Graphics Library) for GUI rendering and touch input.
Initialisation (main.c)
bsp_display_cfg_t cfg = {
.lvgl_port_cfg = ESP_LVGL_PORT_INIT_CONFIG(),
.buffer_size = BSP_LCD_H_RES * CONFIG_BSP_LCD_DRAW_BUF_HEIGHT,
.double_buffer = 0,
.flags = { .buff_dma = true }
};
bsp_display_start_with_config(&cfg);
bsp_board_init();#include "lvgl.h"
#include "bsp/esp-bsp.h"
bsp_display_lock(0); // Lock for thread safety
lv_obj_t *scr = lv_scr_act(); // Get current screen
// Create a button
lv_obj_t *btn = lv_btn_create(scr);
lv_obj_set_size(btn, 100, 50);
lv_obj_align(btn, LV_ALIGN_CENTER, 0, 0);
// Add label
lv_obj_t *label = lv_label_create(btn);
lv_label_set_text(label, "Click Me");
// Add click callback
lv_obj_add_event_cb(btn, on_button_click, LV_EVENT_CLICKED, NULL);
bsp_display_unlock();static void on_touch_event(lv_event_t *e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t *obj = lv_event_get_target(e);
switch (code) {
case LV_EVENT_PRESSED:
lv_obj_set_style_bg_color(obj, lv_color_hex(0x0000FF), 0);
break;
case LV_EVENT_RELEASED:
lv_obj_set_style_bg_color(obj, lv_color_hex(0x00FF00), 0);
break;
case LV_EVENT_CLICKED:
light_ctrl_toggle(); // Perform action
break;
default: break;
}
}Supported Event Types
The project converts BMP from images stored in an array using the image_to_c tool by bitbank2, to LVGL-compatible RGB565 format at runtime using bmp_to_lv_img() in light_ui.c. If you wan you can also use the LVGL image converter tool to convert the images to c array. One other option is to store the image files in the file system and load them from there.
lv_img_set_src(img_obj, "/spiffs/image.bin");Here is an example code snippet showing how to create a new screen for the GUI. The LV object creation macro is used to create or define each screen.
// Screen 1: Main
lv_obj_t *main_screen = lv_obj_create(NULL);
// ... add widgets ...
// Screen 2: Settings
lv_obj_t *settings_screen = lv_obj_create(NULL);
// ... add widgets ...
// Navigate
void goto_settings(lv_event_t *e) { lv_scr_load(settings_screen); }
void goto_main(lv_event_t *e) { lv_scr_load(main_screen); }Warning: Each RGB565 pixel = 2 bytes. A 320×240 screen buffer = ~150 KB. Double buffering doubles that. Consider using PSRAM for large buffers.
For more details on how to use the LVGL library, please check out the official LVGL documentation.
Audio output uses the I2S interface with an ES8311 codec chip for digital-to-analog conversion. The I2S Driver handles audio data transfer. Sample rate: 16 kHz default for SR feedback, 16-bit, stereo (2 channels). The ES8311 codec with I2S input provides analog output to the speaker and volume and mute control.
Audio Playback Flow
WAV File -> Memory Buffer -> I2S Write -> Codec -> SpeakerKey Functions (app_sr_handler.c)
typedef enum {
AUDIO_WAKE, // Wake word detected tone
AUDIO_OK, // Command recognised tone
AUDIO_END, // Timeout / end tone
AUDIO_MAX,
} audio_segment_t;
// Load WAV from SPIFFS -> PSRAM
static esp_err_t load_wav_to_mem(audio_segment_t seg, const char *path)
{
FILE *fp = fopen(path, "rb");
if (!fp) return ESP_ERR_NOT_FOUND;
fseek(fp, 0, SEEK_END);
long sz = ftell(fp);
fseek(fp, 0, SEEK_SET);
s_audio[seg].buf = heap_caps_malloc(sz, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
s_audio[seg].len = (size_t)sz;
fread(s_audio[seg].buf, 1, sz, fp);
fclose(fp);
return ESP_OK;
}⇒ Step 1 - Add Audio Segment Enum
typedef enum {
AUDIO_WAKE,
AUDIO_OK,
AUDIO_END,
AUDIO_CUSTOM_1, // Add your segment
AUDIO_CUSTOM_2,
AUDIO_MAX,
} audio_segment_t;⇒ Step 2 - Add WAV File to SPIFFS
Place your WAV file in the spiffs/ directory. WAV requirements: uncompressed PCM, 16 kHz recommended, 16-bit, mono or stereo.
spiffs/
├── echo_en_wake.wav
├── echo_en_ok.wav
├── echo_en_end.wav
├── custom_sound_1.wav Add here
└── custom_sound_2.wav⇒ Step 3 - Load in Initialisation
ESP_RETURN_ON_ERROR(
load_wav_to_mem(AUDIO_CUSTOM_1, "/spiffs/custom_sound_1.wav"),
TAG, "load custom1 wav failed");⇒ Step 4 - Play When Needed
sr_echo_play(AUDIO_CUSTOM_1);⇒ Step 5 - Rebuild
idf.py build flashThe SPIFFS partition is automatically rebuilt with files from the spiffs/ directory.
| Parameter | Value |
| Sample Rates | 8, 16, 22.05, 44.1, 48 kHz |
| Bit Depth | 16-bit (recommended) |
| Channels | Mono or Stereo |
| Format | Uncompressed PCM WAV |
# Convert to 16 kHz, 16-bit, mono WAV
ffmpeg -i input.mp3 -ar 16000 -acodec pcm_s16le -ac 1 output.wav
# Convert to 16 kHz, 16-bit, stereo WAV
ffmpeg -i input.mp3 -ar 16000 -acodec pcm_s16le -ac 2 output.wavThe following BSP functions (bsp_board.h) control the audio codec:
| Function | Description |
| Set codec sample rate, bit depth, and channel mode |
| Set volume level (0-100) |
| Mute or unmute the audio codec |
| Write audio data buffer to I2S output |
| Stop the codec device |
| Resume the codec device |
Recommendations
Streaming Long Audio
void play_long_audio_stream(const char *wav_path)
{
FILE *fp = fopen(wav_path, "rb");
if (!fp) return;
fseek(fp, 44, SEEK_SET); // Skip WAV header
uint8_t chunk[4096];
size_t bytes_read;
while ((bytes_read = fread(chunk, 1, sizeof(chunk), fp)) > 0) {
size_t bytes_written = 0;
bsp_i2s_write((char *)chunk, bytes_read, &bytes_written, portMAX_DELAY);
}
fclose(fp);
}
1. Open the file: main/app/app_led.c
2. Find this line (around line 15):
#define SINGLE_LED_GPIO GPIO_NUM_403. Change it to a different pin (e.g. GPIO 38):
#define SINGLE_LED_GPIO GPIO_NUM_384. Save the file.
5. Rebuild and flash:
idf.py build flash monitor6. Test: Connect your LED to GPIO 38 instead of GPIO 40.
Once the hardware is connected and the software is set up, follow these steps to compile and upload the code.
⇒ Step 1 - Navigate to the Project Directory
cd /path/to/esp32-box3-voice-led-project⇒ Step 2 - Activate ESP-IDF Environment
. $HOME/esp/esp-idf/export.sh⇒ Step 3 - Configure (Optional)
idf.py menuconfig⇒ Step 4 - Build
idf.py buildThis compiles all source files and creates the firmware binary. The first build may take several minutes as dependencies are downloaded.
⇒ Step 5 - Flash and Monitor
idf.py flash monitor*Tip: Press Ctrl+] to exit the serial monitor.
After successfully flashing the firmware, the ESP32-S3-BOX-3 boots and displays the light control screen. Now we can control the LED with two different methods.
The first method is to use the voice commands. To use it:
1. Say the wake word: "Hi ESP" (speak clearly, about 1 metre from the device).
2. Wait for audio feedback - you'll hear a confirmation sound.
3. Speak the command: "Turn on light" or "Turn off light".
4. Observe: the LED changes state, the screen updates, and audio feedback plays.
5. Once the wake word is detected, you can continuously give commands without using the wake word. If you haven't provided any commands for a certain time(a few seconds), the ESP-SR engine will time out. To use it again, all you have to do is say the wake word again to trigger the wake word detection.
The second method is to use the touch screen. For that:
1. Touch the on-screen toggle button.
2. Observe: the LED toggles and the button image changes.
Here is the final result:
Find the project’s codebase and documentation here. Explore, fork, and contribute on GitHub.
Years ago, if you had opened the door to the hostel room of Venkat Rangan, you would have been greeted by music. One could say tinkering was something he always latched on to, because the door’s latch triggered the music from a system he built himself. "He's always been a tinkerer," recalled Vishal Srivastava, who studied alongside Venkat and now leads Marketing and Business Development at the company.
DTDS’s booth at electronica India 2025 highlighted a cost-effective approach to vehicle lighting systems. The company stated that its Light Control Module offers a competitive advantage, being 25% lighter on the pocket when compared to other market options. Chand Hanif, Senior FAE at the company, walked us through a live demo of the module at the booth. He explained, "We have put that complete setup as a PCB on outside also," giving visitors "more clarity on LED brightness and all."
With 18 years of experience, Bangalore and Chennai-based Sahara Group of Industries has been involved in numerous sectors, including healthcare, aviation, and automobile. Now the company has stepped into thin-film transistor (TFT) LCD display production, which was put on display at electronica India 2025.
At the Laser World of Photonics India 2025, Thorlabs, a photonics company, showcased optics, lasers, modulators, and detectors. Instruments like spectrometers and power meters were scattered across the booth. Stephan Hallwig, Head of Business Development and Marketing Communication EMEA, explained that the industry’s applications extend to semiconductor, medical, and telecommunication.
LiteWing is an open-source ESP32-S3 based drone that offers a flexible platform for experimentation and learning. By default, LiteWing operates using the modified Crazyflie firmware. LiteWing can also be configured using Betaflight, a powerful and widely adopted flight control software used in FPV and racing drones.
In this ESP32 Betaflight tutorial, we will go through the process of configuring the LiteWing drone Betaflight and turning it into a fully tunable drone. LiteWing drone Betaflight integration unlocks a rich set of features such as PID tuning, motor configuration, receiver setup, flight modes, and real-time diagnostics, making it an excellent choice for users who want deeper control over their drone’s behavior.
This ESP32 Betaflight configurator guide is for beginners as well as experienced developers who want to explore how open-source hardware like LiteWing can be integrated with standard flight software. By the end of this ESP32 Betaflight tutorial, you will have a properly configured LiteWing drone and a clear understanding of how ESP32 Betaflight firmware can be used to unlock its full potential. If you want to learn more about the LiteWing drone, its hardware, and other features, make sure to check out the official documentation and resources.
To follow this tutorial, you will need a LiteWing drone, an ExpressLRS (ELRS) receiver, and a compatible ELRS transmitter to control the drone. The receiver and transmitter should already be bound before connecting to the drone. A computer with Betaflight Configurator installed is also required for configuration and tuning. This ESP32 Betaflight configurator setup requires proper hardware connections.
Hardware Requirements:
» LiteWing ESP32-S3 drone with all components assembled
» ExpressLRS (ELRS) receiver for low-latency radio communication
» Compatible ELRS transmitter (pre-bound to receiver)
» USB data cable for computer connection
» LiPo battery suitable for LiteWing drone
Software Requirements:
» Betaflight Configurator v10.10.0 is installed on your computer
» Web browser (Chrome or Edge) for ESP flashing tool
» ESP32 Betaflight firmware binary file for ESP32-S3
Before configuring the LiteWing ESP32 drone Betaflight firmware must be programmed manually using the ESP flashing tool. LiteWing uses an ESP32-S3 based ESP-FC, so the correct binary file must be flashed before proceeding.
Downloading the ESP32 Betaflight Firmware
First, open the ESP-FC open-source GitHub repository using the link below. This firmware is developed and maintained by rtlopez, and his work is highly appreciated for contributing to the open-source community.
GitHub Repository: https://github.com/rtlopez/esp-fc
Once the repository page opens, navigate to the Releases section. The releases page contains precompiled firmware binaries for different ESP based flight controllers. From there, download the firmware .zip file specifically built for the ESP32-S3 microcontroller since LiteWing is based on the ESP32-S3 platform.

To flash the firmware onto the LiteWing drone, open the Espressif ESP Tool (Web-based flasher) in a supported browser. Connect the LiteWing drone to your computer using a USB data cable, ensuring the drone is powered on and detected by your system. On the ESP Tool web page, click Select Port, choose the COM port corresponding to the LiteWing drone from the pop-up list and confirm the selection. Then click Connect to establish communication between the tool and the drone. Once connected successfully, the tool will be ready for firmware upload.

Upload the downloaded firmware file (firmware_0x00.bin) and set the flash address to 0x0000, verifying that both the correct file and address are selected. Click the Program button to begin flashing and wait until the process completes successfully, making sure not to disconnect the drone during programming. Once finished, the firmware will be successfully uploaded to the LiteWing drone, and you can now proceed to configure settings and tune the drone using Betaflight. Once the ESP32 Betaflight firmware upload completes successfully, your LiteWing drone is ready for configuration in Betaflight Configurator.
To configure and tune the LiteWing ESP32 Betaflight drone, you need the Betaflight Configurator installed on your computer. This software allows you to connect to the drone and adjust flight settings.
Downloading and Installing Betaflight Configurator
Visit the official GitHub release page for Betaflight Configurator Releases and download version 10.10.0 is recommended for easy setup. Choose the version compatible with your operating system: Windows, macOS, or Linux.

After installing and opening the ESP32 Betaflight configurator.
Before connecting the LiteWing ESP32 drone to Betaflight, you should adjust some settings in the Options tab as shown in the reference image. Make sure to enable “Show All Serial Devices” this ensures that the software can detect the drone even if it doesn’t appear by default.
These changes help the Betaflight Configurator communicate properly with the drone.

Once the settings are updated, manually select the COM port in the software and click the Connect button to establish communication between the software and the drone.
When you first connect the LiteWing ESP32 drone to Betaflight, you may notice that the real-time updates and the 3D model in the setup tab do not respond correctly when the drone is moved. This happens because the default pin assignments in Betaflight do not match the LiteWing hardware. To fix this, you can update the pin assignments using the CLI tab in Betaflight Configurator. By entering the correct commands, you can map the pins according to LiteWing’s configuration, ensuring that all motors and sensors respond accurately during real-time updates.

ESP32 Betaflight CLI Pin Configuration Commands
Navigate to the CLI tab in Betaflight Configurator and enter the following commands. These commands configure all necessary GPIO pins for the LiteWing ESP32 drone:
set pin_input_rx -1
set pin_output_0 6
set pin_output_1 5
set pin_output_2 3
set pin_output_3 4
set pin_buzzer 8
set pin_serial_0_tx 43
set pin_serial_0_rx 44
set pin_serial_1_tx 17
set pin_serial_1_rx 18
set pin_serial_2_tx -1
set pin_serial_2_rx -1
set pin_i2c_scl 10
set pin_i2c_sda 11
set pin_input_adc_0 2
set pin_input_adc_1 -1
set pin_spi_0_sck 12
set pin_spi_0_mosi 35
set pin_spi_0_miso 37
set pin_spi_cs_0 -1
set pin_spi_cs_1 7
set pin_spi_cs_2 -1
set pin_buzzer_invert -1After pasting the commands, simply press Enter, then type save and press Enter again to save the changes. And then type reboot and press Enter again to apply the changes. This will update the pin configuration automatically, making the setup quick and easy without manually changing each assignment.
After the CLI commands are executed, simply disconnect and reconnect the LiteWing drone. This will allow the ESP32 drone to connect with Betaflight Configurator and to display real-time updates, reflecting the drone’s movements accurately.
The following pin configuration changes are implemented to match the LiteWing hardware setup.
| Pin Type | GPIO Assignment | Function |
|---|---|---|
| Motor Output 1 | GPIO 6 | Front-right motor PWM control |
| Motor Output 2 | GPIO 5 | Rear-right motor PWM control |
| Motor Output 3 | GPIO 3 | Rear-left motor PWM control |
| Motor Output 4 | GPIO 4 | Front-left motor PWM control |
| UART1 TX/RX | GPIO 17/18 | ExpressLRS receiver communication |
| I2C SCL/SDA | GPIO 10/11 | IMU sensor communication (MPU6050) |
| ADC Input | GPIO 2 | Battery voltage monitoring |
After configuring the GPIO pins in your ESP32 Betaflight configurator, you may notice that the 3D model moves when the LiteWing drone is tilted or rotated, but the movements don't exactly match the actual drone orientation. The 3D model in Betaflight moves when the drone is tilted or rotated, but you may notice that its movements do not exactly match the actual drone. This happens because the IMU (Inertial Measurement Unit) on the LiteWing is placed in a different orientation. To correct this, go to the Configuration tab in Betaflight, scroll to Board and Sensor Alignment, and change the First Gyro setting from Default to CW 270°. This aligns the 3D model accurately with the real movements of the drone.

To monitor the battery voltage in the software, make the necessary changes as shown in the reference image below, select Onboard ADC as the voltage meter source and then set the minimum and maximum cell voltage values, and adjust the warning cell voltage according to your requirements.

In the voltage meter settings, set the scale to 10, the divider value to 1, and the multiplier value to 2, as these values are calculated based on the voltage divider used in the LiteWing.
| Parameter | Value | Purpose |
|---|---|---|
| Voltage Scale | 10 | ADC reading multiplier for voltage calculation |
| Voltage Divider | 1 | Hardware divider ratio (pre-calculated in scale) |
| Voltage Multiplier | 2 | Correction factor for LiteWing's voltage divider circuit |
After entering these values, click Save and Reboot to apply the battery monitoring configuration to your ESP32 Betaflight firmware.
LiteWing ESP32 drone uses brushed DC motors, so the motor protocol must be configured accordingly in Betaflight. In the Configuration tab of Betaflight Configurator, set the Motor Protocol to Brushed. Then set the Motor PWM Frequency to 8000 Hz. Keep the remaining motor and ESC-related parameters set as shown in the reference image, as these values are configured for the LiteWing hardware.

After making these changes, click Save and Reboot to apply the settings. Once completed, the motors will respond correctly and smoothly during operation.
In this setup, we are going to control the LiteWing drone using a radio transmitter and receiver. For this setup, we are using an ExpressLRS (ELRS) receiver due to its low-latency radio communication. ELRS is widely used due to its long range, fast response, and open-source support.

Connect the ELRS receiver to the LiteWing according to the UART wiring. Power the receiver using 3.3V and GND. Connect the receiver’s TX pin to the drone’s RX (GPIO18), and the receiver’s RX pin to the drone’s TX (GPIO17). Ensure all power, ground, and signal connections are properly made before proceeding.
Ideal for use within LiteWing Ctrl ESP32 Drone, ExpressLRS Receivers offer the following advantages:
∗ Ultra-low latency - Instantaneous feedback to commands and immediate changes to airframe attitude, with receipt of command inputs occurring at ultra-low latencies (as little as 5ms).
∗ Long distances - An excellent range of operation — several kilometres, assuming optimal use of antennas.
∗ Open Source Protocol - Firmware is open source; support from a community of users.
∗ CRSF Protocol - Fully compliant with the Betaflight CRSF Receiver Mode.
| ELRS Receiver Pin | LiteWing GPIO Pin | Connection Purpose |
|---|---|---|
| VCC (3.3V) | 3.3V Power | Receiver power supply |
| GND | GND | Common ground connection |
| TX | GPIO 18 (RX) | Receiver transmits data to drone |
| RX | GPIO 17 (TX) | Receiver receives data from drone |
Next, open Betaflight Configurator and go to the Ports tab. Enable Serial RX on the UART 2, where the ELRS receiver is connected, and save the settings.

Then go to the Receiver tab, set the Receiver Mode to Serial-based receiver, and select CRSF as the protocol. Save and reboot the drone. After this, power on the transmitter if everything is configured correctly, and you will see real-time channel movements in the Receiver tab when you move the transmitter sticks.
Flight modes define how the LiteWing drone behaves during flight. In this setup, we will configure ARM, ANGLE, and BLACKBOX modes using Betaflight.

Open the Modes tab in Betaflight Configurator. Assign a switch on your transmitter to the ARM mode to enable and disable the motors safely. Next, assign another switch or position to ANGLE mode, which provides self-levelling and is ideal for stable and beginner-friendly flight. Enable BLACKBOX mode to record flight data for tuning and troubleshooting.

After assigning the switches, make sure the activation ranges are set correctly and click Save. These modes will allow you to arm the drone and switch between stable and aggressive flight behavior as needed.
The default PID values in the ESP32 Betaflight firmware are not suitable for the LiteWing drone and can result in unstable flight performance. Since LiteWing is a lightweight drone using brushed DC motors, custom PID values are required to achieve stable and smooth flight.
In the PID Tuning tab of Betaflight Configurator, replace the default values with the recommended LiteWing PID values provided in the reference configuration. These values have been tested and optimized specifically for LiteWing and help eliminate oscillations while improving control and responsiveness.

After entering the PID values, click Save and perform a short test flight. If required, minor adjustments can be made later, but the provided values should give a stable and reliable flying experience right away.
The LiteWing drone requires custom PID tuning because:
∗ Low weight construction: The reduced weight necessitates changes to PID (proportional, integral and derivative) settings for the model.
∗ Brushed motor technology (coreless): Torque curves with different speed exponentials compared to the brushless motor.
∗ Small propellers: Lower inertia creates a need for different stabilization procedures than those required by larger props.
∗ Compact design: The shorter arm lengths between motors affect the rotational characteristics of the various components.
Blackbox is a logging feature in Betaflight that records flight data such as gyro values, motor outputs, PID behavior, and receiver inputs. This data is useful for analyzing flight performance and troubleshooting issues like vibrations, oscillations, or unstable behavior.

After enabling Blackbox in Betaflight, fly the LiteWing drone to record flight data. Once the flight is complete, connect the drone to Betaflight Configurator, go to the Blackbox tab, and download the log files. Open these logs in the Betaflight Blackbox Explorer to analyze gyro data, PID behavior, and vibrations, which help in improving stability and tuning performance.
After completing all the steps in this guide, your LiteWing drone configured with Betaflight is fully ready for flight. You can now safely test it, fine-tune settings if needed, and explore more advanced Betaflight features as you gain experience.
⇥ 1. How to calibrate the IMU?
To calibrate the IMU (Inertial Measurement Unit) in Betaflight, place the LiteWing drone on a flat and stable surface. Open Betaflight Configurator and connect the drone. Go to the Setup tab and click the Calibrate Accelerometer button. Keep the drone completely still during the calibration process. Once finished, the IMU will be calibrated, ensuring accurate orientation and stable flight behavior.
⇥ 2. Why is my LiteWing not connecting to Betaflight Configurator?
After flashing or making configuration changes, disconnect and reconnect the drone, and ensure that no other applications (such as Arduino IDE, serial monitor, or ESP tools) are using the same COM port.
⇥ 3. Do I need to calibrate the accelerometer every time?
No, you do not need to calibrate the accelerometer every time you power on the LiteWing drone. Accelerometer calibration is usually required only once during the initial setup or after making major changes.
⇥ 4. How do I enable FPV (Acro) mode on the LiteWing drone?
Assign a switch for ARM and do not enable ANGLE mode.
When the angle mode is off, the LiteWing drone flies in FPV (Acro) mode.
Beginner-friendly LiteWing drone projects that explore different ways to program, control, and experiment with ESP32 based drones, focusing on practical learning and real-world applications.
DIY Gesture Control Drone using Python with LiteWing and ESP32
Build a gesture-controlled drone using ESP32 and LiteWing. This project explains how to track hand movements with MPU6050 and control the drone via Bluetooth and Python using UDP communication.
How to Use Height Hold Mode in LiteWing ESP32 Drone?
Learn how to add height hold to the LiteWing ESP32 drone using the VL53L1X ToF sensor. This tutorial explains sensor setup, PID control, and app integration for smooth indoor flights.
How to Program the LiteWing Drone using Python with Crazyflie Cflib Python SDK
Learn how to control the LiteWing drone using the Crazyflie cflib Python SDK. This guide covers installation, basic commands, and writing Python code to spin the drone's motors via Wi-Fi.
Your email is safe with us, we don’t spam.
Be a part of our ever growing community.