Week Five: Electronics Design

Assignment and idea:

This week’s assignment focused on using an electronic design automation (EDA) tool to design a development board and interact and communicate with an embedded microcontroller.

I’ve soldered wires in cars with my friends, and soldered a pipe with my dad as a kid, but I had never soldered a microcontroller, so I had to lean on the teaching team for a deep dive at the Harvard REEF!

First, Leo helped me think through what I wanted to do, and I explained my desire to focus on simplicity: to embed the Xiao RP2040 that I learned to control in week 3, and get it to do something, such as blink an LED that I would embed on the board. He encouraged me to consider adding a button and an FTDI header, in case I wanted to expand capabilities in the future.

I started by selecting a simple EDA tool: SVG-PCB (https://leomcelroy.com/svg-pcb-website/#/home). Given that Leo and the teaching team wrote this EDA, I was in good hands!

I started by expanding the black box that appears when your first open SVG-PCB and dragged out the SAM11C and imported in the RP2040, the FTDI header, the LED, and a button using the “import” button, and connected the components with wires to the RP2040 by following the documentation and pinouts found here:

https://wiki.seeedstudio.com/XIAO-RP2040/

SVG PCB Placement

Once I had the layout that I felt I could solder, I deselected the layers on the right-hand side of the tool to strip away the descriptive text and leave paths and footprints that I could turn into a PNG for the milling software:

SVG PCB drop traces SVG PCB descriptions for components only Just traces of a board

We were off to the milling station where I mounted my bit:

Milling bit that broke for everyone

We used Mods CE for our milling tool: https://modsproject.org/

… Mods takes a simple PNG or SVG file, and can turn it into a millable trace, and communicate those traces to a milling machine.

Screenshot of milling settings Path for milling

Our machine, the Roland SRM-20, requires significant setup in Mods once we placed the copper plated PCB board down on a wax block with double-sided tape:

Copper plate and tape

We had to account for the height of the wax, the thickness of the board and tape, and its position on the pad along with the milling bit position in the head by adjusting the X, Y, and Z parameters along with origin and home location. It helps to take a screenshot of all of the parameters you setup to get the bit so it is just touching the surface before you start milling:

Milling in action

When you are ready, you close the door and “send file” to the Roland:

Milled board Milled PCBremoved from board and on soldering station

Once milling is complete, which took less than 10 minutes for my simple board, you snap off the milled section and move on to the soldering station. I placed each component with tweezers, added a little flux onto the traces I wanted to solder to help with flow, and gently heated up some solder against the tip of the iron and the fluxed surface. I repeated this step 15 times to fasten all of the connections with a nice bead:

Components to solder Soldering under a microscope Soldering under a microscope Soldering under a microscope Soldering under a microscope Soldering under a microscope Soldering under a microscope Soldering under a microscope Soldering under a microscope Soldering under a microscope Soldering under a microscope Soldering under a microscope

After about an hour of soldering, I had my first board with an embedded microcontroller that could receive the blink LED code to an embedded LED from week 3!

Assembled board!

If you are looking to recreate this simple board, you can paste in my design code to SVG-PCB: /* @version: v0.1.0 a basic starter design */ /* -- DECLARE_PCB -- */ const board = new PCB(); /* -- DECLARE_COMPONENTS -- */ const R_1206 = footprint({"1":{"shape":"M -0.032,0.034L 0.032,0.034L 0.032,-0.034L -0.032,-0.034L -0.032,0.034","pos":[-0.06,0],"layers":["F.Cu","F.Mask"],"index":1},"2":{"shape":"M -0.032,0.034L 0.032,0.034L 0.032,-0.034L -0.032,-0.034L -0.032,0.034","pos":[0.06,0],"layers":["F.Cu","F.Mask"],"index":2}}); const button_6mm = footprint({"L1":{"shape":"M -0.04,0.03L 0.04,0.03L 0.04,-0.03L -0.04,-0.03L -0.04,0.03","pos":[-0.125,0.08],"layers":["F.Cu","F.Mask"],"index":1},"R1":{"shape":"M -0.04,0.03L 0.04,0.03L 0.04,-0.03L -0.04,-0.03L -0.04,0.03","pos":[-0.125,-0.08],"layers":["F.Cu","F.Mask"],"index":2},"R2":{"shape":"M -0.04,0.03L 0.04,0.03L 0.04,-0.03L -0.04,-0.03L -0.04,0.03","pos":[0.125,-0.08],"layers":["F.Cu","F.Mask"],"index":3},"L2":{"shape":"M -0.04,0.03L 0.04,0.03L 0.04,-0.03L -0.04,-0.03L -0.04,0.03","pos":[0.125,0.08],"layers":["F.Cu","F.Mask"],"index":4}}); const header_FTDI = footprint({"GND":{"shape":"M 0.05,0.025L -0.05,0.025L -0.0509,0.025L -0.0517,0.025L -0.0535,0.0248L -0.0552,0.0244L -0.056,0.0243L -0.0578,0.0237L -0.0593,0.0232L -0.0602,0.0229L -0.061,0.0225L -0.0618,0.0221L -0.0625,0.0216L -0.0633,0.0212L -0.064,0.0208L -0.0654,0.0197L -0.0661,0.0191L -0.0668,0.0186L -0.0686,0.0168L -0.0691,0.0161L -0.0697,0.0154L -0.0708,0.014L -0.0712,0.0133L -0.0716,0.0125L -0.0721,0.0118L -0.0725,0.011L -0.0729,0.0102L -0.0732,0.0093L -0.0737,0.0078L -0.0743,0.006L -0.0744,0.0052L -0.0748,0.0035L -0.075,0.0017L -0.075,0.0009L -0.075,0L -0.075,-0.0009L -0.075,-0.0017L -0.0748,-0.0035L -0.0744,-0.0052L -0.0743,-0.006L -0.0737,-0.0078L -0.0732,-0.0093L -0.0729,-0.0102L -0.0725,-0.011L -0.0721,-0.0118L -0.0716,-0.0125L -0.0712,-0.0133L -0.0708,-0.014L -0.0697,-0.0154L -0.0691,-0.0161L -0.0686,-0.0168L -0.0668,-0.0186L -0.0661,-0.0191L -0.0654,-0.0197L -0.064,-0.0208L -0.0633,-0.0212L -0.0625,-0.0216L -0.0618,-0.0221L -0.061,-0.0225L -0.0602,-0.0229L -0.0593,-0.0232L -0.0578,-0.0237L -0.056,-0.0243L -0.0552,-0.0244L -0.0535,-0.0248L -0.0517,-0.025L 0.05,-0.025L 0.05,0.025","pos":[0,0.25],"layers":["F.Cu","F.Mask"],"index":1},"CTS":{"shape":"M -0.05,0.025L 0.05,0.025L 0.05,-0.025L -0.05,-0.025L -0.05,0.025","pos":[0,0.15],"layers":["F.Cu","F.Mask"],"index":2},"VCC":{"shape":"M -0.05,0.025L 0.05,0.025L 0.05,-0.025L -0.05,-0.025L -0.05,0.025","pos":[0,0.05],"layers":["F.Cu","F.Mask"],"index":3},"Tx":{"shape":"M -0.05,0.025L 0.05,0.025L 0.05,-0.025L -0.05,-0.025L -0.05,0.025","pos":[0,-0.05],"layers":["F.Cu","F.Mask"],"index":4},"Rx":{"shape":"M -0.05,0.025L 0.05,0.025L 0.05,-0.025L -0.05,-0.025L -0.05,0.025","pos":[0,-0.15],"layers":["F.Cu","F.Mask"],"index":5},"RTS":{"shape":"M -0.05,0.025L 0.05,0.025L 0.05,-0.025L -0.05,-0.025L -0.05,0.025","pos":[0,-0.25],"layers":["F.Cu","F.Mask"],"index":6}}); const xiao_copper = footprint({"0": {"pos": [-0.2998031496062992,0.3],"shape": "M -0.05905511811023622 0.031496062992125984 L 0.05905511811023622 0.031496062992125984 L 0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 0.031496062992125984 ","layers": ["F.Cu","F.Paste","F.Mask"],"drill": {"diameter": null,"start": "F.Cu","end": "B.Cu","plated": true}},"1": {"pos": [-0.2998031496062992,0.2],"shape": "M -0.05905511811023622 0.031496062992125984 L 0.05905511811023622 0.031496062992125984 L 0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 0.031496062992125984 ","layers": ["F.Cu","F.Paste","F.Mask"],"drill": {"diameter": null,"start": "F.Cu","end": "B.Cu","plated": true}},"2": {"pos": [-0.2998031496062992,0.1],"shape": "M -0.05905511811023622 0.031496062992125984 L 0.05905511811023622 0.031496062992125984 L 0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 0.031496062992125984 ","layers": ["F.Cu","F.Paste","F.Mask"],"drill": {"diameter": null,"start": "F.Cu","end": "B.Cu","plated": true}},"3": {"pos": [-0.2998031496062992,0],"shape": "M -0.05905511811023622 0.031496062992125984 L 0.05905511811023622 0.031496062992125984 L 0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 0.031496062992125984 ","layers": ["F.Cu","F.Paste","F.Mask"],"drill": {"diameter": null,"start": "F.Cu","end": "B.Cu","plated": true}},"4": {"pos": [-0.2998031496062992,-0.1],"shape": "M -0.05905511811023622 0.031496062992125984 L 0.05905511811023622 0.031496062992125984 L 0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 0.031496062992125984 ","layers": ["F.Cu","F.Paste","F.Mask"],"drill": {"diameter": null,"start": "F.Cu","end": "B.Cu","plated": true}},"5": {"pos": [-0.2998031496062992,-0.2],"shape": "M -0.05905511811023622 0.031496062992125984 L 0.05905511811023622 0.031496062992125984 L 0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 0.031496062992125984 ","layers": ["F.Cu","F.Paste","F.Mask"],"drill": {"diameter": null,"start": "F.Cu","end": "B.Cu","plated": true}},"6": {"pos": [-0.2998031496062992,-0.3],"shape": "M -0.05905511811023622 0.031496062992125984 L 0.05905511811023622 0.031496062992125984 L 0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 0.031496062992125984 ","layers": ["F.Cu","F.Paste","F.Mask"],"drill": {"diameter": null,"start": "F.Cu","end": "B.Cu","plated": true}},"7": {"pos": [0.3,-0.3],"shape": "M -0.05905511811023622 0.031496062992125984 L 0.05905511811023622 0.031496062992125984 L 0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 0.031496062992125984 ","layers": ["F.Cu","F.Paste","F.Mask"],"drill": {"diameter": null,"start": "F.Cu","end": "B.Cu","plated": true}},"8": {"pos": [0.3,-0.2],"shape": "M -0.05905511811023622 0.031496062992125984 L 0.05905511811023622 0.031496062992125984 L 0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 0.031496062992125984 ","layers": ["F.Cu","F.Paste","F.Mask"],"drill": {"diameter": null,"start": "F.Cu","end": "B.Cu","plated": true}},"9": {"pos": [0.3,-0.1],"shape": "M -0.05905511811023622 0.031496062992125984 L 0.05905511811023622 0.031496062992125984 L 0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 0.031496062992125984 ","layers": ["F.Cu","F.Paste","F.Mask"],"drill": {"diameter": null,"start": "F.Cu","end": "B.Cu","plated": true}},"10": {"pos": [0.3,0],"shape": "M -0.05905511811023622 0.031496062992125984 L 0.05905511811023622 0.031496062992125984 L 0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 0.031496062992125984 ","layers": ["F.Cu","F.Paste","F.Mask"],"drill": {"diameter": null,"start": "F.Cu","end": "B.Cu","plated": true}},"3V3": {"pos": [0.3,0.1],"shape": "M -0.05905511811023622 0.031496062992125984 L 0.05905511811023622 0.031496062992125984 L 0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 0.031496062992125984 ","layers": ["F.Cu","F.Paste","F.Mask"],"drill": {"diameter": null,"start": "F.Cu","end": "B.Cu","plated": true}},"GND": {"pos": [0.3,0.2],"shape": "M -0.05905511811023622 0.031496062992125984 L 0.05905511811023622 0.031496062992125984 L 0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 0.031496062992125984 ","layers": ["F.Cu","F.Paste","F.Mask"],"drill": {"diameter": null,"start": "F.Cu","end": "B.Cu","plated": true}},"5V": {"pos": [0.3,0.3],"shape": "M -0.05905511811023622 0.031496062992125984 L 0.05905511811023622 0.031496062992125984 L 0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 -0.031496062992125984 L -0.05905511811023622 0.031496062992125984 ","layers": ["F.Cu","F.Paste","F.Mask"],"drill": {"diameter": null,"start": "F.Cu","end": "B.Cu","plated": true}}}); const SAMD11C = footprint({"A05":{"shape":"M 0.03,0.015L -0.03,0.015L -0.0305,0.015L -0.031,0.015L -0.0321,0.0149L -0.0331,0.0147L -0.0336,0.0146L -0.0347,0.0142L -0.0356,0.0139L -0.0361,0.0137L -0.0366,0.0135L -0.0371,0.0132L -0.0375,0.013L -0.038,0.0127L -0.0384,0.0125L -0.0392,0.0118L -0.0396,0.0115L -0.0401,0.0112L -0.0412,0.0101L -0.0415,0.0096L -0.0418,0.0092L -0.0425,0.0084L -0.0427,0.008L -0.043,0.0075L -0.0432,0.0071L -0.0435,0.0066L -0.0437,0.0061L -0.0439,0.0056L -0.0442,0.0047L -0.0446,0.0036L -0.0447,0.0031L -0.0449,0.0021L -0.045,0.001L -0.045,-0.001L -0.0449,-0.0021L -0.0447,-0.0031L -0.0446,-0.0036L -0.0442,-0.0047L -0.0439,-0.0056L -0.0437,-0.0061L -0.0435,-0.0066L -0.0432,-0.0071L -0.043,-0.0075L -0.0427,-0.008L -0.0425,-0.0084L -0.0418,-0.0092L -0.0415,-0.0096L -0.0412,-0.0101L -0.0401,-0.0112L -0.0396,-0.0115L -0.0392,-0.0118L -0.0384,-0.0125L -0.038,-0.0127L -0.0375,-0.013L -0.0371,-0.0132L -0.0366,-0.0135L -0.0361,-0.0137L -0.0356,-0.0139L -0.0347,-0.0142L -0.0336,-0.0146L -0.0331,-0.0147L -0.0321,-0.0149L -0.031,-0.015L 0.03,-0.015L 0.03,0.015","pos":[-0.11,0.15],"layers":["F.Cu"],"index":1},"A08":{"shape":"M -0.03,0.015L 0.03,0.015L 0.03,-0.015L -0.03,-0.015L -0.03,0.015","pos":[-0.11,0.1],"layers":["F.Cu"],"index":2},"A09":{"shape":"M -0.03,0.015L 0.03,0.015L 0.03,-0.015L -0.03,-0.015L -0.03,0.015","pos":[-0.11,0.05],"layers":["F.Cu"],"index":3},"A14":{"shape":"M -0.03,0.015L 0.03,0.015L 0.03,-0.015L -0.03,-0.015L -0.03,0.015","pos":[-0.11,0],"layers":["F.Cu"],"index":4},"A15":{"shape":"M -0.03,0.015L 0.03,0.015L 0.03,-0.015L -0.03,-0.015L -0.03,0.015","pos":[-0.11,-0.05],"layers":["F.Cu"],"index":5},"RST":{"shape":"M -0.03,0.015L 0.03,0.015L 0.03,-0.015L -0.03,-0.015L -0.03,0.015","pos":[-0.11,-0.1],"layers":["F.Cu"],"index":6},"CLK":{"shape":"M -0.03,0.015L 0.03,0.015L 0.03,-0.015L -0.03,-0.015L -0.03,0.015","pos":[-0.11,-0.15],"layers":["F.Cu"],"index":7},"DIO":{"shape":"M -0.03,0.015L 0.03,0.015L 0.03,-0.015L -0.03,-0.015L -0.03,0.015","pos":[0.11,-0.15],"layers":["F.Cu"],"index":8},"24-":{"shape":"M -0.03,0.015L 0.03,0.015L 0.03,-0.015L -0.03,-0.015L -0.03,0.015","pos":[0.11,-0.1],"layers":["F.Cu"],"index":9},"25+":{"shape":"M -0.03,0.015L 0.03,0.015L 0.03,-0.015L -0.03,-0.015L -0.03,0.015","pos":[0.11,-0.05],"layers":["F.Cu"],"index":10},"GND":{"shape":"M -0.03,0.015L 0.03,0.015L 0.03,-0.015L -0.03,-0.015L -0.03,0.015","pos":[0.11,0],"layers":["F.Cu"],"index":11},"VDD":{"shape":"M -0.03,0.015L 0.03,0.015L 0.03,-0.015L -0.03,-0.015L -0.03,0.015","pos":[0.11,0.05],"layers":["F.Cu"],"index":12},"A02":{"shape":"M -0.03,0.015L 0.03,0.015L 0.03,-0.015L -0.03,-0.015L -0.03,0.015","pos":[0.11,0.1],"layers":["F.Cu"],"index":13},"A04":{"shape":"M -0.03,0.015L 0.03,0.015L 0.03,-0.015L -0.03,-0.015L -0.03,0.015","pos":[0.11,0.15],"layers":["F.Cu"],"index":14}}); /* -- CONSTANTS -- */ const width = 1; const height = 1; /* -- ADD_COMPONENTS -- */ const R_1206_Mzy = board.add(R_1206, { translate: pt(-0.30313430862771873, -0.4447912438031322), rotate: 0, label: "R_1206_Mzy" }) const R_1206_twD = board.add(R_1206, { translate: pt(-0.0911263015751845, -0.5397202021848639), rotate: 0, label: "R_1206_twD" }) const button_6mm_mq4 = board.add(button_6mm, { translate: pt(0.375, -0.525), rotate: 0, label: "button_6mm_mq4" }) const header_FTDI_oT3 = board.add(header_FTDI, { translate: pt(0.4942689417788279, 0.0931395203600144), rotate: 0, label: "header_FTDI_oT3" }) const xiao_copper_sPG = board.add(xiao_copper, { translate: pt(-0.05, 0), rotate: 0, label: "xiao_copper_sPG" }) /* -- BOARD_SIZE_SHAPE -- */ const interior = path( [-0.5, 0.5], [0.7, 0.6], [0.775, -0.775], [-0.45, -0.7], ); board.addShape("interior", interior); /* -- ADD_WIRES -- */ board.wire( path( R_1206_Mzy.pad("1"), xiao_copper_sPG.pad("6"),), .015 ); board.wire( path( R_1206_twD.pad("1"), R_1206_Mzy.pad("2"),), .015 ); board.wire( path( R_1206_twD.pad("2"), [-0.025, -0.375],), .015 ); board.wire( path( button_6mm_mq4.pad("L1"), [-0.025, -0.45], [0.025, 0.2],), .015 ); board.wire( path( xiao_copper_sPG.pad("7"), [0.575, -0.3], button_6mm_mq4.pad("L2"),), .015 ); board.wire( path( header_FTDI_oT3.pad("RTS"), xiao_copper_sPG.pad("8"),), .015 ); board.wire( path( header_FTDI_oT3.pad("Rx"), xiao_copper_sPG.pad("9"),), .015 ); board.wire( path( header_FTDI_oT3.pad("Tx"), xiao_copper_sPG.pad("10"),), .015 ); board.wire( path( header_FTDI_oT3.pad("GND"), [0.475, 0.475], [0.025, 0.4], [0.025, 0.2], [0.025, 0.2], xiao_copper_sPG.pad("GND"),), .015 ); board.wire( path( [0.275, 0.3], header_FTDI_oT3.pad("VCC"),), .015 ); /* -- RENDER_PCB -- */ const limit0 = pt(-0.525, -0.8); const limit1 = pt(0.825, 0.65); const xMin = Math.min(limit0[0], limit1[0]); const xMax = Math.max(limit0[0], limit1[0]); const yMin = Math.min(limit0[1], limit1[1]); const yMax = Math.max(limit0[1], limit1[1]); renderPCB({ pcb: board, layerColors: { /* "F.Paste": "#000000ff", */ "interior": "#000000ff", "F.Cu": "#ffffffff", /* "F.Mask": "#00000000", */ /* "padLabels": "#ffff99e5", */ /* "componentLabels": "#00e5e5e5", */ }, limits: { x: [xMin, xMax], y: [yMin, yMax] }, background: "#00000000", mm_per_unit: 25.4 });

I acknowledge three resources that helped me greatly with the preparation of this assignment and documentation: Leo McElroy for his help with PCB design and milling, and Claire Dorsett for her patience and guidance with soldering. Lastly, ChatGPT 3.5, which helped me take text and images from the native OS X text editor I used to quickly document on my Mac into simple HTML for my git repo.

Updated May 14, 2024