Skip to the content
2 layers68 × 81.5 mmController, the printed circuit board in 3D

Scale for espresso and filter coffee.

Size
68 × 81.5 mm
Copper layers
2
Thickness
1.6 mm
Parts
55
Nets
61
Pads
217
Tracks, vias
341, 54
Pours
1
Routed
Yes
KiCad
KiCad 8.0 (file 20240108)
Created
2 Nov 2022
Updated
1 Nov 2026

Overview

Controller is an open-source printed circuit board by orlopau, from the orlopau/coffee-scale repository on GitHub. It is a 2-layer board of 68 × 81.5 mm with 55 parts on 61 nets, routed with 341 tracks and 54 vias.

It is built around the ESP32-WROOM-32, HX711 and AP2112K-3.3, with the IRLML2502, IRLML6402 and MMBT4403 among its other parts. Its parts include 15 capacitors, 15 resistors, 6 connectors, 5 ICs and 4 transistors. It belongs with the ESP32 boards of this library.

Main components

7

README

README.md

Coffee-Scale

Release Build CI Tests


This project contains the schematics, code and 3D models for a coffee scale based on an ESP32.

Features

  • OTA updates via WiFi
  • Recipe-based brewing
  • Auto averaging of weight values: more values are used to determine weight when weight is relatively constant
  • Brew timer
  • Lift-to-tare: slide a finger up the side of the platform, lifting it a little, and the scale tares with a double beep. Also with a cup on it, and never during a shot. Off, Gentle, Normal or Firm in the settings.
  • USB-C charging
  • Interchangeable Load Cell
  • 3D-printable case
  • Bluetooth and Wi-Fi connectivity

Recipe-Based Brewing

The scale can be used to brew coffee using a step-by-step recipe. The recipe is stored on the scale, and can be adjusted while brewing.

Possible adjustments include:

  • Changing the amount of coffee
  • Changing the brew ratio
  • Other adjustments based on the chosen recipe

Updates

Once Wi-Fi is set up, the scale looks for a new firmware by itself every few starts, in the background while you weigh. When it finds one, it asks "Update to v1.10?" the next time you switch it on. Yes installs it and restarts, Later asks again next time. If a new firmware doesn't start properly, the scale goes back to the one before, says so, and doesn't offer that version again.

To update by hand, hold the button while switching on the scale and choose a language.

Development: Updating From Your Computer

During development, the scale can install a build straight from your computer over Wi-Fi, without USB and without a GitHub release.

  1. In code/, run pio run -t serve. This builds the firmware and serves it on your network. It is found by the scale via mDNS, so your computer's IP does not matter. The first run installs the Python package zeroconf.
  2. Hold the button while switching on the scale to open the updater. It connects to the Wi-Fi saved in the updater.
  3. On the language screen, long-press the button instead of clicking. The scale searches for your computer and installs the build. (If it finds no server, it opens the recorder, see below.)

The server keeps running, so for the next build repeat steps 2 and 3 (pio run -t serve rebuilds when restarted). If the scale already runs the served build, it shows "No update available". Your computer and the scale must be on the same network, and the firewall must allow incoming connections for the server.

Development: Trying Automatic Updates

The scale's automatic updates read GitHub's releases. To try them without publishing one, the dev server can pose as a release, and a build can claim to be an older version.

  • Against GitHub: build with an older version, e.g. FIRMWARE_VERSION=v1.8.0 pio run -t upload. The scale then sees the latest release as newer.
  • Against your computer: run python scripts/dev_server.py .pio/build/esp32dev/firmware.bin --release v9.9.9 --port 8000 in code/. It prints the RELEASES_URL to build the scale with, e.g. RELEASES_URL=http://192.168.1.20:8000/releases pio run -t upload. Build the firmware to serve with the same RELEASES_URL, so it keeps asking your computer. The served build reports the last tag as its version, not --release, so after installing it the scale still finds v9.9.9 at every check; build it with FIRMWARE_VERSION=v9.9.9 too to see the scale stay quiet once it's up to date.

A check runs at the first start of a new firmware if Wi-Fi is set up, then every 5th start; the serial log (AUTO_UPDATE) says when.

Development: Recording the Load Cell

The scale can record the raw readings of its load cell, e.g. of taps or an espresso shot, and save them in its flash. The recordings are test data: native tests replay them with RecordedScale (code/src/native/recorded_scale.h). You don't need your computer while recording.

  1. Install a build with the recorder on the scale, see above.
  2. Open the updater and long-press on the language screen, as for an update. If no server is found, the scale opens the recorder by itself. It shows how many recordings are saved, and "No server".

Click to start a recording. While recording, the scale shows the weight, the recording time, the time left and the number of markers. Click again to set a marker, e.g. when the pump starts. Turn the knob to tare the shown weight, e.g. after putting the cup on; while recording, the tare is saved in the recording too. Long-press to save the recording in the scale's flash; the scale then waits for the click that starts the next one. A recording takes at most 5 minutes, then the scale waits for the long-press. About 50 recordings fit. If saving fails, the recording is kept and the next long-press tries again. A recording that wasn't saved is lost when the scale is switched off.

To get the recordings to your computer, run pio run -t record in code/. It does not build anything, it waits for recordings. Only one of serve and record can run at a time. Open the recorder as above; the scale now finds the server and no longer says "No server". Long-press while idle to send all saved recordings, oldest first. Each one is deleted from the scale after it arrived, so if sending fails, the rest stays and the next long-press tries again.

The computer saves each recording as code/test/recordings/<date>_<time>.csv. Give the useful ones a name that says what they show, commit them, and delete the rest. A recording looks like this, with ms counted from its start on the scale's clock:

text
# coffee-scale recording
# firmware: v1.9.0
# grams_per_count: 0.002381
ms,event,value
0,sample,84012
101,sample,84020
1234,click,
1500,tare,

grams_per_count is the calibration of the scale that recorded, so tests can convert the raw readings to grams. A sample's value is the HX711's raw reading, signed. The samples stay raw after a tare, a tare row only says when it happened (RecordedScale::tares()). Firmware up to v1.9.0 recorded it unsigned (16540413 instead of -236803), and the replay converts those.

Development: Emulator

The emulator runs the firmware on your computer, in a window that shows the scale's display. It needs SDL2 (sudo apt install libsdl2-dev on Debian/Ubuntu).

text
cd code
pio run -e emulator -t exec

With COMPILE_LANG=de in front, it runs in German. The load cell is simulated, and the keyboard replaces the encoder:

KeyAction
Left / Rightturn the encoder
Enter, Spacepress the encoder, hold for a long press
Up / Downput 1 g on the scale or take it off, with Shift 0.1 g
PageUp / PageDown10 g on or off
Home100 g, e.g. for the calibration
0, Backspaceclear the scale
Fpour on/off, 2 g/s
Sespresso shot: 6 s pre-infusion, then about 38 g in 33 s
Llift the platform for a moment (lift-to-tare)
Nnoise on/off
- / +slower/faster time, up to 20x (1x while the button is held)
Psave a screenshot to the current directory
Esc, Qquit

The window title shows the weight on the scale. The frame around the display lights up while the buzzer sounds. Settings are kept in memory only, and the boot splash screen and the updater only run on the device.

Development: Screenshot Tests

The native tests render every screen through u8g2, set up like the scale's display, and compare it with the reference images in code/test/native/test_screenshots/screens/. A screen that changes fails the tests, and its new image is written to code/test/native/test_screenshots/failed/ (on GitHub, attached to the CI run as failed-screenshots).

After changing a screen on purpose, accept the new images and commit them with the change:

text
cd code
UPDATE_SCREENSHOTS=1 pio test -e native -f native/test_screenshots

The diff of the pull request then shows each changed screen before and after.

Parts

55
QtyValueFootprintReferences
70.1uFCapacitor_SMD:C_0603_1608Metric_Pad1.08x0.95mm_HandSolderC1, C4, C6, C7, C9, C14, C15
410uFCapacitor_SMD:C_1206_3216MetricC2, C3, C5, C8
3100Resistor_SMD:R_0603_1608Metric_Pad0.98x0.95mm_HandSolderR3, R4, R5
310kResistor_SMD:R_0603_1608Metric_Pad0.98x0.95mm_HandSolderR1, R2, R6
347kResistor_SMD:R_0603_1608Metric_Pad0.98x0.95mm_HandSolderR10, R11, R12
21uFCapacitor_SMD:C_0805_2012MetricC12, C13
24.7uFCapacitor_SMD:C_0805_2012MetricC10, C11
25.1kResistor_SMD:R_0603_1608Metric_Pad0.98x0.95mm_HandSolderR13, R14
2IRLML2502Package_TO_SOT_SMD:SOT-23Q3, Q4
2MountingHoleLoadcellMountingHole:MountingHole_5.3mm_M5_ISO7380H1, H2
1130Resistor_SMD:R_0603_1608Metric_Pad0.98x0.95mm_HandSolderR9
11N5819Diode_SMD:D_SMA_HandsolderingD2
11kResistor_SMD:R_0603_1608Metric_Pad0.98x0.95mm_HandSolderR15
12kResistor_SMD:R_0603_1608Metric_Pad0.98x0.95mm_HandSolderR8
18.2kResistor_SMD:R_0603_1608Metric_Pad0.98x0.95mm_HandSolderR7
1AP2112K-3.3Package_TO_SOT_SMD:SOT-23-5U4
1BuzzerBuzzer_Beeper:Buzzer_12x9.5RM7.6BZ1
1Conn_DisplayConnector_Wire:SolderWire-0.5sqmm_1x04_P4.8mm_D0.9mm_OD2.3mmJ2
1Conn_G13Connector_Wire:SolderWire-0.5sqmm_1x02_P4.8mm_D0.9mm_OD2.3mmJ5
1Conn_LiPoConnector_Wire:SolderWire-0.5sqmm_1x02_P4.8mm_D0.9mm_OD2.3mmJ4
1Conn_LoadCellConnector_Wire:SolderWire-0.5sqmm_1x05_P4.8mm_D0.9mm_OD2.3mmJ1
1Conn_UARTConnector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_HorizontalJ3
1DW01-PPackage_TO_SOT_SMD:SOT-23-6_HandsolderingU5
1ESP32-WROOM-32RF_Module:ESP32-WROOM-32U1
1HX711Package_SO:SOP-16_3.9x9.9mm_P1.27mmU2
1IRLML6402Package_TO_SOT_SMD:SOT-23Q2
1LEDLED_SMD:LED_1206_3216MetricD1
1MCP73831-2-OTPackage_TO_SOT_SMD:SOT-23-5U3
1MMBT4403Package_TO_SOT_SMD:SOT-23Q1
1RotaryEncoder_SwitchRotary_Encoder:RotaryEncoder_Alps_EC11E-Switch_Vertical_H20mmSW3
1SMAJ6.0CADiode_SMD:D_SMAD3
1SW_BootButton_Switch_THT:SW_PUSH_6mm_H5mmSW2
1SW_ENButton_Switch_THT:SW_PUSH_6mm_H5mmSW1
1SW_PowerConnector_Wire:SolderWire-0.5sqmm_1x02_P4.8mm_D0.9mm_OD2.3mmSW4
1USB-C-6PinCustom:USB_C_6PinP1

Similar boards

  • 2 layers102 × 37 mmCoffee grams, the printed circuit board in 3D

    Coffee grams

    enochchau/coffee_grams

    46 parts
  • 4 layers81.2 × 81.2 mmView base, the printed circuit board in 3D

    View base

    SeedLabs-it/smartknob-hardware

    PCB and CAD files for smartknob devkit

    259 parts47
  • 2 layers65 × 45 mmBb kicad, the printed circuit board in 3D

    Bb kicad

    FilMarini/bigbanger

    An ESP32-based Bluetooth-enabled scaling device for climbing training,compliant with the Tindeq Progressor API, with firmware available in Micropython or Rust.

    57 parts10Apache-2.0
  • 2 layers101.2 × 89.2 mmHX711, the printed circuit board in 3D

    HX711

    SolderedElectronics/Load-cell-ampfilier-HX711-board-hardware-design

    Hardware design, BOM, gerbers and 3D files for Load-cell-ampfilier-HX711-board designed by Soldered Electronics.

    580 parts8
  • 2 layers48 × 32 mmMito, the printed circuit board in 3D

    Mito

    jvasilakes/mito

    A tiny, cheap, hackable, completely open-source force gauge for isometric finger strength training.

    31 parts6
  • 4 layers90.6 × 58.1 mmEcoApi pcb, the printed circuit board in 3D

    EcoApi pcb

    EcoApi/EcoApi_BeeHiveMonitoring

    describ options with 0R resistors. etc ...

    179 parts4GPL-3.0
  • 4 layers75 × 100 mmTest rig black box, the printed circuit board in 3D

    Test rig black box

    callumsnowden/aero21412_test_rig

    AERO21412 Avionics Coursework 1 – Wind Tunnel Test Rig "Black Box"

    102 parts1MIT
  • 2 layers83.8 × 61 mmThrust v2, the printed circuit board in 3D

    Thrust v2

    jmajew/thrust_tool

    DIY tool for measurements of thrust, torque, etc., of an electric motor with propeller

    187 parts1GPL-3.0

Questions

How big is the Controller PCB?

It measures 68 × 81.5 mm and has 2 copper layers, 1.6 mm thick.

What parts does the Controller use?

55 parts, built around the ESP32-WROOM-32, HX711, AP2112K-3.3 and IRLML2502. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the Controller KiCad files?

From the orlopau/coffee-scale repository on GitHub, at the commit this page was made from: the board is schematics/controller.kicad_pcb and its schematic schematics/controller.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the Controller design in my own project?

Its repository states no licence, so its author keeps all rights: ask orlopau before reusing the design.