The Problem

Victron’s "Instant Readout" is great on a smartphone, but a dedicated wall-mounted display is often preferred in an RV or boat. While the official Victron GX Touch displays are beautiful, they require a GX-device (Cerbo) and a significant budget. I wanted a standalone, low-power display that I could mount in a cabinet and dim at night with a single tap.

The Build

The heart of the project is the ESP32 using the VictronBLE library.

Key Features:

  • Flicker-Free UI: Implemented using a double-buffered Sprite strategy (via TFT_eSPI). Only half the screen is updated in memory at a time to stay within RAM limits while maintaining 60fps-style smooth transitions.
  • Smart Data Filtering: To prevent "ghost" readings or corrupted BLE packets from showing wild values, I implemented a Plausibility Engine. It checks the delta between the last known good reading and the new packet (e.g., rejecting a 2% SOC jump in 1 second).
  • Touch-to-Dim: Integrated the XPT2046 touchscreen to cycle the backlight through three brightness levels via PWM—essential for sleeping in an RV.
  • Color-Coded Status: Visual cues use Cyan for charging and Orange for discharging, making it readable from across the rig.

Technical Breakdown

  • Hardware: ESP32-2432S028R (ILI9341 2.8" TFT).
  • Connectivity: BLE (for data) and WiFi (for OTA updates).
  • Backlight Control: PWM on GPIO 21.
  • Validation: Custom packetPlausible() function to filter out transient EMI noise often found in automotive environments.

The Code

The software is written in the Arduino IDE. It uses a custom callback structure to handle incoming BLE advertisements. When a packet is decrypted using the Shunt's 32-character key, the UI is updated instantly.

Lessons Learned

The biggest challenge was memory management. Running a full BLE stack alongside a high-resolution display driver on an ESP32 is tight. Moving to a "Half-Sprite" rendering method (updating the top and bottom 120 pixels separately) saved enough RAM to keep the Bluetooth connection stable without crashes.