◆ PROJECT MILO — HUMANOID PLATFORM

Hello. I am being
assembled in public.

A bipedal, conversational robot built one subsystem at a time — Raspberry Pi 5 for the body, Jetson for the brain, RealSense for the eyes. Nothing is assembled yet: the skull is still CAD, and zero steps have been taken. Everything I learn gets logged here, and every file ends up downloadable.

Concept render of Milo: a white humanoid robot with a visored head, mid-stride against a dark background.

/ SUBSYSTEM STATUS

Head ACTIVE

2026-07-27 : Finally got shell had to get help from designer to create it for me, I added the camera bracket to hold RealSense D435if 2026-08-01 : Finally Finalized Head decide to only have D435if in head for now, and move speakers and microphones to chese. All is left is to print head, and cut out visor, and then do some testing.

90% COMPLETE
Hands ACTIVE

2026-07-20 -- Started Researching different hands for humanoids. 2026-07-25 -- Still In Design Phase, Setting up Fusion Project

10% COMPLETE
Vision SPEC'D

RealSense D435if streaming depth. No tracking loop yet.

5% COMPLETE
Compute SPEC'D

Pi 5 + Jetson split decided. Power budget open.

5% COMPLETE
Speech / LLM R&D

R&D

0% COMPLETE
Locomotion R&D

Bipedal walking. Hardest problem, deliberately last.

5% COMPLETE
Torso / Frame R&D

R&D

0% COMPLETE
Power R&D

R&D

0% COMPLETE

/ ANATOMY

▸ HEAD

Head + Sensor Pod

Finished Design of Shell, added bracket to house the Intel RealSense D435if for RGB + depth, decided after more research to move the speak and mics to chest area, so this finalize the head, and is read for print

STATUS ACTIVE

/ DEVLOG

Tactile board schematic, done (almost)

Spent today finishing the schematic for the 32×16 tactile readout board — 512 taxels, one board per hand, forearm-mounted near the wrist. It’s the readout layer for the ORCA hand v2 Touch, based on Binghao Huang’s Columbia design but adapted off Arduino Nano onto a bare ATmega328P so it actually fits somewhere sensible.

Every part is now placed. What’s left is DRC and layout.

What went in

The architecture hasn’t changed since I last wrote about it: four SN74HC595 shift registers drive 32 columns out to a 32-pin FPC, a CD74HC4067 muxes 16 rows back into a single ADC pin through a 20k pulldown, and Velostat sandwiched between the two flex circuits is the sensor. The ATmega scans columns, reads rows, ships frames over UART.

Today was the unglamorous half — power, decoupling, programming access, and a lot of net housekeeping.

Power OR-ing. BAT54C common-cathode diode so the board runs off USB-C on the bench or the JST harness in the arm, whichever is present, with no backfeed either way. Costs ~0.35V, which puts the rail at about 4.65V. Still comfortably above the 4.5V floor for 16MHz, and since the Velostat divider is ratiometric against AVCC, rail sag cancels out of the reading anyway.

Decoupling pass. 0.1µF at every 595’s VCC pin, the mux, both ATmega VCC pins, AVCC and AREF. 10µF at power entry and a second 10µF that belongs physically in the middle of the shift register bank. When RCLK pulses, all 32 columns update simultaneously — that’s the biggest current transient on this board, and it lands on the same rail feeding the analog supply.

AVCC filter. Ferrite bead (Sunlord GZ2012D101TF, 100Ω @ 100MHz) in series between the 5V rail and AVCC, with its own 0.1µF on the analog side. The mux common node is high-impedance — 20k against Velostat in the kΩ–MΩ range — so digital hash on the supply lands straight in the ADC if you let it.

Programming access. Went with six SMD test points instead of a real ISP header: MISO, SCK, MOSI, RESET, 5V, GND. Copper only, nothing populated, excluded from the BOM. A blank ATmega has no bootloader, so USB can’t reach it the first time — the CP2102N only gives you a UART, and there’s nothing on the chip listening yet. ISP is silicon, not software, so it works on a virgin part. One-time operation to burn the bootloader and set the fuses (factory default is internal 8MHz with CKDIV8, so the crystal gets ignored until you fix the low fuse). After that everything goes over USB-C forever.

Six pads, ~24mm² of board. For two boards a pogo jig isn’t worth buying — I’ll tack wires on, flash, and desolder.

The one that nearly got me

I renamed a batch of nets from PIN_nn to real names and broke the shift register chain doing it.

Renamed the QH’ outputs, didn’t rename the matching SER inputs, and the numbering ran backwards on top of that. Result: SR_CHAIN_2 ended up with three pins on it — two shift register outputs shorted together. Both push-pull. Any time U3 and U4 disagreed, that’s a direct rail-to-rail short through both output stages. Part-killer, not a logic bug.

Meanwhile three other nets were sitting there orphaned at one pin each, doing nothing.

The schematic looked correct at every intermediate step. Nothing renders differently when a net has three pins instead of two. The only thing that catches it is the pin count.

New rule: rename both ends of a net in the same edit, then check that net’s pin count before touching the next one. Batch renaming and verifying afterward is exactly how this happened.

Related: I flagged the SRCLR# ties as possibly missing at one point based on a PDF text export, and they were fine — the export just dropped them. Text extraction from a schematic PDF is not a netlist. Trust the netlist.

Also learned the hard way

Capacitors go across a rail to ground. Ferrites and series resistors go in the rail. I managed to wire a cap in series (blocks DC entirely, chip gets no power) and then later wire the ferrite as a shunt to ground (does nothing). Both in the same afternoon. Writing it down so it sticks.

Next

  • DRC, then verify netlist pin counts — 5V should read 25, SRCLK 6, SER 3, RESET 4, AVCC 3
  • Confirm the two schematic pages resolve into single nets rather than splitting at the page boundary. That’s the failure mode that would silently disconnect the entire ATmega from everything it drives
  • Layout. Targeting 35×25mm, 4-layer. The extra layers buy a dedicated ground plane, which matters more here than 5mm of board edge — TACT_ADC needs to be short, guarded, and nowhere near SRCLK
  • Price JLCPCB assembly against hand-building it. Leaning toward hand assembly with a stencil, but the CP2102N is QFN-28 with an exposed pad, and both FPC connectors are 0.5mm pitch. Ordering spare boards and spare parts either way
NEXT → PCB Layout, Wire Routing

projectmilo.dev

Seven months in, the project gets a home. projectmilo.dev, on Cloudflare.

Naming was less obvious than it looks — there’s a well-known commercial robot called Milo (RoboKind’s autism-education humanoid) that owns the search results, so the .dev suffix and the “project” prefix are doing real work.

The site is flat static HTML, no build step, dropped straight into Cloudflare Pages. Dark depth-map visual system: a live canvas point cloud rendering Milo’s proportions in roughly 2,800 particles, coloured on a depth ramp from indigo at distance through cyan and amber to hot orange up close, with mouse parallax and a sensor sweep line running down the figure. The hero sets MILO enormous with the same gradient through the letterforms.

Status board covers seven subsystems. The stat rail ends on “0 steps taken” — which is honest, and it stays there until it isn’t true.

Backdating the log to day zero. Turns out that’s 30 December 2025, not 1 January 2026. Two days earlier than I thought, which is a fitting way to discover you’ve been at something longer than you remember.

NEXT → Backfill every entry above and keep this thing current.

Five cuts that make a machined hand printable

Printed the index finger at 61% and learned what everyone learns: a hand designed for machined tolerances does not survive FDM at 61% scale. The fork-and-tab joints bind, bottom out, and won’t seat.

Validated the fix on the Finger_1 coupon. Five operations plus one rule:

  1. Scale to 61% natively in SolidWorks. Not in the slicer. Export the STL and print at 100% — this keeps parametric control and stops the slicer silently scaling tolerances that shouldn’t scale.
  2. Widen the fork slot ~0.25 mm per side into a funnel mouth so the tab self-centres on the way in.
  3. Chamfer or dome the tab lead-in edges.
  4. Slot depth relief so the tab tip doesn’t bottom out before the joint seats.
  5. Shoulder relief so the fork rings seat fully forward.

Then bores: leave them at ~3.05 mm and drill through the assembled joint to fit the 3 mm steel pins. Drilling through assembly trues the alignment in a way no amount of modelling does.

The other outcome — the finger caps are deleted from the BOM. They split along layer seams under hoop stress every time. Retention has to live in the joint geometry itself, not in a separate retaining part. That’s a real design principle, not a workaround.

Sourced precision 3 × 12 mm 18-8 stainless dowel pins, slip fit, 50-pack, as the production pin.

Also confirmed the PTFE Bowden tube trick from the Yeah Hand design solves tendon channel friction, which was going to be the next problem.

NEXT → Apply the same surgery to fingers 2 through 4.

/ ROADMAP

P0 · IN PROGRESS

Head + sensing

I've finalized the head for v1, we will move speakers and microphones to the chest area instead. All is left is to print and test mounting brackets before completed this part and upload files. Still need to cut out the visor as well.

P1 · IN PROGRESS

Arms + hands

Tendon-driven hands

P2 · QUEUED

Perception loop

Track a person, follow with the neck, no jitter.

P3 · QUEUED

Voice + conversation

STT, LLM, TTS on the Jetson. Latency under a second.

P4 · QUEUED

Torso + power

Frame, compute bay, battery and rail isolation.

P5 · QUEUED

Legs + walking

Bipedal balance, then flat-floor walking. The big one.

/ BILL OF MATERIALS

Raspberry Pi 5 (8GB)
body controller
IN HAND
NVIDIA Jetson
perception + LLM
IN HAND
Intel RealSense D435if
RGB + depth vision
IN HAND
Filament + hardware
everything else
ONGOING

/ CHANGELOG

  • v0.4 Depth stream running on Jetson
  • v0.3 Compute architecture locked (Pi 5 + Jetson)
  • v0.2 Head assembly complete
  • v0.1 Scope defined, parts ordered

/ ABOUT

Milo is a humanoid robot I'm building from scratch, and this is the lab notebook. Twenty-plus years as a software engineer means I can make almost anything think. It does not mean I know what a moment arm is. Closing that gap is most of the project.

Almost every part gets manufactured at home — printed on a Bambu Lab H2C, milled on a Makera Air. The constraint is deliberate: keep this cheap enough that anyone with the same two machines can follow along and build their own. Some of what I need doesn't exist yet, so part of the work is building the tools that build Milo.

Everything gets documented — the decisions, the part numbers, the print that warped at hour nine. Every file ends up downloadable. This is going to take a while, and that's fine. Let's get started.