ESP32/MASS_DEPLOY.md

7.5 KiB

Mass ESP32 Deployment Guide

Complete guide for flashing 32+ ESP32 devices with unique static IPs.

Overview

This system allows you to:

  • Flash multiple ESP32/ESP32-S2/ESP32-S3 devices automatically
  • Assign unique static IP addresses to each device (192.168.1.50-192.168.1.81)
  • Configure WiFi credentials during build
  • Reconfigure WiFi after flashing via console

Prerequisites

# Install Python dependencies
pip install pyserial

# Ensure ESP-IDF is installed with all targets
cd ~/Code/esp32/esp-idf
./install.sh esp32,esp32s2,esp32s3

# Activate ESP-IDF environment
. ~/Code/esp32/esp-idf/export.sh

Prepare Your Devices

  1. Connect all ESP32 devices to USB hubs
  2. Verify detection:
    cd ~/Code/esp32/esp32-iperf
    python3 detect_esp32.py
    

Flash All Devices

cd ~/Code/esp32/esp32-iperf

# Dry run to see the plan
python3 flash_all.py \
  --ssid "YourWiFiSSID" \
  --password "YourPassword" \
  --start-ip 192.168.1.50 \
  --gateway 192.168.1.1 \
  --dry-run

# Actually flash (this will take a while!)
python3 flash_all.py \
  --ssid "YourWiFiSSID" \
  --password "YourPassword" \
  --start-ip 192.168.1.50 \
  --gateway 192.168.1.1

# With chip probing (slower but more accurate)
python3 flash_all.py \
  --ssid "YourWiFiSSID" \
  --password "YourPassword" \
  --start-ip 192.168.1.50 \
  --probe

Script Options

  • --ssid: WiFi network name (required)
  • --password: WiFi password (required)
  • --start-ip: Starting IP address (default: 192.168.1.50)
  • --gateway: Gateway IP (default: 192.168.1.1)
  • --probe: Probe each device to detect exact chip type (slower)
  • --dry-run: Show plan without flashing
  • --project-dir: Custom project directory

What the Script Does

For each device:

  1. Detects chip type (ESP32/ESP32-S2/ESP32-S3)
  2. Calculates unique IP address (increments from start IP)
  3. Creates custom sdkconfig.defaults with WiFi and IP settings
  4. Sets the correct target (esp32/esp32s2/esp32s3)
  5. Builds firmware with custom configuration
  6. Flashes the device

Method 2: Manual Configuration Per Device

If you want to flash devices one at a time or need custom settings:

Create sdkconfig.defaults

cd ~/Code/esp32/esp32-iperf
cat > sdkconfig.defaults << EOF
# WiFi Configuration
CONFIG_WIFI_SSID="YourSSID"
CONFIG_WIFI_PASSWORD="YourPassword"
CONFIG_WIFI_MAXIMUM_RETRY=5

# Static IP Configuration
CONFIG_USE_STATIC_IP=y
CONFIG_STATIC_IP_ADDR="192.168.1.50"
CONFIG_STATIC_GATEWAY_ADDR="192.168.1.1"
CONFIG_STATIC_NETMASK_ADDR="255.255.255.0"
EOF

Build and Flash

# Set target (choose one)
idf.py set-target esp32     # for ESP32
idf.py set-target esp32s2   # for ESP32-S2
idf.py set-target esp32s3   # for ESP32-S3

# Build
idf.py build

# Flash to specific device
idf.py -p /dev/ttyUSB0 flash monitor

# For next device, edit sdkconfig.defaults with new IP
# Then clean and rebuild
idf.py fullclean
# ... edit sdkconfig.defaults ...
idf.py build
idf.py -p /dev/ttyUSB1 flash

Method 3: Reconfigure After Flashing

If devices are already flashed but need different WiFi credentials:

Via Console

# Connect to device
idf.py -p /dev/ttyUSB0 monitor

# At the prompt
iperf> wifi -s "NewSSID" -p "NewPassword"

Via Script (Multiple Devices)

Create a script to update all devices:

#!/bin/bash
for port in /dev/ttyUSB{0..31}; do
    echo "Updating $port..."
    # Send commands via screen or minicom
    screen -S esp_config $port 115200 -X stuff "wifi -s \"NewSSID\" -p \"NewPassword\"\n"
done

IP Address Assignment

Based on your 32 detected devices:

Device 1  -> /dev/ttyUSB0  -> 192.168.1.50
Device 2  -> /dev/ttyUSB1  -> 192.168.1.51
Device 3  -> /dev/ttyUSB2  -> 192.168.1.52
...
Device 32 -> /dev/ttyUSB31 -> 192.168.1.81

Testing Your Deployment

Check Device Connectivity

# Ping all devices
for i in {50..81}; do
    ping -c 1 -W 1 192.168.1.$i && echo "192.168.1.$i is UP" || echo "192.168.1.$i is DOWN"
done

Run iperf Tests

# Start all devices as iperf servers
# (via console on each device)
iperf> iperf -s

# From your PC, test each device
for i in {50..81}; do
    echo "Testing 192.168.1.$i"
    iperf -c 192.168.1.$i -t 5
done

Batch iperf Test Script

#!/usr/bin/env python3
import subprocess
import sys

start_ip = "192.168.1.50"
end_ip = "192.168.1.81"

base = start_ip.rsplit('.', 1)[0]
start = int(start_ip.rsplit('.', 1)[1])
end = int(end_ip.rsplit('.', 1)[1])

results = []
for i in range(start, end + 1):
    ip = f"{base}.{i}"
    print(f"Testing {ip}...", end=' ', flush=True)
    
    result = subprocess.run(
        ['iperf', '-c', ip, '-t', '5', '-f', 'm'],
        capture_output=True,
        text=True,
        timeout=10
    )
    
    if result.returncode == 0:
        # Parse bandwidth from output
        for line in result.stdout.split('\n'):
            if 'Mbits/sec' in line:
                bandwidth = line.split()[-2]
                print(f"✓ {bandwidth} Mbits/sec")
                results.append((ip, bandwidth))
                break
    else:
        print("✗ FAILED")

print(f"\nTested {len(results)}/{end-start+1} devices successfully")

Troubleshooting

Device Not Detected

# Check USB connection
lsusb

# Check permissions
sudo usermod -a -G dialout $USER
# Log out and back in

# Check if port exists
ls -la /dev/ttyUSB*

Flash Failed

# Try holding BOOT button during flash
idf.py -p /dev/ttyUSB0 flash

# Lower baud rate
idf.py -p /dev/ttyUSB0 -b 115200 flash

# Erase flash first
idf.py -p /dev/ttyUSB0 erase-flash
idf.py -p /dev/ttyUSB0 flash

WiFi Not Connecting

# Monitor the device
idf.py -p /dev/ttyUSB0 monitor

# Check logs for WiFi errors
# Try reconfiguring via console:
iperf> wifi -s "YourSSID" -p "YourPassword"

IP Address Conflict

# Check what's using the IP
ping 192.168.1.50
arp -a | grep 192.168.1.50

# Reflash with different IP range
python3 flash_all.py \
  --ssid "YourSSID" \
  --password "YourPassword" \
  --start-ip 192.168.1.100

Console Commands Reference

WiFi Configuration

wifi -s <ssid> -p <password>

iperf Commands

# TCP server
iperf -s

# TCP client
iperf -c <ip>

# UDP server
iperf -s -u

# UDP client
iperf -c <ip> -u

# Custom port
iperf -s -p 5002

# Custom duration
iperf -c <ip> -t 30

# Stop running test
iperf -a

Advanced: Parallel Flashing

To flash multiple devices simultaneously:

#!/bin/bash
# flash_parallel.sh

# Flash 4 devices at once
idf.py -p /dev/ttyUSB0 flash &
idf.py -p /dev/ttyUSB1 flash &
idf.py -p /dev/ttyUSB2 flash &
idf.py -p /dev/ttyUSB3 flash &

wait
echo "Batch complete"

Note: Each device still needs its own build with unique IP.

Production Deployment Workflow

  1. Prepare: Connect all devices, verify detection
  2. Flash: Run mass flash script with dry-run first
  3. Verify: Ping all IPs to confirm connectivity
  4. Test: Run iperf from PC to each device
  5. Deploy: Mount devices in test locations
  6. Monitor: Use iperf console to run tests

File Structure

esp32-iperf/
├── main/
│   ├── main.c              # Main app with WiFi
│   ├── iperf.c             # iperf implementation
│   ├── iperf.h             # iperf header
│   └── Kconfig.projbuild   # Configuration options
├── CMakeLists.txt
├── README.md
├── flash_all.py            # Mass flash script
├── detect_esp32.py         # Device detection
└── sdkconfig.defaults      # Auto-generated config