AI is right about ESP32 pins two-thirds of the time, and that's worse than always being wrong

AI is right about ESP32 pins two-thirds of the time, and that's worse than always being wrong

Published Aug 25, 2026, 3:31 PM EDT I’m Adam Conway, an Irish technology fanatic with a BSc in Computer Science and I'm XDA’s Lead Technical Editor. My Bachelor’s thesis was conducted on the viability of benchmarking the non-functional elements of Android apps and smartphones such as performance, and I’ve been working in the tech industry in some way or another since 2017. In my spare time, you’ll probably find me playing Counter-Strike or VALORANT, and you can reach out to me at adam@xda-developers.com, on Twitter as @AdamConwayIE, on Instagram as AdamConwayIE, or u/AdamConwayIE on Reddit. Sign in to your XDA account Close to two years ago, I remember asking a Claude model for help with an ESP32 project, and I remember that it told me to use a GPIO pin that straight up didn't exist on that ESP32. I remember looking at the answer, looking at the pins, and feeling very confused at the confidence the response exuded, despite being so clearly wrong. I'd seen failures from AI models lots of times, of course, but this one felt... odd. Everything else was right, but the pin wasn't. As it turns out, this is a very particular problem with microcontrollers and ESP32s. To be fair, it mostly doesn't happen anymore. I ran the same basic ESP32 wiring prompt fifteen times across Sonnet 5 and Opus 5 models, and they didn't invent a pin, so that was good, and they even provided the correct explanation each time for each pin... except for one. For context, on the ESP32, GPIO2 is the pin that decides whether the board boots up its normal firmware, or boots in flashing mode. With both Opus 5 and Sonnet 5, both models gave me advice that changed from run to run, including statements about how boot mode works that were flatly untrue, in opposite directions, each contradicted by other runs of the same model. Opus 5, the more expensive model, wasn't even significantly more accurate; it just consistently picked safer pins instead. I mostly focus on Claude throughout, but similar errors occur with similar frequency using GPT-5.6 Sol. The ESP32 has 34 GPIO pins, but some numbers are skipped Not all of them are real Credit: Major-Nebula1743 The ESP32-D0WD is the classic ESP32, and it's inside every WROOM-32 module and every cheap DevKit clone. It has GPIO0 to 19, 21 to 23, 25 to 27, and 32 to 39. That makes for a total of 34 pins, and the gaps are just completely empty. If you only know the world of Arduino, where pin labels are ordered and the number on the board matches the number in your code, that could definitely catch you out. Those gaps are the least of it, though, because there are even more "gotchas" you need to be aware of. For example, GPIO6 through 11 are wired to the SPI flash chip, so you can't use them without affecting flash access. As well, GPIO34 to 39 are input-only with no internal pull-ups, which means outting to them does absolutely nothing at all. Meanwhile, GPIO0, 2, 5, 12, and 15 are strapping pins, which are measured at start-time and change how the chip boots. And ADC2, which covers GPIO0, 2, 4, 12 to 15, and 25 to 27, is owned by the Wi-Fi driver, so reading them when Wi-Fi is enabled returns garbled data rather than anything usable. Meanwhile, for GPIO20, things get a bit strange: many guides will tell you that it doesn't exist on the ESP32, but that's not quite the case. In ESP-IDF, the valid-GPIO mask for the ESP32 excludes 24 and 28 through 31 and nothing else, so GPIO20 is accepted. The reason is that some of the PICO boards can use it, but none of the other classic ESP32s can. To be fair, current models mostly have this one right. I asked GPT.5-6 Sol, GPT-5.5 Instant, Opus 5, Sonnet 5, and Haiku 4.5 whether GPIO20 was available on a DevKit, and all four got to the right answer. Haiku was the only one that wavered somewhat, but in an interesting way: it correctly said the pin isn't exposed on WROOM modules, then offered as an alternative that GPIO20 might be “reserved internally for the flash memory interface,” which it isn't, and signed off by recommending GPIO0 to 19 and 21 to 27 as the reliable range. That range contains all six flash pins and leaves out 32 to 39 altogether. Models used to invent pins all the time Nonexistent pin numbers, register names, and library references Back in 2023, researchers at the University of Washington ran 450 experiments against GPT-3.5, GPT-4, and PaLM 2 (the precursor to Gemini), and detailed all of the weird ways those models broke. Hallucinations were a focus point, and their findings on how models responded to topics around embedded systems are particularly interesting: “In the context of embedded systems, we see this issue arise with models generating nonexistent pin numbers, register names, and library references.” At the time, they put it down partly to missing system-level context, noting that models tend to fill in unknown values rather than say they don't know. On one task, GPT-3.5 hallucinated at least one address or configuration value in every single trial. It doesn't help that the ESP32 is also significantly harder than comparable boards, including the Arduino, for LLMs to work with. EmbedAgent, a 2025 benchmark covering 126 test cases across Arduino Uno, ESP32, and RP2040, asked models to migrate an Arduino design to another platform. Moving to an RP2040, the best model managed 60.3% pass@1. Moving the same class of design to an ESP32, the best managed 29.4%. A fair chunk of that gap was ESP-IDF syntax rather than pin knowledge, since 41.9% of the ESP32 outputs didn't even compile cleanly, but it's still a huge difference. Part of the reason for that is what these models have learned from. Looking at would-be training data, Stack Overflow holds several clues. When searching for questions tagged Arduino, there are 19,411 questions, and only 475 are tagged esp-idf. Things get worse when looking to GitHub: 415,082 repositories for Arduino, just 9,865 for esp-idf. The ESP32, in both instances, is roughly 40-times smaller in volume than Arduino, which would suggest that models simply have a lot less to learn from. This particularly explains why a high number of compiler errors specifically came from functions that are incompatible with the ESP-IDF version used, even then the ESP-IDF version was specified in the prompt. On top of that, "ESP32" isn't one chip, in the same way that "Arduino" isn't either. The S2 and S3 have no GPIO22 through 25 but can go up to 46 and 48, and the C3 only goes up to 21 with no gaps at all. However, the C6 does go to 30, but its documentation states that variants with in-package flash disable GPIO10 and 11, while variants without it don't expose GPIO14 at all. In other words, even in the same chip family, with the same documentation, you can end up with different pins depending on something seemingly unrelated to the rest of the board. Nowadays, models don't seem to invent pins anymore, but they do fail in other ways. Both Opus and Sonnet contradicted themselves on GPIO2 And it's a pretty important pin GPIO2 is a strapping pin; to enter the serial bootloader, GPIO0 has to be held low, and GPIO2 has to be either floating or driven low, both have to be at the same time. If you hold GPIO2 high, it stops you entering download mode, meaning that you can't flash the board with new firmware. One of my prompts to Sonnet 5 did something interesting: it put the display's DC line on GPIO2 in three of the six runs I did with a vague prompt. SPI DC lines commonly idle high, so that's actually pretty risky to do while assuming that it will just work. In one of those runs, it justified the choice by saying that it was "generally fine as long as your display doesn't hold it low at boot." That's backwards, as low is the safe state, and high is the one that breaks things. In two other Sonnet runs, it started off well by stating that GPIO2 was a strapping pin and should be avoided... before using it anyway, and one of them did so without even addressing the contradiction. The remaining three runs stated that rule correctly while also routing around it. Opus 5 didn't put GPIO2 on a display line across the other runs on the same prompt, but it was still incorrect on the behavior of the pin in one run. It stated that “an LED plus resistor pulling it around at boot can put the chip into download mode," but the thing is, again, that's not how it works. Download mode needs GPIO0 to be low, and with GPIO0 sitting at its normal resting high, nothing GPIO2 does matters to boot mode. An LED to ground on GPIO2 is standard wiring and is completely safe, so if I hadn't known any better, I'd have been pushed away from a more conventional setup because of a mechanism that doesn't exist. Unfortunately, nothing in any of the ouputs makes it clear what's right and what's wrong, unless you're already familiar with what you're asking about. All of the answers came across well-worded and confident, all of them had some kind of warning about strapping pins, yet some of them were the wrong answer. The more expensive model picked better pins It still made factual errors To be fair to more modern LLMs, Opus never tried to assign anything to the risky pin, but Sonnet did half of the time. I tested Sonnet as it's the cheaper model and comes with higher limits, so it's feasible that some people might be asking it for help with building an ESP32-related project. There was one thing I was impressed by, and it's a similar situation to GPIO20. When I asked where a moisture sensor should go, four of the Opus runs gave the ADC1 range as 32 to 36 and 39, while leaving out GPIO37 and 38. What's interesting is that Espressif's documentation, published with v4.2 of the ESP-IDF SDK, say ADC1 covers 32 to 39, so it might seem like an error, but it's actually correct. GPIO37 and 38 are real, but they don't lead anywhere on a WROOM-32. There are plenty of other guides out there that mention the 32-39 range as well without that qualifier. Unfortunately, the other Opus runs gave the range as 32 to 39 and left it there, so it clearly isn't something concretely in the model's knowledge, and Sonnet made the same omission every time. When I ran the prompt with the exact specified board, both models got it repeatedly, whereas they struggled with the more vague prompt. It's clear that naming the actual board allows the model a better reasoning process that lands on the right answer more often than not. Still, that GPIO2 error is a big one, and both Opus and Sonnet made the same mistake. If you're using the more expensive model, it doesn't really seem to change what can happen when it comes to ESP32 pins, and it likely comes back to that lack of training data we mentioned. Models have improved significantly over the last few years, but they'll never be perfect, especially when there's such a big gap in what's available. What's also true is that the models that are reliably wrong are easy enough to work around, but the one that's right two-thirds of the time is the harder one to figure out. A wrong starting point is still a useful one It can help you figure out what you don't know Going back to that University of Washington paper, they found something else that's extremely relevant here, stating that “even when these tools fail to produce working code, they consistently generate helpful reasoning about embedded design tasks.” With that assymetry, they built a workflow where the output was treated as a hypothesis rather than the answer, compiled it, and gave the errors back to the model. Across fifteen users, success on a LoRa environmental sensor build went from 25% to 100%, including for people with no hardware or C experience at all. These findings are consistent with the learning science field, where attempting a problem and getting a wrong answer before being taught the correct method results in a better conceptual understanding than being taught the right way first. A model confidently producing a wrong pin assignment means you get that failure without the painstaking work leading up to it, and the ESP32 is a good teacher as the feedback is quick. It boots, but the LED stays dark, you see from the logs that it's bootlooping, and you investigate. You can’t get a plausible-looking wrong answer past hardware, so you dig deeper, and eventually you find the answer. There are easy ways to prevent this from happening, like naming the exact part rather than just stating an "ESP32." It also helps that Espressif publishes machine-readable constraint data in espressif/esp-gpio-tool, covering per-GPIO alternate functions, RTC flags, and strapping pins, which likely helps models a lot. As well, you can compile your code before flashing it and the SDK will highlight inverted pins, improper peripheral names, and nonexistent libraries. Frontier models have got a lot better at the ESP32, and the specific failure I ran into a couple of years ago seems to be less of an issue these days. What we're left with are some teething issues about specific pins and what they do, and those issues can actually help you learn more and figure out how it all works. If you're using AI for your ESP32 projects, be mindful of the fact that you may need to be a lot more involved than you would have had to be with other development projects.

Original Source

Read the full article at Xda-developers →

KhanList aggregates and links to publicly available news content. We do not host full articles from third-party sources. Always verify important information with original sources.