Show and Tell and Lessons Learned: Macro Keyboard

  • Projects


KiCAD and CircuitPython files are at:

I randomly stumbled1 onto a FREE (!) class teaching Intro to Printed Circuit Board (PCB) design. It may shock you to know that even as an Electrical Engineer I never learned how to make PCBs and it’s always been something I’ve wanted to do.

Astute readers may remember that I tried making a PCB several years ago, but it never worked2 and I abandoned it.

I can’t rave enough about the class, it’s been a wonderful experience, I learned a lot, made some new friends, and I look forward to taking some other class offerings through!

The goal of the class was learn about PCB design (including designing footprints and symbols), design the PCB itself (including how to use hierarchical layouts), learn about design rule check (DRC) and design for manufacture (DFM), have the PCB fabricated, and then assemble the PCB.

TeachMePCB Course Objective

Everyone in the course made a macro keyboard of some sort. The core “requirements” were:

  • Raspberry Pi Pico microcontroller
  • 10 MX-style key switches
  • 2 Rotary Encoders with RGB LEDs
  • VEML7700 Ambient Light Sensor (I2C)
  • NLSF595 LED Driver (SPI)
  • 10 NeoPixel lights (1-wire)
  • Don’t make a rectangular PCB

I made a couple of changes:

  • Swapped PCA9745B for NLSF595
  • Added ePaper display (because why not make my first project harder)

I used KiCAD, a free and opensource electronic design automation tool to design mine.

Schematic Layout

I actually jumped the gun and started laying out my board in Week 3 because I thought this was the best way to figure out what items I needed for my Bill of Material (BOM). Creating the schematic this way was an — interesting — exercise, and it turned out I was over complicating what that weeks assignment was.

You could layout the board like this, but don’t.

Note for example how I’ve repeated the NeoPixel LEDs ten times (grid ref: A1 to A5), as well as the pushbutton switches ten times (located just below the LEDs). As I would later learn, there’s no need to do that; just make the switch (or NeoPixel) once and then duplicate it (pointing the copy the same schematic so updates propagate correctly). Et voilà!

Once I stopped over complicating it, schematic layout was relatively simple for this particular board.

Top level view of my schematic showing the various sub-sheets

I think the hardest part was making sure I got the eInk circuit right3. The design seems to be a prototypical DC-DC Boost Converter and was the same circuit design used by both the manufacturer (Pervasive Displays) as well as Adafruit’s eInk Breakout Friend.

eInk Display schematic, one of many sheets I designed. This is the updated version once I fixed my issue with RESET line.

Schematic Errors

After I put together my schematics, I would discover (and have corrected in the latest design files) several mistakes

I initially had my pins reversed (Pin 1 was Pin 24, Pin 2 was 23, etc), fortunately I caught that before I had sent my PCB off to be fabricated.

I was less fortunate with the following issues, which I didn’t catch until after the PCB had been fabricated and I started assembly:

Not shown (and fixed via software):

  • S3001 (Bottom Rotary Encoder) Pin 01 (red LED) and Pin 04 (blue LED) are swapped, so they got mapped as BGR instead of RGB.
  • Flipped pin GPIO assignments on U2801:
    • Pin 15 should be labeled as GPIO11 and connect to J2901 Pin 09 (BUSY signal for eInk)
    • Pin 16 should be labeled as GPIO12 and connect to J2901 Pin 11 (Command/Data signal for eInk)

I also ended up removing the rotary encoders I had got from SparkFun (P/N COM-15141) and replacing them with Bourne P/N PEL12T-4225S-S1024 (which I got from Mouser, since they had them in stock) because the red LEDs weren’t really working (they were really, really dim) and the rotary function was very finicky.

Not so much error, per se, but after I printed my paper doll (a scaled 1:1 print) I switched to a different Flat Flexible Cable (FFC) connector so I would have a little more space to hand solder.

PCB Outline

Coming up with a design was challenging and I went through several design ideas:

Several of my earlier designs had fewer keys and rotary encoder since I wasn’t sure I really had a use for a 10-key and two rotary encoders. But I eventually got to a design I liked and then expanded to be a 10-key with two encoders.

I also went from a guarded momentary switch to more of an e-stop button with deflector shroud. Originally I was trying to source once, but then realized I could probably just as easily design one and have it 3D printed—so I did that.

I designed the button assembly in FreeCAD and had it printed in nylon by JLCPCB. The files are up on Thingiverse so go grab it! I originally was going to paint it, but then realized I could let the NeoPixel shine through the nylon—and I didn’t have the paint I needed.

Getting the PCB outline from my head and into KiCAD was rather difficult process, in my opinion. I thought about using Inkscape, but I’m not super familiar with it and so I went with FreeCAD and ended up spending almost an entire day on it.

I was able to export my outline as a DXF and import it in to KiCAD and then lay everything out.

PCB Layout

Layout was incredibly fun and it was hard to stop—there’s always something that can be tweaked. I did a two layer board. I probably spent way to much time adding fun little things. See if you can spot them all!

Most of the parts I used had footprints (either provided by the class, from the vendor, or through Ultralibrarian). I did have to make a couple footprints, such as for the Amphenol connector:

F31L-1A7H1-11024 footprint I had to design

Going from the schematic to the layout might be a confusing, so I put together this graphic showing how the NeoPixel schematic and the switch schematic end up as looking on the laid-out PCB:

Also potentially confusing is that most of the time I’m working without the filled-in areas shown. In reality though, all the empty space is actually filled in as part of the ground plane.

The final design looks something like this:

One of the nice things about KiCAD is that is does a pretty decent render which I think is helpful for doing spacing checks on components

Parts Ordering

I order most of my component parts through DigiKey, but some from Mouser and SparkFun as well. All total, it was about $51.87+tax (in reality the total is a bit more because I bought some extras of certain components). I also had to make several orders because of course I forgot things.

The PCB was ordered from JLCPCB4. It’s amazing how inexpensive PCBs can be! I opted for Electroless nickel immersion gold (ENIG) plating because of aesthetics, so my board was $27.90 + S&H — and that includes 5 copies of the PCB (their minimum order). However, if I did the basic PCB manufacturing it would have been about $9.20 + S&H!

Strange Parts has a great tour of the JLCPCB factory that’s worth watching!

I also had JLCPCB print the e-stop button and deflector should since they could do it in nylon and it only cost $1/each + S&H.


Assembly was pretty straight forward, I printed out my BOM and started soldering. My approach was to solder in stages, doing the most difficult soldering first, and then do it by sub-system (starting with the NeoPixels) so I could do integration testing as I progressed.

While this was my first PCB design, this was not my first PCB assembly and I feel pretty comfortable with the soldering iron. The passive components are Surface Mount Device (SMD) size 2012 (0805 imperial), which means they 2.0 mm (not cm) long and 1.2mm wide. That is very tiny. Ideally I would use solder paste and a reflow oven, but I don’t have one…yet.

I had a flux pen, but I found getting some liquid flux was extremely helpful — especially with the PCA9745B IC and FPC connector, which have a lot of fine pitch legs. I spent a lot of time trying to get the FPC connector soldered without the liquid flux and it was a nightmare.

I also ended up getting a stereo inspection microscope (which has been on my wishlist for ages) and that was helpful in inspecting some of my solder joints for any bridging. Having a good and bright light source is key though.

Board Bring Up

Bringing up the board was pretty easy for the most part.

This was my first foray into CircuitPython and had I RTFM, I would have known that while “some of the CircuitPython compatible boards come with CircuitPython installed. Others [such as the Pico] are CircuitPython-ready, but need to have it installed.”

The two most challenging things were the eInk display and the PCA9745B LED driver (which I used for the RGB LEDs on the rotary encoders). The biggest issue: there was no CircuitPython module for either of those.

I ended up writing a module for both, which you can find on GitHub for now and hopefully PiPy in the future:

The PCA9745B was probably the easiest and least complex. I was also able to find a micropython library for the PCA9745B written by Mirko Vogt at Sensorberg GmbH that was helpful to validate some of my assumptions with.

The Pervasive Display eInk display was more challenging and involved a fair amount of integration hell. Between flip-flopped Busy and Command/Data lines, not having a RESET line (which I’m still not convinced I need), and using the wrong resistor on the current sense line for the DC-DC booster, I was never really sure if my problems were software or hardware or both.

The eInk display was a reach goal and I had to step away from it many times because of the often head-banging frustration.

I was eventually able to find an Arduino library from Pervasive Display, and so I was able to use that to verify if my hardware was correct — it wasn’t.

I actually ended up ordering their development breakout kit (which has all the hardware needed to run the board, including—crucially—the DC-DC booster, and another Pico so I do development with known-good hardware (best $20 spent).

Adafruit/CircuitPython (by way of micropython) has a displayio.EPaperDisplay class that I was able to extend, so I didn’t have to write much of the code from scratch.

One of the interesting things about the Pervasive Display eInk display I was using is that it’s part of their Spectra line which has a chip on glass (CoG) and internal timing circuitry instead of a separate controller (such as the IL0373 or SSD1608). In theory it’s easier to drive since you don’t have to deal with complicated look up tables (LUT), you just send it the bitmap data you want and it handles the rest.

I have an MSO-19, which is a USB oscilloscope and logic analyzer and that was incredibly helpful as well.


The code running on the keypad is CircuitPython, an open source version of Python for tiny, inexpensive computers called microcontrollers.

I may be new to CircuitPython, but not Python. So it’s a pretty natural fit for my programming.

I basically wrote my program as a state machine. It really wasn’t the point of the course, and there’s nothing terribly novel or exciting about it (outside of the two modules I wrote: Fergcorp_CircuitPython_PCA9745B and Fergcorp_CircuitPython_PDISpectra). The code is on GitHub ( and I’m still tinkering with it as of this writing.

I leverage Adafruit’s vast library of CircuitPython modules to handle almost everything, including all the heaving lifting for:

  • USB HID (the part which makes the Pico act like a keyboard) via adafruit_hid
  • Button debouncing via adafruit_debouncer
  • Interfacing with the VEML7700 via adafruit_veml7700

The primary function is, of course, as a Macro Keyboard: keys that I can program to do things on the computer. I’ve also added some other stuff to show off off the board and have some fun:

  • Show the TeachMePCB logo, which also shows off the NeoPixel animation and ambient light sensor
  • Generate and show a QR code (that of course points to the Rick Roll video)
  • Play Tic-Tac-Toe against the computer (implementing the minimax algorithm)
Demonstration of the ambient light sensor dimming all the LEDs.

The screen is crisp and has great resolution (152×152), but it takes 25 seconds to refresh:

Display refresh time is agonizingly slow

In theory I should be able to shave 10 seconds off the refresh rate since the datasheet says it should typically take 14.5 seconds. Unfortunately, since the CoG of this particular display generates the actual waveforms I can’t hack a faster refresh the way Ben did in his video on Applied Science.

As a learning exercise in making my own PCB this has been a resounding success for me and I can’t thank the TeachMePCB facilitators (Mark and Jesse) enough! I managed to get everything working (despite my several snafus) and I’m pretty pleased with it.

Adding the eInk was a good challenge and I’m glad I got it working.

I have lots of ideas for other things I’d like to make, so who knows what will show up next in a Show and Tell.


As a bonus, I also got to show off an almost completed version a couple weeks ago (26 January 2022) at Adafruit’s Show and Tell (I’m at the very end, start at 22m24s):

  1. probably via 

  2. see and 

  3. Narrator: “He didn’t” 

  4. contrary to what my wife thought, I was not using my 3D printer to make the PCB 

Pikler Ladder

View model on Fusion360


Pikler Ladders are expensive. Building one seemed like a good idea. There’s many different designs out there, but none that I was terribly thrilled with. So I designed my own. Then I roped my friend Charlie into helping me build one (spoiler alert: other friends wanted one too…so we made four).

Design requirements:

  1. Safe to use
  2. As low-cost as practical
  3. Easy to store when not in use
  4. Varied angles of use
  5. Easy to make

Version 1

The original concept was this folding design that had two climbing positions, but could also be folded up. I originally was going to use ¾” diameter dowels, but wood is a rather vexing material in terms of strength — it’s what called an anisotropic material which means that it has different material properties in different directions. This is in addition to the varied strength tree-to-tree. I wasn’t confident that ¾” diameter dowels would be sufficient (“safe to use” requirement) and so I upped it to 1″ during Version 3 of the design. However, this designed was ultimately scrapped because the board along the bottom side was unnecessarily, a bit unwieldy, and wouldn’t fulfill the “as low-cost as practical” requirement.

Version 2

This used a removable bar that could be moved up or down a rung to vary the angle. I think this is actually version 2.5, which introduced the “scalloped” edges on the one side to allow the ladder to fold together all the way.

This design was ultimately scrapped because using 1″ diameter dowels didn’t leave sufficient edge margin (“safe to use” requirement) without going to a 1″x6″ board (which would have increased the cost — “as low-cost as practical” requirement). I experimented with offsetting the rungs, but decided that would make it harder to manufacture (“easy to make” requirement). Also cutting all the “scallops” would have been time consuming (also “easy to make” requirement).

Version 3

This is the design we ended up making (see the build notes for deviations and such) and the one I made the drawings for that you can download. I originally discounted this option because there’s no good way to get a 10″x20″x¾” piece of wood without buying an unnecessarily large sheet (“as low-cost as practical” requirement), but by building several ladders at once it helped make this more cost effective. This design also uses 1″ dowels

Material List

This was designed such that you should be able to buy everything at your local major hardware store (and probably most local stores as well). Poplar is recommended as a good compromise of quality, strength, and cost.

This was not sponsored by Lowe’s, but I did end up buying everything from there because they had Poplar dowels and Home Depot did not.

Total Cost: ~$74 (+tax)

Hillman ¼” Wood Insert Lock Nut, Brass
Hillman ¼”-20 x 1½” Machine Screw
Power Pro #8 x 2½” Wood Screw

Build Notes

  • Charlie and I built a total of four of these at first go and it took roughly 15 hours over five (I think) build sessions. So factor in setup and tear-down time as well.
  • You probably don’t need to secure the rungs with screws (though you will still need them to secure the Plate to the the Long and Short Leg Assemblies). We ended up only using screws for the first of the four we built (the rest just used wood glue). If you decide to use screws, it might be a good idea to use a shorter length for those that don’t go through the Plates — it’s a bit harrowing making sure the screws are sufficiently aligned so they don’t split out the dowels.
  • With the cabinet screws we used you don’t have to drill a pilot-hold for the dowels.
  • We broke the sharp edges on the boards using 120 grit sandpaper.
  • We sanded the dowels with 220 grit sandpaper to help give a good finish for little hands.
  • We put a small chamfer on the dowels to help them seat properly during assembly.
  • We used an edge-glued spruce board for the Plate, in retrospect we should have used a plywood with a veneer.
  • The Plate Assembly is a somewhat complex design to manually make. Because I needed to make eight of them I did some math and made a jig of sorts. However I also designed a paper template1that you can just adhere to your plywood.
  • The Storage Position hole is waaaay to close to the edge and will blow out. I’ve left it in the design because I like the idea of being able to keep the bolt with the ladder when it’s folded. If you want to include it then do what I did premptively blow out the hole and sand it so it looks nice-ish — otherwise don’t drill it.
  • If you’re building lots of these, maybe call ahead to make sure they have enough dowels. I ended buying every single 1″x48″ dowel that Lowe’s had on the shelf.
  1. a trick I learned from  

Progress Continues

I got an oscilloscope for my birthday and was able to get through a very important hurdle last week.

I spent the weekend laying out a new PCB, which should arrive in late next week.

Interestingly I’ve also ventured into gray market IC chips from China. We’ll see how this goes.

Don’t worry, it’s still not a bomb…despite all the wires.