Lessons Learned - KiCad Footprints and I2C "invalid pins"

A project log for A DC27 CircuitPython Shitty Add-On V1.69BIS Totem

Use CircuitPython to control up to 4 Shitty Add-Ons (SAO) with the V1.69BIS "standard" connectors

Corey BennCorey Benn 07/05/2019 at 16:230 Comments

While saving a lot of details for DefCon, wanted to document a few of the issue we've had in the prototyping stage (still waiting on the final batch of PCBs which we're reflowing/assembling ourselves... we still have like 4 weeks until heading to Vegas right?)

The LEDs

It was my first time looking for and using "Bottom Entry" LEDs which shine through the PCB. Looking at other badges, the SunLED SMD LEDs (XZM2CYK45WT) seemed a popular choice. Also first time doing an area of the PCB which should have no copper, mask, or silk-screen on either side, so was great to find a footprint layout on the KiCad forum.

This worked well for hand soldering, but has a very narrow window on how the LED can be positioned to reach both pads. Then when reflowing, I noticed a number of them being pulled all the way to one pad and sometimes connecting to the copper around the keep-out area during the reflow (did I mention it's a home built toaster oven?). Since I'm not using any filled zones around these LEDs, I dropped the copper around there and moved the pads a little closer while shrinking their total size. This might make it a little harder for hand-soldering, but getting much better results from the reflow. Also included the polarization dot in the silk-screen (lets just make this easy to remember during the light night last minute assembly)

Here's my updated footprint for Kicad XZM2CYK45WT.kicad_mod 

(module "XZM2CYK45WT" (layer F.Cu) (tedit 5D1D1705)
  (fp_text reference "D2" (at 0 -3.2) (layer B.SilkS)
    (effects (font (size 1 1) (thickness 0.15)) (justify mirror))
  (fp_text value "LED" (at -1 -3) (layer B.Fab)
    (effects (font (size 1 1) (thickness 0.15)) (justify mirror))
  (fp_poly (pts (xy -1 1.75) (xy 1 1.75) (xy 1.75 0.75) (xy 1.75 -0.75)
    (xy 1 -1.75) (xy -1 -1.75) (xy -1.75 -0.75) (xy -1.75 0.75)) (layer B.Mask) (width 0.15))
  (fp_line (start 0.575 2.825) (end 0.575 4.125) (layer B.SilkS) (width 0.25))
  (fp_line (start -0.325 2.825) (end -0.325 4.025) (layer B.SilkS) (width 0.25))
  (fp_line (start -0.325 4.025) (end 0.475 3.425) (layer B.SilkS) (width 0.25))
  (fp_line (start 0.475 3.425) (end -0.325 2.825) (layer B.SilkS) (width 0.25))
  (fp_text user "." (at -1.016 2.286) (layer B.SilkS)
    (effects (font (size 1.5 1.5) (thickness 0.15)))
  (pad "2" smd rect (at -2.5 0) (size 1.1 2.6) (layers "B.Cu" "B.Paste" "B.SilkS" "B.Mask"))
  (pad "1" smd rect (at 2.5 0) (size 1.1 2.6) (layers "B.Cu" "B.Paste" "B.SilkS" "B.Mask"))

All The I2C's

We thought it would be bad-ass to have full support for all the pins on the SAO's connectors, even though few of them make use of anything other than power and ground. We also though it would be great if we could support turning an Add-On on or off via code. Routing though quickly became an issue as this was just a 2 layer board and we wanted to keep traces off from the front layer (its just a big pretty ground plane... you can barely notice the vias). So a small compromise is that are two shared i2c buses, instead of each connector getting its own. In the end, we're routing 32 of the 44 SAMD21 pins with just two 0 Ohms resistors (cheating a little there, but for me, that was a cool accomplishment).

Here's the rub, while the SAMD21 supports a number SERCOMs accross different pins, for I2C there are "fixed" pads. So the SDA line can only be on a PAD 0 and a SCL line only on a PAD 1. CircuitPython is great about throwing an "Invalid pins" message when you screw this up like I did on the prototype boards. Adafruit again goes into the details in this blog post which I probably should have fully read first.