ESP32 development and debugging with ESP-IDF framework. Use when working with ESP32 microcontrollers for: (1) Creating new ESP32 projects with interactive ESP-IDF version selection, (2) Building and compiling firmware with configurable target chips, (3) Flashing to development boards with auto-detected serial ports, (4) Serial monitoring and log analysis with filtering, (5) Troubleshooting ESP32 issues. Supports ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6, ESP32-H2 chips and popular development boards with interactive configuration wizard.
This skill provides comprehensive support for ESP32 development using the official ESP-IDF framework. It covers project creation, building, flashing, debugging, and troubleshooting for ESP32 family chips (ESP32, ESP32-S2/S3, ESP32-C3/C6, ESP32-H2). Includes interactive configuration wizard for ESP-IDF version selection and chip type configuration.
Enhanced Features:
export.shidf.py monitor or pyserial methodsKey Improvements from v1:
Before using the skill, run the configuration wizard to set up your ESP-IDF environment:
python scripts/config_manager.py --setup
The wizard will:
Settings are saved to ~/.esp32-developer-config.json. You can:
python scripts/config_manager.py --showpython scripts/config_manager.py --resetpython scripts/config_manager.py --pathAll scripts (create_esp32_project.py, build_esp32_project.py, etc.) will:
--setup option to force wizard)source $IDF_PATH/export.sh (skill scripts handle this automatically)pip install pyserial (optional, but recommended)Create and run a Hello World project (recommended):
# Configure ESP-IDF first (if not already configured)
python scripts/config_manager.py --setup
# Create a new project
python scripts/create_esp32_project.py my_project --target esp32
cd my_project
# Build the project
python scripts/build_esp32_project.py
# Flash to board (auto-detects port)
python scripts/flash_esp32.py
# Monitor output (non-interactive)
python scripts/monitor_serial.py --method pyserial
Quick workflow with skill scripts:
# One-liner: build, flash, and monitor
python scripts/build_esp32_project.py && \
python scripts/flash_esp32.py --monitor
# For non-interactive environments:
python scripts/flash_esp32.py && \
python scripts/monitor_serial.py --method pyserial --timeout 10
Or use ESP-IDF commands directly:
# Copy example
cp -r $IDF_PATH/examples/get-started/hello_world my_project
cd my_project
# Build and flash
idf.py set-target esp32
idf.py build
idf.py flash monitor
The scripts/create_esp32_project.py script creates a new ESP32 project from the official Hello World example with interactive configuration support:
python scripts/create_esp32_project.py <project_name> [--target TARGET] [--path PATH] [--setup]
Features:
~/.esp32-developer-config.json--setup to force wizard)Examples:
# Create project with interactive setup (if not configured)
python scripts/create_esp32_project.py my_app
# Run setup wizard first, then create project
python scripts/create_esp32_project.py my_app --setup
# Create ESP32-S3 project in specific directory
python scripts/create_esp32_project.py my_s3_app --target esp32s3 --path ~/projects
# Create project using default target from config
python scripts/create_esp32_project.py my_app # Uses configured default target
cp -r $IDF_PATH/examples/get-started/hello_world my_projectA template project is available in assets/esp32_hello_world/ containing:
The scripts/build_esp32_project.py script handles building with proper environment checks and configuration support:
python scripts/build_esp32_project.py [--path PROJECT_PATH] [--target TARGET] [--clean] [--setup] [--verbose]
Enhanced Features:
Examples:
# Build current directory project (uses default target from config)
python scripts/build_esp32_project.py
# Run setup wizard first, then build
python scripts/build_esp32_project.py --setup
# Build specific project with target
python scripts/build_esp32_project.py --path ~/projects/my_app --target esp32s3
# Clean build with verbose output
python scripts/build_esp32_project.py --clean --verbose
# Build with detailed error reporting
python scripts/build_esp32_project.py --verbose
# Set target (if not default esp32)
idf.py set-target <chip>
# Configure (optional)
idf.py menuconfig
# Build
idf.py build
# Parallel build for speed
idf.py -j $(nproc) build
build/bin/ (.bin, .elf files)build/<project_name>.mapidf.py sizeThe scripts/flash_esp32.py script handles flashing with automatic port detection and configuration support:
python scripts/flash_esp32.py [--port SERIAL_PORT] [--baud BAUD_RATE] [--path PROJECT_PATH]
[--monitor] [--setup] [--verbose] [--no-reset]
Enhanced Features:
Examples:
# Flash with auto-detected port
python scripts/flash_esp32.py
# Run setup wizard first, then flash
python scripts/flash_esp32.py --setup
# Specify port and baud rate
python scripts/flash_esp32.py --port /dev/ttyUSB0 --baud 460800
# Flash with verbose output
python scripts/flash_esp32.py --port /dev/ttyUSB0 --verbose
# Flash without auto-reset (press BOOT button manually)
python scripts/flash_esp32.py --port /dev/ttyUSB0 --no-reset
# Windows example
python scripts/flash_esp32.py --port COM3 --baud 115200
# Auto-detect port
idf.py flash
# Specify port
idf.py -p /dev/ttyUSB0 flash
# Specify baud rate
idf.py -p /dev/ttyUSB0 -b 460800 flash
# Flash and monitor
idf.py flash monitor
See ESP32 Boards Reference for details.
The scripts/monitor_serial.py script provides enhanced serial monitoring with filtering, logging, and configuration support:
python scripts/monitor_serial.py [--port SERIAL_PORT] [--baud BAUD_RATE] [--path PROJECT_PATH]
[--filter PATTERN] [--save LOG_FILE] [--no-color] [--setup]
[--method {idf,pyserial}] [--timeout SECONDS] [--exit-on ERROR_PATTERN]
Enhanced Features:
idf.py monitor (interactive) or pyserial (non-interactive)Examples:
# Basic monitor with auto-detected port (uses pyserial by default)
python scripts/monitor_serial.py
# Run setup wizard first, then monitor
python scripts/monitor_serial.py --setup
# Monitor with error filtering
python scripts/monitor_serial.py --filter "error|warn|fail"
# Save log to file with timeout
python scripts/monitor_serial.py --save debug.log --timeout 30
# Monitor specific port with pyserial method
python scripts/monitor_serial.py --port /dev/ttyUSB0 --baud 115200 --method pyserial
# Monitor and exit on panic
python scripts/monitor_serial.py --exit-on "panic|abort"
# Use idf.py monitor (interactive terminals only)
python scripts/monitor_serial.py --method idf --no-color
# Start monitor
idf.py monitor
# Specify port and baud rate
idf.py -p /dev/ttyUSB0 -b 115200 monitor
# Exit monitor: Ctrl+]
--method pyserial optionESP_LOGI(), ESP_LOGW(), ESP_LOGE() for structured loggingesp_log_level_set("*", ESP_LOG_VERBOSE)--filter option to show only specific messages (errors, warnings, etc.)--save option to capture logs to file for later analysisidf.py --versionls /dev/ttyUSB* /dev/ttyACM*--no-reset optionsudo usermod -a -G dialout $USERidf.py fullclean, check CMakeLists.txt--method pyserial optionprintf("Debug: value=%d\n", variable);esp_get_free_heap_size()See Troubleshooting Guide for detailed solutions.
Load these references as needed for specific tasks:
idf.py command listscripts/config_manager.pyConfiguration manager for ESP-IDF setup. Handles ESP-IDF installation detection, version selection, and user preferences. Run python scripts/config_manager.py --setup for interactive configuration wizard.
scripts/esp32_utils.pyNew: Shared utility module providing common functions for ESP32 development:
scripts/create_esp32_project.pyCreates new ESP32 projects from Hello World example with target chip configuration and interactive setup support.
scripts/build_esp32_project.py (Enhanced)Builds ESP32 projects with enhanced features:
scripts/flash_esp32.py (Enhanced)Flashes firmware to ESP32 boards with enhanced features:
scripts/monitor_serial.py (Enhanced)Monitors serial output with enhanced features:
assets/esp32_hello_world/ - Minimal Hello World project templateWhen scripts aren't needed, use standard ESP-IDF commands:
# Complete workflow
cp -r $IDF_PATH/examples/get-started/hello_world my_project
cd my_project
idf.py set-target esp32
idf.py menuconfig
idf.py build
idf.py flash monitor
When to use skill scripts vs direct commands:
--method pyserial when idf.py monitor fails in non-interactive terminalsBased on real-world ESP32 project experience (OpenClaw Monitor), follow these practices for secure and maintainable projects:
ESP-IDF projects should never commit sensitive data (WiFi credentials, API keys) to version control. Use a layered configuration strategy:
sdkconfig.defaults (committed): Non-sensitive default values, template for new setups
# Example: Define placeholder values
CONFIG_WIFI_SSID="your_wifi_ssid"
CONFIG_WIFI_PASSWORD="your_wifi_password"
CONFIG_GATEWAY_HOST="192.168.2.195"
sdkconfig.ci (committed): CI/CD configuration with environment variable placeholders
# Use environment variables for CI/CD pipelines
CONFIG_WIFI_SSID="$WIFI_SSID"
CONFIG_WIFI_PASSWORD="$WIFI_PASSWORD"
CONFIG_GATEWAY_HOST="$GATEWAY_HOST"
sdkconfig (.gitignore): Local configuration with real values - never commit
# Generated by menuconfig or manually edited
CONFIG_WIFI_SSID="MyHomeWiFi"
CONFIG_WIFI_PASSWORD="secure_password"
CONFIG_GATEWAY_HOST="192.168.2.195"
Chip-specific defaults: sdkconfig.defaults.esp32s2 for target-specific settings
Initialization workflow:
# First-time setup: Copy defaults template
cp sdkconfig.defaults sdkconfig
# Configure via menuconfig
idf.py menuconfig
# Or edit directly (for CI/CD)
idf.py -D SDKCONFIG_DEFAULTS="sdkconfig.ci" build
Branch strategy:
main: Production-ready releasesdevelop: Active development branchfeature/, fix/, refactor/.gitignore essentials for ESP-IDF:
# Build artifacts
build/
sdkconfig
sdkconfig.old
# IDE and editor files
.vscode/
.idea/
*.swp
# Auto-generated components
managed_components/
# Dependency locks
dependencies.lock
Sensitive information protection:
sdkconfig with real credentialssdkconfig.ci)ESP-IDF provides comprehensive testing support:
Unit Testing (Unity framework):
// components/my_component/test/test_my_component.c
#include "unity.h"
#include "my_component.h"
TEST_CASE("Test function returns expected value", "[my_component]")
{
TEST_ASSERT_EQUAL(42, my_function());
}
Test project structure:
project/
├── components/my_component/
│ ├── my_component.c
│ └── test/ # Component tests
│ ├── CMakeLists.txt
│ └── test_my_component.c
└── test/ # Test runner project
├── CMakeLists.txt # Sets TEST_COMPONENTS
└── main/test_runner.c # unity_run_all_tests()
Integration Testing (pytest-embedded):
# pytest_project.py
import pytest
from pytest_embedded import Dut
@pytest.mark.esp32s2
def test_wifi_connection(dut: Dut):
dut.expect('Connecting to WiFi...')
dut.expect('WiFi connected')
CI/CD Testing Commands:
# Build test project
cd test
idf.py set-target esp32s2
idf.py build
# Run unit tests (hardware optional for mocked tests)
idf.py flash monitor # Runs registered tests
# Run pytest tests
pytest pytest_project.py --target esp32s2
Example GitHub Actions workflow: