Build log · Embedded & high current

A VESC, rebuilt phase wiring, and a handlebar display I actually wrote

The Jasion Retrovolt Pro ships with a sealed controller and a display that tells you almost nothing. I replaced the controller with a Flipsky 75100 V2.0 VESC, rebuilt the phase and hall terminations through a printed block I designed for the job, and put a Waveshare ESP32-S3 touchscreen on the bars running my own LVGL firmware — fed live over CAN at 500 kbit/s from the controller itself.

Flipsky 75100VESC ToolFOC ESP32-S3LVGLTWAI / CAN OpenSCADPlatformIO

01 — Premise

Why replace a controller that worked

A stock ebike controller is a black box with a throttle input and a speed limit. You cannot see phase current, you cannot see FET temperature, you cannot change the ramp, and when it fails it fails silently. The stock display is worse: a battery bar with four segments and a number that is nominally miles per hour.

A VESC turns all of that into a documented, configurable, instrumented system. It runs field-oriented control instead of trapezoidal commutation, it reports every state variable I care about over CAN, and it lets me set the current limits from the actual ratings of the pack and the board rather than from whatever the factory decided.

The catch is that a VESC also lets you destroy the board and the motor in about four seconds if you commission it carelessly. Most of the work below is about not doing that.

The Jasion Retrovolt Pro fat-tire ebike in the garage with custom ESP32-S3 touchscreen display mounted on handlebars.
The bike on its stand. Jasion Retrovolt Pro fat-tire ebike with the custom 3D-printed ESP32-S3 dashboard enclosure clamped to the handlebars, 52V battery pack, and motorcycle-style grill headlight. media/retrovolt/bike-hero.jpg

02 — Hardware

Three boxes and the wires between them

The whole system is a pack, a controller, and a display. Everything interesting happens at the boundaries.

System inventory
PartSpecRole
Jasion Retrovolt Pro 14S Li-ion, 52 V nominal / 58.8 V full, 20 Ah, 20×4 fat tire Donor bike and pack
Flipsky 75100 V2.0 14–84 V (4S–20S), 100 A cont. / 250 A peak, aluminium PCB Motor controller
Rear hub motor 46 poles (23 pole pairs), hall sensored, 2000 W advertised peak Drive
Waveshare ESP32-S3-Touch-LCD-4.3B 4.3″ 800×480 IPS, GT911 touch, 16 MB flash / 8 MB PSRAM, onboard CAN transceiver Handlebar dashboard

The display board is the right board for this

Most ESP32 dev boards would need an external CAN transceiver bolted on. This one has a transceiver, a 16-position screw terminal that exposes CAN-H and CAN-L directly, a 120 Ω termination switch on the back, and a 7–36 V input — so it takes bike power through a buck converter without another regulator board in the loop.

Verified GPIO map

Waveshare ESP32-S3-Touch-LCD-4.3B — pins confirmed working in firmware
FunctionPins
CAN (TWAI)TX GPIO15, RX GPIO16 → onboard transceiver
I²C busSDA GPIO8, SCL GPIO9 — touch, CH422G expander, terminal pins
GT911 touchI²C 0x5D (or 0x14), INT on GPIO4
CH422G expanderIO1 = touch reset, IO2 = backlight, IO3 = LCD reset
RGB panel clock16 MHz, pclk_active_neg = 1
Voltage

The display's VIN terminal is 36 V absolute maximum. The pack is 58.8 V at full charge. Pack voltage never touches VIN — it goes through a fused DC-DC buck to 5 V first. Getting this backwards destroys the board instantly.

Flipsky 75100 V2.0 VESC on the bench with its JST connector ports and 12 AWG phase leads visible.
The controller on the bench. Flipsky 75100 V2.0 aluminum PCB controller showing the 5-pin CAN port, 8-pin COMM harness (ADC1/ADC2), and 6-pin HALL sensor header before installation. media/retrovolt/vesc-bench.jpg
The Waveshare ESP32-S3 touchscreen in its printed enclosure clamped to the handlebars with wiring harness routed down the stem.
Handlebar cockpit & mount. The custom 3D-printed enclosure mounted via dual handlebar clamps, with power, CAN telemetry, and sensor wiring harness zip-tied and routed down the steering stem. media/retrovolt/display-handlebar.jpg

03 — High current

Phase and hall terminations

The replacement controller arrived with a different connector scheme than the motor's harness, which means the three phase leads have to be joined somewhere. At 100 A continuous this is the single most consequential mechanical joint on the bike — a bad phase connection does not fail gracefully, it arcs, heats, and eventually welds or opens under load.

A printed block instead of a bundle of heat shrink

Rather than butt-splice and hope, I designed a parametric 3-post terminal block in OpenSCAD and printed it. It joins each controller phase to its motor phase with crimped M5 ring terminals on a shared stud, inside a shell that makes a phase-to-phase short physically difficult.

  • 22 mm post pitch — clears M5 ring terminals of roughly 15 mm outer diameter with real margin at 100 A+.
  • Captured hex pocket under each post, so the bolt cannot spin while the nut is torqued from above. Bolts drop in from below before assembly.
  • Six 12 mm open-top wire entries cut fully through both long walls, so flexible 12 AWG and its lug necks enter without a sharp bend.
  • Full-height divider walls between phases, so a loose lug or a dropped tool cannot bridge two of them.
  • Snap-on lid closing the entire live area while keeping the joints serviceable.
Print material

PETG or nylon, not PLA. This sits near a hot motor and a hot controller. PLA softens well below the temperatures this part will see in a summer hill climb.

The printed part is an insulator and a strain relief. The metal lug-to-lug joint carries the current — the plastic is not structural to the electrical path. Do not solder-only terminate high-current phase leads; crimp them properly with a tool matched to the lug.

Hardware per block

  • 3 × M5 × 16 mm hex-head bolts
  • 3 × M5 all-metal lock nuts, kept within their temperature rating
  • 6 × copper ring terminals, 5 mm stud hole, crimped to the real wire gauge

Hall sensors

The motor is hall-sensored, which is what makes smooth starts from zero possible without sensorless startup tricks. The controller's HALL port carries 5 V, a temperature line, three hall signals, and ground. Those run back to the motor's sensor connector unmodified — the hall harness is low current and the factory connector is fine.

The temperature pin is the interesting one: the controller can read a motor thermistor through it, but only if you know which thermistor type the motor actually uses. I have not confirmed that, so motor temperature sensing stays disabled rather than configured with a guess.

The printed three-post phase terminal block with ring terminals bolted down and the lid off.
Phase block, open. Parametric PETG 3-post terminal block with captured hex M5 pockets, 22 mm post pitch, full-height isolation barriers, and crimped M5 copper ring terminals. media/retrovolt/phase-block.jpg
The motor hall sensor connector and the controller's HALL port harness.
Hall sensor harness. The motor sensor harness mated to the controller's HALL port (5V, GND, 3 hall signals; motor thermistor pin left unconfigured until characterized). media/retrovolt/hall-connector.jpg

05 — Tuning

Commissioning without cooking it

Read this first

Everything in this section is what I did on my bike, with my pack, controller and motor. Current limits are not transferable between builds. Back up both configurations, lift the driven wheel for the first spin, commission at conservative values, and change one group at a time.

The phase-filter trap

This is the failure mode that kills these boards, and it is worth understanding before you plug anything in.

Flipsky's 75-series firmware from 5.03 onward has a Enable Phase Filters option. The Pro variant has phase-filter hardware. The non-Pro variant does not. If the option is set true on a board without the hardware and the motor spins, the board can be destroyed. Worse, the motor detection wizard offers to load default parameters — and answering yes re-enables the filter after you have carefully turned it off.

  1. Identify which board you actually have

    Pro and non-Pro both report the 75_300_R2 firmware hardware target, so the firmware label tells you nothing. Go by the product listing and the physical board. Mine is documented as the non-Pro 75100 V2.0.

  2. Set phase filters false, and write it

    Motor Settings → FOC → Filters. Set Enable Phase Filters = False and write the motor configuration before running detection. Not after.

  3. Say no to "Load Default Parameters"

    During the wizard, when it offers to reload defaults, answer no. This is the step that undoes step 2 and cooks the board.

  4. Run detection with the wheel off the ground

    FOC detection spins the motor. Do it on a stand, with nothing in the way, and with a hand on the disconnect.

The shipped configuration was wrong in six places

After capturing 24 screenshots of the controller's as-delivered state, six settings were not "untuned" but actively incorrect for this hardware:

Configuration corrections — these are correctness fixes, not preferences
SettingAs shippedCorrected toWhy
Enable Phase Filters True False No phase-filter hardware on the non-Pro board
Regen voltage cutoff 1000 / 1100 V 57.4 / 58.8 V 4.10 and 4.20 V per cell × 14S. The shipped values disable the taper entirely
Max ERPM ±100,000 30,000 to start At 46 poles, 2.769:1 and a 508 mm wheel, 100,000 ERPM is about 93 mph. Not a bike limit
ADC input mode Current No Reverse Brake Center Current No Reverse Brake ADC2 Throttle on ADC1 and brake on ADC2 are separate inputs, not one centred bidirectional one
Multiple VESCs Over CAN True False The display is a passive telemetry node, not a second drive controller
BMS Type VESC BMS None The stock pack's BMS is not a VESC CAN BMS. Voltage and current limits stay active either way

Staged current limits, with a gate on each stage

Motor current is phase current and mostly controls low-speed torque. Battery current controls pack draw and roughly sets electrical power. They are not interchangeable, and the shipped values exceeded both the controller rating and the pack's label.

Current limits — shipped, shakedown, and target
Parameter Shipped Stage 1 Stage 2 Gate before stage 2
Motor current max199.27 A60 A90 A Clean starts, no faults, phase joints stay cool
Motor current max brake−199.27 A−40 A−60 A Rear wheel does not lock; mechanical braking stays predictable
Absolute max current298.91 A150 A180 A No unexplained ABS_OVER_CURRENT; never past the 250 A rating
Battery current max35 A30 A30 A Hard ceiling — the pack label says 30 A max discharge
Battery regen max−10 A−5 A−5 A Only raise after the BMS charge limit is confirmed
The reasoning

The stage-2 motor current target deliberately leaves margin below the controller's 100 A continuous rating. The pack stays at its labelled 30 A ceiling — about 1.55 kW at nominal, 1.76 kW at full charge — because launch feel comes from phase current and throttle mapping, not from overloading the cells.

Regen stays low and mechanical brakes stay primary. Near full charge the regen taper reduces braking force exactly when the pack cannot absorb more, so a bike that relies on regen to stop is a bike that does not stop at the top of a hill.

VESC Tool motor settings screen showing the corrected current limits and regen cutoffs.
VESC Tool 6.06. Motor configuration after safety corrections: 14S regen cutoffs (57.4 V / 58.8 V), 30k ERPM ceiling, disabled phase filters, and staged phase current limits. media/retrovolt/vesc-tool.png

06 — Firmware & UI

The display firmware and cockpit architecture

PlatformIO, Arduino framework, LVGL 8/9 for the interface, and ESP-IDF's TWAI driver for CAN. The board runs a qio_opi flash and PSRAM configuration, which the 800×480 RGB panel needs for its double-buffered frame buffer and vector map runways.

Production screens (800×480) & layout hierarchy

The UI is designed around fixed 800×480 production roots with strict touch ergonomics (minimum 46 px interactive touch targets):

  • Full-Map Drive Cockpit (Drive · Night / Drive · Day): The full canvas is occupied by a vector map runway backed by PSRAM with smooth GPS auto-follow, heading rotation, manual pan, recenter, and optical zoom steps (75%, 100%, 125%, 150%). Status pill, large digital speed, estimated range, ODO, trip meter, power gauge, and zoom controls float neatly along the borders.
  • Thumb Rail (Right 76 px): The right 76 px is reserved as a thumb-friendly navigation and ride-mode selector (Eco, Normal, Sport) reachable while keeping a hand near the grip.
  • Live Data & Settings (Live Data · Night / Settings · Day): Uses a 724×54 px top rail (status pills, clock, battery %) paired with a 724×426 px content canvas containing real-time telemetry tiles (FET temp, phase amps, pack volts, watt-hours) and persistent NVS settings.
LVGL Component Library Mapping
ComponentVariantsRuntime Contract
Status PillLive, Searching, OfflineCAN heartbeat & GPS lock state
Mode ButtonEco, Normal, SportVESC current profile ramp switching
Telemetry TileCompact & WideData-driven label, live value, unit
GaugeSpeed, Power, BatteryInterpolated needle/arc with peak holds
Navigation ItemSelected & DefaultDrive, Live Telemetry, Trip Log, Config

Interactive Tool: You can inspect, modify, and test this dashboard layout in the ESPboards LVGL Designer Canvas → with live gradient arcs, animated VESC throttle simulation, and battery sliders.

Built in stages, each one provable

  • Stage 1 · Panel

    Get the RGB panel and its timings right in isolation. Nothing else works until pixels do.

  • Stage 2 · Cluster

    LVGL gauge layout driven by fake data, so the interface can be designed without the bike present.

  • Stage 3 · Telemetry

    Real VESC CAN frames decoded and bound to the gauges. This is where the fake data gets deleted.

  • Stage 4 · Settings

    Touch input, NVS calibration, and persistent odometer/trip storage.

Configuration on the screen, not in a rebuild

Wheel diameter, pole pairs, gear ratio, cell count, units and power scale are all set on the touchscreen and persisted to NVS. That was a deliberate call: those values needed verification against GPS on real rides, and a tuning loop that requires reflashing the firmware between every guess is a tuning loop nobody finishes.

Build and flash

# build and upload; the port is auto-detected
pio run -t upload

# serial logs on the native USB port
pio device monitor -b 115200

The board enumerates as a native USB JTAG/serial device (303A:1001), so it auto-flashes without touching the BOOT button. On macOS the port name moves around between usbmodem101, usbmodem2101 and similar, which is why the upload target auto-detects rather than hardcoding it.

07 — Status

Where it stands

Panel, LVGL cluster and live VESC CAN telemetry are working. Touch and the settings page are in progress. Next up are SD-card raster map tiles with GPS, and iPhone music metadata over BLE — the board has BLE 5 but no Bluetooth Classic, so there is no A2DP audio path; it uses Apple's Media Service to read track metadata and send transport controls while the phone keeps playing to its own output.

Accessory & Lighting Integration

The Jasion Retrovolt Pro's stock lighting harness (headlight model JZX-DDC-014 48V with integrated DC-DC converter, horn, and turn signals) runs directly off full pack voltage (~52–58.8 V). The display board's isolated digital inputs (DI0, DI1) are rated for 5–36 V, so turn-signal sensing uses a series dropping resistor network (or PC817 optocoupler front-end) to safely feed blinker states into the dashboard's top indicator bar.

The 3D printed handlebar enclosure for the Waveshare ESP32-S3 display.
Printed enclosure housing. Custom PETG handlebar enclosure for the 4.3″ display with 75 mm dual M4 rear mounts, side cutouts for USB-C & TF card, and weather-sealed bezel. media/retrovolt/enclosure-print.jpg

What this one taught me

The firmware was the easy half. The hard half was refusing to accept any number I could not source — the pack's real discharge limit came off the label, the controller's real rating came off the manufacturer's specification, and the settings I could not verify (thermistor type, measured rollout) stayed explicitly disabled instead of being filled in with something plausible. On a system that turns a battery into torque, a plausible guess and a verified value look identical right up until they don't.