Build a GravityMon (ESP32)
Build a digital hydrometer using a modern ESP32 board with Bluetooth support — running GravityMon firmware for advanced gravity monitoring, velocity tracking, and multi-service data forwarding.
What is GravityMon?
What is GravityMon?
GravityMon is open-source firmware for building your own digital hydrometer — a small, battery-powered device that floats inside your fermenter and continuously measures gravity and temperature throughout fermentation. It eliminates the need to pull samples, giving you real-time insight into how your beer is progressing.
The device works on the same principle as the iSpindel: an accelerometer inside a sealed tube measures the tilt angle as the density of the liquid changes during fermentation. GravityMon converts that tilt angle into a gravity reading and transmits it over WiFi or Bluetooth to your brewing software.
Why GravityMon?
GravityMon is 100% compatible with iSpindel hardware — no modifications required. If you have an existing iSpindel, you can flash GravityMon and immediately benefit from its features. If you're building from scratch, the hardware is the same.
What sets GravityMon apart:
- Advanced calibration — a built-in formula editor with graphical validation helps you dial in accurate gravity readings
- Broad service support — push data to Brewfather, Fermentrack, Brewers Friend, BrewSpy, Home Assistant, ThingSpeak, MQTT, InfluxDB, and more — up to 5 endpoints simultaneously
- OTA updates — update firmware over WiFi without opening the tube
- Gravity velocity (ESP32) — shows how many gravity points you're dropping per 24 hours, so you can see fermentation activity at a glance
- Advanced filtering (ESP32) — filters the data to avoid peaks during very active fermentations
- Bluetooth transmission (ESP32) — broadcast in Tilt, GravityMon, or RAPT Pill formats for local receivers
- Modern ESP32 support — runs on ESP8266 (classic iSpindel) as well as ESP32-C3, S2, and S3 boards
How It Works
- The device floats in your fermenter at an angle determined by the liquid's density
- The accelerometer measures the tilt angle, which changes as sugars are consumed during fermentation
- The microcontroller wakes periodically, reads the angle and temperature, converts them to a gravity reading using your calibration formula, and transmits the data over WiFi
- Your brewing software receives the data and logs it — giving you a complete fermentation curve without touching the fermenter
Between readings, the device enters deep sleep to conserve battery. A typical 18650 cell lasts several weeks on a single charge.
What You'll Need
Parts Needed
What You'll Need
This build uses a modern ESP32 board instead of the classic ESP8266. The wiring is nearly identical, but you get Bluetooth support, more memory, and access to all of GravityMon's advanced features.
The Microcontroller
GravityMon supports several ESP32 boards that are pin-compatible with the original D1 Mini form factor:
| Board | Bluetooth | Notes |
|---|---|---|
| Lolin ESP32-S3 Mini | Yes (BLE 5) | Most capable, slightly more expensive |
| Lolin ESP32-C3 Mini | Yes (BLE 5) | Recommended — good balance of features and availability |
| Lolin ESP32-S2 Mini | No | WiFi only — no Bluetooth transmission |
| Waveshare ESP32-C3 Zero | Yes (BLE 5) | Compact 18-pin form factor |
The ESP32-C3 Mini is the a good choice (and popular) for most builds. It supports Bluetooth (for broadcasting in Tilt/RAPT format to local receivers), has RTC memory for filtering and gravity velocity calculations, and is widely available.
If you don't need Bluetooth transmission and only plan to use WiFi, the ESP32-S2 Mini works well and is typically the cheapest option.
Gyroscope Options
The ESP32 build supports the same GY-521 (MPU6050) as the classic build. GravityMon also supports two alternatives:
| Gyroscope | Calibration | Notes |
|---|---|---|
| MPU6050 (GY-521) | Manual | Standard choice, cheapest, widely available |
| MPU6500 | Manual | Drop-in replacement for MPU6050 |
| ICM-42670-P | Factory calibrated | No manual gyro calibration needed (requires GravityMon v2.2+) |
The ICM-42670-P is factory calibrated, which simplifies setup — but it's harder to source and more expensive. The MPU6050 works great and will give good results in combination with the filtering feature, calibration only takes a minute in GravityMon's web interface.
Other Components
The remaining parts are the same as the classic build:
- DS18B20 waterproof temperature sensor with 4.7kΩ pull-up resistor
- TP4056 battery charger module with protection
- 18650 battery (unprotected, flat-top)
- Slide switch for power
- PET preform tube (130mm Petling)
- 3D-printed sled to hold everything
Tools
- Soldering iron and solder
- Wire strippers
- Hot glue gun (for securing components to the sled)
- A computer with a USB port and web browser (for flashing firmware)
- A USB-C data cable (most ESP32 mini boards use USB-C)
Assemble the Hardware
Assemble the Hardware
The ESP32 build uses the same wiring layout as the classic ESP8266 build — the ESP32 mini boards are designed to be pin-compatible. The only differences are pin labels and the USB connector.
Wiring Diagram
Gyroscope (GY-521 / MPU6050)
| GY-521 Pin | ESP32 Mini Pin |
|---|---|
| VCC | 3.3V |
| GND | GND |
| SCL | GPIO9 (SCL) |
| SDA | GPIO8 (SDA) |
On Lolin ESP32 mini boards, the default I2C pins are GPIO8 (SDA) and GPIO9 (SCL). These are in the same physical position as D2/D1 on the D1 Mini, so if you're using a sled designed for the D1 Mini form factor, the wiring routes the same way.
Temperature Sensor (DS18B20)
| DS18B20 Wire | ESP32 Mini Pin |
|---|---|
| Red (VCC) | 3.3V |
| Black (GND) | GND |
| Yellow (Data) | GPIO0 |
Solder the 4.7kΩ resistor between the data line and 3.3V.
Note: The default one-wire pin differs from the ESP8266 build. GravityMon auto-detects the board type and uses the correct pin.
Power Circuit
The power wiring is identical to the classic build:
- Slide switch between battery positive and TP4056 B+
- TP4056 B- to battery negative
- TP4056 OUT+ to ESP32 Mini 5V (or VBUS on some boards)
- TP4056 OUT- to ESP32 Mini GND
Optional: Battery Voltage Monitoring
For battery monitoring, the ESP32 mini boards have different ADC behavior than the ESP8266. The voltage divider values depend on your specific board — check the GravityMon documentation for the recommended resistor values for your ESP32 variant. GravityMon's hardware test feature (accessible in configuration mode) will show you the raw ADC reading to help verify your voltage divider is working.
Assembly
The physical assembly is the same as the classic build — the ESP32 mini boards have the same form factor as the D1 Mini:
- Mount the ESP32 board on the sled — USB port facing the cap end
- Mount the GY-521 flat on the sled, parallel to the tube length
- Route the DS18B20 probe toward the bottom of the tube, securing with hot glue
- Seat the battery in the sled
- Secure the TP4056 and switch near the cap end
Fit, Seal, and Balance
Slide the assembly into the PET tube, screw the cap tight, and test for leaks.
The ballast and balance requirements are the same — aim for roughly 25° of tilt in plain water. See the classic build's ballast section for tips on adjusting the angle.
Flash the Firmware with BrewFlasher
Flash the Firmware with BrewFlasher
BrewFlasher is a free tool that downloads and flashes the correct firmware to your ESP32 or ESP8266 automatically — no command line needed. It supports all of the major brewing-related ESP projects including BrewPi-ESP, TiltBridge, and more.
You have three options for flashing: the desktop app (Windows/macOS), the web edition (Desktop Chrome/Edge only), or the command line edition (most OSes, including Raspbian/Raspberry Pi OS).
Option A: BrewFlasher Desktop App
- Download the latest release from the BrewFlasher GitHub releases page
- Connect your ESP32 to your computer with a USB cable
- Open the app — no installation required, just double-click
- Select the appropriate serial port (or choose Auto-select)
- Select the appropriate project, device family, and firmware you want to flash
- Click Flash and wait for it to complete
Note - When flashing some devices for the first time, you may need to hold down a button (typically labeled "boot" or "0") when connecting to the computer. You can release the button a few seconds after the device is plugged in.
Option B: BrewFlasher Web Edition
- Open web.brewflasher.com in Google Chrome, Microsoft Edge, or Opera on a computer (other browsers including Safari and Firefox don't support WebSerial)
- Connect your ESP32 to your computer with a USB cable
- Select the project, device family, and firmware you want to flash
- Click "Flash to Controller"
- You will be prompted by your browser to connect a device - select the controller you connected (typically "USB Serial" or similar)
- Click "Install" and wait for the flash to complete
Option C: BrewFlasher Command Line Edition
The command line edition works on any platform with Python — including Raspberry Pi / Raspbian — and provides the same interactive firmware selection as the desktop app.
- Install via pip (if not already installed):
pip install --upgrade brewflasher_cli - Connect your ESP32 to your computer with a USB cable
- Run
brewflasher— it will interactively walk you through selecting a project, device family, firmware, and serial port - Wait for the flash to complete
You can also skip the interactive prompts by passing options directly:
brewflasher --serial-port /dev/ttyUSB0 --baud 460800
Run brewflasher --help for a full list of options.
Troubleshooting
- Device not detected? Try a different USB cable — some cables are charge-only and don't carry data. Also try a different USB port.
- Flash fails on ESP32-S2? Some boards require you to manually enter flash mode: hold the 0 button, press RST, then release 0. Then try flashing again.
- Linux permissions error? Run
sudo usermod -a -G dialout $USER, log out and back in, then try again.
Once the flash completes, your device will reboot and the new firmware will be running.
For GravityMon, select **GravityMon** as the project in BrewFlasher, and choose the firmware for your specific ESP32 variant (C3, S2, or S3).
Initial Setup
Initial Setup
After flashing, GravityMon needs to be configured with your WiFi credentials and basic settings. All configuration happens through a web-based interface — no apps or special software required.
If you are using the Gravitymon webflasher the WiFi settings can be set after flashing has been completed.
Enter Configuration Mode
GravityMon enters configuration mode in two ways:
- Place the device on a flat surface — the accelerometer detects it's horizontal (not floating at an angle) and activates the web interface
- Plug in the USB charger — the device detects charging voltage and enters configuration mode automatically
When in configuration mode and no WiFi has been configured, the device creates its own WiFi access point.
Connect to the Access Point
If you configured WiFi in the Gravitymon web flasher you can skip this step.
- On your phone or computer, look for a WiFi network named GravityMon
- Connect to the GravityMon network
- A captive portal should open automatically. If it doesn't, open a browser and navigate to
http://192.168.4.1
Configure WiFi
If you configured WiFi in the Gravitymon web flasher you can skip this step.
- In the web interface, go to the WiFi settings
- Select your home WiFi network from the scanned list, or enter the SSID manually
- Enter your WiFi password
- Save the settings
GravityMon will connect to your home network. You can then access the configuration interface from any device on the same network by navigating to the device's IP address or hostname.
Find GravityMon on Your Network
After connecting to WiFi, you can access the full configuration interface:
- mDNS: The mDNS name will be unique for that device so the easy way is to use an mDNS dicovery app to identify the device on the network. If you were configuring the device via the portal the device name can be viewed and set. The url will be http://devicename.local
- IP address: Check your router's connected devices list for the GravityMon device
Basic Settings
From the web interface, configure these essentials:
- Device name — useful if you have multiple GravityMon devices
- Temperature unit — Celsius or Fahrenheit
- Gravity unit — Specific Gravity (SG) or Plato
- Sleep interval — how often the device wakes to take a reading (default is 300 seconds / 5 minutes). Shorter intervals give more data points but drain the battery faster
Leave the gravity formula and service endpoints for later — you'll set those up during calibration and service configuration.
Calibrate the Gravity Formula
Calibrate the Gravity Formula
Calibration is the most important step — it translates the raw tilt angle from your accelerometer into an accurate gravity reading. Every device tilts slightly differently depending on weight distribution and balance, so each one needs its own calibration formula.
What You'll Need
- Your assembled GravityMon device, fully charged
- A tall container (a graduated cylinder works best, but any vessel tall enough to let the device float freely will do)
- Plain water (for a 1.000 SG reference point)
- Sugar (table sugar works fine) to make solutions of known gravity
- A traditional hydrometer or refractometer to verify your reference solutions
- A scale (optional, for measuring sugar by weight)
The Calibration Process
The goal is to float your device in several solutions of known gravity and record the tilt angle at each point. GravityMon then fits a polynomial formula to these data points.
Step 1: Prepare Reference Solutions
You need at least 3 data points, but more points give a better formula. A good set:
| Solution | Approximate SG | Sugar per liter of water |
|---|---|---|
| Plain water | 1.000 | 0g |
| Light | 1.020 | ~52g |
| Medium | 1.040 | ~108g |
| Heavy | 1.060 | ~166g |
| Very heavy | 1.080 | ~228g |
Verify each solution's actual gravity with your hydrometer or refractometer — the sugar amounts above are approximate. For best result calibrate in liquid of 20°C (68°F) and you dont need to use the exact SG values as in the table.
Step 2: Record Tilt Angles
- Enter configuration mode (place the device flat or plug in the charger)
- Open the GravityMon web interface and toggle the force config mode on the main screen
- Navigate to the Formula section where the formula is created
- Float the device in your first solution (plain water) and let it stabilize for 30 seconds
- Record the tilt angle shown in the interface alongside the known gravity value
- Repeat for each solution, stirring well, measure SG with hydrometer and letting the device settle each time
Step 3: Generate the Formula
GravityMon's built-in formula editor takes your data points and calculates the best-fit polynomial. The interface shows:
- Multiple formula options (linear, quadratic, cubic, etc.)
- A graph plotting your data points against each formula
- The correlation coefficient (R²) for each — higher is better
For most devices, a 3rd or 4th order polynomial provides the best accuracy. Select the formula that fits your data points most closely on the graph.
Step 4: Save and Verify
- Select your preferred formula and save it
- Float the device in a solution of known gravity
- Check that the reported gravity matches your hydrometer reading within ±0.002 SG
Tips for Better Calibration
- Use 20°C (68°F) water for your solutions — temperature affects density
- Let the device stabilize for at least 30 seconds at each point before recording
- More data points = better accuracy, especially at the extremes of your expected range
- Recalibrate if you change the battery or modify the ballast — anything that shifts the center of gravity affects the tilt
- GravityMon applies temperature correction to readings, but calibrating near your expected fermentation temperature still helps
Migrating from iSpindel
If you previously ran iSpindel ESP8266 firmware and already have a calibration formula, GravityMon can import it. In the formula section of the web interface, enter your existing polynomial coefficients directly — no need to recalibrate from scratch.
Connect to Brewing Services
Connect to Brewing Services
GravityMon can push your gravity and temperature data to up to 5 endpoints simultaneously. Whether you use a cloud service, a local server, or a home automation platform, setup takes just a few minutes.
Supported Services
GravityMon has built-in support for these services:
| Service | Type | What It Does |
|---|---|---|
| Brewfather | Cloud | Full-featured brew logging with fermentation tracking |
| Brewers Friend | Cloud | Brew logging and recipe management |
| BrewSpy | Cloud | Fermentation monitoring dashboard |
| Fermentrack | Local | Self-hosted fermentation management |
| Home Assistant | Local | Home automation integration via MQTT |
| ThingSpeak | Cloud | IoT data logging and visualization |
| InfluxDB | Local/Cloud | Time-series database for custom dashboards |
| MQTT | Local | Generic message broker for any subscriber |
| Custom HTTP/HTTPS | Any | Send data to any endpoint using a customizable format |
See the gravitymon documentation for more details.
Configure an Endpoint
- Enter configuration mode (place the device flat or plug in the charger)
- Open the GravityMon web interface
- Navigate to the endpoint configuration section
- Select the service type and enter the required credentials
Brewfather Example
- In Brewfather, go to Settings → Custom Stream
- Copy the Custom Stream URL
- In GravityMon's web interface, select Brewfather as the endpoint type
- Paste the stream URL
- Save
MQTT Example
- Enter your MQTT broker address (e.g.,
192.168.1.100) - Set the port (default: 1883)
- Enter username/password if your broker requires authentication
- Set the topic (e.g.,
gravitymon/fermenter1) - Save
Custom Data Formats
For advanced users, GravityMon includes a data format editor that lets you customize the JSON payload sent to HTTP/HTTPS endpoints. You can include any combination of:
- Gravity (SG or Plato)
- Temperature
- Tilt angle
- Battery voltage
- Gravity velocity (points per 24 hours)
- RSSI (WiFi signal strength)
This is useful for integrating with services that expect a specific data format, or for sending data to your own logging infrastructure.
Bluetooth Transmission
In addition to WiFi endpoints, ESP32-based GravityMon devices can broadcast over Bluetooth in three formats:
- Tilt — compatible with any Tilt Hydrometer receiver (TiltBridge, Tilt app, etc.)
- GravityMon — native format with extended data
- RAPT — compatible with RAPT Pill receivers
Bluetooth transmission works independently of WiFi — you can use both simultaneously. This is useful if you have a TiltBridge or other BLE receiver nearby.
Verify Data Flow
After configuring an endpoint:
- Let the device take a reading (wait for one sleep/wake cycle, or trigger a manual reading from the web interface)
- Check your service's dashboard or logs to confirm data is arriving
- Verify the gravity and temperature values look reasonable
Test Your GravityMon
Test Your GravityMon
Before dropping your GravityMon into a batch of beer, run through these checks to make sure everything is working correctly.
Hardware Test
GravityMon has a built-in hardware test accessible from the web interface:
- Enter configuration mode (place the device flat or plug in the charger)
- Open the web interface and navigate to the Hardware Test section
- The test checks:
- Gyroscope — confirms the accelerometer is responding and reading angles
- Temperature sensor — confirms the DS18B20 is connected and returning a valid temperature
- Battery voltage — shows the current voltage (if you wired the voltage divider)
- WiFi — confirms connectivity and signal strength
If any test fails, double-check your wiring for that component.
Float Test
- Fill a tall container with plain water at room temperature
- Drop your GravityMon device in — it should float at roughly 20–35° from vertical
- Enter configuration mode and check the web interface:
- The tilt angle should be stable (not jumping around)
- The temperature should match the water temperature within a degree or two
- The gravity should read close to 1.000 SG (if you've already calibrated)
If the angle reading is unstable or jumping, the accelerometer may need recalibration — use the gyro calibration option in the web interface.
End-to-End Test
Run a complete cycle to verify everything from sensor to cloud:
- Float the device in water
- Turn it on and let it go through a full sleep/wake cycle
- Check your configured service (Brewfather, Fermentrack, etc.) for the incoming data point
- Verify the reported gravity and temperature are reasonable
Leak Test
Before using the device in actual beer:
- Seal the PET tube tightly (put some keg greese around the cap to better seal it)
- Submerge it in water for at least 30 minutes
- Remove and dry the outside
- Open the cap and check for any moisture inside
If you find moisture, reseal the cap — apply a thin ring of food-safe silicone sealant or plumber's tape around the threads if needed.
Troubleshooting
- Device won't enter configuration mode: Make sure it's on a truly flat, level surface. The accelerometer must detect a near-horizontal orientation. Alternatively, plug in the USB charger.
- WiFi won't connect: Double-check SSID and password. GravityMon supports 2.4 GHz networks only — 5 GHz networks won't appear in the scan.
- Gravity reading is way off: Recalibrate. If you haven't calibrated yet, the default formula won't match your device's specific tilt characteristics.
- Temperature reads incorrectly: Check the DS18B20 wiring, especially the pull-up resistor. A missing or wrong-value pull-up causes erratic readings.
- Battery drains quickly: Increase the sleep interval. At 15-minute intervals, a 2200mAh 18650 should last several weeks. At 1-minute intervals, battery life drops to a few days.
- Data not arriving at cloud service: Verify the endpoint URL/credentials in GravityMon's settings. Check that the device has a stable WiFi connection (good RSSI). Try the hardware test to confirm WiFi is working.
- Tilt angle is unstable: The device may be bumping against the side of the container, or there's CO₂ buildup on the tube. During active fermentation, bubbles on the surface of the tube can affect the angle — this is normal and GravityMon's low-pass filter smooths it out.
