Not in the top 1,000 by GitHub stars
Esmail-sarhadi/esp32-agent-skills
Two hundred and one agent skills and ten checkers that stop AI coding agents from writing ESP32 firmware that compiles and then kills the board. Installable as a Claude Code plugin.
History
Review weekly changes to SKILL.md before updating. Dates mark the weeks in which we observed each version; checks apply to the recorded commits.
View weekly changes
skills/esp32-adc-and-sensors/SKILL.md
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Instructions only
First observation → 6241e61eedf9
No earlier version was observed for comparison.
skills/esp32-addressable-leds/SKILL.md
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Instructions only
First observation → 6241e61eedf9
No earlier version was observed for comparison.
skills/esp32-debugging/SKILL.md
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Local scripts
First observation → 6241e61eedf9
No earlier version was observed for comparison.
skills/esp32-field-gotchas/SKILL.md
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 6241e61eedf9
No earlier version was observed for comparison.
skills/esp32-freertos/SKILL.md
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Instructions only
First observation → 6241e61eedf9
No earlier version was observed for comparison.
skills/esp32-gaming-rgb/SKILL.md
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Instructions only
First observation → 6241e61eedf9
No earlier version was observed for comparison.
skills/esp32-i2c-bus/SKILL.md
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Instructions only
First observation → 6241e61eedf9
No earlier version was observed for comparison.
skills/esp32-modbus-rs485/SKILL.md
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Instructions only
First observation → 6241e61eedf9
No earlier version was observed for comparison.
skills/esp32-mqtt-and-cloud/SKILL.md
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Instructions only
First observation → 6241e61eedf9
No earlier version was observed for comparison.
skills/esp32-partitions-and-ota/SKILL.md
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Local scripts
First observation → 6241e61eedf9
No earlier version was observed for comparison.
skills/esp32-pin-safety/SKILL.md
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Local scripts
First observation → 6241e61eedf9
No earlier version was observed for comparison.
skills/esp32-power-and-boot/SKILL.md
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Instructions only
First observation → 6241e61eedf9
No earlier version was observed for comparison.
skills/esp32-pwm-and-timing/SKILL.md
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Instructions only
First observation → 6241e61eedf9
No earlier version was observed for comparison.
skills/esp32-wifi-reliability/SKILL.md
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Instructions only
First observation → 6241e61eedf9
No earlier version was observed for comparison.
Heat
Insufficient historyNot enough history yet to measure heat. It appears after a few days of data.
Heat never changes the order by stars, and sponsorship never touches it. How heat works
Stars over time
30-day change not yet available: not enough history.
Individual skills in this repository
- esp32-adc-and-sensors
skills/esp32-adc-and-sensors - esp32-addressable-leds
skills/esp32-addressable-leds - esp32-debugging
skills/esp32-debugging - esp32-field-gotchas
skills/esp32-field-gotchas - esp32-freertos
skills/esp32-freertos - esp32-gaming-rgb
skills/esp32-gaming-rgb - esp32-i2c-bus
skills/esp32-i2c-bus - esp32-modbus-rs485
skills/esp32-modbus-rs485 - esp32-mqtt-and-cloud
skills/esp32-mqtt-and-cloud - esp32-partitions-and-ota
skills/esp32-partitions-and-ota - esp32-pin-safety
skills/esp32-pin-safety - esp32-power-and-boot
skills/esp32-power-and-boot - esp32-pwm-and-timing
skills/esp32-pwm-and-timing - esp32-wifi-reliability
skills/esp32-wifi-reliability
How it works
esp32-adc-and-sensors
When your agent uses it
Use when reading an analog sensor on an ESP32 - the reading is noisy, saturates, drifts, or returns nonsense once Wi-Fi connects. Covers ADC1 vs ADC2, attenuation, calibration, source impedance and averaging.
What it loads into context
Frontmatter
58 tokensAlways available to the agent
SKILL.md
918 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- Pin choice decides everything
- Attenuation sets the range
- Calibration
- Source impedance
- Averaging, honestly
- Rules for the agent
Files
LICENSE.txtdoc857 bytesSKILL.mdcore3,340 bytesSKILL.mdcore3,340 bytesSKILL.mdcore3,340 bytes
Read SKILL.md
# Reading analog sensors on ESP32
The ESP32 ADC is the weakest peripheral on the chip. It is usable, but only if
you know which pin you are on and what the input looks like.
## Pin choice decides everything
- **ADC1** is `GPIO32`-`GPIO39`. It keeps working while Wi-Fi is active.
- **ADC2** is `GPIO0`, `2`, `4`, `12`-`15`, `25`-`27`. It is **unavailable
while Wi-Fi is on**: `analogRead` returns 0 or garbage. This is not a bug and
there is no workaround.
- `GPIO34`-`GPIO39` are input-only, which is fine for an analog input, but they
have no internal pull-up. A floating input reads noise, not zero.
View the complete source on GitHubesp32-addressable-leds
When your agent uses it
Use when driving WS2812, SK6812 or APA102 strips from an ESP32 - power sizing, the 3.3 V data problem, colour order, refresh budget and why a strip flickers once Wi-Fi is on.
What it loads into context
Frontmatter
59 tokensAlways available to the agent
SKILL.md
1,010 tokensWhen the skill is activated
Reference documents
900 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- Power comes first
- The 3.3 V data problem
- Colour order and depth
- Refresh budget
- Why it flickers when Wi-Fi connects
- Rules for the agent
- Reference
Files
LICENSE.txtdoc857 bytesSKILL.mdcore3,744 bytesreference/timing-and-power.mddoc2,851 bytes
Read SKILL.md
# Addressable LEDs on ESP32
An LED strip is a power supply problem with a data protocol attached. Most
"flickering" and "the last LEDs are the wrong colour" reports are power, not
code, and most "it works on 10 LEDs and breaks on 300" reports are refresh
budget.
## Power comes first
- Budget up to **60 mA per LED at full white** (vendor figure). 300 LEDs is
about 18 A, not 1 A. A USB port cannot do this.
- Inject power every 100-150 LEDs. Voltage drop along the strip turns the far
end orange because the blue channel needs the most headroom.
- Put a 1000 µF electrolytic across 5 V and GND near the strip. It absorbs theView the complete source on GitHubesp32-debugging
When your agent uses it
Use when an ESP32 crashes, reboots, or prints a Guru Meditation dump - decoding the backtrace, enabling the exception decoder, reading a core dump, and telling a panic from a watchdog from a brownout.
What it loads into context
Frontmatter
53 tokensAlways available to the agent
SKILL.md
1,031 tokensWhen the skill is activated
Reference documents
833 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- Step 1: read the first line, not the dump
- Step 2: turn the backtrace into file:line
- Step 3: when there is no backtrace
- Rules for the agent
- Reference
Scripts executed separately
../../tools/panic_decode.py
Files
LICENSE.txtdoc857 bytesSKILL.mdcore3,788 bytesSKILL.mdcore3,788 bytesreference/panic-codes.mddoc3,246 bytes../../tools/panic_decode.pyruns4,911 bytes
Read SKILL.md
# Debugging an ESP32 crash
The board prints a page of hex and reboots. Everything needed to find the bug
is in that page, and almost nobody reads it because the first line is scary.
## Step 1: read the first line, not the dump
| First line | What it means |
|---|---|
| `Guru Meditation Error: Core 1 panic'ed (LoadProhibited)` | A read through a bad pointer. Null, freed, or out of bounds. |
| `... (StoreProhibited)` | A write through a bad pointer. Usually a buffer overrun. |
| `... (IllegalInstruction)` | Execution reached data. A corrupted function pointer. |
| `... (InstrFetchProhibited)` | The CPU jumped somewhere that is not code. |
| `Task watchdog got triggered` | A task held the CPU without yielding. Not a crash. |View the complete source on GitHubesp32-field-gotchas
When your agent uses it
Use when an ESP32 misbehaves in a way the code does not explain - reboots, brownouts, dead I2C, garbled UART, a sketch that will not flash, a crash with no line number. One hundred and ten failures collected from Stack Overflow, each with the cause and the fix.
What it loads into context
Frontmatter
75 tokensAlways available to the agent
SKILL.md
841 tokensWhen the skill is activated
Reference documents
8,893 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- The five that account for most "random" failures
- Before you change code, check these
- How to use this skill
Files
LICENSE.txtdoc857 bytesSKILL.mdcore3,397 bytesreference/field-notes.mddoc34,362 bytes
Read SKILL.md
# ESP32 field notes
Everything here is a failure that compiles, runs on someone's desk, and then
stops working. They are grouped by symptom, because that is what you have when
you arrive: not "an ADC problem" but "the reading is garbage since I enabled
Wi-Fi".
The full list - 110 entries, each linked to the thread that solved it - is in
[`reference/field-notes.md`](reference/field-notes.md). This page is the
part to read first.
## The five that account for most "random" failures
**1. Brownout is a power problem, never a code problem.** `Brownout detector wasView the complete source on GitHubesp32-freertos
When your agent uses it
Use when adding tasks, timers or interrupts to an ESP32 sketch, when the device resets with a watchdog or stack overflow, or when two tasks fight over a shared variable.
What it loads into context
Frontmatter
45 tokensAlways available to the agent
SKILL.md
725 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- What the sketch actually is
- The three resets you will actually see
- Interrupts
- Sharing data between tasks
- Rules for the agent
Files
LICENSE.txtdoc857 bytesSKILL.mdcore2,981 bytes
Read SKILL.md
# FreeRTOS on ESP32
`setup()` and `loop()` are not "the program". They are one task among several,
and the rest of the system keeps running whether the sketch expects it or not.
## What the sketch actually is
- `loop()` runs inside a task created by the Arduino core (`loopTask`), on core
1, at priority 1, with a stack in the low kilobytes.
- The Wi-Fi stack, the Bluetooth stack and the idle tasks are separate tasks
with their own priorities. A tight loop in `loop()` does not starve them on a
dual-core chip, but it does starve anything pinned to the same core.
- `delay()` yields. A busy `while` loop does not, and that is what triggers the
task watchdog.View the complete source on GitHubesp32-gaming-rgb
When your agent uses it
Use when making an ESP32 LED strip appear inside a gaming lighting app such as OpenRGB or SignalRGB, or when the lighting lags behind the screen or the music.
What it loads into context
Frontmatter
46 tokensAlways available to the agent
SKILL.md
910 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- OpenRGB SDK, the part that matters
- SignalRGB
- Latency, honestly
- Rules for the agent
Files
LICENSE.txtdoc857 bytesSKILL.mdcore3,700 bytes
Read SKILL.md
# Gaming RGB from an ESP32
Desktop lighting apps expect a device they can enumerate and push colours to.
An ESP32 is not one of those by default, so the work is a bridge: implement the
protocol the app speaks, and be honest about latency.
The constants below are taken from the OpenRGB reference client
(`openrgb-python`, `openrgb/utils.py`), not from memory. Check them again if you
target a newer protocol version.
## OpenRGB SDK, the part that matters
OpenRGB's SDK server is a plain TCP server. A device that implements it appears
in the OpenRGB device list with no plugin and no driver.View the complete source on GitHubesp32-i2c-bus
When your agent uses it
Use when adding I2C devices to an ESP32, when a sensor is not detected, or when the bus works alone and fails with a second device. Covers pull-ups, address conflicts, clock stretching and stuck-bus recovery.
What it loads into context
Frontmatter
59 tokensAlways available to the agent
SKILL.md
854 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- Wiring, before any code
- Address conflicts
- The three failure modes
- Rules for the agent
Files
LICENSE.txtdoc857 bytesSKILL.mdcore3,078 bytes
Read SKILL.md
# I2C on ESP32
I2C fails in ways that look like a broken sensor. Almost always it is the bus.
## Wiring, before any code
- Default pins on the Arduino core are `SDA=21`, `SCL=22`. Any pin can be used
with `Wire.begin(sda, scl)`; changing them is not the problem, changing them
to an input-only pin (`GPIO34`-`GPIO39`) is.
- **The internal pull-ups are not enough.** They are in the tens of kilo-ohms,
which is fine for a slow single device and marginal for everything else.
Add external resistors: roughly 4.7 kΩ for 100 kHz, 2.2 kΩ for 400 kHz. These
are rules of thumb, not spec values.
- The I2C specification caps total bus capacitance at 400 pF. Long wires,View the complete source on GitHubesp32-modbus-rs485
When your agent uses it
Use when an ESP32 talks Modbus RTU over RS485 - wiring a MAX485, timing the DE pin, computing the CRC, or debugging a slave that never answers.
What it loads into context
Frontmatter
48 tokensAlways available to the agent
SKILL.md
909 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- The physical layer
- The DE pin is a timing problem, not a wiring problem
- Frame timing
- The CRC
- Register addressing
- Rules for the agent
Files
LICENSE.txtdoc857 bytesSKILL.mdcore3,450 bytes
Read SKILL.md
# Modbus RTU over RS485 on ESP32
Modbus is simple enough to look trivial and precise enough that every shortcut
produces silence. A slave that does not answer gives no error, so the timing and
the wiring have to be right by construction.
## The physical layer
- RS485 is a differential two-wire bus. `A` and `B` naming is not standardised:
vendors swap them. If every frame times out, swap `A` and `B` before touching
the code. This is the single most common cause of "no response".
- A MAX485 module has `DE` and `RE`; tie them together and drive the pin high to
transmit, low to listen. If `DE` stays high, the transceiver holds the bus and
no slave can answer.View the complete source on GitHubesp32-mqtt-and-cloud
When your agent uses it
Use when an ESP32 publishes to MQTT, talks to a cloud endpoint, or drops messages. Covers the 256 byte buffer that silently truncates payloads, keepalive and last will, TLS memory, and why QoS 0 loses data.
What it loads into context
Frontmatter
61 tokensAlways available to the agent
SKILL.md
862 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- The buffer that eats your payload
- Keepalive and last will
- QoS, honestly
- TLS on a microcontroller
- Rules for the agent
Files
LICENSE.txtdoc857 bytesSKILL.mdcore3,529 bytesSKILL.mdcore3,529 bytesSKILL.mdcore3,529 bytesSKILL.mdcore3,529 bytes
Read SKILL.md
# MQTT and cloud endpoints from ESP32
The failures here are quiet. A payload over the buffer size is not sent, a
message at QoS 0 is not retried, and a TLS connection that cannot allocate its
buffers fails in a way that reads like a network problem.
## The buffer that eats your payload
`PubSubClient` has a fixed packet buffer. The long-standing default is 256
bytes, and anything larger is silently dropped - `publish()` returns `false` and
a lot of code ignores that return value.
```cpp
// ArduinoJson payloads grow fast: 20 sensors in one document is not 256 bytes.View the complete source on GitHubesp32-partitions-and-ota
When your agent uses it
Use when enabling OTA, when the build says "Sketch too big", or when a device boot-loops after a partition change. Covers the table layout, the 64 KB alignment rule and what an OTA rollback actually needs.
What it loads into context
Frontmatter
57 tokensAlways available to the agent
SKILL.md
898 tokensWhen the skill is activated
Reference documents
1,151 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- The fixed part of the map
- The two rules that break builds
- A 4 MB layout with OTA
- OTA is more than a second slot
- Rules for the agent
- Reference
Scripts executed separately
../../tools/partition_check.py
Files
LICENSE.txtdoc857 bytesSKILL.mdcore3,300 bytesSKILL.mdcore3,300 bytesreference/partition-layouts.mddoc3,020 bytes../../tools/partition_check.pyruns8,641 bytes
Read SKILL.md
# Partitions and OTA on ESP32
The partition table is the file where a wrong number produces a device that
flashes successfully and then boot-loops with no readable error.
## The fixed part of the map
These addresses are not negotiable:
| Region | Offset |
|---|---|
| Bootloader | `0x1000` |
| Partition table itself | `0x8000` (4 KB) |
| First usable partition | `0x9000` |View the complete source on GitHubesp32-pin-safety
When your agent uses it
Use when choosing, reviewing or debugging ESP32 GPIO assignments in firmware. Catches the four failure modes that compile cleanly and then kill the board — flash pins, input-only pins, strapping pins, ADC2 with Wi-Fi — before anything is flashed.
What it loads into context
Frontmatter
62 tokensAlways available to the agent
SKILL.md
975 tokensWhen the skill is activated
Reference documents
2,388 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- Order of checks
- Rules for the agent
- Automated check
- Worked example
- Reference
Scripts executed separately
../../tools/pincheck.py
Files
LICENSE.txtdoc857 bytesSKILL.mdcore3,492 bytesSKILL.mdcore3,492 bytesreference/pin-table.mddoc4,772 bytes../../tools/pincheck.pyruns6,686 bytes
Read SKILL.md
# ESP32 pin safety
Most ESP32 firmware that "compiles but does not work" fails on the pin map, not
on the logic. Check the pin map before writing driver code.
## Order of checks
Work through these in order. Each one can invalidate everything after it.
1. **Does the pin exist on this module?**
`GPIO6`-`GPIO11` are wired to the SPI flash. `GPIO16`/`GPIO17` exist only on
WROVER modules; on WROOM they are inside the PSRAM package. Touching either
group produces a board that will not boot, not an error message.
2. **Is the pin allowed to drive an output?**View the complete source on GitHubesp32-power-and-boot
When your agent uses it
Use when an ESP32 board resets randomly, browns out, fails to boot, or drains a battery in days. Covers the power budget, the boot strap states and deep-sleep leakage, and says what to measure before changing code.
What it loads into context
Frontmatter
59 tokensAlways available to the agent
SKILL.md
765 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- Layer 1: is the supply actually able to deliver?
- Layer 2: did it even get to `setup()`?
- Layer 3: deep sleep
- What to ask the user before proposing a fix
Files
LICENSE.txtdoc857 bytesSKILL.mdcore2,986 bytes
Read SKILL.md
# ESP32 power and boot
"Random resets" is the most misdiagnosed symptom on this platform. It is almost
never the code. Work through the three layers below in order, and measure before
changing anything.
## Layer 1: is the supply actually able to deliver?
The radio is the load. An ESP32 transmitting draws peaks in the region of 240 mA
(the datasheet figure for 802.11b at 17 dBm), while the average is far lower.
A USB port or a small LDO that is fine on average can still dip below the
brownout threshold on every packet.
- The brownout detector trips at roughly 2.4 V by default. A reset whose causeView the complete source on GitHubesp32-pwm-and-timing
When your agent uses it
Use when driving an LED, a motor, a servo or a buzzer with PWM on ESP32 - the frequency is wrong, the resolution collapses, the servo jitters, or the duty value does nothing. Covers LEDC's frequency/resolution trade-off.
What it loads into context
Frontmatter
65 tokensAlways available to the agent
SKILL.md
948 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- The trade-off, in one line
- What different loads need
- Duty is a count, not a percentage
- API changed in Arduino core 3.x
- Servos
- Rules for the agent
Files
LICENSE.txtdoc857 bytesSKILL.mdcore3,393 bytesSKILL.mdcore3,393 bytes
Read SKILL.md
# PWM and timing on ESP32
The ESP32 does not have "PWM pins". It has the LEDC peripheral: 4 timers and 16
channels, and every channel borrows a timer. The frequency and the resolution
are not independent, and that is the source of most surprises.
## The trade-off, in one line
```
frequency = 80 MHz / (divider × 2^resolution)
```
So at a fixed clock, resolution and frequency trade against each other:
View the complete source on GitHubesp32-wifi-reliability
When your agent uses it
Use when an ESP32 drops off Wi-Fi, reconnects in a loop, is slow to respond, or works on the bench and fails in the field. Covers reconnect storms, power save, AP+STA, and what the RSSI actually tells you.
What it loads into context
Frontmatter
64 tokensAlways available to the agent
SKILL.md
873 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- The reconnect loop
- Power save is a latency setting
- AP+STA is not free
- What RSSI tells you, and what it does not
- Symptoms and their usual cause
- Rules for the agent
Files
LICENSE.txtdoc857 bytesSKILL.mdcore3,550 bytesSKILL.mdcore3,550 bytes
Read SKILL.md
# Wi-Fi that stays connected
An ESP32 that connects once is easy. One that is still connected after a week,
after a router reboot, and after the neighbour bought a new access point is a
different problem, and it is almost always the reconnect logic.
## The reconnect loop
The Arduino core already has a reconnect mechanism. Turning on your own as well
produces two reconnects racing each other, which looks like a board that
connects and drops every few seconds.
- Let the core handle it: `WiFi.setAutoReconnect(true)`.
- Do not call `WiFi.begin()` in a tight loop. Each call tears down the stateView the complete source on GitHubSkills included
- esp32-adc-and-sensors
- esp32-addressable-leds
- esp32-debugging
- esp32-field-gotchas
- esp32-freertos
- esp32-gaming-rgb
- esp32-i2c-bus
- esp32-modbus-rs485
- esp32-mqtt-and-cloud
- esp32-partitions-and-ota
- esp32-pin-safety
- esp32-power-and-boot
- esp32-pwm-and-timing
- esp32-wifi-reliability
Repository facts
- License
- MIT
- Created
- Oct 31, 2026
- Last pushed
- Nov 5, 2026
- Forks
- 8
- Open issues
- 5
- Project activity
- Active
Before you install
Network or broad shellAutomated signals, not a guarantee
Checked Nov 6, 2026
Not fully analyzed: some files were too long, unreadable or missing. This never lowers the level.
Show 10 notes
skills/esp32-adc-and-sensors/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedskills/esp32-adc-and-sensors/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedskills/esp32-debugging/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedskills/esp32-mqtt-and-cloud/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedskills/esp32-mqtt-and-cloud/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedskills/esp32-mqtt-and-cloud/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedskills/esp32-partitions-and-ota/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedskills/esp32-pin-safety/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedskills/esp32-pwm-and-timing/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedskills/esp32-wifi-reliability/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzed
- No broad tool permissions
- No dangerous shell commands
- 110 network referencesin 1 file: esp32-field-gotchas/reference/field-notes.md:13
- No hidden or obfuscated text
- No instruction overrides
- 3 executable scriptsin 3 files: tools/panic_decode.py:1 tools/partition_check.py:1 tools/pincheck.py:1
- No access to secrets
- No requests to vote in Hot
Show all 113 signals by file
skills/esp32-field-gotchas/reference/field-notes.md
- Network accessline 13
1. **Brownout when Wi-Fi starts** — see: `Brownout detector was triggered` right after `WiFi.begin()`. cause: the radio's transmit peaks pull ~350 mA and a thin USB cable or a small LDO sags below 2.5 V. fix: 470 µF bulk capacitor at the mo - Network accessline 14
2. **ESP32-CAM browns out at boot** — see: reboot loop as soon as the camera initialises. cause: camera and Wi-Fi start together and exceed the board's regulator. fix: separate 5 V supply with a large capacitor; the on-board regulator is no - Network accessline 15
3. **Board will not enter download mode** — see: `Failed to connect ... Timed out waiting for packet header`. cause: the auto-reset circuit did not assert GPIO0 low, or the cable is charge-only. fix: hold BOOT, tap EN, release; try another - Network accessline 16
4. **Invalid head of packet** — see: `Failed to connect to ESP32: Invalid head of packet (0x00)`. cause: something else is talking on the UART at boot, or the baud is wrong. fix: disconnect other serial devices, lower the upload speed to 11 - Network accessline 17
5. **The port does not exist** — see: no COM port at all. cause: missing CP210x/CH340 driver, or the board is in a state where the USB bridge is unpowered. fix: install the bridge driver, check Device Manager, try a powered hub. · [73923341 - Network accessline 18
6. **ESP32-CAM sends nothing on serial** — see: upload succeeds, monitor is silent. cause: the camera boards power the USB-serial chip only when GPIO0 is low, and the sketch reconfigures the UART pins. fix: use a USB-TTL adapter on U0TXD/U0 - Network accessline 19
7. **Stack canary watchpoint triggered** — see: `Debug exception reason: Stack canary watchpoint triggered`. cause: a stack buffer overflow, usually a large local array or `sprintf` into a small buffer. fix: move large buffers to static or - Network accessline 20
8. **TG1WDT_SYS_RST on minimal code** — see: an ESP32-C3 resets immediately even with an empty sketch. cause: a bootloader or partition mismatch, often after flashing a binary built for another target. fix: erase the flash (`esptool erase_f - Network accessline 21
9. **Board stops booting after a partition change** — see: boot loop, or `invalid header` in the ROM log. cause: `boot_app0.bin` missing, or the app partition offset no longer matches the table. fix: reflash bootloader, partitions and boot_ - Network accessline 25
10. **Driving GPIO6-11 kills the board** — see: it compiles, flashes, then never boots again. cause: those pins are the SPI flash bus. fix: never use them; `pincheck.py` rejects them. · [65125302](https://stackoverflow.com/q/65125302) - Network accessline 26
11. **`INPUT_PULLUP` does nothing on GPIO34-39** — see: a button reads floating noise. cause: those pins are input-only and have no internal pull-up or pull-down at all. fix: external 10 kΩ resistor, or move the button to a pin that has one - Network accessline 27
12. **It boots on the bench, fails in the enclosure** — see: works until power is cycled. cause: a strapping pin (0, 2, 12, 15) is held at the wrong level by attached hardware at reset. fix: keep GPIO12 low at boot, do not load GPIO0/2/15 w - Network accessline 28
13. **The on-board LED will not blink** — see: `digitalWrite(2, HIGH)` changes nothing. cause: on many boards the LED is on GPIO2 but wired active-low, or it is a WS2812 on a different pin. fix: invert the logic, and check the board's schem - Network accessline 29
14. **`digitalWrite` is too slow** — see: a bit-banged protocol misses timing. cause: the Arduino API costs microseconds per call. fix: direct register access (`GPIO.out_w1ts`), or better, use the RMT/LEDC peripheral. · [52348930](https://s - Network accessline 30
15. **Touch pins stop working with Wi-Fi** — see: `touchRead` returns garbage. cause: the touch peripheral shares hardware with the radio. fix: do not mix touch and Wi-Fi on the same channel plan; read touch only while the radio is idle. · - Network accessline 31
16. **A pin works as input but not output** — see: the output never changes. cause: it is one of GPIO34-39, which have no output driver. fix: pick another pin; there is nothing to enable. · [53324715](https://stackoverflow.com/q/53324715) - Network accessline 32
17. **Board reboots when a relay switches** — see: reset exactly when the load turns on. cause: inductive kickback on the GPIO rail, or a ground loop. fix: flyback diode across the coil, opto-isolation, separate supply for the relay board. - Network accessline 36
18. **`analogRead` returns 0 once Wi-Fi connects** — see: readings worked before `WiFi.begin()`. cause: ADC2 is unavailable while the radio is on; there is no workaround. fix: move the sensor to ADC1 (GPIO32-39). · [65125302](https://stacko - Network accessline 37
19. **The top of the range is compressed** — see: values flatten near 3.2 V. cause: at 11 dB attenuation the ADC is not linear above ~2.5 V. fix: use a divider so the signal lands mid-range, or calibrate with `analogReadMilliVolts`. · [5683 - Network accessline 38
20. **Measuring battery voltage** — see: a divider reads low and drifts. cause: the sample-and-hold capacitor loads a high-impedance divider. fix: keep the divider under 10 kΩ, add 100 nF at the pin. · [56266857](https://stackoverflow.com/q - Network accessline 39
21. **Reading VCC without an external pin** — see: no way to know the supply. cause: there is no internal VCC channel. fix: measure an internal reference through a known divider, or use `esp_adc_cal` with a factory-calibrated reference. · [ - Network accessline 40
22. **Readings are noisy** — see: ±20 counts of jitter. cause: the ADC is noisy by design. fix: average N samples (noise drops by √N), add a capacitor, keep the sensor wire short. · [65725609](https://stackoverflow.com/q/65725609) - Network accessline 41
23. **Sampling audio or a fast signal** — see: `analogRead` cannot keep up. cause: it is a slow, blocking call. fix: use I2S in ADC mode with DMA; it samples continuously without the CPU. · [65725609](https://stackoverflow.com/q/65725609) - Network accessline 45
24. **The sensor is never detected** — see: `i2c.scan()` finds nothing. cause: no pull-ups, wrong pins, or the device is on a different address than the datasheet's default. fix: 4.7 kΩ to 3.3 V on SDA and SCL, confirm the address with a sc - Network accessline 46
25. **SCL stuck low** — see: the bus is dead until power cycle. cause: a slave is holding the line after a partial transfer. fix: clock SCL manually nine times to let it release, then issue a STOP. · [79237471](https://stackoverflow.com/q/7 - Network accessline 47
26. **`ENODEV` but the scan works** — see: MicroPython finds the address then throws `[Errno 19]`. cause: the driver was constructed with the wrong address or a stale bus object. fix: recreate the bus, pass the scanned address explicitly. · - Network accessline 48
27. **SPI transfer ends early** — see: the transaction stops mid-buffer. cause: the length was given in bytes where the driver expects words, or CS was released too soon. fix: check the length units and keep CS asserted for the whole transa - Network accessline 49
28. **MPU-6050 FIFO returns nonsense** — see: the first samples are correct then garbage. cause: the FIFO is read without checking the count register, or without clearing it. fix: read `FIFO_COUNT`, read exactly that many bytes, reset the F - Network accessline 50
29. **I2C works alone, fails with Wi-Fi** — see: timeouts only when the radio is active. cause: the radio's interrupts delay the bus, and the default timeout is short. fix: raise the I2C timeout, lower the clock to 100 kHz, retry the transa - Network accessline 51
30. **Two devices with the same address** — see: both respond, both return the other's data. cause: fixed-address parts cannot share a bus. fix: use a TCA9548A multiplexer, or move one device to a second I2C bus. · [79330446](https://stacko - Network accessline 55
31. **Garbled serial output** — see: readable at first, then symbols. cause: baud mismatch, or the monitor is attached to the wrong UART (USB CDC vs UART0). fix: match the baud exactly, and print to the same port the monitor is on. · [79670 - Network accessline 56
32. **`Serial.print` and `Serial.printf` disagree** — see: different values for the same variable. cause: the format specifier does not match the type (`%d` for a `long`, `%f` for a double that was promoted). fix: use `PRIu32`/`%lu` and cas - Network accessline 57
33. **Long lines get truncated** — see: only the first ~120 characters arrive. cause: the RX buffer is 256 bytes by default. fix: raise `SERIAL_RX_BUFFER_SIZE` at build time, or drain faster. · [60879021](https://stackoverflow.com/q/6087902 - Network accessline 58
34. **`SoftwareSerial` does not work** — see: nothing received. cause: the ESP32 has three hardware UARTs; bit-banging is unreliable and unsupported. fix: use `HardwareSerial(1)` or `(2)` with explicit pins. · [60094545](https://stackoverfl - Network accessline 59
35. **Waking from light sleep on serial data** — see: the UART does not wake the chip. cause: the wake source must be enabled before sleeping and the pin must be a valid wake pin. fix: `gpio_wakeup_enable` on the RX pin plus `esp_sleep_enab - Network accessline 63
36. **The board drops off and reconnects in a loop** — see: connects, disconnects, repeats every few seconds. cause: the application reconnects on top of the core's own reconnect logic, and both fight. fix: disable one of them; add exponent - Network accessline 64
37. **Wi-Fi and Bluetooth together are unstable** — see: enabling both makes one of them fail. cause: they share one radio and one antenna; coexistence needs time-slicing. fix: enable coexistence in `menuconfig`, expect lower throughput on - Network accessline 65
38. **The antenna choice is not what you think** — see: terrible range on a module with an external antenna connector. cause: the RF switch must be told which antenna to use, and some modules need a solder jumper moved. fix: check the modul - Network accessline 66
39. **The access point always uses 192.168.4.1** — see: clients cannot reach the device on another subnet. cause: the default AP IP is fixed. fix: `WiFi.softAPConfig()` before `softAP()`. · [58976055](https://stackoverflow.com/q/58976055) 4 - Network accessline 67
40. **mDNS works on one device and not another** — see: `device.local` resolves from a laptop but not a phone. cause: Android's resolver does not do mDNS by default. fix: do not rely on mDNS for discovery; publish the IP over the protocol y - Network accessline 68
41. **`connect()` returns errno 104** — see: `Connection reset by peer` after a few requests. cause: the server closed a keep-alive connection and the client reused it. fix: handle the reset by reconnecting, do not assume a socket stays ope - Network accessline 69
42. **HTTP GET takes seconds** — see: each request is slow even on a good network. cause: DNS resolution and a new TLS handshake per request. fix: reuse the connection, cache the resolved IP, or move to a persistent protocol. · [72242061](h - Network accessline 70
43. **Checking whether the internet is up** — see: `WiFi.status()` says connected but nothing loads. cause: it only reports the link, not reachability. fix: ping the gateway or fetch a small known URL with a short timeout, and cache the res - Network accessline 74
44. **Advertising stops once a client connects** — see: no longer discoverable after the first connection. cause: advertising is not restarted on disconnect, and some stacks stop it on connect. fix: restart advertising in the disconnect han - Network accessline 75
45. **BLE keeps the chip awake** — see: deep sleep never reaches microamps. cause: the BLE stack holds the radio and a timer. fix: deinit BLE before sleeping, and use `esp_bluedroid_disable`. · [61811536](https://stackoverflow.com/q/6181153 - Network accessline 76
46. **A device will not pair** — see: the phone sees it, pairing fails. cause: missing bonding flags, or a security request the peripheral never answers. fix: set bonding and MITM explicitly and store the keys in NVS. · [67864472](https://s - Network accessline 77
47. **BLE and Wi-Fi share the antenna** — see: throughput collapses when both are active. cause: single radio, time-sliced. fix: expect it, or schedule BLE advertising only in Wi-Fi idle windows. · [65636417](https://stackoverflow.com/q/656 - Network accessline 81
48. **"Sketch too big"** — see: the build fails at link time. cause: the default partition table gives the app only ~1.2 MB. fix: choose a partition scheme with a bigger app slot; do not shrink the code. · [75396355](https://stackoverflow.c - Network accessline 82
49. **NVS runs out of space** — see: `ESP_ERR_NVS_NO_FREE_PAGES`. cause: the NVS partition is 20 KB by default and entries have overhead. fix: enlarge the NVS partition in the table, or store large blobs in SPIFFS/LittleFS. · [55222899](htt - Network accessline 83
50. **Writing flash every second** — see: the device dies after months. cause: flash endurance is ~100k erase cycles per sector. fix: buffer in RAM and flush on a timer or on change; never log to NVS in a loop. · [73783849](https://stackove - Network accessline 84
51. **EEPROM, NVS or SPIFFS?** — see: no clear choice. cause: they solve different problems. fix: NVS for small key-values, SPIFFS/LittleFS for files, EEPROM emulation only for compatibility. · [70826170](https://stackoverflow.com/q/7082617 - Network accessline 85
52. **EEPROM wear** — see: `EEPROM.commit()` in a loop. cause: each commit erases a sector. fix: commit on change with a debounce, or keep the value in NVS which does wear levelling. · [59817278](https://stackoverflow.com/q/59817278) - Network accessline 86
53. **Storing a string permanently** — see: `EEPROM.write` truncates. cause: it writes bytes, not strings. fix: write length + bytes, or use NVS with `nvs_set_str`. · [56139657](https://stackoverflow.com/q/56139657) - Network accessline 87
54. **The best way to store frequent data** — see: samples every second. cause: flash is the wrong medium for that rate. fix: ring buffer in RAM, flush batches to flash, or use RTC memory across deep sleep. · [63780850](https://stackoverflo - Network accessline 88
55. **Writing NVS during production flashing** — see: each unit needs a unique ID. cause: NVS is initialised at first boot, not at flash time. fix: generate an NVS partition image and flash it with the rest, or provision over serial on firs - Network accessline 92
56. **`LoadProhibited`** — see: `Guru Meditation Error: Core 1 panic'ed (LoadProhibited)`. cause: dereferencing NULL or a freed pointer. fix: check every pointer that came from `malloc`, `strchr`, or a failed lookup; `EXCVADDR` in the dump - Network accessline 93
57. **Reading a backtrace** — see: a list of addresses. cause: the addresses are only meaningful with the matching ELF. fix: keep the ELF from that exact build and run `xtensa-esp32-elf-addr2line -pfiaC -e firmware.elf <addresses>`. · [6563 - Network accessline 94
58. **`Interrupt wdt timeout on CPU1`** — see: panic with no obvious code path. cause: an ISR ran longer than the interrupt watchdog allows. fix: move work out of the ISR into a task via a queue; never call `delay`, `printf` or allocate ins - Network accessline 95
59. **`Task watchdog got triggered`** — see: reset after ~5 s of silence. cause: a task blocked or looped without yielding. fix: find the blocking call; add `vTaskDelay` only if the loop is genuinely idle. · [66278271](https://stackoverflow - Network accessline 96
60. **The watchdog fires during a long operation** — see: a legitimate long flash write or computation trips it. cause: the task never yields to the idle task. fix: subscribe the task to the TWDT and call `esp_task_wdt_reset()` inside the l - Network accessline 97
61. **Zeroing PSRAM eats all memory** — see: allocation fails after initialising a large buffer. cause: `calloc`-style zeroing touches every page and commits it. fix: allocate, then zero only what you use; check `ESP.getFreePsram()` before - Network accessline 98
62. **MQTT publish crashes with a stack overflow** — see: reboot inside the publish call. cause: TLS plus MQTT needs more stack than the default task size. fix: raise the task stack to 8-16 KB, or publish from a dedicated task. · [67824787] - Network accessline 99
63. **`multiple definition of ...`** — see: link error after adding a second source file. cause: a variable defined in a header included twice. fix: `extern` in the header, define it in exactly one `.c`. · [57759461](https://stackoverflow.c - Network accessline 103
64. **A task must never return** — see: crash or silent stop when the function ends. cause: FreeRTOS tasks are not allowed to return; there is nowhere to return to. fix: end with `vTaskDelete(NULL)` or an infinite loop. · [63634917](https:/ - Network accessline 104
65. **Stopping a task cleanly** — see: `vTaskDelete` from outside leaves resources held. cause: the task never gets to free its own memory. fix: signal it with a notification or a flag, let it clean up, then delete itself. · [62113104](http - Network accessline 105
66. **`std::mutex` versus `xSemaphore`** — see: a C++ mutex deadlocks or does not protect. cause: the C++ wrapper is not integrated with the RTOS scheduler the way the native primitives are. fix: use `xSemaphoreCreateMutex` / `std::mutex` c - Network accessline 106
67. **Rotary encoder misses steps** — see: counts are lost when the motor runs. cause: the ISR is too slow, or the pins have no hardware filter. fix: keep the ISR to a single counter increment, use the PCNT peripheral for real encoders. · [ - Network accessline 110
68. **`esp_wifi.h: No such file or directory`** — see: the build cannot find an IDF header. cause: the component is not in `REQUIRES`, or the include path is not set. fix: add the component to the CMake `REQUIRES`/`PRIV_REQUIRES` list. · [7 - Network accessline 111
69. **`idf.py` is not recognised** — see: the command is missing after install. cause: the export script was not sourced in this shell. fix: run `export.sh` (or `. ./export.sh`) in the same terminal, every time. · [63615242](https://stackov - Network accessline 112
70. **`collect2.exe: error: ld returned 1 exit status`** — see: the build fails only at link. cause: two libraries define the same symbol, or a library is missing from the build. fix: read the lines above the error — the linker always names - Network accessline 134
71. **Deep sleep still draws milliamps** — see: 8 mA instead of 10 µA. cause: the USB-serial chip is still powered, a GPIO is left driving a load, or the regulator has high quiescent current. fix: measure on the battery rail only, `gpio_hol - Network accessline 135
72. **A GPIO change does not wake the chip** — see: the interrupt works while awake, nothing after deep sleep. cause: only RTC-capable pins (0-15 on the classic ESP32) can wake from deep sleep. fix: use `esp_sleep_enable_ext1_wakeup()` with - Network accessline 136
73. **The ULP cannot touch a normal peripheral** — see: ULP code reads zero or hangs. cause: the ULP has its own tiny instruction set and can only reach RTC memory and a few registers. fix: keep the ULP to sampling and simple arithmetic, an - Network accessline 137
74. **ULP wake period drifts by minutes** — see: a "60 s" wake drifts. cause: the RTC slow clock is an RC oscillator with several percent tolerance. fix: calibrate it against the XTAL, or accept the drift and resync time when the radio is o - Network accessline 138
75. **Variables lose their value after sleep** — see: a counter resets every wake. cause: deep sleep powers down normal RAM; only RTC memory survives. fix: `RTC_DATA_ATTR` on the few values that must persist, and keep them small. · [5654870 - Network accessline 139
76. **`ext0` wake never fires** — see: no wake on a valid pin. cause: `ext0` works on a single RTC pin and a specific level, and the pin must be configured as an RTC IO first. fix: `rtc_gpio_init` + `rtc_gpio_pullup`, then `esp_sleep_enable - Network accessline 140
77. **Touch does not wake the board** — see: touch works while awake, not as a wake source. cause: touch wake has to be armed separately and only works on touch-capable pins. fix: `esp_sleep_enable_touchpad_wakeup()` plus `touch_pad_set_fsm - Network accessline 141
78. **Light sleep and deep sleep behave differently** — see: a sketch that survives light sleep dies after deep sleep. cause: light sleep keeps RAM and the peripherals; deep sleep keeps almost nothing. fix: treat them as different features, - Network accessline 142
79. **Brownout right after waking** — see: a reset exactly when the radio starts. cause: the bulk capacitor is discharged after a long sleep and the RF inrush pulls the rail down. fix: larger capacitor, and bring the radio up after a short - Network accessline 146
80. **OTA uploads but nothing changes** — see: the write succeeds, the old firmware still runs. cause: the OTA API writes to the inactive partition; without `set_boot_partition` and a reboot the bootloader still starts the old one. fix: `es - Network accessline 147
81. **A bad OTA bricks the device** — see: the new image boots once and dies. cause: no rollback configured, so a broken image stays active. fix: enable `CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` and call `esp_ota_mark_app_valid_cancel_rollbac - Network accessline 148
82. **Boot loop after editing the partition table** — see: `invalid header` or an immediate reset. cause: the table moved the app offset but the bootloader and `otadata` were not reflashed with it. fix: flash bootloader, partition table and - Network accessline 149
83. **SPIFFS shows far less than 4 MB** — see: `SPIFFS.totalBytes()` reports a few hundred KB. cause: the filesystem size is whatever the partition table gives it, not the flash size. fix: enlarge the `spiffs`/`littlefs` partition in the ta - Network accessline 150
84. **The filesystem corrupts after a power cut** — see: mount fails after an unexpected reset. cause: SPIFFS is not power-loss resilient. fix: move to LittleFS, which keeps a journal, or call `format` on mount failure and rebuild. · [63568 - Network accessline 151
85. **The device crashes during OTA writes** — see: a panic inside a flash write. cause: writing flash disables the cache, so any code running from flash — including ISRs — faults. fix: put interrupt handlers in IRAM (`IRAM_ATTR`) and stop - Network accessline 152
86. **HTTPS OTA fails the handshake** — see: `HTTPClient` returns -1 over `https`. cause: no certificate, or a clock so wrong that the cert looks not-yet-valid. fix: set the time first and pin a CA; `setInsecure()` works but removes the onl - Network accessline 153
87. **OTA over a slow link times out** — see: the download stalls near the end. cause: the default HTTP timeout is shorter than the transfer. fix: raise the timeout, stream into `esp_ota_write` in chunks, and never buffer the whole image. · - Network accessline 157
88. **TLS handshake fails with a valid certificate** — see: `setCACert` still fails. cause: the system clock is at 1970, so the certificate is not valid yet. fix: sync time over SNTP before the first HTTPS call. · [68356924](https://stackov - Network accessline 158
89. **The certificate expires and the product dies** — see: every device stops talking on the same day. cause: a leaf certificate was pinned instead of a CA, or the root changed. fix: pin a CA bundle, ship an update path for the bundle, and - Network accessline 159
90. **`time(nullptr)` returns a 1970 timestamp** — see: time is never valid. cause: `configTime` is asynchronous and returns immediately. fix: wait until the value is above a sane floor (e.g. 1.6e9) before trusting it, with a timeout. · [68 - Network accessline 160
91. **WebSocket closes with code 1006** — see: the socket dies with no close frame. cause: nothing was sent for longer than the proxy or server idle timeout. fix: send a ping every 20-30 s and handle a reconnect instead of assuming the link - Network accessline 161
92. **UDP packets vanish on the soft-AP** — see: heavy loss when the ESP32 is the access point. cause: modem sleep parks the radio between beacons. fix: `WiFi.setSleep(false)` while streaming, and expect lower throughput than the datasheet - Network accessline 165
93. **TWAI receives nothing** — see: no frames at all. cause: no transceiver on the bus, TX/RX swapped, no 120 Ω termination, or a bitrate mismatch. fix: check the transceiver first, then the termination, then the timing. · [68527367](https - Network accessline 166
94. **The LED strip flickers when CAN is active** — see: WS2812 glitches under bus load. cause: the strip refresh is timing-critical and the CAN ISR delays it. fix: drive the strip from RMT, keep the CAN ISR short, and do not refresh from i - Network accessline 167
95. **`rmtWrite` blocks the whole loop** — see: the main loop stutters during a strip update. cause: the blocking variant waits for the transmission. fix: `rmt_write_items(..., false)` and wait on the done semaphore, or double-buffer two tr - Network accessline 168
96. **DAC output does nothing** — see: `dacWrite` has no effect. cause: the DAC exists only on GPIO25 and GPIO26, and both are also ADC2 channels. fix: use those two pins only, and do not expect them to work as ADC while Wi-Fi is on. · [792 - Network accessline 169
97. **Touch readings drift over hours** — see: thresholds that worked stop working. cause: the touch baseline is not recalibrated and the environment changed. fix: run `touch_pad_set_meas_time` sensibly, recalibrate the baseline periodicall - Network accessline 170
98. **A PCNT pin cannot be used for wake** — see: `ext1` wake does nothing on a pin that works elsewhere. cause: the pulse counter has taken the pin. fix: `pcnt_unit_disable` and release the GPIO before arming the wake source. · [54316980]( - Network accessline 171
99. **The servo jitters** — see: random twitches even with a clean PWM signal. cause: the servo's current spikes brown out the shared 5 V rail. fix: separate supply, common ground, and a capacitor at the servo. · [60171641](https://stackove - Network accessline 175
100. **A queue send from an ISR crashes** — see: `LoadProhibited` inside the interrupt. cause: `xQueueSend` was used instead of the ISR variant. fix: `xQueueSendFromISR` with the woken flag, and create the queue before attaching the interru - Network accessline 176
101. **The task stack overflows when parsing JSON** — see: a reset inside `deserializeJson`. cause: JSON parsing needs several KB of stack, and the default task stack is smaller than that. fix: parse on a dedicated task with 8-16 KB, or use - Network accessline 177
102. **PSRAM allocation fails** — see: `ps_malloc` returns NULL on a module with PSRAM. cause: PSRAM is not enabled in the build, or the allocator was asked for internal RAM. fix: enable SPIRAM in the board config and use `heap_caps_malloc( - Network accessline 178
103. **The watchdog still fires after disabling it** — see: WDT resets continue. cause: there are three watchdogs — task, interrupt and RTC — and they are configured separately. fix: identify which one from the reset reason, then handle tha - Network accessline 179
104. **`LoadProhibited` only in a task** — see: the same code works in `loop()`. cause: the task stack is too small, or it holds a pointer to another task's stack. fix: size the stack in bytes, pass data by value or by heap, never by a poin - Network accessline 180
105. **Heap shrinks over days** — see: free heap falls and never recovers. cause: fragmentation from `String` concatenation and many small allocations of different sizes. fix: fixed-size buffers, reserve() up front, and check `heap_caps_get - Network accessline 184
106. **The captive portal never opens on Android** — see: the phone connects and does nothing. cause: Android probes `connectivitycheck.gstatic.com/generate_204` and expects a 204 or a redirect. fix: answer that path explicitly and resolve - Network accessline 185
107. **Clients on the soft-AP have no internet** — see: they connect but cannot reach the web. cause: the ESP32 is an access point, not a router; there is no NAT in the default stack. fix: add a NAT layer (`esp_netif_napt_enable` on newer I - Network accessline 186
108. **The AP IP is printed before it exists** — see: `WiFi.softAPIP()` returns 0.0.0.0. cause: the AP starts asynchronously. fix: wait for the `AP_START` / `got_ip` event before printing or advertising the address. · [73999244](https://sta - Network accessline 187
109. **Two BLE profiles fight over one callback** — see: notifications stop when a second service is added. cause: a single GATTS handler cannot own two profiles' events. fix: register one handler per profile and dispatch on `gatts_if`. · [ - Network accessline 188
110. **A phone will not reconnect after reflashing** — see: the device is invisible to a phone that paired before. cause: the phone still holds the old bond while the ESP32 lost its keys. fix: delete the bond on the phone, or call `esp_ble_
tools/panic_decode.py
- Executable scriptline 1
#!/usr/bin/env python3
tools/partition_check.py
- Executable scriptline 1
#!/usr/bin/env python3
tools/pincheck.py
- Executable scriptline 1
#!/usr/bin/env python3
How the signals fit together
Facts from a static read of the files at the pinned commit. They describe what the code does, not why.
Some files could not be read; the facts below still hold.
Signal confidence: 113 facts
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:13Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:14Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:15Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:16Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:17Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:18Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:19Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:20Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:21Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:25Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:26Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:27Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:28Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:29Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:30Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:31Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:32Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:36Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:37Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:38Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:39Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:40Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:41Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:45Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:46Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:47Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:48Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:49Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:50Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:51Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:55Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:56Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:57Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:58Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:59Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:63Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:64Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:65Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:66Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:67Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:68Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:69Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:70Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:74Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:75Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:76Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:77Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:81Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:82Low confidence
- Network access in prose of documentationesp32-field-gotchas/reference/field-notes.md:83Low confidence
and 63 more
Works with
| Agent | Status | Evidence | Install to |
|---|---|---|---|
| Claude Code | Compatible | Standard SKILL.md skills/esp32-adc-and-sensors/SKILL.md | .claude/skills/<skill-name>/ |
| Codex | Compatible | Standard SKILL.md skills/esp32-adc-and-sensors/SKILL.md | .agents/skills/<skill-name>/ |
| Cursor | Compatible | Standard SKILL.md skills/esp32-adc-and-sensors/SKILL.md | .cursor/skills/<skill-name>/ |
| Gemini CLI | Compatible | Standard SKILL.md skills/esp32-adc-and-sensors/SKILL.md | .gemini/skills/<skill-name>/ |
| GitHub Copilot | Compatible | Standard SKILL.md skills/esp32-adc-and-sensors/SKILL.md | .github/skills/<skill-name>/ |
| OpenCode | Compatible | Standard SKILL.md skills/esp32-adc-and-sensors/SKILL.md | .opencode/skills/<skill-name>/ |
- Native The repository ships a manifest, folder or frontmatter field for this agent.
- Compatible A standard SKILL.md that this agent can read.
- Unknown No evidence either way.
Derived automatically from paths, manifests and frontmatter. Not tested on each agent.