My $3,000 setup
Brew-bot
Say “brew recipe A1” and it doses, grinds, heats and pours a pour-over. It’s built from parts you can buy, costs about $1,040 in parts, and any Claude can run it.
Dictate with Wispr Flow, or just type. Try a recipe:
A Stagg EKG Pro kettle sits in a hinged cradle, and a small "dial bot" turns and presses its dial to set the temperature, the way your hand would. A geared motor tips it to pour while the dripper turns and a rail moves the spout in and out, so the water spirals. Three hoppers dose beans by weight into a grinder. A scale under the cup runs the whole pour, and a small connector lets any Claude call brew(recipe="A1").
The full blueprint is below: drawings, wiring, the control loops, safety, the software, the build steps and every part.
- Bean hoppers ×3, printed PETG, 250 g each, one coffee per hopper.
- Augers ×3, each turned by an N20 gear motor, push beans into one chute.
- Dose cup on the 1 kg load cell. When it reads the target, an SG90 servo tips it into the grinder.
- Baratza Encore ESP, on Shelly plug 1. It grinds until its power draw drops to idle, which means the beans are gone.
- MGN12 rail, 300 mm, belt-driven by a NEMA 17. It moves the kettle in and out to draw the spiral.
- Carriage and cradle hanging from the rail.
- Stagg EKG Pro and its base, fixed in the cradle so they tilt together. The dial bot clips to the base, and a probe goes in through the lid.
- Hinge and tilt motor (see the side view).
- V60 or Origami dripper on a fixed ring above the server.
- Turntable: a 6-inch lazy-susan bearing, belt-driven, spinning the server and dripper at 30–40 rpm.
- 5 kg load cell under the turntable. It's the scale for the whole pour.
- Electronics box: Pi 5, 3× TMC2209, 2× DRV8833, HX711s, 12 V input.
- Emergency stop, normally closed, cutting 12 V to every motor.
The kettle and its power base are clamped in an aluminium L-cradle, so they tilt together and the base contact never breaks. The hinge sits under the spout side, in front of the kettle's centre of mass. That means gravity always pulls the cradle back upright: the motor has to hold every degree of tilt, and if power drops the kettle falls back to 0°. It can't spill toward the cup.
Torque: a full Stagg with its base and the dial bot weighs about 2.4 kg, and its centre of mass sits at most about 6 cm from the pivot. That needs about 15 kg·cm. A 17HS19 motor through a 100:1 planetary gearbox gives over 30 kg·cm, so there's about 2× margin. A printed hard stop at 40° stops it ever tipping past a full pour.
The kettle is a Fellow Stagg EKG Pro, which already holds any temperature from 40 to 100 °C to within a degree. It has no API, but it has one dial on its base: turn to set the temperature, quick-press to switch on or off (Fellow's guide). So the Pi works that dial the way a hand would, with a small printed "dial bot" clipped to the base:
- Turn: a 28BYJ-48 geared stepper with a silicone O-ring wheel pressed against the dial's knurled edge. The wheel grips it like a thumb.
- Press: an MG90S servo with a felt-tipped arm over the dial's centre.
- Check: the Pi's own DS18B20 probe in a steel sleeve through the lid. The kettle does the heating, and the probe confirms it.
set_temp(93): # from brew(recipe="A1")
if kettle is off: press() # quick press → on, screen lights
turn(-70 clicks) # spin to the bottom: it clamps at 40 °C, a known zero
turn(+(93 - 40) clicks) # 1 click = 1 °C (calibrated once in °C mode)
wait until probe ≥ 92 °C # usually 3-4 min from cold
if probe settles 1–2 °C off: turn(±1) and re-check
# safety: the base is on Shelly plug 2 with toggle_after=10, renewed while brewing
# if the Pi stops, the kettle loses power in 10 s and wakes up off
Two settings are made once by hand in the kettle's menu: Celsius, and hold for 60 minutes. Between brews the bot leaves the kettle holding at the last temperature, so a second cup at the same temperature is ready straight away.
If you'd rather not touch the dial: remove the dial bot and let the Pi switch a plain gooseneck on and off by its probe (±1 °C, using the same plug). The rest of the build stays the same.
The 5 kg cell under the turntable is the only thing the pour trusts. It reads 80 times a second, and a median filter turns that into grams and grams per second.
tare() # cup + dripper + grounds = 0 g
bloom = 2.5 × dose # A1: 45 g
pour_to(bloom); wait(bloom_s) # A1: 45 s
for target in thirds(out_ml - bloom): # 3 pulses
pour_to(target); wait(10 s)
wait until rate < 0.1 g/s # draw-down finished → "ready"
pour_to(g):
turntable(35 rpm); tilt to 20°, then creep until flow > 0.5 g/s
while weight < g:
tilt += k × (5 g/s − flow) # hold 5 g/s whatever the kettle's level
rail = r_max × |sin(π·t/T)| # centre → edge → centre: the spiral
if flow ≈ 0 for 2 s: abort("stream missing the cup")
tilt to 0° # gravity helps
Why tilt is controlled by flow and not by angle: as the kettle empties, the same angle pours less and less. Closing the loop on grams per second keeps every pulse even, from a full kettle to the last 200 ml.
- Dose: the chosen auger runs fast until the 1 kg cell reads 90% of the target, then pulses in 150 ms bursts until it's within ±0.2 g. The SG90 servo then tips the cup into the grinder and returns it, and the cell re-tares.
- Grind: the Encore ESP's dial is set once for pour-over, around 14–16. Shelly plug 1 turns it on. The plug also measures watts, so when the draw falls to idle the burrs are empty and the Pi switches it off. There's no fixed timer to guess.
- Into the dripper: the grounds bin is swapped for a printed funnel that drops straight into the filter.
One Raspberry Pi 5 runs everything; the probe in the kettle is on GPIO4. The dial bot's 28BYJ-48 runs through a ULN2003 on GPIO9/10/11/14, and both servos (dial press, dose tip) are on a PCA9685 on the I²C bus at 0x40. Motors get 12 V through the emergency-stop loop. Mains only goes through the two Shelly plugs. Common ground.
| Power rail | Feeds | |
|---|---|---|
| 27 W USB-C | Pi 5 only | |
| 12 V 5 A brick | E-stop NC loop → 3× TMC2209 VM · LM2596 buck → 6 V → DRV8833 VM | |
| Mains | Only through the two Shelly plugs (grinder, kettle base), behind an RCCB socket |
- No cup, no pour. The cup cell has to read inside the known tare window and the time-of-flight sensor has to see the server. Either one failing cancels the brew.
- Overflow: every brew stops at target + 5%, there's an absolute ceiling of 450 g, and a stream that misses the cup stops within 2 s.
- Boil-dry: the Stagg has its own empty-kettle cut-off. The Pi also cuts the base's power if its probe reads above 101 °C.
- The Pi dies: both plugs switch themselves off within 10 s (
toggle_after), the motor drivers disable, and gravity tips the kettle upright. - Hands: a mushroom emergency stop cuts 12 V to every motor in hardware, and the Pi sees it on GPIO18. Mains only goes through the two certified plugs, behind an RCCB socket.
- Strangers: the connector needs a bearer token, allows one brew per person every 10 minutes and one brew at a time, and
cancel()always works.
Raspberry Pi OS Lite (64-bit) · Python 3.11 · one asyncio service, systemd brewbot/ hw/scale.py HX711 ×2 via lgpio, 80 Hz, median-of-5, tare + calibrate hw/steppers.py TMC2209 STEP/DIR via lgpio, accel ramps, EN on GPIO26 hw/augers.py DRV8833 PWM, dose loop hw/probe.py DS18B20 on 1-Wire (/sys/bus/w1) hw/dialbot.py 28BYJ-48 turn + MG90S press on the kettle dial (PCA9685) hw/shelly.py HTTP RPC Switch.Set / Switch.GetStatus (watts) brew.py the recipe → dose → grind → heat → bloom → pulses state machine server.py MCP connector + status page (download below)
- Saturday 1, frame and scales. Cut and bolt the 2020 frame: 600 × 450 × 300 mm. Mount the 5 kg cell under the turntable plate and the 1 kg cell under the dose cup. Calibrate both with a 500 g weight and check the drift over 10 minutes is under 0.3 g.
- Sunday 1, beans. Print the hoppers, augers and dose cup. Wire the N20 motors to the DRV8833s and the servo to GPIO10. Put the grinder on Shelly 1 and set its dial to 15. Test 20 doses of 18 g: each should land within ±0.2 g.
- Saturday 2, water. Build the cradle and hinge, and fit the hard stop at 40°. Put the kettle base on Shelly 2, fit the dial bot and the probe. Calibrate clicks per °C, then run 10 set-and-check cycles from 80 to 96 °C: each should settle within 1 °C. Then fit the rail and turntable.
- Sunday 2, pour and safety. Tune the flow loop until pulses hold 5 g/s ±0.5. Wire the emergency stop and the cup sensor, and test each failure on purpose: pull the cup mid-pour, kill the Pi, run the kettle empty. Then run
server.pywithBREWBOT_HW=1and add it to Claude.
Prices checked November 2026. "est." means a generic part at a typical price.
| # | Part | Model | Price |
|---|---|---|---|
| 1 | Fellow Stagg EKG Pro 0.9 LHolds 40–100 °C itself; the dial bot sets it. India: Timemore Fish Smart Pro 900 ml, ₹12,899. | EKG Pro | $179.95 |
| 2 | Baratza Encore ESP grinder | ZCG495 | $199.95 |
| 3 | Raspberry Pi 5 4 GB + 27 W PSU + 32 GB card + case | Pi 5 4GB | $90 |
| 4 | SparkFun load-cell amplifier ×2 | SEN-13879 | $22 |
| 5 | 5 kg straight-bar load cell (pour scale) | TAL220B · SEN-14729 | $12 est. |
| 6 | 1 kg straight-bar load cell (dose cup) | 80 mm bar | $5 est. |
| 7 | NEMA 17 + 100:1 planetary (tilt) | 17HS19-1684S-PG100 | $30.17 |
| 8 | NEMA 17 ×2 (turntable, rail) | 17HS19-2004S1 | $28 est. |
| 9 | Stepper drivers ×3 | BIGTREETECH TMC2209 V1.3 | $25 est. |
| 10 | Linear rail 300 mm + carriage | MGN12H | $20 est. |
| 11 | 6-inch lazy-susan bearing + GT2 belt + 20T/60T pulleys | GT2 6 mm | $20 est. |
| 12 | Gear motors ×3 (augers) | N20 6 V 100 rpm | $15 est. |
| 13 | Dual motor drivers ×2 | Pololu DRV8833 #2130 | $10 est. |
| 14 | Micro servo (tips the dose cup) | SG90 | $3 est. |
| 14a | Dial bot: geared stepper + driver (turns the kettle dial) | 28BYJ-48 + ULN2003 | $4 est. |
| 14b | Dial bot: metal-gear servo (presses the dial) | MG90S | $5 est. |
| 14c | 16-channel servo board (I²C) | PCA9685 | $6 est. |
| 14d | Silicone O-rings for the dial wheel + felt pads | $3 est. | |
| 15 | 12 → 6 V buck converter | LM2596 | $3 est. |
| 16 | Waterproof temperature probe + 4.7 kΩ | Adafruit DS18B20 #381 | $10 est. |
| 17 | Stainless 6 mm probe sleeve + silicone lid grommetKeeps the probe food-safe and in the same spot every brew. | thermowell | $8 est. |
| 18 | Time-of-flight cup sensor | Adafruit VL53L0X #3317 | $15 est. |
| 19 | 22 mm emergency stop, normally closed | NC mushroom | $10 est. |
| 20 | 12 V 5 A desktop power brick | barrel jack | $15 est. |
| 21 | Shelly Plug S Gen3 ×2 (kettle, grinder)Local HTTP API, auto-off timer, and power metering. In India, use a 16 A adapter. | Plug S Gen3 | $52 |
| 22 | Frame: 4× 600 + 4× 450 + 4× 300 mm extrusion, brackets, T-nuts | 2020 V-slot | $60 est. |
| 23 | Cradle: 40×40 aluminium angle, 8 mm shaft, 2 flange bearings | KFL08 | $18 est. |
| 24 | 18 mm walnut ply top + silicone drip mat | $30 est. | |
| 25 | PETG 1 kg (hoppers, augers, dose cup, funnel, hard stop) | PETG | $22 est. |
| 26 | Hario V60 02 ceramic + Range Server 600 ml + 100 filters | VDC-02 · VCF-02-100W | $52 est. |
| 27 | Origami Dripper M + wave filters | Origami M | $40 est. |
| 28 | GPIO screw-terminal breakout, wire, ferrules | $25 est. | |
| One Brew-bot | $1,038 |
One Brew-bot for the whole office, with what it needs to run every day.
| Brew-bot (parts above) | $1,038 |
| Raspberry Pi Touch Display 2 on the rig: the queue, who's brewing, the live stage | $60 |
| Auto-refill: a 5 L filter tank and a pump that tops the kettle up 400 ml after every brew | $75 |
| Acrylic splash guard and front doors | $120 |
| 12 glass servers and cups | $60 |
| Spares: load cells, drivers, servos, filters | $150 |
| 4 months of beans for the office: Riverdale and Attikan, about 6 cups a day | $315 |
| Friday-night bartender pilot (see below): SO-101 arm kit + 4 drink pumps and a bottle rack | $639 |
| 10% buffer | $246 |
| Shipping and Indian import duty on the US parts | $297 |
| Total | $3,000 |
Same rig, same connector, a second job. On Friday evenings, "brew recipe F2" makes a Negroni.
- The arm doesn't lift bottles. A full bottle weighs 1.2 kg, and arms in this price range carry about 500 g. Spirits and mixers sit on a rack with four food-grade peristaltic pumps, each dosing by millilitre. That's the same kind of pump people use for precise dosing.
- The arm does the theatre. An SO-101 (open source, about $500 as a complete kit, roughly 500 g payload) places a glass under the pumps, stirs, drops the garnish and slides the drink across. With a second "leader" arm you teach it each move by doing it once, using Hugging Face's LeRobot.
- Recipes: F1 Old Fashioned, F2 Negroni, F3 a no-alcohol spritz. The pour stops by weight on the same 5 kg cell.
- Rules built into the connector: drinks only unlock on Fridays after 6 pm with an admin token, one drink per person every 30 minutes, and no cup means no pour.
- Later: a UFactory Lite 6 (from $2,999, 600 g payload, ±0.5 mm) could shake a light shaker too. That's a separate ask, not part of this $3,000.
A small Python MCP server for the Pi. It starts in simulator mode, so it works with no hardware. Calls without the token get a 401.
pip install "mcp[cli]<2" uvicorn BREWBOT_TOKEN=pick-a-secret python server.py # simulator BREWBOT_HW=1 BREWBOT_TOKEN=... python server.py # on the Pi brew(recipe="A1") or brew(coffee, grams, temp_c, out_ml?, bloom_s?) status() → stage, grams, °C, grams in the cup menu() → the three coffees and their default recipes cancel() → motors off, kettle tips upright, plugs off
Tell your Claude: in Claude, open Settings → Connectors → Add custom connector. Paste the rig's URL (for example https://brewbot.your-office.dev/mcp) and the token you were given. Then just say, "make me a Riverdale, 18 grams, 92 degrees." Each person gets one brew every 10 minutes, one brew runs at a time, and nothing pours without a cup on the scale. Live status shows at the same URL without /mcp.
Concept. The demo is a simulation; the parts list and connector are real. The $3,000 builds the first one.