Moving from Dev Kit to Custom PCB: What Changes and What Breaks

Your firmware runs. Your sensor reads clean data. The Wi-Fi connects on the first try. You’ve been demoing this prototype for weeks on an ESP32-DevKitC wired to a breadboard, and everything works. You open KiCad, place the same ESP32-WROOM module on a schematic, route a PCB, send it to fab, and wait.
The boards arrive. You solder the module, plug in USB, and get nothing. No serial output. No LED. No boot. Just a dead board staring back at you and a two-week wait for the next revision.
This is not a PCB layout tutorial. This is about the hidden delta between a dev kit and your board: the silent infrastructure that a dev kit provides and that you are now responsible for replicating. These are the things that break at the seam when you move from dev kit to custom PCB, and nearly all of them are avoidable if you know to look.
The examples here use the ESP32 because it’s ubiquitous, but the principles apply to any dev kit to production board transition: STM32 Nucleo, nRF52 DK, RP2040, or anything else with a friendly USB port and a “just works” reputation.
What a Dev Kit Secretly Does for You
Take an ESP32-DevKitC off your desk and look at it. You see a USB port, a module, and some pin headers. What you don’t see is the infrastructure between them:
+-------------------------------------------------------+
| DEV KIT (e.g. ESP32-DevKitC) |
| |
| +----------+ +----------+ +-----------------+ |
| | USB-UART | | Voltage | | Reset + Boot | |
| | Bridge | | Regulator| | Circuitry | |
| | (CP2102/ | | (AMS1117 | | (Auto DTR/RTS | |
| | CH340) | | 3.3V) | | toggle) | |
| +----+-----+ +----+-----+ +--------+--------+ |
| | | | |
| +----v---------------v-------------------v----------+ |
| | MCU (e.g. ESP32-WROOM) | |
| | - Internal flash - Crystal / oscillator | |
| | - Antenna (matched) - Decoupling caps | |
| | - Strapping pins (set) - ESD protection | |
| +---------------------------------------------------+ |
+-------------------------------------------------------+Every one of those blocks is now your responsibility. The USB-UART bridge chip (CP2102 or CH340) that lets you flash and debug over USB: yours to include or replace. The AMS1117 3.3V regulator that quietly handles 5V USB input: yours to spec. The auto-reset circuit that uses DTR and RTS toggling through transistors to put the chip into bootloader mode: yours to design.
The matched antenna, the crystal with correctly calculated load capacitors, the decoupling caps sprinkled across power pins, the pull-ups and pull-downs on strapping pins that determine boot mode: all of these exist on the dev kit’s PCB, doing their jobs invisibly.
Here is the non-optional first step: download and read the schematic for your dev kit. Espressif publishes the ESP32-DevKitC schematic. ST publishes Nucleo schematics. Nordic publishes DK schematics. Every block in that schematic that you don’t consciously replicate or consciously omit is a potential failure on your first custom board.
Hardware Pitfalls: What Breaks on the Board
Power Regulation
The AMS1117 on an ESP32-DevKitC is a 1A-capable LDO. It works fine for bench prototyping. On your board, you need to actually think about what you’re powering.
The ESP32 pulls up to 500mA during RF transmit bursts. If your regulator can only source 300mA, or if you chose one with high dropout voltage and your input rail is only 3.7V from a LiPo, the rail sags during transmission. The module browns out, resets, and you get an endless reboot loop with no obvious cause.
You also need decoupling. Not just one 10µF bulk cap on the regulator output. You need 100nF ceramic caps physically close to each VDD pin on the module. The dev kit has these. Your board needs them in the same places.
Reset and Boot Mode Strapping Pins
This is the single most common killer of first custom ESP32 PCBs. On boot, the ESP32 samples GPIO0, GPIO2, and GPIO12 (MTDI) to determine whether to boot from flash or enter the bootloader. If these pins are floating, because you connected a sensor to GPIO0 without understanding its boot-time role, the chip enters download mode instead of running your firmware.
The dev kit ties these pins to known states through pull-up and pull-down resistors. Your board must do the same. And if you’ve assigned GPIO0 to a peripheral, you need to ensure that peripheral doesn’t drag the pin low during power-on.
Crystal and Clock
The ESP32-WROOM module includes an internal 40MHz crystal, so this is less of an issue there. But if you’re designing around a bare ESP32 chip, or using an STM32 or nRF52 that expects an external crystal, you need to match the load capacitance to the crystal’s datasheet specification. A 20pF-rated crystal with 12pF load caps won’t oscillate reliably. No oscillation means no clock means no boot, and the failure mode is complete silence with no error output.
Antenna and RF
The WROOM module has a PCB trace antenna with a specific keep-out zone requirement: no copper pour, no signal traces, and no ground plane under the antenna area. Espressif’s Hardware Design Guidelines document this with exact dimensions.
First-timers routinely violate this. They pour a ground plane across the entire board, including under the antenna. Or they route I2C traces right beneath it. The result is a board that boots and runs but has 10-15 dBm worse RF performance than the dev kit. Wi-Fi that barely connects at one meter, Bluetooth that drops constantly.
USB Programming Interface
If you drop the USB-UART bridge to save cost or board space, you now need two things: a programming header (TX, RX, GND, and boot/reset control) and a way to enter bootloader mode. The auto-reset circuit on the dev kit uses two NPN transistors (or MOSFETs) driven by the DTR and RTS lines of the USB-UART bridge to toggle GPIO0 and EN in the correct sequence. Without this, you’re manually holding a button while plugging in power, which works on a bench but doesn’t work in any real deployment.
ESD and Input Protection
Dev kits typically include TVS diodes on the USB lines and sometimes on GPIO headers. Your custom board has none unless you add them. This won’t cause a failure on the bench, but it will cause random field failures when a user touches a connector and zaps an unprotected input.
Firmware Pitfalls: What Breaks in the Code
The hardware works. The chip boots. Then the firmware misbehaves in new and confusing ways.
Pin Remapping Surprises
Your dev kit’s silk screen says “D2” but that’s GPIO4. Your custom board routes GPIO4 to a net called SENSOR_SDA. But did you also verify that GPIO4 supports the peripheral you assigned? On the ESP32, some GPIOs are input-only (34-39). Some are connected to internal flash on certain module variants and can’t be used at all (6-11 on WROOM).
| Dev Kit Silk | GPIO # | Function | Custom Board Net | Notes |
|---|---|---|---|---|
| D2 | GPIO4 | I2C SDA | SENSOR_SDA | Needs ext. pull-up |
| D5 | GPIO0 | SPI CS | – | BOOT STRAP PIN! |
| D15 | GPIO12 | PWM out | MOTOR_EN | Strapping: MTDI |
| TX | GPIO1 | UART TX | DEBUG_TX | Shared w/ USB-UART |
Update your pin definitions in firmware before you power on. This sounds obvious and gets skipped constantly.
Flash Configuration Mismatch
If your custom board uses a different flash chip or module variant, the flash mode matters. The ESP-IDF default is DIO, but your module might require QIO, or vice versa. A wrong setting here means the firmware can’t read from flash after the bootloader hands off. The symptom is a boot loop with a flash read error in the early serial output, if you even have serial output.
In ESP-IDF menuconfig:
Serial flasher config → Flash mode → [QIO / DIO / DOUT]
Serial flasher config → Flash speed → [40MHz / 80MHz]Missing Pull-Ups and Pull-Downs
Your I2C bus worked on the dev kit because the dev kit had 4.7kΩ pull-ups on SDA and SCL. Your custom board doesn’t have them. The bus looks electrically dead: lines float, ACKs never come, and your sensor driver returns timeout errors.
Same issue with SPI chip-select lines. If a CS pin floats during boot before your firmware configures it as an output, an attached SPI device responds to garbage on the bus and corrupts the first transactions.
Power Sequencing and Brownout Loops
Your firmware initializes a GPS module, an IMU, and a LoRa radio within the first 100ms of boot. On the dev kit with a beefy USB power supply, this works. On your custom board running from a coin cell or small LiPo through an undersized regulator, the voltage sags below the brownout threshold. The ESP32’s brownout detector triggers a reset. The board reboots, tries to initialize everything again, sags again, resets again. Infinite loop, no useful output.
No More Printf Debugging
If you removed the USB-UART bridge, your printf statements go nowhere. Plan for this before you finalize the design. Break out UART TX/RX to test pads. Add an SWD/JTAG header if your MCU supports it. At absolute minimum, put an LED on a known-good GPIO so you can blink-code your way through first boot.
The “Debuggable First Board” Mindset
Your first custom PCB is not your production board. It is a translation board, a way to verify that you’ve correctly transferred the dev kit’s hidden infrastructure into your own design. Treat it that way.
Practical rules for a first board:
- Test points on every power rail. You need to probe 3.3V, 1.8V (if applicable), and battery voltage without touching IC pins with a scope probe.
- Break out unused GPIOs to a header. You will need them for debugging something you haven’t anticipated.
- Include an LED on a known-good GPIO. The first thing you test is whether the chip boots and runs code. Blink an LED. Everything else comes after.
- Add 0Ω resistors or solder jumpers on power lines. This lets you measure current draw by removing the jumper and inserting a meter. On the dev kit, you never knew your idle current was 80mA because you never measured it.
- Use 0805 passives, not 0402. You will need to rework components. Larger packages are forgiving. Shrink them in revision two.
A debuggable first board costs an extra $2-3 in BOM and maybe 10% more board area. A blind respin costs $500-2000 and two to four weeks. The math is obvious.
Pre-Fabrication Sanity Checklist
Print this. Tape it to your monitor. Check every box before you submit your fabrication order.
PRE-FAB SANITY CHECKLIST
─────────────────────────────────────────
[ ] Dev kit schematic reviewed and understood
[ ] Power: regulator handles peak current + margin
[ ] Power: bulk + local decoupling caps placed
[ ] Boot/strapping pins: defined states (pull-up/down)
[ ] Reset: RC circuit or supervisor IC present
[ ] Programming header: pinout matches toolchain
[ ] Crystal: load caps match datasheet spec
[ ] Antenna: keep-out zone respected, impedance matched
[ ] I2C pull-ups on board (not relying on external)
[ ] Test points on: VCC, GND, TX, RX, RESET, key GPIOs
[ ] Firmware pin map updated to new schematic
[ ] Flash mode / partition config reviewed
[ ] BOM cross-checked against schematic (not layout)
[ ] At least one "blinky" LED for first power-on test
─────────────────────────────────────────Every unchecked box is a potential dead board.
Your First Board Revision Is Not a Failure
Professional hardware teams at companies with decades of experience budget for board revisions. Two or three spins before production is normal. One spin is lucky. Zero is fantasy.
The gap between a working dev kit prototype and a working custom board is not about skill or intelligence. It’s about awareness of hidden infrastructure: the regulators, pull resistors, boot circuits, and protection components that a dev kit provides silently and that your board must provide explicitly.
You know where to look. Read your dev kit’s schematic. Run the checklist. Design for debuggability. And when revision A doesn’t work perfectly, because it probably won’t, you’ll know exactly where to probe first.
Hubble Network enables Bluetooth connectivity from custom PCBs directly to satellite — without ground infrastructure or gateway dependencies. See how it works →