Week 08: Electronics Production¶
Motor driving board¶
Motor Driving Board — Designed and milled the motor driver board for my final project. It will drive 2 stepping motors and 1 servo driver. The servo worked well with this board.
Assignments¶
Group assignment:¶
- characterize the design rules for your in-house PCB production process
- submit a PCB design to a board house
Individual assignment:¶
- make and test an embedded microcontroller system that you designed
- extra credit: make it with another process
1. Group Assignment¶
We tested our new SainSmart Genmitsu Cubiko CNC with Candle as the GRBL controller. This affordable little CNC, paired with the open-source GRBL controller and its heightmap feature, turned out to be a great choice!
2. Individual Assignment¶
2-1. Design revision¶
The first step was to revise the PCB design I made in week 06. Last time I forgot to set the custom design rules of minimum 16 mil copper width and copper clearance, so I had to fix those along with some wiring errors and spacing issues. I also had to replace some parts with SMD ones available from the pinhead2 library. Finally, I drew the outline.
| Before | After |
|---|---|
![]() |
![]() |
Then, I turned off some layers and obtained clean files for the interior and the outline for PCB milling.

Finally, I exported the files as PNG.

2-2. Milling¶
2-2-1. mods CE — Generating toolpaths¶
For milling, we used mods CE to generate G-code toolpaths, using the same settings as the group project.
Step 1 — Select the program
Open modsproject.org in a browser. From the Programs menu, choose G-code > mill 2D PCB.

A node graph for the full PCB milling workflow opens.
Step 2 — Upload the PNG
In the select png file node (top-left of the graph), upload the interior trace PNG exported from Fusion.

Step 3 — Enable the output node
Find the on/off toggle node and switch it to on to enable G-code file output.

Step 4 — Set the V-bit calculator
In the V-bit calculator node, enter the tool parameters:
| Parameter | Value |
|---|---|
| Tip diameter | 0.1 mm |
| Angle | 20° |
| Offsets | 2 |
| Stepover | 0.5 |
| Speed | 4 mm/s |
mods CE calculates the resulting cut width = 0.1353 mm and cut depth = 0.1001 mm. Click send calculated settings to propagate these values to the mill raster node.

Step 5 — Select the drill for the interior
For the interior traces, select the 0.79mm drill preset.

Step 6 — Adjust the mill raster 2D node
In the mill raster 2D node, fine-tune the tool diameter to 0.7 mm to match the actual bit.

Step 7 — Calculate and export
Click Calculate to generate the toolpath, then View to preview it. The G-code .nc file is downloaded automatically.

Repeat steps 2–7 with the outline PNG to generate the outline cut G-code.
2-2-2. Candle — Heightmap and milling¶
Because the copper-clad board surface is never perfectly flat, we used Candle’s heightmap feature to probe the board surface and compensate the Z-height during cutting. Without this, the shallow V-bit cut would be uneven — too deep in some areas, not cutting at all in others.
Step 1 — Open Candle and load the G-code
Launch Candle (the GRBL controller software). Open the trace G-code file (my_trace.png.nc) via File > Open.

The toolpath preview appears in the Visualizer panel. The Heightmap panel at the bottom shows the board border dimensions (automatically detected from the G-code: X: 66.61 mm, Y: 48.88 mm).

Step 2 — Configure the probe grid
In the Heightmap panel on the left, set the probe grid parameters:
| Parameter | Value | Meaning |
|---|---|---|
| Xi | 5 | Number of probe points in X |
| Yi | 3 | Number of probe points in Y |
| Zi | 1.00 mm | Z start height (above surface) |
| Zb | −1.00 mm | Z probe bottom limit |
| Fi | 10 mm/min | Probe feed rate |
Check Show probe grid and Show border to visualize the grid on the board.

This creates a 5 × 3 grid of 15 probe points across the board.
Step 3 — Run the probe
Home the machine and set the work origin (XY and Z zero) on the board surface. Then click Probe — the CNC automatically touches the surface at each of the 15 grid points and records the Z height.
Once complete, the heightmap table fills with measured values (in mm, relative to the set Z-zero). The Visualizer shows orange height compensation lines overlaid on the toolpath. Save the map as a .map file.

Step 4 — Enable heightmap and send the G-code
Check Use heightmap in the panel — Candle loads the saved .map file. During milling, it interpolates Z compensation values between probe points, continuously adjusting the Z-axis so the bit stays at a consistent cut depth.
Click Send to start the interior trace cut.

Step 5 — Mill the outline
Load the outline G-code file and run it in the same way. (The same heightmap can be reused since the board hasn’t moved.)

The milling with the SainSmart Genmitsu Cubiko came out clean and even — the heightmap made a visible difference.


2-4. Stuffing and Soldering¶
For stuffing, I first got the parts from FabLab Kannai inventory based on the BOM in Fusion.

I learned from Tamiya-san, the Kannai instructor, about how to solder SMD parts. The key is to fix the part by soldering one leg first with a small amount of solder. I struggled a lot with soldering, so there is no photo here…
2-5. Testing¶
With the tester, I tested the connections with a multimeter. I found some unconnected parts and fixed them with soldering.

I wrote the test program for the servo using Google Gemini, with the following prompt and the schematic from Fusion attached.
Based on this schematic, write a MicroPython program to test the servo.
The generated code sets up PWM on Pin D6 (GPIO 0) of the XIAO RP2040 and sweeps the servo through 0°, 90°, and 180°:
import machine
import utime
# According to the schematic, the servo is on Pin D6 (GPIO 0)
SERVO_PIN = 0
# Set up PWM on the servo pin
servo = machine.PWM(machine.Pin(SERVO_PIN))
servo.freq(50) # Standard servos operate at 50 Hz
def set_angle(angle):
# Map 0–180° to duty cycle range 1638–8192 (at 50 Hz, 16-bit)
# 0.5 ms (0°) → duty ≈ 1638
# 2.5 ms (180°) → duty ≈ 8192
duty = int((angle / 180) * (8192 - 1638) + 1638)
servo.duty_u16(duty)
print("Starting Servo Test...")
try:
while True:
set_angle(0)
utime.sleep(1)
set_angle(90)
utime.sleep(1)
set_angle(180)
utime.sleep(1)
except KeyboardInterrupt:
servo.deinit()
print("Test stopped.")
And voilà!
I wanted to test the circuit for two stepping motors but found out that I need extra batteries and circuits to power those motors.
Reflections¶
- Soldering would have been easier if the wiring ran straight out of the footprint pads.
- I realized I need to design an extra battery circuit to drive the stepping motors.
Design Files¶
Source Code¶
References¶
- How to use height mapping in Candle
- Using heightmap with Grblcontrol or Candle
- How to create a Heightmap
- Heightmap creation with Candle
AI Usage¶
- I used Google Gemini to write the test code for Servo motor.
- I used Claude Code to grammar-check and polish the documentation.
Checklist¶
- [x] Linked to the group assignment page
- [x] Documented how you made the toolpath
- [x] Documented how you made (milled, stuffed, soldered) the board
- [x] Documented that your board is functional
- [x] Explained any problems and how you fixed them
- [x] Uploaded your source code
- [x] Included a ‘hero shot’ of your board
–
Copyright¶
Copyright 2026 Fumiko Toyoda - Creative Commons Attribution Non Commercial Source code hosted at gitlab.fabcloud.org

