Designing a custom PCB with a push button input and LED output using the Seeed XIAO ESP32-C3
For this week's assignment, I designed a custom PCB that incorporates a push button as an input device and an LED as a visual output indicator. The goal was to build a complete inputβoutput system from scratch β designing the schematic and layout in KiCad, fabricating the board, soldering the components, and writing firmware that reads the button state and responds by toggling the LED.
This exercise builds directly on my earlier work in electronics design and production, allowing me to integrate input sensing into a self-designed board rather than relying on a development kit. It also pushes toward my final project, which involves a smart light fixture where user inputs control lighting behavior.
| Component / Tool | Details |
|---|---|
| Microcontroller | Seeed XIAO ESP32-C3 |
| Input device | SMD tactile push button |
| Output indicator | Through-hole LED |
| Design software | KiCad |
| Programming IDE | Arduino IDE |
| Pin assignments | Button β D1, LED β D9 |
I started by designing the circuit in KiCad. The design centers on the Seeed XIAO ESP32-C3, chosen for its compact footprint, built-in Wi-Fi/Bluetooth capabilities, and compatibility with the Arduino ecosystem. For this assignment I used only its GPIO functionality, but the wireless capability will be relevant for my final project.
The schematic includes:
I chose a through-hole LED for ease of soldering and visual clarity, and an SMD tactile button to practice working with surface-mount components.
With the schematic complete, I moved to the PCB layout design phase in KiCad.
Key layout decisions: button placed at the board edge for easy thumb access; 0.8 mm trace widths for signal lines; ground fill on the bottom copper layer to reduce noise and simplify routing.
The firmware was written in the Arduino IDE, using the ESP32-C3's Arduino-compatible environment. The logic is simple: poll the button state continuously and mirror it to the LED.
// XIAO ESP32 C3 - LED and Button
const int LED_PIN = 9; // GPIO9
const int BUTTON_PIN = 3; // GPIO3
void setup() {
pinMode(LED_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP); // Internal pull-up resistor
}
void loop() {
int buttonState = digitalRead(BUTTON_PIN);
// Button is LOW when pressed (due to INPUT_PULLUP)
if (buttonState == LOW) {
digitalWrite(LED_PIN, HIGH); // Turn LED ON
} else {
digitalWrite(LED_PIN, LOW); // Turn LED OFF
}
}
}
After uploading the firmware, I tested the board by pressing and releasing the button repeatedly to confirm:
All four conditions were satisfied. The response felt instantaneous β confirming that the INPUT_PULLUP configuration and polling-based loop are sufficient for this interaction speed.
The following video demonstrates the board in operation: pressing the button illuminates the LED, releasing it turns the LED off.
| File | Description | Download |
|---|---|---|
W09_Input_Button_LED_KiCAD.zip |
Full KiCad project (schematic, PCB, BOM, netlist) | β¬ Download |
The Arduino firmware is fully reproduced in the Code section above. All KiCad design files are available for download above.
This assignment made concrete something I had understood only theoretically: designing the schematic, laying out the PCB, fabricating it, soldering it, and then writing code that makes a physical LED respond to a physical button press gives a deeply satisfying sense of the whole system.
My final project is a smart light fixture where user inputs control lighting behaviour. The button-to-LED circuit built here is a simplified version of that user-input subsystem. This week consolidated the electronics design and production skills from Weeks 6 and 8 β I now feel capable of designing a board that integrates sensors, writing firmware that reads and reacts to them, and debugging the result systematically.
AI Disclosure: Claude (Anthropic) was used as a writing tool to help proofread and structure the documentation on this page. All designs, fabrication, and technical decisions are my own.