The “available but not really” pins on many ESP32 models is one of the bigger “traps for young players” with the ESP32. The pins for flash memory are one, the pins for external PSRAM on WROVER models is another, and another are the bootstrapping pins, which control the boot process and are usable after startup, but are tricky to use if your circuit pulls them high or low. That’s GPIOs 0, 2, 4, 5, 12, and 15, though usually only 0 and 2 are critical. Another common trap is that ADC2 is somehow involved in wifi, so if you enable wifi, you cannot use the second ADC.
This is a good overview of the pin restrictions:
https://randomnerdtutorials.com/esp32-pinout-reference-gpios/Some, but not all, of these limitations are addressed in the newer ESP32 models like the S3 (which I need to try out more).
I HIGHLY suggest creating an IO assignment spreadsheet for any ESP32 project that needs more pins than the few that are totally unencumbered. Paste an image of the ESP32 in the middle and scale it to match the cell sizes. (Basically, make a diagram similar to the one at the top of the link above, then add a column or two for your own signal names.)
Believe it or not, though, the ESP32’s pin assignment capability is otherwise quite flexible, more so than many MCUs. (On many, especially older ones, many things like SPI, I2C, and UART cannot be moved at all.)
P.S. Pro tip: add a 1-10uF capacitor from the EN pin to ground. This will ensure it enters firmware programming mode reliably. I don’t know why sometimes it’s needed and sometimes it’s not (sometimes it even appears to depend on what code is running on the ESP32 already!), so when designing anything with an ESP32, I just add it as a matter of course since it costs peanuts. (The cap’s function is to ensure the ESP32 is held in reset long enough for GPIO0 to be pulled low
before it tries to boot. The cap takes time to charge, extending the time the EN pin is held at a voltage considered “low”.)