My awesome macropad!
Hardware- 9 Devlogs
- 16 Total hours
Building a macro pad to learn about PCB designs and firmware
Building a macro pad to learn about PCB designs and firmware
Devlog #9 (Hopefully the last one)
I spent this session pulling everything together for shipping. I sorted out the actual folder structure needed for submission: a top-level project folder containing CAD, PCB, and Firmware source folders, plus a separate production folder with the manufacturing-ready files. I copied the firmware source files (keyboard.json, keymap.c, rules.mk) over from the WSL environment into the Windows-side project folder to get everything in one place ready to push to GitHub. I also wrote the README covering the CAD assembly, schematic, PCB, case, and firmware.
Challenges:
I didn’t face many challenges during this step. Most questions were answered by searching on Google.
Next Steps:
All I need to do now post in #hackpad-ships and fill out the submission form! Wish me luck!
Devlog #8
I wrote and compiled the updated firmware.
I got the QMK firmware finished for the final 7-key layout plus the rotary encoder and OLED. I updated keyboard.json to match my actual pinout, then ran into a string of small compile errors working through keymap.c: wrong argument count for LAYOUT() since my key count changed, a stray trailing comma, and using MATRIX_LAYERS which isn’t actually a valid macro in this QMK version, just needed a “1” for a single layer.
I ended up swapping Close Tab for Paste in the final key layout so Copy and Paste are usable together instead of just having Copy on its own. The final layout is New Tab, New Window, Undo, Redo, Refresh, Paste, Copy, with the encoder controlling volume and the OLED showing a static ready message for now.
Challenges:
Getting a clean compile didn’t actually mean the firmware did what I expected, since I realized later that I was still missing the rules.mk file.
Next Steps:
The firmware compiles clean and outputs a working .uf2 file. I’m going to package everything up for submission: Gerbers, case files, firmware, README, and BOM. I might also add some flair to the Tinkercad case to make it more personalized.
Devlog #7
I spent this session finishing the plate and case design.
For the switch plate, I used ai03’s plate generator, converting my actual switch coordinates from KiCad into KLE units to match my diagonal layout. The generator only handles switch cutouts though, so I had to add the encoder shaft and OLED window manually afterward.
For the OLED cutout specifically, I went back and forth on sizing. I initially calculated the exact active pixel area from the display’s diagonal and aspect ratio, landing on 22.4mm by 5.6mm, and later confirmed that matched published specs for this exact 0.91 inch 128x32 panel almost exactly. But once I found and applied an actual KiCad footprint for the specific SSD1306 module in my kit, it gave me a real, confirmed “OLED Panel” reference rectangle at 12 by 29.5mm, which I ended up using instead since it meant I had exact coordinates to work from rather than an estimate, and it also gives a cleaner look showing the whole black display bezel rather than a tightly cropped window.
I also reconsidered how the XIAO should sit in the case after seeing a reference build with the microcontroller mounted visibly on the front instead of hidden on the back. I decided I liked that look better and flipped my XIAO footprint back to the front layer, which meant deleting and rerouting all of its traces from scratch since flipping a footprint doesn’t automatically carry old routing over to the new pad positions.
I also seriously considered adding SK6812 addressable LEDs under the switches, since the kit includes them. Worked out a plan to free up a pin by moving the encoder’s click button into an open matrix slot instead of giving it a dedicated GPIO, but ultimately decided against it. My switches and keycaps are just standard opaque parts, not shine-through ones, so the LEDs likely wouldn’t have been very visible anyway, and it didn’t seem worth the rework for a feature that might not even show up.
Challenges:
The diagonal-stagger switch layout kept creating small complications throughout this whole case-building process, from margin offsets to plate generation to figuring out exact cutout positions. Also learned the hard way that flipping a footprint mirrors the pads but doesn’t move existing traces with it, so that was a full reroute rather than a quick fix. Overall, my time spent with Tinkercad was difficult, and if I had to restart the design I would’ve used OnShape for greater precision and its advanced features.
Next Steps:
The case and plate are both done. Now I’m moving on to firmware, starting with the keymap and getting the encoder and OLED working in QMK.
Devlog #6
I started rebuilding the case for the new PCB design.
After finishing the PCB layout with its diagonal-stagger switch arrangement, I moved into CAD to build a matching case, working through a much more complex shape than my first attempt since the board isn’t a plain rectangle anymore.
My first try at this was rough. I was eyeballing most placements, zooming in super close and manually nudging shapes by dragging until things looked roughly aligned. It kind of worked, but margins ended up inconsistent between edges, and rounding corners or offsetting the diagonal edge properly was nearly impossible to get right by eye. I ended up scrapping that entire first attempt once I learned Tinkercad actually has real alignment tools and exact coordinate input in the properties panel, instead of relying on visual snapping and guesswork. I threw away around 1.5 hours of work and redid the whole model from scratch using typed coordinates and the align tool wherever two edges needed to match exactly, which gave a cleaner result.
Also had to work out how to offset the diagonal edge specifically, since scaling a duplicate shape up distorts a diagonal edge into a taper instead of a consistent parallel margin, so I calculated the perpendicular offset separately from the straight edges to keep the margin even all the way around.
Overall, I got the base and outer walls built with a consistent 10mm margin, added 4 mounting holes using the guide’s direct-into-plastic method with 2.9mm holes, and rounded the four corners for a cleaner look.
I was also considering an LED backlighting idea, but decided to drop it since it would’ve needed a spare GPIO pin I don’t actually have on the XIAO.
Challenges:
I realized that I probably should have learned to use Tinkercad a bit more before jumping into the project, as I didn’t know how unreliable eyeballing was. Also I caught a mismatch between my schematic and PCB where a switch had been removed from the board but was still present in the schematic, which needed re-syncing.
Next Steps:
The case walls and base are done. I still need cutouts for the OLED window, encoder shaft, and USB-C port.
Devlog #5
I spent this session finishing the physical PCB layout, which ended up being a much longer process than I expected because I went through three fairly different approaches before landing on something that actually worked.
First off, I decided to give the left column of switches a diagonal stagger instead of a straight grid, inspired by a macropad by Froskeys in the Hackpad galley, that used a similar fanned-out layout. The idea is that a diagonal arrangement follows the natural arc your fingers make when your hand rests on the board, so reach feels more even across all the keys instead of some being awkward stretches.
My first attempt was just a plain grid of 8 switches with no real thought behind the physical arrangement. It technically worked, but it didn’t fit within the 100x100mm size limit the Hackpad program requires, coming in at 108mm vertically. I also tried to save space by placing the XIAO microcontroller underneath three of the switches. Even though the components were on opposite sides of the board, the actual drill holes for switch legs and XIAO pins still passed through the entire board thickness, and landed on top of each other. That was a good lesson that opposite layers doesn’t always mean that a collision won’t occur.
My second attempt scrapped the overlap idea entirely and instead focused on compressing spacing everywhere: tightening the switch pitch to exactly 19.05mm, pulling the encoder and XIAO in closer, and moving the OLED header and capacitor out of dead space. This got me under the limit, but the layout still felt a bit boxy and arbitrary.
For the final version, I took some advice from my brother who walked had walked into my room and immediately told me that the design would look better if it was entirely rotated. Initially, my diagonal edge was on the left, but instead rotating it to the bottom also provided a distinct asymmetric shape while keeping it’s ergonomic function.
Along the way I also had to fix a wave of Design Rules Checker errors and add mounting holes without letting their clearance rings collide with nearby components, which happened more than once. Finally, I designed the copper pathways to connect all the components and provide a finalized PCB.
Challenges:
The biggest recurring issue was learning that visual inspection alone isn’t reliable for catching real electrical problems. I found that several times a layout looked fine by eye but DRC caught actual shorts or courtyard violations I hadn’t noticed. I also learned the hard way that mounting hole footprints include a much larger keepout zone than just the drill hole itself, which caused an unexpected collision with the XIAO’s pins.
Next Steps:
The layout is finalized and DRC is clean. Next is fixing the case design I have in Tinkercad to update the new PCB layout, and eventually writing the firmware to match this final pinout.
Devlog #4
Finished assigning the footprints for the project and finally got a completely clean ERC with 0 errors.
Moved into the PCB editor after that and immediately hit the 100x100mm size constraint. My first layout came in at 108mm vertically, so I spent a while compressing the diagonal switch stagger, tightening spacing to exactly 19.05mm, and moving the OLED header and capacitor out of dead space.
Then I tried to reclaim even more space by tucking the XIAO underneath three of the switches instead of placing it separately, since it’s flipped to the back layer anyway for assembly. Ran DRC to check for collisions and it came back ugly, with actual solder mask bridges between XIAO pins and switch pins on completely different nets. Also had courtyard overlaps between a few diodes and switches, and hadn’t drawn the board outline yet so some checks couldn’t even run properly.
Challenges:
I’m still learning that even parts on opposite layers can collide, as the pins themselves are still physical holes drilled through the entire board. So a switch’s hole and the XIAO’s pad can still land on top of each other even though the components sit on opposite faces.
Next Steps:
I’m going to scrap the XIAO-under-switches idea. Going back to a layout where nothing overlaps, and instead squeezing space by tightening gaps between all components more aggressively across the whole board. Once placement is solid and collision-free, I can finally draw the board outline and start routing.
Devlog #3
I went back into the schematic after realizing I was only using 3 of the 16 switches from the kit. Expanded the design to 8 switches wired in a proper 4x2 diode matrix, added one of the rotary encoders, and wired in the 0.91” OLED screen. I spent most of the session debugging the Electrical Rules Checker, which kept flagging power pin errors I didn’t understand at first. I think it’s because I had multiple 3V3 symbols that weren’t actually connected to each other since power symbols only merge nets if they’re physically wired together, not just because they share a name. Fixed that by adding a PWR_FLAG.
Challenges:
Understanding how diodes and rotary encoders work helped me implement new ideas into my hackpad.
Next Steps:
Get the XIAO footprint sorted with the correct library, then finish assigning footprints to the diodes, header, and encoder. After that I can finally generate the PCB layout from the schematic and start routing traces for the full 8-switch matrix instead of just the 3 I had before.
Devlog #2
Started and finished the Hackpad case design, and it was also my first time ever doing any real CAD work. The guide used Fusion360, but I ended up using Tinkercad instead due to storage limitations, which made the workflow a bit different. I started by recreating the PCB dimensions with tolerance, then built the outer case. After that, I extruded the base and walls, and worked through aligning everything properly so the PCB would actually fit inside the enclosure. I also imported the plate design and positioned it so it aligned correctly with the case, then added the USB cutout to finish the basic structure.
Challenges:
This took a lot longer than expected because I had no prior CAD experience. There were definitely shortcuts for actions I wanted to do, which I did not know. Understanding tolerances and how much extra space to leave for a real-world fit was also something I had to figure out as I went.
Next Steps:
I will continue following the guide for now, where I plan to write the firmware and start bringing the macropad to life. After that, I want to start making the project more unique with my own design changes instead of just following the base tutorial.
Devlog #1
Started working on the Hackpad mission today, and it’s also my first time ever using KiCad or designing a PCB. Coming from mostly a software-based background, the whole workflow was completely new to me. I spent a lot of time figuring out the difference between symbols, footprints, schematics, and the PCB layout. Today I drew the schematic, connected the switches to the XIAO microcontroller, assigned footprints, and started laying everything out in the PCB editor. Seeing the design come together in the 3D viewer for the first time was really satisfying and made it feel like a real piece of hardware instead of just a diagram.
Challenges:
Routing traces was definitely the biggest learning curve so far. It’s a lot more like solving a puzzle than I expected.
Next Steps:
I will continue following the guide for now, where I plan to design the case in Tinkercad and write the firmware. Then I will add my own design changes.
I’m excited to keep building and (hopefully) end up with a working macropad!