This is the board I made to learn PCB design properly. Most people in the class were building "hats" that sit on top of an STM32 Nucleo board, no MCU of their own. They just have headers and a few peripherals wired out. That felt like skipping the part I actually wanted to learn, so I designed a board with the microcontroller on it and everything a microcontroller needs around it.
It is the controller side of an RC car: two joysticks, an OLED to show what you are doing, and an HC-05 to get it across to the car.
Feature set
- STM32F446RE as the MCU, with its own crystal, decoupling, and boot config.
- USB-C for power and programming, with 90 ohm differential impedance controlled traces.
- BQ24092DGQR single-cell LiPo charger, so it runs off a battery and charges over USB.
- 5 V and 3.3 V buck converters for the rails.
- SWD header for flashing and debugging.
- HC-05 Bluetooth module for the link to the car.
- SSD1306 OLED over I2C.
- Two analog joysticks.
Why not a Nucleo hat
A hat is a fine assignment, but the Nucleo does all the interesting parts for you. It already has the crystal, the regulator, the reset circuit, the USB, the programmer, and a pinout someone else decided on. If you build a hat, you learn connector footprints and not much else.
Putting the MCU on my own board meant I had to work out the power tree, the boot and reset pins, the crystal load capacitors, the debug header, and how to program a bare chip. All of that was new to me, and all of it is the part that actually transfers to the next board.
MCU selection
I went with the STM32F446RE mostly because it is the chip on the Nucleo the course used, so I already had a board to prototype against and a toolchain that worked. 180 MHz, plenty of flash, and more timers and ADC channels than this project needs. Using a part I could buy in a hurry mattered more than picking something optimal.
Power
USB-C in, battery in, one of them powering the board at a time.
The BQ24092DGQR handles the LiPo side. It is a linear charger, which is less efficient than a switcher, but at the currents a single cell wants that does not matter and it needs almost no external parts. It also does the thing I cared about most: it lets the board run while the battery is charging.
From there, a 5 V buck for the OLED and the HC-05 rail, and a 3.3 V buck for the MCU. Bucks rather than LDOs because dropping from a charged cell down to 3.3 V through a linear regulator wastes most of it as heat.
USB-C and the differential pair
This was the part I was most nervous about. USB 2.0 full speed wants a 90 ohm differential pair, and until this board I had never thought about impedance at all.
I picked a stack-up, used the jlcpcb's calculator to get the trace width and gap for 90 ohm, kept the pair short, kept it over a solid ground plane, and length matched the two legs. It is not a fast interface and it would probably have worked without any of that, but doing it properly on something forgiving felt like the right place to learn it.
Input and display
Two analog joysticks into the ADC, and an SSD1306 OLED over I2C. Nothing clever here, but routing the joystick lines away from the switching regulators mattered more than I expected.
The HC-05 sits on a UART. It is an old module and there are better options now, but it is cheap, the documentation is everywhere, and pairing it is a solved problem.
Media
What I got out of it
- A better understanding of how to design a PCB from scratch.
- Designing a power tree instead of being handed one.
- Impedance control, on an interface slow enough to forgive getting it wrong.
- MCU decoupling, reset, and boot configuration.