Smart Espresso Scale
Layout Verification Notes — Smart Espresso Scale
esp32-c3-devkitm-1 as a practical starting target for ESP32-C3 modulesTable
| Function | ESP32-C3 GPIO | Schematic Net | Direction | Notes |
|---|---|---|---|---|
| HX711 data | GPIO0 | HX711_DOUT | Input | Data ready + serial data from HX711. |
| HX711 clock | GPIO1 | HX711_SCK | Output | Keep low when idle. |
| Battery ADC | GPIO3 | BAT_SENSE | Analog input | 1M/330k divider. |
| Tare button | GPIO4 | BTN_TARE | Input pull-up | Active-low. |
| OLED SDA | GPIO5 | I2C_SDA | I2C | 4.7k pull-up. |
| OLED SCL | GPIO6 | I2C_SCL | I2C | 4.7k pull-up. |
| Mode button | GPIO7 | BTN_MODE | Input pull-up | Active-low. |
| Boot | GPIO9 | ESP_BOOT_GPIO9 | Strap/input | Pull-up + boot button. |
| UART RX | GPIO20/RXD | UART_RXD | Input | J5 programming header. |
| UART TX | GPIO21/TXD | UART_TXD | Output | J5 programming header. |
platformio.ini:Ini
[env:espresso_scale] platform = espressif32 board = esp32-c3-devkitm-1 framework = arduino monitor_speed = 115200 build_flags = -D ARDUINO_USB_MODE=1 -D ARDUINO_USB_CDC_ON_BOOT=1 lib_deps = bogde/HX711@^0.7.5 olikraus/U8g2@^2.35.30
src/main.cpp:Cpp
#include <Arduino.h> #include <Wire.h> #include <WiFi.h> #include <HX711.h> #include <U8g2lib.h> #define HX711_DOUT_PIN 0 #define HX711_SCK_PIN 1 #define BAT_SENSE_PIN 3 #define BTN_TARE_PIN 4 #define I2C_SDA_PIN 5 #define I2C_SCL_PIN 6 #define BTN_MODE_PIN 7 #define VBAT_TOP_OHMS 1000000.0f #define VBAT_BOTTOM_OHMS 330000.0f #define ADC_MAX_COUNTS 4095.0f #define ADC_REF_VOLTS 3.3f #define SCALE_READ_INTERVAL_MS 100 #define DISPLAY_INTERVAL_MS 250 #define LONG_PRESS_MS 800 HX711 scale; U8G2_SSD1306_128X64_NONAME_F_HW_I2C display(U8G2_R0, U8X8_PIN_NONE); static float calibrationFactor = 1000.0f; // TODO: calibrate with known mass static unsigned long lastScaleRead = 0; static unsigned long lastDisplay = 0; static float weightGrams = 0.0f; static bool timerRunning = false; static unsigned long timerStartMs = 0; float readBatteryVoltage() { uint16_t raw = analogRead(BAT_SENSE_PIN); float adcVoltage = (raw / ADC_MAX_COUNTS) * ADC_REF_VOLTS; return adcVoltage * ((VBAT_TOP_OHMS + VBAT_BOTTOM_OHMS) / VBAT_BOTTOM_OHMS); } bool pressed(uint8_t pin) { static unsigned long lastDebounce[10] = {0}; static bool lastState[10] = {false}; bool nowPressed = digitalRead(pin) == LOW; uint8_t idx = pin < 10 ? pin : 0; if (nowPressed != lastState[idx] && millis() - lastDebounce[idx] > 40) { lastDebounce[idx] = millis(); lastState[idx] = nowPressed; return nowPressed; } return false; } void initScale() { scale.begin(HX711_DOUT_PIN, HX711_SCK_PIN); scale.set_scale(calibrationFactor); scale.tare(20); } void initDisplay() { Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN); display.begin(); display.setFont(u8g2_font_6x12_tf); } void updateDisplay() { float vbat = readBatteryVoltage(); unsigned long elapsed = timerRunning ? (millis() - timerStartMs) / 1000UL : 0; display.clearBuffer(); display.setCursor(0, 12); display.print("Smart Espresso Scale"); display.setCursor(0, 30); display.print("Weight: "); display.print(weightGrams, 1); display.print(" g"); display.setCursor(0, 46); display.print("Timer: "); display.print(elapsed); display.print(" s"); display.setCursor(0, 62); display.print("VBAT: "); display.print(vbat, 2); display.print(" V"); display.sendBuffer(); } void setup() { Serial.begin(115200); delay(300); Serial.println("Smart Espresso Scale booting"); WiFi.mode(WIFI_OFF); // keep RF quiet during precision measurements by default pinMode(BTN_TARE_PIN, INPUT_PULLUP); pinMode(BTN_MODE_PIN, INPUT_PULLUP); analogReadResolution(12); analogSetPinAttenuation(BAT_SENSE_PIN, ADC_11db); initDisplay(); initScale(); updateDisplay(); } void loop() { unsigned long now = millis(); if (pressed(BTN_TARE_PIN)) { Serial.println("Tare requested"); scale.tare(20); } if (pressed(BTN_MODE_PIN)) { timerRunning = !timerRunning; if (timerRunning) timerStartMs = now; Serial.printf("Timer %s\n", timerRunning ? "started" : "stopped"); } if (now - lastScaleRead >= SCALE_READ_INTERVAL_MS) { lastScaleRead = now; if (scale.is_ready()) { weightGrams = scale.get_units(3); Serial.printf("Weight: %.2f g, VBAT: %.2f V\n", weightGrams, readBatteryVoltage()); } else { Serial.println("HX711 not ready"); } } if (now - lastDisplay >= DISPLAY_INTERVAL_MS) { lastDisplay = now; updateDisplay(); } }
Bash
pio run pio run -t upload pio device monitor
calibrationFactor with a known weight before using the scale.Platform & Toolchain
Pin Mapping
Dependencies & Project Setup
Complete Firmware Source
Build & Flash Instructions