Skip to content

chriskaschner/tublemetry

Repository files navigation

Tublemetry

ESPHome-based hot tub automation for Balboa VS300FL4 controllers. Reads the topside panel display via synchronous clock+data protocol and exposes water temperature as a Home Assistant climate entity.

This is the first published automation for the Balboa VS-series board family. The VS300FL4 (PCB: VS500Z) uses a synchronous clock+data protocol that is completely different from the BWA Wi-Fi protocol used by newer BP-series boards.

Topside panel showing 104F

Spa

Developed on an Evolution by Strong Spas Rockport (Costco Item 1003651).

Spec Value
Model Evolution by Strong Spas Rockport 27-Jet
Seating Lounger for up to 6, or non-lounger for up to 7
Jets 27 stainless steel
Water capacity 300 US gallons
Dimensions 74.5" L x 74.5" W x 32" H (outside cabinet)
Shell 66" x 66" x 30" (inside), rugged resin (rotomolded)
Weight 425 lbs dry, 2,933 lbs filled
Pump 1x 2BHP (1.5CHP) 2-speed
Heater 1kW / 4kW stainless steel all-season
Electrical 120V plug-n-play (GFCI cord included), convertible to 240V
Sanitation Ozone
Controller Balboa VS300FL4 (PCB: VS500Z, P/N 22972_E2)
Topside panel Balboa VL-series (VL401/VL403/VL406U) -- digital backlit, analog buttons, no microcontroller
Features Built-in ice bucket with lid, dual water columns, programmable LED underwater lighting, headrests
Cover Heavy-duty 4" to 2" tapered vinyl soft cover (R-13.8), locking clips, lifting handles
Steps Included

This controller is common in rotomolded spas from Strong Spas, Lifesmart, AquaRest, and other brands sold at Costco, Sam's Club, and Home Depot. If your tub has a VL-series topside panel with a 3-digit 7-segment display and an RJ45 connector at J1, this project likely applies.

Identifying Your Board

Balboa VS300FL4 controller label Balboa VS300FL4 rating label -- 120V/240V, 16A/32A, P/N 54626-03

Strong Industries model plate Strong Industries model plate -- Model S6-0001

PCB label close-up PCB label: VS300FLXR1B, Balboa P/N 22972_E2, VS500Z

Board and Connectors

VS500Z board overview VS500Z board with J1 RJ45 connector (topside panel cable plugged in)

J1 RJ45 connector close-up J1 RJ45 jack -- this is where you tap the clock and data signals

T568B stub cable vs OEM panel cable Left: T568B stub cable (standard colors). Right: OEM panel cable (non-standard colors). Always go by pin number, not wire color, when working with the OEM cable.

Hardware

  • ESP32: WROOM-32 (any dev board)
  • Connection: RJ45 T-splitter at J1
  • Power: Pin 1 (+5V) → ESP32 VIN with 540µF bulk capacitance (2x 220µF + 1x 100µF in parallel)
  • Level shifting: Voltage divider required on clock and data lines (5V → 3.3V)
  • Button injection: 2x AQY212EH photorelays (Temp Up on GPIO18, Temp Down on GPIO19)

Protocol

The VS300FL4 does not use RS-485, BWA framing, or any documented Balboa protocol. The topside panel connector carries a synchronous clock+data signal:

RJ45 Pin T568B Color Signal
1 Orange/White +5V power
2 Orange Temp Up (analog button)
3 Green/White Lights (analog button)
4 Blue GND
5 Blue/White Data (display segments, sampled on clock rising edge)
6 Green Clock (24 pulses per frame at 60Hz)
7 Brown/White Jets (analog button)
8 Brown Temp Down (analog button)

Frame Structure (24 bits)

[7 bits: digit 1] [7 bits: digit 2] [7 bits: digit 3] [3 bits: status]
  • 3 x 7-bit display digits + 3 status bits = 24 bits per frame
  • Frames repeat at 60Hz (16.7ms period)
  • Frame boundary: gap > 500us between clock pulses
  • Data sampled on clock rising edge (MSB-first within each digit)

7-Segment Encoding

Confirmed via logic analyzer ladder capture (temperatures 86-105F + mode displays):

Value Character Segments Notes
0x7E 0 a,b,c,d,e,f
0x30 1 b,c
0x6D 2 a,b,d,e,g
0x79 3 a,b,c,d,g
0x33 4 b,c,f,g
0x5B 5/S a,c,d,f,g Same glyph
0x5F 6 a,c,d,e,f,g
0x70 7 a,b,c
0x7F 8 a,b,c,d,e,f,g
0x73 9 a,b,c,f,g Differs from GS510SZ (0x7B) -- no bottom segment
0x00 (blank) none
0x37 H b,c,e,f,g OH error display
0x4F E a,d,e,f,g Ec (economy mode)
0x0D c d,e,g Ec (economy mode)
0x0E L d,e,f SL (sleep mode)
0x0F t d,e,f,g St (standby mode)

Segment mapping: bit6=a, bit5=b, bit4=c, bit3=d, bit2=e, bit1=f, bit0=g

Wiring

                          RJ45 T-splitter at J1
                         /                      \
              Topside panel cable            Stub cable (T568B, cut end)
              (undisturbed)                       |
                                            3 bare wires
                                                  |
                                        Voltage divider (5V->3.3V)
                                                  |
                                        ESP32 GPIO pins
                                          Clock -> GPIO16
                                          Data  -> GPIO17
                                          GND   -> GND

The stub cable is a standard T568B patch cable with one end cut, exposing Blue (Pin 4 / GND), Blue/White (Pin 5 / Data), and Green (Pin 6 / Clock).

A resistor voltage divider is required on the Clock and Data lines to shift from 5V to 3.3V for ESP32 GPIO input.

Button Injection

The VL-series topside panel uses analog button lines -- each button connects +5V to its pin through a resistive network. Pressing a button raises the pin voltage from idle (~2.3V) to ~4.7V.

Measured Voltages

Button RJ45 Pin Idle Voltage Pressed Voltage Delta
Temp Up 2 2.82V 4.69V +1.87V
Temp Down 8 2.26V 4.70V +2.44V
Lights 3 2.27V 4.71V +2.44V
Jets 7 2.26V 4.71V +2.45V

Circuit Design

ESP32 GPIO ──> AQY212EH photorelay ──> Button pin
                                        │
                   +5V (Pin 1) ─────────┘
  • AQY212EH photorelays provide galvanic isolation between the ESP32 and the tub's sensitive analog button lines
  • When the ESP32 drives the relay LED, it closes the switch between +5V and the button pin, simulating a press
  • When idle, the relay is open (high-impedance) -- no interference with the panel

Why photorelays? The analog button lines are extremely sensitive to loading. An unterminated Cat5 breakout cable caused phantom Temp Up presses. Photorelays provide the high-impedance isolation needed to prevent interference when idle.

Wiring (button injection)

ESP32 GPIO18 ──> AQY212EH ──> RJ45 Pin 8 (Brown)    -- Temp Down
ESP32 GPIO19 ──> AQY212EH ──> RJ45 Pin 2 (Orange)   -- Temp Up

Setpoint Strategy (probe + cache)

The firmware uses a two-phase strategy to set the target temperature without a full sweep:

  1. First call (setpoint unknown at boot): press Temp Down once to reveal the current setpoint on the display, read it, then press up or down the exact delta to the target.
  2. Subsequent calls (setpoint cached from last success): calculate the delta directly and press up or down without any probe. Typical TOU shift of 2-4°F = 2-4 presses total.

The setpoint cache is invalidated on reboot, triggering a single probe press on the next request. The display reading after the probe press is used to determine the exact delta -- no blind sweeping to the floor.

Installation

ESPHome

  1. Copy the esphome/ directory to your ESPHome config folder
  2. Edit tublemetry.yaml:
    • Set your WiFi credentials (or use secrets.yaml)
    • Adjust clock_pin and data_pin GPIO numbers for your wiring
  3. Compile and flash:
    uv run esphome run esphome/tublemetry.yaml
  4. The device will appear in Home Assistant with:
    • Climate entity: "Hot Tub" -- shows current water temperature
    • Text sensors: display string, raw hex, display state, digit values (diagnostic)
    • Sensor: decode confidence percentage (diagnostic)

Python Tools (for protocol analysis)

# Install dependencies
uv sync

# Run tests
uv run pytest tests/ -v

# Decode a logic analyzer capture (sigrok CSV export)
uv run python 485/scripts/decode_clockdata_v2.py capture.csv

# Interactive ladder capture with sigrok-cli
uv run python 485/scripts/ladder_sigrok.py

Project Status

  • Protocol reverse-engineered (synchronous clock+data, not RS-485)
  • 7-segment lookup table fully confirmed (all digits 0-9, mode letters)
  • Python decode library with 212 tests
  • ESPHome component (GPIO interrupt-driven)
  • Hardware validated -- ESP32 reading live display at 60Hz
  • Button injection via AQY212EH photorelays -- both directions confirmed
  • Closed-loop setpoint control -- probe+cache strategy, display-verified
  • Home Assistant climate entity -- interactive thermostat card
  • TOU automation in Home Assistant
  • Heating rate tracker (time-to-setpoint vs outdoor temp logging)

Related Projects

Key Differences from GS510SZ

VS300FL4 GS510SZ
Bits per frame 24 39
Display digits 3 4+
"9" encoding 0x73 (no bottom segment) 0x7B (with bottom segment)
Panel VL401/403 VL801D
Board generation VS-series GS-series

License

MIT

About

ESP32 + ESPHome integration for Balboa VS300FL4 hot tub controllers. Reads the topside panel display and exposes water temperature to Home Assistant.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors