Skip to content

ESP32 support#29

Merged
puddly merged 61 commits into
devfrom
puddly/esp32-test
Jul 1, 2026
Merged

ESP32 support#29
puddly merged 61 commits into
devfrom
puddly/esp32-test

Conversation

@puddly

@puddly puddly commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

This is an experimental a functional branch to add support for ESP32 via Embassy.

The majority of the changes are restructuring the stack to be no_std (simple) and rewriting all fire-and-forget background task spawns to instead be persistent, reactive tasks that have defined lifetimes (hard). ESP32 support seems very feasible, I want to try and tunnel the provisional JSON wire format over serial. The only feature missing so far is an energy scanning API in the ESP32 crates.

This PR depends on:

@tube0013

Copy link
Copy Markdown

Quick question is the ESP32 support targeting a certain variant?

Cool to see the project moving forward.

@puddly

puddly commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

This is targeting the C6 for now because of the built-in radio but the radio backend is intentionally very generic, you could totally split it up between two chips like we do for the host. I'd have to double check what chips Espressif actually supports with their Rust crates. The C6 is RISC-V so I think anything else with that architecture should work identically?

@tube0013

Copy link
Copy Markdown

Got it, thanks. I was wondering if it was a split as you described or all in one radio stack so you answered my question.

@MattWestb

Copy link
Copy Markdown

C6(X) and H2(X) is RISC-V with 15.4 radios that is compatible in there IDF.
On the host part is the C3 and C6 compatible but the C3 is weaker and dont have WiFi (its not bad then C6 its using the same radio path so can only communicating with one network at the time but they is OK if using USB or UART and no WiFi).
S3 is the best for the host side application and is used in Espressives Zigbe / Thread GW example (it shall also working with CX chips) but its not RISC-V so can being little problematic and need more testing for knowing it working OK.

I have the Zigbee/Thread GW with ETH HAT if need testing in the future then its very standard but is having one very hotted S3 module (16M flash) but all modules used on it is original so have good PCB antennas and not like the clones mini board that have lost all RF tuning on the way from the factory (compared with the reference design).

If you need help testing of ESP32 or EFR32 MG1 or MG21 devices give my one sign Puddly !!

@Hedda

This comment was marked as off-topic.

@MattWestb

Copy link
Copy Markdown

Great work Puddly !!!

For the radio performance i think it can being good documentation what is devices is good and bad.
95% of all stamp size boards is have normally dissent onboard chip (its one folded PCB) antenna but normally is having very much tracks around and / or under it > not working OK in all directions.
The same board oft only having one capacitor (some have places for 2 more but not populated) in the chip - RF path and the reference design is having 3 or more (depends of how good interference filtering shall being done) components (capacitor and coils). Some exceptions can being find but not easy to getting.

The Seeed XIAO ESP32-C6 is having internal ceramic (with very narrow components) and one external connection and both shall working OK but must setting the GPIO right in the firmware for selecting witch RF path shall being used (if selected external without external antenna its being one big mess and can destroying the chip RF part).

Other ESP32 original or good made clones with PCB antennas shall working OK and is (shall) being FCC/CE certed so must have OK RF filtering implemented (but no 100% grantee its in-place and working).
Most modules / board with external antenna shall being better but still no grantee for being perfect and also must having OK RF matching and if having soft / hardware switching it must being correct done.

@MattWestb

Copy link
Copy Markdown

@puddly Is the radio in the ESP32-C6-DevKitM-1 working better the Seeed XIAO ESP32-C6 with internal antenna or still bad RF performance ?

PM: The Zigbee / OTBR dev kits with OTBR firmwaare is using its ESP32-H2 with max TX output and i think its bad then getting more one star network and also the radio links is being asymmetrical and not getting good bidirectional paths for routing traffic.

@puddly

puddly commented Jul 1, 2026

Copy link
Copy Markdown
Contributor Author

@MattWestb It does look better! The Seeed XIAO board let you switch between the on-board antenna and a U.FL connector via GPIO but neither one of those seemed to work well. The dev kit is working a lot better.


  • LQI for the ESP32-C6 seems to be broken. I was only ever seeing values between 0 and 11 for my home network, which should span the whole 0-255 range. I've switched over to the esp-idf algorithm of computing it from RSSI. Maybe we can centralize this logic into Ziggurat itself and use something more sophisticated than a linear rescaling of RSSI to derive LQI (802.15.4 retry counts, ACK latency, etc.)

  • I've cleaned up more of the background async tasks and replaced them with persistent, static tables and long-lived processing tasks. The async task spawning model was nice for host (which has unlimited resources) but it was too heavy for the ESP32. There's no performance penalty, it just slightly unrolls the async state machine and IMO is a better model because it lets us inspect these tables at runtime (for debugging) instead of hiding the real discovery state inside of an async task's local variables. At this point the only dynamically spawned tasks are for joins and some ZDP handling, which should never grow unbounded. The typical send path just grows a small in-memory table. I saw about ~90KB of peak heap allocation for my ~100 device home network.

    I think this is essentially the model Silicon Labs Simplicity SDK was moving towards with their dynamic memory allocation? Older Gecko SDK used statically allocated tables for everything.

  • Sends have been split into two phases: enqueue and receive a delivery callback (broadcasts are considered sent when a large fraction of active neighbor routers have re-broadcast the frame, unicasts without APS ACK are considered sent when the next hop router accepts the frame, and unicasts with APS ACK are considered sent when an APS ACK is received)

At this point the ESP32-C6 performance is pretty good, I'm able to run it just fine at home without any noticeable slowdown compare to the host stack. I think the weak antenna and some strange behavior with the ESP32's low-level IEEE 802.15.4 API (it's very prone to CCA failures) make it perform slightly worse but I think as an experiment this is practically done and ready to merge. Porting to the EFR32MG24 is very much possible at this point.

Zigpy side is here: zigpy/zigpy-ziggurat#3, since this change modifies the wire protocol.

@puddly puddly marked this pull request as ready for review July 1, 2026 17:36
@puddly puddly changed the title Experiment: ESP32 support ESP32 support Jul 1, 2026
@MattWestb

Copy link
Copy Markdown

If have using high power setting and transmitting and have the external antenna selected but no antenna connected the RF signal is reflected 100% back and doing it longer time the RF part is destroyed of overheating in the chip = one bricked chip.

Great work done and next MG24 !!!

@puddly puddly merged commit 99845bc into dev Jul 1, 2026
1 check passed
@puddly puddly deleted the puddly/esp32-test branch July 1, 2026 22:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants