r/esp32projects

▲ 11 r/esp32projects+1 crossposts

ESP32 Sonos controller update: full library browsing, favourites now playable

Touchscreen Sonos remote running on an ESP32-P4 board.

The Sources screen used to show one entry, "Sonos Playlists". Now it lists what your system actually has:

  • Music Library (artists, albums, genres, composers, tracks)
  • Sonos Favourites
  • Internet Radio
  • NAS shares
  • Current queue
  • Line-in, if the speaker has one

Favourites is the useful one. Anything in your Sonos favourites now plays from the panel, whatever service it came from. Spotify, YouTube Music, radio stations, all of it.

Also recently:

  • 3 player themes, 4 clock faces
  • 7" screen support
  • Accented characters render properly now
  • Lots of stability fixes

https://github.com/OpenSurface/SonosESP

https://opensurface.github.io/SonosESP/

u/Professional_Ad_6098 — 11 hours ago
▲ 2 r/esp32projects+2 crossposts

Necesito ideas para proyectos con un esp32cam, escucho ideas

Quiero hacer un proyecto como componente principal un esp 32cam, que me recomiendan ? El proyecto necesita también un apartado de trabajo práctico dónde usemos componentes electrónicos, para que el profe vea que estamos haciendo algo y no solo programando el esp32.

u/alexsanabria — 18 hours ago

ESP32 CYD desk companion/timer/weather display

I made this wall-e style desk companion/timer/weather display using an esp32 cyd i bought from amazon. the code is fairly simple. one screen is the wall-e, the next is a timer, and the third is weather. the wall-e and timer are simply downloaded onto the device while the weather display is connecting to my wifi and pulling data from open weather.

in addition, there is also code written to connect a PIR HC-SR501 sensor. when it senses movement the display turns on after 10 minutes of inactivity on the screen the wall-e goes into a sleep animation and after 15 minutes the display turns off and will turn back on when it senses movement or when you touch it.

i know this is a fairly simple project but it is my first one and i thought i would share! i am currently 3-d printing a case for it. if you have any questions let me know!

u/Green-Ad-2668 — 17 hours ago
▲ 16 r/esp32projects+1 crossposts

IoT industry-ready: Should I move from Arduino to ESP-IDF?

Hi everyone,

I’m preparing myself to become industry-ready for IoT/Embedded Systems and would appreciate some advice from people working in the industry.

So far, I’ve worked with ESP32 using the Arduino framework and have built projects involving sensors, MQTT, Wi-Fi, etc.

Now I’m wondering whether I should move to ESP-IDF and use PlatformIO as my development environment.

My main questions are:

- Is learning ESP-IDF important for becoming industry-ready?

- Should I stop using Arduino framework and move completely to ESP-IDF?

- Is PlatformIO worth learning, or should I stick with Espressif’s official tools?

- For someone targeting IoT/Embedded Firmware roles, what would you recommend learning next?

- Should I focus more on FreeRTOS, ESP-IDF, C, debugging, communication protocols, and Linux rather than spending too much time on frameworks?

I’m not trying to just build hobby projects—I want to develop skills that actually translate to professional IoT/embedded development.

Would really appreciate advice from experienced engineers and people who have gone through a similar transition. Thanks!

reddit.com
▲ 25 r/esp32projects+3 crossposts

The NM-CYD-C5 external version board is coming - thanks for your feedback

Since launching the NM-CYD-C5 (the ESP32-C5 based CYD variant with dual-band WiFi 6), the single most common piece of feedback has been:

"Could you make a 1u variant that I could connect an antenna to?"

"Does it have external antenna connector"

"Will an external antenna be supported this time, or is a DIY solution again required to attach an external antenna?"

Fair point. 5GHz attenuates much faster than 2.4GHz, and a small PCB trace antenna surrounded by a display and ground planes has its limits.

So: the NM-CYD-C5-Colorful-Ant is coming.

• IPEX-1 connector + bundled dual-band 2.4G/5G antenna • External antenna only — no onboard PCB antenna on this version • Same ESP32-C5 (dual-band WiFi 6, BLE 5.3, Zigbee/Thread), same 16MB Flash + 8MB PSRAM, same CYD-compatible footprint • Still works with Bruce / Marauder / ESPHome, etc as before

The default External Antenna Parameters

  • Frequency range: 2400-2500MHz / 5000-5800MHz
  • VSWR: 2400-2500 ≤ 2.5, 5000-5800 ≤ 2.5
  • Efficiency %: 2400-2500: 83.3 AVG; 5000-5800: 73.8 AVG
  • Peak Gain (dBi): 2400-2500: 3.2 AVG; 5000-5800: 3.7 AVG
  • Radiation Properties: Omni-directional
  • Polarization: Linear

The 3D printed shells (see from the picture) will be released on GitHub repository soon.

https://github.com/RockBase-iot/NM-CYD-C5

u/NMTech-Official — 1 day ago
▲ 6 r/esp32projects+3 crossposts

Is my Schematic correct? ESP32-C3-WROOM-02-N4 with Batterie

Hey, i am basically a complete beginner and wanted to design a board with a batterie powered Bluetooth compatible chip and a USB-C port used for charging and uploading code. So I tried my best, read some datasheets but mostly composed this Schematic with the help of AI. Will it somehow work, or is it just complete bs? Any Information is useful to me (:

Schematic image (titles in german)

BOM:

No. Quantity Comment Designator Footprint Value Manufacturer Part Manufacturer Supplier Part Supplier
1 5 10uF C1,C2,C4,C5,C6 C0805 10uF CL21A106KAYNNNE SAMSUNG(三星) C15850 LCSC
2 3 100nF C3,C7,C8 C0603 100nF CC0603KRX7R9BB104 YAGEO(国巨) C14663 LCSC
3 1 XY-B2B-PH-K-S CN1 CONN-TH_B2B-PH-K-S XY-B2B-PH-K-S XYECONN(辛译) C51940125 LCSC
4 1 SS14 D1 SMA_L4.2-W2.6-LS5.0-RD_1 SS14 MDD(辰达半导体) C2480 LCSC
5 1 FS8205A Q1 SOT-23-6_L2.9-W1.6-P0.95-LS2.8-BR FS8205A FUXINSEMI(富芯森美) C908265 LCSC
6 1 AO3401A Q2 SOT-23_L2.9-W1.3-P1.90-LS2.4-BR AO3401A AOS C15127 LCSC
7 2 5.1kΩ R1,R3 R0603 5.1kΩ 0603WAF5101T5E UNI-ROYAL(厚声) C23186 LCSC
8 1 2kΩ R2 R1206 2kΩ 1206W4F2001T5E UNI-ROYAL(厚声) C17944 LCSC
9 2 27Ω R4,R6 R0603 27Ω 0603WAF270JT5E UNI-ROYAL(厚声) C25190 LCSC
10 4 10kΩ R5,R7,R10,R11 R0805 10kΩ 0805W8F1002T5E UNI-ROYAL(厚声) C17414 LCSC
11 1 1kΩ R8 R0603 1kΩ 0603WAF1001T5E UNI-ROYAL(厚声) C21190 LCSC
12 1 100Ω R9 R0805 100Ω 0805W8F1000T5E UNI-ROYAL(厚声) C17408 LCSC
13 1 TS-1187A-B-A-B SW1 SW-SMD_4P-L5.1-W5.1-P3.70-LS6.5-TL_H1.5 TS-1187A-B-A-B XKB Connection(中国星坤) C318884 LCSC
14 1 TP4057 U1 SOT-23-6_L2.9-W1.6-P0.95-LS2.8-BL TP4057-42-SOT26-R TOPPOWER(南京拓微) C12044 LCSC
15 1 2.4GHz U2 BULETM-SMD_ESPRESSIF_ESP32-C3-WROOM-02-N4-4MB 2.4GHz ESP32-C3-WROOM-02-N4 ESPRESSIF(乐鑫) C2934560 LCSC
16 1 WSTDW01 U3 SOT-23-6_L2.9-W1.6-P0.95-LS2.8-BR WSTDW01 WINSOK(微硕) C86873 LCSC
17 1 AP2112K-3.3TRG1 U4 SOT-23-5_L2.9-W1.6-P0.95-LS2.8-BR AP2112K-3.3TRG1 TECH PUBLIC(台舟) C23380830 LCSC
18 1 TYPE-C-31-M-12 USBC1 USB-C_SMD-TYPE-C-31-M-12_1 TYPE-C-31-M-12 韩国韩荣 C165948 LCSC
reddit.com
u/Mobiluel — 1 day ago
▲ 50 r/esp32projects+2 crossposts

PWM Fan controller with ESP32

I made a PWM fan hub/controller for my passive cooling gpu. Support DS18B20, NTC, manual as temperature source, Curve-based controller, scheduling,... Temporarily closed-source for development, open-source soon.

For PWM, I'm using an NPN open-collector driver, combined with a tachometer level-shifter/divider which I found from here

u/Traditional_Bell8153 — 2 days ago

Ive been having a hard time trying to code an oled display but its always corrupted

Can anyone help me fix this problem, im coding in arduino ide and ive been using adafruit gfx library but the display is corrupted, I tried using U8g2 to swtich to sh1106 address but it doesnt turn what is the problem here ive been trying to solve this for 3 days

u/Beginning-Big6028 — 1 day ago

IOT project thesis

IoT Gas, Smoke & Flame Detection System with Email & SIM800L Alerts

I developed an IoT-based safety monitoring and automatic ventilation system using a microcontroller, MQ-2, MQ-5, KY-026 flame sensor, exhaust fan, email notifications, and SIM800L GSM module.

The system continuously monitors for smoke, combustible gases, LPG/natural gas, and flame. When a dangerous condition is detected, the microcontroller automatically activates the exhaust fan and triggers an alarm. It can also send notifications through email and SMS using the SIM800L, allowing the user to receive alerts even when they are away from the system.

Main Features:

  • 🔥 KY-026 flame detection
  • 💨 MQ-2 smoke/gas detection
  • 🛢️ MQ-5 LPG/natural gas detection
  • 🌬️ Automatic exhaust fan activation
  • 📧 Email alerts
  • 📱 SMS alerts through SIM800L
  • 🔊 Buzzer/alarm notification
  • 🤖 Microcontroller-based automatic control

I'm offering the complete source code and project logic for students, hobbyists, and developers who want to build or modify a similar IoT safety system.

DM me if you're interested in the code or need more details about the project.

reddit.com
▲ 3 r/esp32projects+1 crossposts

Using mobile charger to power esp32 for weeks for my plant watering?

Hello everyone, I went through all the posts and understood that chargers are fine as they output 5v with esp32 having voltage regulator to accept 3.3v. However, I have a question. I am going away for 4-5 weeks, and I want to remotely operate esp32 to turn on water pump(through another constantly on 12v adapter plugged into a wall socket). Is it okay to keep these 2 unattended for 5-ish weeks? Anything I need to take care of for safety measures?

Clarification: I want to plug my phone charger with micro usb cable to esp32, and keep the wall socket on for weeks.

reddit.com
u/dssagar93 — 2 days ago
▲ 181 r/esp32projects+1 crossposts

I made the first M5Stack CardPuter emulator , runs in the browser, no install

I've been working on a browser-based simulator "Velxio", and I just got the CardPuter ADV working in it. You write your Arduino code in the editor and the whole device runs live , display, inputs, serial console

It uses real ESP32-S3 emulation, so your code runs the way it would on the actual hardware. The on-board display is rendered in real time.

Here's a working demo you can try right now on the online version:
https://velxio.dev/example/cardputer-adv-m5-display

Honest note on how it was built: I used AI to speed up parts of the development, but nothing shipped without being tested on real hardware and cross-checked against my own experience as a computer engineer. Emulation is only trustworthy when you verify it against the actual device .I did that on every step

u/LeadingFun1849 — 3 days ago
▲ 62 r/esp32projects+3 crossposts

ESP32 based audio system

Hey everyone,

I want to share a synchronized multi-room wireless audio system I built entirely on ESP32s. The main motivations were to get sub-30ms audio distribution without the cost of running a Raspberry Pi/Snapcast at every endpoint, and to keep the setup incredibly simple. It’s designed to be plug-and-play: the system can run completely off-grid by generating its own Wi-Fi network, or it can seamlessly integrate into your existing home router. Additionally, I built in the flexibility for the slave nodes to switch roles and act as independent, standalone Bluetooth receivers if you just want to connect to a single speaker.

Repo (code, schematics, docs): https://github.com/chagoguila/SonicStream

I ran into several architectural bottlenecks while building this, so I wanted to share how the system handles them under the hood:

1. Solving BT/Wi-Fi Radio Contention If you've tried running an A2DP sink and a Wi-Fi server on a single ESP32, you know antenna timesharing causes massive packet jitter. To fix this, the system splits the ingress gateway into two microcontrollers:

  • BT Ingress Node (ESP32 WROOM): Acts as a dedicated A2DP sink. I tuned the I2S DMA buffers down to 4x512 bytes, which cut the hardware transport delay to about 12ms. It sends raw PCM over a physical I2S cable (BCK, WS, DATA) to the Master.
  • Master Controller (ESP32 WROVER): Receives the PCM stream via I2S, runs the DSP pipeline on Core 1, encodes it, and blasts it out over Wi-Fi.

2. Network Transport & Fault Tolerance Standard streaming protocols had too much overhead for the latency I wanted. The system supports two custom modes:

  • UDP Multicast (239.0.0.1): This is the ultra-low latency mode. To survive 2.4GHz RF burst interference, the Master sends time-separated twin-packet redundancy (broadcasting a duplicate packet with a 1ms micro-delay).
  • TCP Mode: For congested Wi-Fi environments. It uses non-blocking socket polling with slow-client pruning. If one receiver drops its connection or falls behind, its socket is dropped to prevent backpressure on the healthy nodes.

On the receiver side (WROOM or C3 slaves), there's a 5-second TCP inactivity watchdog to handle silent network drops (like router reboots) and a 500ms idle auto-reset on the jitter buffer to prevent decoder stalls after you pause the music. As mentioned, the stereo slave nodes can also be toggled to drop off the multi-room network and function as standard, independent Bluetooth A2DP receivers.

3. DSP Pipeline & Encoding Since the Master is a WROVER, I threw the DSP workload onto Core 1 prior to SBC encoding, meaning the slave nodes incur zero extra CPU overhead.

  • Encoding: SBC at Bitpool 53 (~328 kbps stereo).
  • EQ: 5-band parametric EQ using cascaded Direct Form I Biquad IIR filters (60Hz, 230Hz, 910Hz, 3.6kHz, 14kHz) with real-time gain adjustment.
  • Anti-clipping: Instead of fixed linear attenuation, I wrote a soft-knee peak limiter. Signals below 85% peak amplitude pass through untouched. Anything above triggers a 2:1 compression ratio capped at 95% to eliminate intersample clipping.

4. Web UI & Wi-Fi Management The Master runs an async web server with a dark-mode dashboard. You can configure AP/STA Wi-Fi modes (switching between isolated network or home router), toggle UDP/TCP, adjust system-wide playout delay, set individual speaker delays, assign L/R/Stereo roles to slaves, and tweak the 5-band EQ live. Slaves send UDP announcement packets so the dashboard shows real-time online/offline status.

If you are interested in the code, I'd love to hear your thoughts on the DSP pipeline or the I2S DMA config. I'm currently looking into adding Opus encoding and AAC passthrough for the next update.

u/Maleficent_Tone_4047 — 3 days ago
▲ 62 r/esp32projects+5 crossposts

I built an AI-powered smart irrigation system using an ESP32 + ML

I built an AI-powered smart irrigation system using an ESP32 + ML

I've been working on this project for a while, and I finally finished the main AI/ML pipeline.

The system uses an ESP32, a capacitive soil-moisture sensor, and a DHT11 to collect environmental data. I then built a machine-learning model that uses these readings to predict whether irrigation is required.

The interesting part for me was getting the different pieces to actually work together.

The pipeline is basically:

ESP32 sensors → dashboard → Flask API → ML model → irrigation prediction

In the video, I walk through the whole project, including:

  • Collecting soil moisture, temperature, and humidity data
  • Building the web dashboard
  • Preparing the data for ML
  • Training the model
  • Evaluating it with a confusion matrix
  • Looking at feature importance
  • Deploying the model through a Flask server
  • Connecting the dashboard to the ML model through an API
  • Testing the final live prediction

One thing I found particularly interesting was seeing how the model's predictions changed once the inference server was running and the dashboard could communicate with the model.

This started as a simple ESP32 soil-moisture monitoring project, but I gradually expanded it into a complete IoT + AI system.

I'm still planning improvements, especially collecting more real-world data and adding additional environmental inputs such as light intensity.

I'd really appreciate feedback on the project, especially on the ML approach, system architecture, and what I could improve next.

🎥 Full project walkthrough attached.

Github Repository:

https://github.com/aqib-ai-ml/ai-powered-smart-irrigation

u/aqib_builds — 3 days ago

Built a GPS Tracker Prototype 📍

​

Made this GPS tracker using an ESP32 + GPS module, with a 4-digit display, buzzer, LED indicator and relay. It’s currently a prototype on perfboard. Looking for feedback on the design and ideas to improve it before making a proper PCB.

u/arstukhan — 3 days ago
▲ 22 r/esp32projects+3 crossposts

Show your Plex/Emby/Jellyfin "now playing" card on a cheap ESP32 touch panel (ESPHome + a tiny screenshot sidecar)

There's a slick project called **[Marquee](https://github.com/Jamisonfitz/marquee)\*\* (by Jamisonfitz) that turns a Google Nest Hub into a beautiful "now playing" card for Plex/Emby/Jellyfin — poster, plot, ratings, progress bar, clock.

For those who don't own a Nest Hub, or are moving away from them, or just love ESP projects, I wanted to expand the project to support ESP32 displays. I bought the first, most popular disoplay on Amazon compatible with ESPhome, a **7" Elecrow CrowPanel** (an ESP32-S3 touch screen). So I made it show the *exact same card* using **ESPHome**. It's on my wall now and I wrote it all up so others can build one.

**Repo:** https://github.com/TRusselo/marquee-esp32

### How it works (the whole trick)

The ESP32 is intentionally dumb. All the layout happens on my server:

```

Plex/Emby/Jellyfin → Marquee (renders a web card)

→ marquee-shot (screenshots the card to a JPEG)

→ ESP32 panel downloads the JPEG and shows it full-screen

```

`marquee-shot` is a tiny container that opens Marquee's real card in headless Chromium and serves it at `/card.jpg`. The panel just downloads that image — so it looks **pixel-identical** to the Nest Hub version, and the ESP config stays dead simple (no on-device layout code). It's a decoupled add-on: it never modifies Marquee, so it works against the plain upstream image too.

### What you need

- Elecrow CrowPanel "Basic" 7" (ESP32-S3-WROOM-1-N4R8, 800×480, GT911 touch). Other panels work — just swap the display pins.

- Marquee running on your LAN (Docker; one-click template on Unraid).

- The `marquee-shot` sidecar: `ghcr.io/trusselo/marquee-shot`.

- ESPHome.

### Quick start

Run the sidecar:

docker run -d --name marquee-shot --network host --restart unless-stopped \

-e MARQUEE_URL=http://127.0.0.1:8084 \

-e PANEL_WIDTH=800 -e PANEL_HEIGHT=480 -e SERVE_PORT=8088 \

ghcr.io/trusselo/marquee-shot:latest

Check `http://your-server:8088/card.jpg\`, then flash `marquee-crowpanel-shot.yaml` in ESPHome (set the sidecar IP up top; first flash over USB, then OTA). Play something → card shows up in a few seconds.

It also taps-to-wake + brightens on a new episode, goes full-bright when paused, dims during playback, and turns the backlight fully off when nothing's playing.

### The RGB-panel gotchas I hit (the actually-useful part)

- **Console on UART0** — ESPHome 2026.7 defaults logs to USB-Serial-JTAG, but those pins are this board's touch i2c bus, so the default kills your logs. `logger: hardware_uart: UART0`. (Cost me an evening of "why no logs?")

- **PSRAM mandatory** — 800×480 framebuffer won't fit in internal RAM. `psram: mode: octal`, keep the `CONFIG_SPIRAM_*` flags or a fresh flash hangs at `entry`.

- **LVGL `buffer_size: 5%`** — the 25% default eats the DMA RAM Wi-Fi needs on an RGB panel, so **Wi-Fi silently won't associate**. Looked like a Wi-Fi bug; was really out-of-RAM. (Screenshot mode skips LVGL entirely.)

- **Pin the ESP-IDF version** if Wi-Fi drops with "Association Expired" — recent IDF had a Wi-Fi regression.

- **GT911 touch: polled, no interrupt pin** (reset is behind a GPIO expander; wiring the IRQ crashed boot). Address `0x5D`.

- **Elecrow's docs for this board are wrong in places.** The reference that actually worked: https://www.espboards.dev/blog/esphome-configuring-elecrow-7-inch-display/

All of this is already handled in the repo's YAML — sharing it because it applies to any RGB ESP32-S3 panel.

Big credit to **[Jamisonfitz/marquee](https://github.com/Jamisonfitz/marquee)\*\* for the actual card — go star it. My repo just adds the ESP32 path on top.

Happy to help anyone adapting it to a different panel. Photos welcome if you build one.

u/Dur-P — 4 days ago
▲ 728 r/esp32projects+1 crossposts

I serve my website with a swarm of six ESP32-S3s on a shelf - elected load balancer, vMAC failover, OTA with rollback

I've loved microcontrollers since uni. For me, studying ASM clicked the physics and maths fundamentals together:

  1. Electrical circuits → transistors → logic gates → ICs → SoCs on one end
  2. Boolean logic → min canonical forms → Zhegalkin algebra → combinational circuits → computer arithmetic → finite state machines → Markov chains on the other.

There is beauty in it, and the feeling that my field of study starts making sense is priceless.

Decades later, my career has firmly gone into distributed systems. I've had the chance to witness the emergence of CUDA, as well as the rise of Cloud Computing: from virtualization, to containerization, to "serverless" at scale.

Nowadays, hosting your own website on hardware that you own and manage seems almost laughable.

Having some time on my hands this summer, I have embarked on a journey to disprove such a ridiculous notion!

First, I wanted to host a website from my own closet, to make a point (mainly to myself), and going with a Raspberry Pi would have probably been the prudent way of doing it.

But what's the fun in that?

The project below is the result of figuring out the fun:

  1. What if... the website is hosted on a 5x3cm microcontroller board weighing under 20 grams?
  2. It wouldn't scale, though? Now we're talking, let's make it four microcontrollers then!
  3. How do we distribute the work then? Let's make one of them tell the others what to do!
  4. And how would I know what's going on in my own system? Let's get a display and render things on it!
  5. What about knowing that everything's okay quickly? Fine, let's add a bright LED rail to color-code the state!
  6. Tiny screen is a tiny window for a lot of data, though? Right, let's buy a Bigger Screen and show All The Data there!
  7. But the screens don't have Ethernet! How would they even learn about anything in the fleet? Indeed, so we'll make the fleet talk to each other over radio instead!
  8. How would I deploy any changes for this system? Let's do it over the air and make it safe, too!
  9. Where would all this hardware reside? On a shelf, of course, in tiny plastic cases!
  10. The screens are useless in a closet though. Also, what about the power supply, and networking, in this heat? Fine, let's build a rack for it all!

As a result, https://kyrylonovotarskyi.com is served from six ESP32-S3 microcontrollers on a shelf in a London flat.

No CDN in front, no Cloud behind, no hosting provider, no Raspberry Pis, and most definitely no hardware load balancers anywhere in the building. The whole rack, screens and fans included, draws about 22 watts. The primary fleet serves the website and terminates TLS on 240 MHz chips, load-balances across itself with a bespoke L4 TCP splicer, monitors itself, and heals itself. It survives pulling any individual plug in it, including the leader's, recovering in under four seconds.

Whether the fleet will be able to survive visitors this thread - only time will tell. I must ask the readers to be forgiving and gentle with it - there is a very real ceiling on how much TLS termination an ESP32 is able to physically do. Under nominal pressure, a fresh HTTPS connection costs ~650 ms for a P-256 handshake, with a ~325 ms TTFB. Spread across the existing fleet, ~2.9-3.0 new visitors per second is where the first connection drops would start. Once your browser is in, however, requests over the warm connections return within ~40-60 ms, and the fleet does okay at ~40-50 RPS. Beyond ~100 RPS the network throughput of a single splicer blade starts becoming a limiting factor.

Under severe backpressure, the website shouldn't cascade and fall over: it will serve at its ceiling and gradually shed the excess. If the site is slow when you try it, chances are it's not because the machines are struggling, but rather because you're sitting in a queue behind other visitors.

Here is what it took to get there.

ORIGIN LORE ✍️

A good story must have its own lore! Since I'm Ukrainian, the fleet is named after Ivan Bohun, a renowned Cossack colonel, but also a folklore hero. As the story goes, he broke his sabre rather than swear the oath of allegiance to the Russian monarch at Pereiaslav. He's also a Kharakternyk (Ukrainian: Характерник) - a shamanistic warrior mage, a shapeshifter with superhuman abilities, a brilliant tactician, and an avid warfare intelligence practitioner. In other words, the right patron for a website where the entire design is a refusal to be hosted. The leader of the fleet is the Otaman and the mask is the office he holds.

KEY RULE OF THUMB 👍

There was only one hard constraint in this project: the serving path is microcontrollers only. No single-board computer, no mini PC, nothing with a Linux kernel anywhere near a request. This is what made the whole thing interesting to me. Arguably, using ESP32-S3 microcontrollers to serve HTTPS traffic en-masse is not the sharpest idea. However! It is surely doable, because the tiny cute ESP32-S3s can do a lot! In raw integer work, one is roughly a match for a mid-90s desktop CPU. And if people have famously run Doom on these chips, surely we'd be able to serve a page or two as well! And we'll most definitely do it, because we can and for the sake of it!

The serving blades ended up being, rather accidentally, four LILYGO T-ETH-Lite boards, costing about £12 (~$16) each: an ESP32-S3 with a W5500 wired-Ethernet chip. Everything else in the rack exists to power them, connect them, or tell me the truth about them.

SHAPESHIFTING PROBLEM 🦊

The interesting problem in a fleet like this is not necessarily about serving itself, but rather about figuring out who answers.

Four blades share one public identity: a vMAC address, which I've locally administered, and one LAN IPv4 address that the router forwards port 80 and 443 to. Whoever in the serving fleet wins the election writes that MAC into its W5500 and announces it with a gratuitous ARP. Failover is fast precisely because nothing upstream learns anything: the router's ARP entry never changes, only the local switch relearns one port. The W5500 makes the trick possible by having no factory MAC at all. Instead, the host must program one, which, ironically, turned a nuisance into a key design feature.

The election itself runs over the ESP-NOW encrypted radio protocol and off the wire. This means a cable or a switch failure cannot split the brain that decides who owns the cable. The leader election mechanics are deliberately simple: the lowest-numbered blade that is alive on the radio, healthy on the wire, and is actually able to serve - leads. Determinism often beats cleverness hands-down, and this case is no exception.

THE LEADER DOES NOT SERVE 🍀

Initially, the elected blade served every request while three blades idled. However, having active hardware sitting there idling just for the sake of failover didn't feel right. To make use of it all, the fleet leader now acts as a layer-4 TCP splicer: it accepts your connection on 443 and relays raw bytes to whichever blade has the fewest connections in flight, never terminating TLS or parsing HTTP. The encrypted session runs from your browser straight past the balancer to a downstream serving blade which answers on a port that is never forwarded.

The balancer is an elected role that moves between blades. Every blade carries both programs, and which one it runs is decided by the election. The splicer rebuilds its set every second from the radio gossip, taking whoever is alive, serving, and holding an address. Kill the leader, and the next blade takes the mask and balances to what remains. Kill all but one and the survivor splices to its own server over loopback: the ladder ends at the original single-blade site.

Misbehaving backends go on a bench: accept a connection and return nothing three times, and you sit out 15s, doubling up to 240s. The blade is forgiven completely if a single byte is returned. Hard lesson learned while implementing: the bench should only decide who gets the next visitor, never whether there is one to receive, otherwise a fully benched fleet will turn visitors away forever. Now, in the case where every downstream backend becomes suspect, one is going to be tried anyway.

BLADES THAT PROVE THEIR OWN HEALTH 🚑

The nastiest bug this fleet ever had was a blade whose TCP stack wedged while everything else stayed alive. It gossiped on the radio, held its link, reported 'serving', and ate real traffic for hours - because the 'serving' flag was set at boot and never re-examined. The flag got eventually replaced by two mechanics.

  1. Every blade now opens a TCP connection to its own public port every 7s. On two consecutive failures, the blade reports itself out, leaves the election, and the balancer benches it within about ~2s. Six failures and the blade crashes itself on purpose, followed by a clean reboot attempt. A forced deliberate crash felt like the sensible path allowing the blade to write a recoverable coredump naming the exact task its server was stuck in to troubleshoot.
  2. Separately, the balancer judges backends only by what comes back from them, independently of their self-reported state.

Fixing this bug was the toughest firmware bit of this project. The root cause, in the end, was quite typical for a person who doesn't really know C well: a 'break' statement that was intended for an 'if' bound to the enclosing 'for' loop instead - which is exactly what 'break' does in C, just not what I meant. The relay task returned. I have subsequently also learned that FreeRTOS treats a relay task returning as fatal :)

THE METAL 🤘

The whole project is best described as one massive cascade of failures. I never soldered anything in my entire life and didn't intend to learn. However, when the LILYGO blades arrived, I was eventually confronted with reality: how are we going to power this thing?

A LILYGO T-ETH-Lite board does have an Ethernet port. And I have assumed that, technically, Ethernet should be able to draw some current to power the tiny thing, right? Well, yes, in theory, but no - not this port and not on this board it can't! Throwing away six perfectly good microcontrollers felt like a waste, so let's order a pack of USB-C breakout ports! So how do we connect the two? With some wires, right? Absolutely! But wait, where are the board pins? Ah, a separate plastic bag...well, at least they're there!

The sunk cost was high, so I figured that it's about time to learn how to solder things!

In the end, almost everything got soldered by hand, 292 total joints across the fleet. The soldering and the wiring quickly turned my work desk into a wired mess. To compress space, each blade now lives in a Kurin (Ukrainian: Курінь), a 3D-printed ventilated barracks it slides into like a drawer, RJ45 nose out.

To reduce entropy further, the four Kurins rack into a 10-inch, 8U desktop cabinet behind a laser-cut smoked-acrylic face: both screens glow through the smoke, six status pixels glow beneath them.

Finally, since summer in London is extra hot this year, three fans got plugged in to pull one vertical draw of air through the whole thing: intake low, exhaust high.

Networking is an eight-port switch that uplinks to the home router, which forwards exactly two ports to the mask's address and nothing to anything else. The admin plane, the OTA door, and the backend port exist only on the LAN.

Power supply comes from a single 200W GaN charger feeding six USB-C leads up an internal spine. The rack itself draws a ~1/10th of what's available, taking up two wall plugs: one for the charger, the other for the switch.

GLASS MENAGERIE 🥂

The rack is very much physical, so the observability stack is too.

A six-pixel LED rail glows through the face's lower band, one pixel per member, driven through a separately built level shifter circuit. The reason I needed one is that ESP32's 3.3V data line is out of spec for LED strip expecting 5V. The color-coding of the LED rail is status-based: lime-green for fleet leader, white for blades serving, amber solid for a benched blade, blinking amber for blades booting or taking a release, red for lost. The scribe screen's pixel burns deepest blue and the bard's deepest purple.

The 2.8" screen is the pysar, the scribe: the live roster, per-blade served counts, signal bars, fleet availability. The 4.3" touch panel is the kobzar, the bard: a mission control blade with a chronicle that explains every reboot by cause (the chip latches why it died in a register that survives reset), a ledger page counting every HTTP 200 and every refusal per blade, a radio page showing the last 45 seconds of gossip with missed-heartbeat markers, and a fourth page holding the website itself, baked to RGB565 into a 12 MB flash partition, scrollable under a finger. The website rendering page serves no particular purpose, built to learn a bit about LVGL.

None of the observer blades poll the fleet. The screens only witness via listening to the same encrypted radio, hearing the same 1 Hz heartbeats as everyone else.

UPDATES THAT CANNOT BRICK THE FLEET ❤️

Early on, bad config updates bricked the fleet's update path itself on multiple occasions, making the nodes recoverable only by hand via USB-C.

To make updates less risky, deployments now run on followers first, leader last, and every node holds a new image on trial: it must survive 90 seconds of continuous serving within a 5min deadline, otherwise the bootloader rolls back to the previous slot.

Hard lesson re-learned: a release must never brick its own delivery path.

WHO BUILT IT 👀

Claude did most of the typing on this project. This post is mine, however.

To my surprise, it proved much less capable at this kind of software than I expected, and it performed extremely poorly at designing anything for the physical world. Model tier mattered more than I would have guessed, too: Fable 5 could mostly keep up with the engineering, while dropping down to Opus regularly cost three steps back for every step forward.

Still, it types much faster than I do, so we made it work. The division of labour we've settled on: I decide what is true and what ships. Every measurement came off my bench, every disaster above happened to my actual hardware, and the solder burns are mine.

The whole build is open source and is available in a GitHub repo here It contains the firmware for all three images, the OpenSCADs, various tooling, and a comprehensive build guide that starts at the first solder joint and ends with a fleet holding an election.

The living proof is the website itself: https://kyrylonovotarskyi.com

The roster at the top of the page is an actual live status of the setup sitting on my desk.

u/disco-jack — 5 days ago

I connected an ESP32 to my online store so it notifies me in real time every time I make a sale

So I run a small online store (3D-printed cat toys) and I got tired of constantly checking my phone to see if anything sold. So I built a little gadget to solve it.

Basically, I hooked up an ESP32 (a tiny board with built-in WiFi) to my store. Here’s how it works at a high level:

Whenever someone buys something, the store sends out a little signal over the internet. My ESP32 is listening for that signal, and the moment it arrives, the device reacts — it lets me know a sale just happened. No app, no refreshing, no staring at my phone. The hardware just tells me.

Right now it’s pretty basic, but I’m adding some upgrades:

A small screen to display the sale info at a glance
A speaker that plays a sound with every sale
A proper 3D-printed case so it doesn’t look like a pile of wires

The fun part is I print my own products AND built the thing that tells me when they sell. Full loop, all done by me.

Happy to answer questions if anyone’s curious about the setup!

reddit.com
u/AgreeableMood577 — 4 days ago

Every ESP32 has a unique mac address burned in at the factory. I turned mine into a face

this is Gurenu, he was technically inside the chip before I even bought it, I just wrote the code that draws him. reflash all you want, he stays.

all open source (MIT), engine and firmware are separate repos so you can port it to whatever esp32 thing you have lying around. blame @mannay for this one, I saw his doodle faces the other day and couldn't let it go

also made a page where you can see who's inside YOUR chip. plug it in, chrome reads the mac and draws the face right there in the browser (same c++ code compiled to wasm, so it can't lie). works even if your board has no screen

https://evandroguedes.github.io/doodlesoul

Flash yours and post it here!

u/evandroguedes — 5 days ago
▲ 52 r/esp32projects+5 crossposts

ESP32 CYD Ham Clock Dashboard, new pages new features and fixes

Posted this a while ago but there have been improvements since then, better quality map image, improved colours on propagation pages, added smooth scrolling to DX spots page.

Two new dashboard pages, taking the total to seven.

PSKReporter — reception reports for your callsign plotted on the world map, one marker per four-character grid, coloured by band, with a band legend and a furthest-report line.

POTA Spots — live Parks on the Air activator spots, with an optional great-circle distance filter from your locator and an option to hide automated RBN spots.

GitHub link

streamable.com
u/enormousaardvark — 5 days ago