Scale Sense — ESP32-C3 PCB Design Brief¶
Revision: 1.3 (pre-layout) Branch: main Prepared for: Hardware / PCB fabrication handoff
1. Purpose¶
This document describes the custom PCB for the Scale Sense keg scale unit, targeting the Espressif ESP32-C3-MINI-1U module as the MCU. The -1U variant uses an external antenna via U.FL connector rather than an onboard PCB trace antenna. This is required for our deployment environment: scales mount inside metal walk-in coolers (Faraday cages) at bar locations. An external antenna on a short U.FL cable can be routed outside the enclosure or to the lid.
The design is derived from the Olimex ESP32-C3-DevKit-LiPo (reference schematic, Rev C) and adds the HX711 load cell amplifier, SSD1306 OLED display, and supporting power circuitry to produce a single, self-contained board.
Target volume: ~500 units (initial production run for US bar/restaurant market).
2. Functional block diagram¶
┌─────────────────────────────────┐
USB-C (charge) ────►│ TP4056 (charge IC) │
│ USB-C receptacle (5V/GND only) │
└────────────┬────────────────────┘
│ VBAT (3.7–4.2V nominal, 4.25V max) ← always live when battery present
│
┌────────────▼────────────────────┐
│ LiPo pouch cell (J1) │◄──── TP4056 BAT pin charges here
│ 3.7V 5000mAh, 10×54×60mm │ regardless of SW2 position
└────────────┬────────────────────┘
│ VBAT
┌────────────▼────────────────────┐
│ SW2 — power switch (SPST) │ OFF: load dead, charge still works
└────────────┬────────────────────┘ ON: load powered
│ VBAT (switched)
┌────────────▼────────────────────┐
│ HT7333 LDO → 3V3 rail │
│ 470kΩ/470kΩ divider → GPIO4 │
└────────────┬────────────────────┘
│ 3V3
┌───────────────────▼───────────────────────────┐
│ ESP32-C3-MINI-1U module │
│ (U.FL → external antenna) │
│ │
│ GPIO0 ◄──── HX711 DOUT │
│ GPIO10 ────► HX711 CLK │
│ GPIO4 ◄──── BAT_ADC (divider midpoint) │
│ GPIO7 ◄───► SSD1306 SDA (I2C) │
│ GPIO3 ────► SSD1306 SCL (I2C) │
│ GPIO8 ────► STATUS LED (active high) │
│ GPIO18/19 USB D± (programming only) │
│ GPIO20/21 UART0 RX/TX (debug header) │
└───────────────────────────────────────────────┘
│
┌────────────▼────────────────────┐
│ HX711 breakout or onboard IC │
│ E+/E−/A+/A− → 4-pin load cell │
└─────────────────────────────────┘
3. Bill of materials (key components)¶
| Ref | Component | Value / Part | Notes |
|---|---|---|---|
| U1 | MCU module | Espressif ESP32-C3-MINI-1U-H4X | External U.FL antenna — required for metal enclosure. 13.2×12.5×2.4 mm. Recommended SKU (−40~105°C, chip rev v1.1) |
| J5 | Antenna connector | U.FL (IPEX/MHF) SMD receptacle | Molex 73412-0110 or equiv. Mates with pigtail to external 2.4GHz antenna |
| ANT1 | External antenna | 2.4GHz omnidirectional, U.FL pigtail | e.g. Taoglas FXP73 (adhesive patch, fits enclosure lid) or rod antenna. Keep pigtail ≤150mm |
| U2 | Load cell amp | AVIA HX711 | SOP-16 |
| U3 | LDO regulator | Holtek HT7333-A SOT-23-3 | 3.3V, 250mA — NOT AMS1117 (wrong dropout/noise) |
| U4 | LiPo charge IC | TP4056 SOT-23-8 or TC4056 | USB-C input, 1A max, Prog resistor for 500mA |
| J1 | Battery connector | JST PH 2.0mm 2-pin | Design footprint with P+ on pin 1 (standard). Selected cell has reversed wiring — reseat wires before connecting (see constraint #11) |
| J2 | Load cell connector | 6-pin 2.54mm KK or screw terminal | 4 cells wired in parallel: E+, E−, A+, A−, Shield, spare. All 4 cell E+ → pin 1, etc. |
| J3 | USB-C receptacle | 16-pin mid-mount | 5V + GND only wired; D± to GPIO18/19 for JTAG/flashing |
| J4 | Debug header | 4-pin 2.54mm | 3V3, GND, TX (GPIO20), RX (GPIO21) |
| D1 | Charge indicator LED | 0402 amber | TP4056 CHRG pin — on while charging, off when complete |
| LED1 | Status LED | 0402 blue | GPIO8, 1kΩ series |
| SW2 | Power switch | SPST slide or rocker, panel-mount, ≥0.5A 12V DC | In series with VBAT → HT7333 path. Wires from PCB pad to panel-mount body. 2-pin PCB footprint on board edge |
| DISP1 | OLED display | SSD1306 128×32 I2C module | 4-pin FPC or pin header — 3V3, GND, SDA, SCL |
| R1, R2 | Battery divider | 470kΩ 0402 1% | VBAT → R1 → GPIO4 → R2 → GND |
| C1 | Bulk cap | 100µF electrolytic | VBAT rail |
| C2 | LDO bypass | 10µF 0402 ceramic | 3V3 rail |
| C3, C4 | Decoupling | 100nF 0402 ceramic | U2 VCC, U1 3V3 |
| C5 | TP4056 Vcc bypass | 100nF 0402 | Per datasheet |
Cost note: At volume, the ESP32-C3-MINI-1U is ~$2–3. HX711 ~$0.30. TP4056 ~$0.15. Total BOM target: < $12 (excluding LiPo cell, enclosure, and antenna).
4. Subcircuit details¶
4.1 Power — LiPo charge + regulation + switch¶
USB-C 5V ──► TP4056 IN
TP4056 BAT ↔ LiPo cell (J1) ← charge path, always active with USB
VBAT (from cell) ──► SW2 (power switch) ──► HT7333 IN ──► 3V3 rail
Switch truth table:
| SW2 | USB present | System | Charging |
|---|---|---|---|
| OFF | No | Off | No |
| OFF | Yes | Off | Yes — TP4056 charges cell through the BAT pin regardless of SW2 |
| ON | No | Running on battery | No |
| ON | Yes | Running | Yes |
The TP4056 BAT pin connects directly between the charger IC and the cell — it is not in the SW2 switched path. SW2 only interrupts current flowing into the HT7333 LDO. This is the key layout constraint: the cell, J1, and TP4056 form a loop that must remain intact independent of SW2.
Battery specs (selected cell):
| Parameter | Value |
|---|---|
| Chemistry | Lithium Polymer (LiPo pouch) |
| Capacity | 5000 mAh |
| Nominal voltage | 3.7V |
| Max charge voltage | 4.25V |
| Max charge current | 2500mA (2.5A) |
| Physical (T×W×L) | 10 × 54 × 60mm |
| Connector | JST PH 2.0mm — CAUTION: polarity reversed (− on pin 1, + on pin 2). Reseat wires before connecting |
| Cable length | 50mm |
Runtime estimate: With power optimisations (HX711 sleep between readings, OLED on between updates, WiFi MAX_MODEM sleep, connect/disconnect MQTT pattern, delta publishing): ~15–20mA average. 5000mAh ÷ 17mA ≈ 290h ≈ ~12 days per charge. Without those optimisations (spinning loop, HX711/OLED always on, MIN_MODEM): ~100mA → 2 days. See firmware v0.3.8+ for the optimisations. Battery life test pending on dev hardware.
Charge rate: TP4056 at 1A (R_prog = 1.2kΩ) = 0.2C — well within cell's 2.5A max. Conservative and safe. Full charge from empty ≈ 5h.
Charge termination voltage: TP4056 terminates at 4.2V. Cell's max is 4.25V. TP4056 will stop at 4.2V — safe, slightly under-charges (~97% capacity), which is better for long-term cycle life. Do not modify the TP4056 to target 4.25V.
- TP4056 charge current: set with R_prog = 1.2kΩ → 1A charge rate. Reduce to 2.4kΩ (500mA) if thermal headroom is tight in enclosure.
- SW2 must be rated for battery current: ≥0.5A at 5V DC. System peak ~200mA (WiFi TX burst). A standard mini rocker or slide switch handles this easily.
- SW2 wires: short as practical, 26AWG minimum. Place PCB pads on board edge adjacent to the enclosure cutout for the switch body.
- HT7333: input cap 10µF + 100nF, output cap 10µF + 100nF. Place close to U1.
- VBAT and 3V3 are separate rails. Do not connect them downstream.
- VBAT powers the HX711 AVDD (3.7–4.2V is fine per HX711 datasheet 2.6–5.5V). Alternative: power HX711 AVDD from 3V3 for consistency — either works.
4.2 Battery voltage sense¶
- Ratio: 0.5 — at 4.2V (TP4056 termination), GPIO4 sees 2.1V. At 4.25V cell max, GPIO4 sees 2.125V. Both well within 3.3V ADC range.
- Use 1% resistors. 5% tolerance gives ±100mV error at full charge.
- Add 100nF cap from GPIO4 to GND to reduce ADC noise.
- Wire directly to GPIO4 (ADC1_CH4) as above. Do NOT use GPIO5 — it is ADC2_CH0, which is disabled during WiFi operation (hardware limitation of the ESP32-C3 SoC). This is also why the Olimex dev kit's BAT_SENS_E1 jumper must not be soldered on the dev board; on this custom PCB, simply avoid GPIO5 for any analog function.
4.3 HX711 load cell amplifier¶
Load cell (4-wire Wheatstone) ──► HX711:
E+ → AVDD (excitation +)
E− → AGND (excitation −)
A+ → INA+ (signal +, channel A)
A− → INA− (signal −, channel A)
HX711 digital interface:
DOUT → GPIO0 (ESP32-C3 input)
SCK → GPIO10 (ESP32-C3 output)
VCC → 3V3
DVDD → 3V3
AVDD → VBAT or 3V3 (tie AVDD to 3V3 for consistency)
AGND, DVDD → GND
- Channel B is unused; leave INA+/INB+ open or tied to GND.
- HX711 RATE pin: tie LOW (pin 15) for 10 SPS (less noise, preferred for scale). Tie HIGH for 80 SPS only if faster reads are needed during calibration.
- Decouple HX711 AVDD with 10µF + 100nF close to pin.
- Keep HX711 analog traces short; pour analog GND under HX711.
- Add 4-pin connector (J2) for load cell wires: E+, E−, A+, A−.
4.4 OLED display (SSD1306 128×32)¶
- I2C address: 0x3C (SA0 pin = GND)
- SDA → GPIO7, SCL → GPIO3
- Pull-ups: 4.7kΩ to 3V3 on both lines. If using an OLED module with onboard pull-ups, do not add external ones (double pull-up causes issues).
- Power: 3V3. Add 10µF bypass cap on OLED Vcc.
- Interface options: 4-pin FPC connector or 4-pin 1.27mm header for flat cable.
4.5 Status LED¶
- GPIO8 → 1kΩ → LED anode → LED cathode → GND
- Blue 0402 LED (Vf ≈ 3.0V, If ≈ 3mA at 1kΩ with 3.3V supply)
- Firmware drives active high.
4.6 USB-C connector¶
- Wire VBUS (pin A4/B4) → TP4056 IN (charge only).
- Wire GND (A1/B1) → GND.
- Wire D+ (A6) → ESP32-C3 GPIO19, D− (A7) → GPIO18 (JTAG/flashing over USB).
- CC1, CC2: 5.1kΩ pull-downs to GND each (tells host this is a 5V/0.9A device).
- No USB data switch needed — USB-C ↔ ESP32-C3 native USB is direct.
4.7 USB VBUS sense¶
When USB is connected, VBUS is 5V. The battery ADC will read the TP4056 output (~4.2V) rather than the real battery state. Firmware suppresses battery reporting and shows "charging" instead when it detects USB presence.
- Divider midpoint = 2.5V when USB present (5V), 0V when absent. Both within ADC range.
- 100kΩ/100kΩ values — high impedance keeps idle draw < 25µA.
- GPIO1 configured as
INPUTin firmware (no internal pull-up/down needed). - Firmware reads HIGH (≥2.5V) = USB present; LOW (0V) = battery only.
- Add 100nF cap from GPIO1 to GND for noise filtering.
5. GPIO assignment summary¶
| GPIO | Direction | Function | Notes |
|---|---|---|---|
| GPIO0 | Input | HX711 DOUT | Digital only, no ADC needed |
| GPIO3 | Output | I2C SCL (SSD1306) | 4.7kΩ pull-up to 3V3 |
| GPIO4 | Input | Battery ADC | ADC1_CH4 — external 470kΩ/470kΩ divider |
| GPIO7 | Bidirectional | I2C SDA (SSD1306) | 4.7kΩ pull-up to 3V3 |
| GPIO8 | Output | Status LED | Active high, 1kΩ series |
| GPIO10 | Output | HX711 CLK | Digital only |
| GPIO18 | Bidirectional | USB D− | Native USB / JTAG |
| GPIO19 | Bidirectional | USB D+ | Native USB / JTAG |
| GPIO20 | Output | UART0 TX | Debug header J4 |
| GPIO21 | Input | UART0 RX | Debug header J4 |
| GPIO1 | Input | USB VBUS sense | 100kΩ/100kΩ divider from VBUS — HIGH = USB present, LOW = battery only |
Do not use: GPIO5 (ADC2 — broken during WiFi), GPIO11–17 (internal flash SPI on ESP32-C3-MINI-1U — not bonded to module pads but reserved).
6. Mechanical / form factor¶
6.1 Overall assembly concept¶
The Scale Sense unit uses the DeVault Enterprises ICD2000 keg stacker ring as the structural base. The ring cross-section is a moat/bathtub shape — flat platform on top, outer ring wall hangs down on the outside, inner ring wall hangs down on the inside, with an annular gap between them where the pucks sit. The outer ring is taller than the inner ring.
←──────────── outer OD ~415mm ──────────────→
←──── inner OD ~335mm ────→
──────────────────────────────────────────── ← platform top (upper keg sits here)
│ │←────── annular gap ~40mm ──────→│ │
│ │ (4 pucks go here) │ │
│ │ │ │
│ └─────────────────────────────────┘ │ ← inner ring base (20mm tall)
│ │
└────────────────────────────────────────┘ ← outer ring base (30mm tall)
There are three variants — same electronics, same pucks, puck height differs:
Variant 1 — Keg on keg (stacked cooler setup)
Bottom keg fits up inside both rings and contacts the platform underside. Pucks sit in the annular gap on the bottom keg's top surface.
────────────────────────────────────── ← platform top (upper keg above)
│ │ [puck] [puck] [puck] [puck]│ │ ← pucks in annular gap
│ │ on bottom keg top surface │ │
│ └───────────────────────────────-┘ │ ← inner ring (inside bottom keg)
│ ← bottom keg body → │ ← outer ring (around bottom keg)
────────────────────────────────────── ← bottom keg top (keg not weighed)
Puck height: any — shorter is better for stability. Just needs to fill the gap between the bottom keg top surface and the platform underside.
Variant 2 — Floor standing (single keg, no bottom keg)
Without pucks, the outer ring base contacts the floor first (tallest point). Pucks must protrude below the outer ring base to lift it off the floor.
────────────────────────────────────── ← platform top (keg above)
│ │ [puck] [puck] [puck] [puck]│ │ ← pucks in annular gap
│ │ │ │ pucks extend below outer ring base
│ └───────────────────────────────-┘ │ ← inner ring (raised off floor)
│ [puck feet] │
└──────────│──────────────────────│────┘ ← outer ring base (lifted by pucks)
─────┼──────────────────────┼────── floor
Puck height > outer ring leg length. Outer ring lifts clear of floor.
Variant 3 — Dolly (mobile setup, DeVault 3000 or similar)
The dolly is taller than the outer ring leg length, so the outer ring dangles free. The inner ring makes first contact with the dolly platform (without pucks). Pucks protrude below the inner ring base to lift it off the dolly platform.
────────────────────────────────────── ← platform top (keg above)
│ │ [puck] [puck] [puck] [puck]│ │ ← pucks in annular gap
│ │ │ │ pucks extend below inner ring base
│ └────────────────────────────────┘ │ ← inner ring (lifted off dolly by pucks)
│ [puck feet on dolly] │
│ ────────────────────────────── │ ← dolly platform
│ │
└──────────────────────────────────────┘ ← outer ring dangles free (no contact)
│ caster │
Puck height > inner ring leg length. Outer ring hangs free — no lateral constraint from the ring in this variant (dolly provides its own stability).
Puck height summary:
| Variant | Puck height requirement | Practical target |
|---|---|---|
| 1 — keg on keg | Any. Shorter = better stability | ~10–15mm |
| 2 — floor | > 30mm (outer ring height) | ~35mm |
| 3 — dolly | > 20mm (inner ring height) | ~25mm |
Measured ICD2000 dimensions (physical ring): - Outer ring height: 30mm - Inner ring height: 20mm - Annular gap width (inside outer to inside inner): 40mm — puck footprint must fit within this - Overall diameter: ~415mm (16")
Electronics housing (same for all variants) — bolted to outside of ICD2000 ring:
┌──────────────────────────────────────────┐
│ [OLED] [●CHG] [●STATUS] │
│ [USB-C] [SW2 ↑] │
└──────────────────────────────────────────┘
What is being measured: ICD2000 ring weight + keg weight.
Ring tare (~1.3–3 lbs) is constant — subtracted automatically during tare procedure
(tare_empty with empty ring on pucks, tare_full with ring + full keg).
Critical requirement for all variants: The ICD2000 platform must rest only on the 4 puck top plates — no other surface contact. Any bypass contact carries load and causes under-reading.
6.2 Load cell pucks¶
Load cell spec: - 4× bar-type load cells, rated 50 kg each (200 kg / 440 lbs combined — well above the 161 lbs max for a full half-barrel) - Prefer 1kΩ bridge resistance cells — lower excitation current at 3.3V AVDD (~13mA at 1kΩ vs ~38mA at 350Ω). Either works; firmware power_down limits active time to ~400ms per 60s cycle regardless.
Puck housing (per cell — 4 required):
┌─────────────────────┐ ← top plate (~50×50×5mm aluminium)
│ ring base contact │ ICD2000 ring underside rests here
└──────────┬──────────┘
│ load point (center of bar cell free end, facing UP)
┌──────────▼──────────┐
│ bar load cell │ ~80×13×13mm typical 50kg bar cell
└──────────┬──────────┘
│ fixed end bolted to bottom plate
┌──────────▼──────────┐ ← bottom plate (~50×50×5mm aluminium)
│ bottom keg contact │ sits on flat top rim of bottom keg
└─────────────────────┘
Wiring: - Each puck has a short 4-wire cable (E+, E−, A+, A−) - All 4 cables parallel at a small junction point inside the ring (terminal block or junction PCB) before a single 6-wire cable exits through the ring wall to J2 - This keeps 4 cables inside the ring and only 1 cable reaching the electronics housing - J2 connector: 6-pin, 2.54mm or Molex KK — E+, E−, A+, A−, Shield, spare
6.3 Electronics housing¶
The electronics housing mounts on the outside wall of the ICD2000 ring. It is not constrained by the ring height — it can extend above the ring top as needed.
PCB target size: 60 × 40mm. 2-layer is sufficient.
Housing height constraint: ≤ 30mm — must not exceed the outer ring height so the assembly sits flush. This is tight: battery (10mm) + PCB with components (~12mm) + housing walls (~2mm each side) = ~26mm internal. Achievable with low-profile SMD components. Confirm component heights before finalising housing.
Internal layout (PCB + battery): - Battery (10 × 54 × 60mm) and PCB (60 × 40mm) sit side by side or stacked. Minimum housing internal floor: ~65 × 65mm side-by-side, or ~65 × 105mm stacked. - Battery sizing: current cell is 5000mAh. May downsize once overnight battery life test on dev prototype is confirmed — smaller cell reduces housing footprint. Do not finalise housing dimensions until test is complete.
Housing face (user-visible):
| Feature | Position | Notes |
|---|---|---|
| OLED (128×32) | Top-left of face | Window cutout with light diffuser or direct viewing hole |
| D1 — CHG LED (amber) | Right of OLED | TP4056 CHRG pin — on while charging, off when complete. 3mm LED or light pipe |
| LED1 — Status (blue) | Right of D1 | GPIO8 — identify flash / maintenance pulse / OTA. 3mm LED or light pipe |
| USB-C (J3) | Bottom-right of face | Flush or recessed; IP-rated plug cover for cooler use |
| SW2 (power switch) | Bottom-left of face | Panel-mount rocker or slide; accessible without tools |
Housing construction: ABS or polycarbonate, IP54 minimum (cooler condensation). Mount to ring wall with 2–4× M4 bolts through ring wall, or stainless hose-clamp if drilling the ring is undesirable.
Connector placement on PCB: - J1 (battery): inner edge, JST PH2.0 — short fly lead to battery in housing - J2 (load cell): bottom edge — 6-pin, wires pass through ring wall grommet - J3 (USB-C): aligns with housing face cutout - J4 (debug header): internal — not accessible through housing face - SW2 pads: near bottom-left edge — short fly leads to panel-mount switch
Layer count: 2-layer. Keep HX711 analog section (left) separated from MCU (right). GND pour on both layers, stitched with vias.
Mounting holes: 4× M3, one per corner, 3mm from edge.
6.4 Antenna¶
- U.FL receptacle (J5) on PCB board edge nearest housing antenna exit
- ≤150mm RG178 pigtail to external antenna
- Antenna mounts on outside face of housing or ring wall — not inside the housing
- Keep pigtail away from load cell wires (RF interference on HX711 analog lines)
6.5 Height budget (ring interior, puck stack)¶
Puck top plate: ~5mm
Load cell body height: ~13mm (typical 50kg bar cell)
Puck bottom plate: ~5mm
Ring floor to ring top: 38–76mm (ICD2000 range)
─────────────────────────────────────────────
Puck total height: ~23mm ✓ (well within 38mm minimum ring height)
Remaining clearance: ~15–53mm above puck to ring top edge
Keg bottom rim should contact puck top plates, not the ring top edge. If puck height + keg rim clearance is tight, shim the puck bottom plates.
7. Design constraints and gotchas¶
| # | Constraint | Why |
|---|---|---|
| 1 | Use HT7333, not AMS1117 | AMS1117 has insufficient noise rejection for ADC accuracy; wrong dropout for 3.3V from 3.7V LiPo; we got burned replacing these on prototype boards |
| 2 | Battery ADC must use GPIO4 (ADC1), not GPIO5 | ESP32-C3 ADC2 is disabled when WiFi radio is active; GPIO5 routes to ADC2 |
| 3 | 470kΩ divider resistors, not 100kΩ | Lower power draw — at 4.2V, 470kΩ pair draws ~4.5µA vs ~21µA with 100kΩ. Matters in modem-sleep |
| 4 | HX711 RATE pin LOW | 10 SPS reduces quantisation noise for a scale; 80 SPS only needed in bench test rigs |
| 5 | Use ESP32-C3-MINI-1U, not MINI-1 | Scales mount inside metal walk-in coolers (Faraday cages) — onboard PCB antenna (MINI-1) is blocked. MINI-1U routes RF out via U.FL pigtail to an antenna outside the enclosure. Bonus: MINI-1U is 4mm shorter (no antenna protrusion), and requires no keepout zone on the host PCB |
| 6 | U.FL connector placement on board edge | Short pigtail (≤150mm RG178) to external antenna. Mount J5 near the enclosure wall exit. Do not route high-current traces under U.FL pad |
| 7 | GPIO9 strapping pin | Must be HIGH at boot. No button connected — leave GPIO9 unconnected or pull HIGH. Do NOT tie it permanently low |
| 8 | No deep sleep | Firmware uses modem sleep only (BLE + MQTT must stay alive). Power saving comes from C3's lower sleep current, not from deep sleep mode |
| 9 | CC resistors on USB-C | 5.1kΩ pull-downs required on CC1 and CC2 for USB-C host to detect and supply power |
| 10 | SW2 must NOT interrupt the TP4056 BAT–cell path | The charge loop (TP4056 BAT ↔ cell) must stay intact when SW2 is open. SW2 only breaks VBAT → HT7333. If SW2 is wired incorrectly (in series with the battery, before the TP4056 BAT node), charging will not work when the unit is switched off — which is the primary charging use case (shipped off, plugged in to pre-charge) |
| 11 | J1 LiPo polarity — reseat wires before connecting | PCB footprint has P+ on pin 1 (standard). The selected cell (Amazon B0GL1MH5YT) ships with reversed wiring (− on pin 1, + on pin 2). Plugging in reversed will likely destroy the TP4056 and may damage the cell. Reseat the wires in the JST housing before first connection. Confirm against actual cell before layout sign-off |
| 12 | LED1 wired active-high | GPIO8 → 1kΩ → LED → GND. Firmware production env must NOT include -DLED_ACTIVE_LOW (that flag is only for the Olimex dev board, where the LED is wired active-low) |
8. Firmware context (for hardware verification)¶
The firmware is PlatformIO / Arduino framework. Key configuration once PCB is populated:
// firmware/include/config.h — production PCB pin mapping (add to BOARD_ESP32_C3 block)
#define PIN_HX711_DOUT 0
#define PIN_HX711_CLK 10
#define PIN_BATTERY_ADC 4
#define PIN_USB_SENSE 1 // add when PCB is built — not present on dev board
#define PIN_LED 8
#define PIN_I2C_SDA 7
#define PIN_I2C_SCL 3
#define BATTERY_DIVIDER_RATIO 2.0f // 470k/470k divider
Note: the production PCB firmware env should not include -DLED_ACTIVE_LOW (LED1 is wired active-high on the PCB). The dev board env uses this flag because the Olimex board wires GPIO8 active-low.
Note: the production PCB firmware env should not include -DARDUINO_USB_CDC_ON_BOOT=1. That flag is required on the dev board for USB serial monitor, but it prevents esp_light_sleep_start() from engaging (light sleep powers down the USB peripheral and panics the CDC stack). Without it, light sleep works correctly on production hardware. Initial firmware flashing on the production PCB should be done via the UART debug header (J4) using esptool.py; subsequent updates go via OTA.
Build target: esp32-c3-devkitm-1 in PlatformIO. The ESP32-C3-MINI-1U uses the
same ESP32-C3 SoC as the MINI-1 — PlatformIO board ID, firmware, and all GPIO
assignments are identical. The only physical difference is the antenna.
Hardware bring-up checklist (in order):
1. Power: measure 3V3 rail with no MCU populated — confirm HT7333 output.
2. Charge: plug USB-C, confirm D1 amber LED lights, cell voltage rises.
3. Boot: flash firmware via USB-C (no programmer needed — native USB DFU).
4. HX711: confirm stable weight readings over serial (unloaded + loaded).
5. Battery ADC: read GPIO4, verify maps to correct voltage (expect ~2.1V at 4.2V cell).
6. USB sense: plug/unplug USB-C, confirm GPIO1 reads HIGH/LOW; firmware shows "charging" on OLED when USB present.
7. OLED: confirm display renders beer name + level bar.
8. BLE: scan from phone, confirm SCALE-xxxx advertises.
9. WiFi + MQTT: connect to Pi AP, confirm readings publishing.
10. Power meter: measure modem-sleep current — target < 10mA average.
9. Reference documents¶
- Espressif ESP32-C3-MINI-1 & MINI-1U datasheet v2.1 (covers both variants): https://www.espressif.com/sites/default/files/documentation/esp32-c3-mini-1_datasheet_en.pdf
- Espressif ESP32-C3-MINI-1U Reference Design (Altium — schematics, PCB layout, Gerbers, BOM): https://www.espressif.com/sites/default/files/documentation/ESP32-C3-MINI-1U_Reference_Design.zip Use this for the module footprint and land pattern in Altium. This is the primary hardware design resource for the custom PCB.
- Olimex ESP32-C3-DevKit-LiPo schematic (KiCad Rev C — circuit reference only, not Altium): https://github.com/OLIMEX/ESP32-C3-DevKit-LiPo
- HX711 datasheet (AVIA Semiconductor)
- HT7333 datasheet (Holtek)
- TP4056 datasheet
- SSD1306 datasheet (Solomon Systech)
- Scale Sense firmware repo: https://github.com/scale-sense/keg-scale —
firmware/directory, branchmain