rforssen.net / projects / esp32

ESP32 Notes & Projects

MicroPython on ESP32 — homelab integrations and experiments
01

Environment setup

Development is done on the k3s control-plane RPi (raspberrypi, 192.168.100.1) via VS Code Remote SSH. The ESP32 is connected via USB to that same node.

Directory layout

~/esp32/
├── projects/
│   ├── blink/
│   └── wifi-test/
├── lib/              # reusable MicroPython modules
├── firmware/         # .bin firmware files
├── scripts/          # host-side helpers
└── venv/             # esptool + mpremote

Tooling

Python env
venv
Flash tool
esptool 5.2
REPL / deploy
mpremote
Serial port
/dev/ttyUSB0
Group
dialout

tmux session

Added esp32 session to ~/shbin/tmux-init.sh. Activates the venv automatically on attach.

create_session esp32 "cd $HOME/esp32 && source $HOME/esp32/venv/bin/activate"

Deploy script

# scripts/deploy.sh
mpremote connect $PORT cp ~/esp32/projects/$PROJECT/main.py :main.py
mpremote connect $PORT reset
02

Board identification

Chip
ESP32 (plain)
LED type
NeoPixel RGB
LED pin
GPIO 16
WiFi
2.4 GHz only

Firmware

Build
ESP32_GENERIC
Version
v1.24.1
Date
20241129

Flash commands

esptool --chip esp32 --port /dev/ttyUSB0 erase-flash

esptool --chip esp32 --port /dev/ttyUSB0 --baud 460800 \
  write-flash -z 0x1000 ESP32_GENERIC-20241129-v1.24.1.bin
04

Project: wifi-test + Telegram

working wifi https telegram

Connects to WiFi and sends a Telegram notification via the /notify/telegram endpoint on api.rforssen.net. The ESP32 never holds a Telegram token — it calls the internal API instead.

SSID
otraFruta (2.4GHz)
IP assigned
192.168.86.26
Network
192.168.86.x
API endpoint
POST /notify/telegram

Gotchas discovered

The API expects field text, not message. The urequests.post() data parameter must be bytes, not a plain string — encode with .encode("utf-8").

main.py

import network, time, urequests, json

SSID     = "otraFruta"
PASSWORD = "***"
API      = "https://api.rforssen.net/notify/telegram"

def connect_wifi():
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    wlan.connect(SSID, PASSWORD)
    while not wlan.isconnected():
        time.sleep(0.5)
    print("IP:", wlan.ifconfig()[0])

def send_telegram(text):
    payload = json.dumps({"text": text}).encode("utf-8")
    headers = {"Content-Type": "application/json"}
    r = urequests.post(API, data=payload, headers=headers)
    r.close()

connect_wifi()
send_telegram("Hello from ESP32!")

Reusable library modules

  • PY ~/esp32/lib/wifi.py — connect(ssid, password) → wlan
  • PY ~/esp32/lib/telegram.py — send(text) via api.rforssen.net

Usage in any project

import wifi
import telegram

wifi.connect("otraFruta", "your-password")
telegram.send("Hello from ESP32!")
05

WLED installation

working wled ws2812b wifi

WLED is a ready-made firmware for ESP32 that provides a full web UI, app control, and 100+ effects for addressable LED strips (WS2812B/NeoPixel). No coding required — the ESP32 becomes a dedicated LED controller.

WLED version
0.15.0
LED type
WS2812B
LED pin
GPIO 16
IP
192.168.86.26
Web UI
http://192.168.86.26
Network
otraFruta (2.4GHz)

Download firmware

cd ~/esp32/firmware
wget https://github.com/wled/WLED/releases/download/v0.15.0/WLED_0.15.0_ESP32.bin

Flash

WLED firmware is flashed at 0x10000 on top of an existing bootloader. The MicroPython bootloader at 0x1000 is compatible — no erase needed.

esptool --chip esp32 --port /dev/ttyUSB0 --baud 460800 \
  write-flash 0x10000 WLED_0.15.0_ESP32.bin

First boot

On first boot WLED creates a WiFi AP called WLED-AP (password: wled1234). Connect to it, enter your home WiFi credentials, save. The device reboots and joins your network.

LED configuration

In the WLED web UI go to Config → LED Preferences and set the data pin to 16. Set the LED type to WS2812B and configure the number of LEDs in your strip.

OTA updates

Once running, future firmware updates can be done via OTA directly from the WLED web UI — no USB cable needed.