Locked differential for AWD esk8s

I’ve manually switched my boards to speed control mode when stuck in an off road situation. It’s worked to great effect to get me out of low traction situations.

Below is a plan to automate that and make it easy.

6 Likes

Bro!! This is suck as fuuuuuck

It writes the whole vesc configuration to the flash memory each time you press the button. It will kill the flash memory after many rewrites

I think that’s what metr does for modes as well… I will blow up the ESC before I rewrite enough to kill the flash memory :rofl:

1 Like

Ooo I had no idea this was something to look out for! Thanks for the catch.

How do other consumer grade electronics handle this problem?

Temporary changes go to ram, but vescuart doesn’t support that.

My solution is to send the throttle to esp32 and then send set.current or speed commands to vesc

1 Like

I rather wear out my flash memory than have my controls go through an extra component. Are there any other Solutions?

1 Like

My company’s claude code max plan said this :slight_smile:

I read the whole thread. The core issue: jack.luis built an ESP32 sidecar that rewrites the entire VESC config to flash on every button press (current mode ↔ speed mode). Dimos15 rightly flagged that this kills flash. Dimos’s fix (route throttle through ESP32) jack rejects because it adds a failure point in the throttle path.
Here are three realistic solutions, best to most pragmatic:

  1. VESC LISP script — cleanest fix, eliminates the ESP32 entirely
    Modern VESC firmware has a built-in LISP interpreter. A script on the master VESC can:
    • read the button and pot directly on the COMM port ADC pins
    • change control_mode in RAM via conf-set (no flash write)
    • broadcast the change to the other 3 VESCs over CAN
    No ESP32, no flash wear, throttle still goes straight to the VESCs as before. Only downside is learning VESC LISP, but there are plenty of examples in VESC Tool.
  2. COMM_SET_MCCONF_TEMP_SETUP packet — RAM-only configuration
    VESC firmware supports a temp variant of the config write that doesn’t touch flash (this is what VESC Tool uses when you click “Apply” instead of “Write”). SolidGeek’s VescUart library doesn’t expose it, but it’s easy to extend — the packet is similar to COMM_SET_MCCONF, just a different command byte. The entire current architecture stays, you only change one call. This is the least invasive change.
  3. Hybrid RT commands — compromise with Dimos’s idea
    • Current mode (default): ESP32 stays silent. Throttle goes directly to the VESCs via PPM, exactly as today.
    • Speed mode: ESP32 reads the PPM signal as an input (high-impedance tap, doesn’t interrupt the signal) and sends COMM_SET_RPM at ~50Hz over CAN.
    • If the ESP32 dies in speed mode, the VESC has a timeout (~1s) and automatically falls back to PPM control.
    Counter to jack’s objection: the ESP32 only touches throttle in speed mode, which is already the “emergency” off-road mode. For 99% of riding, the throttle path is untouched.

My recommendation: option 2 if he wants the minimal change to the existing project, option 1 if he’s building for the long run.

This could be total bullahit and AI slop, or something useful. You tell me :joy:

2 Likes

Option 1 is very appealing because there’s no MCU needed and we don’t use our ADC pins anyways.

3 Likes

I’ve been going back and forth with my clanker and eventually got this. I asked it to explain briefly:

4WD Mode Switcher with No MCU and No Flash Wear

I built a button-and-knob system that toggles my 4WD VESC skateboard between torque control (normal riding) and synchronised speed control (low-traction crawl mode), with a knob to set the speed cap from 0.3 mph to 8 mph. Posting it here because the design might be useful to others, and the safety reasoning is worth sharing.

The Setup

Standard 4WD VESC build with one master and three slaves on CAN. The only added hardware is on the master VESC’s COMM port:

  • 10kΩ pot wired between 3.3V and GND, wiper to ADC1
  • Momentary button between ADC2 and GND, with a 10kΩ pull-up to 3.3V
  • 100nF cap from ADC1 to GND for ADC noise

That’s it. No ESP32, no Arduino, no buck converter, no level shifter.

How It Works

A small VESC LispBM script runs on the master VESC. LispBM is built into VESC firmware 6.00+ and runs sandboxed alongside the motor control task.

  • Current mode (default): The script does nothing. All 4 VESCs run their own PPM apps independently. The receiver wires to all 4 PPM inputs in parallel — exactly like a stock 4WD build.
  • Speed mode (button engaged): The script detaches the master’s PPM app, computes a synced ERPM target from throttle × knob limit, and drives all 4 motors at 50 Hz using set-rpm and canset-rpm. Each VESC runs its own speed PID locally with hall-sensor feedback.

The button toggles a Lisp variable. The knob is read every loop tick.

Why I Didn’t Use an ESP32

The first version used an ESP32 sidecar that called setMcconf over UART to switch modes. Flagged on another thread that this writes flash on every button press, and Vedder confirmed conf-store writes to flash but conf-set does not. So the LISP version uses conf-set-style RAM-only operations exclusively — actually it doesn’t even need those, since set-rpm and app-ppm-detach are pure runtime state.

Zero flash wear after the one-time script install. Press the button a million times if you want.

The Safety Architecture

The whole design is built around one rule: in current mode, nothing the script or master VESC does can affect the rider.

The non-negotiables

  • Timeout Brake Current = 0 on every VESC. Any loss of control input results in coasting, never braking. This was already my standard config but it’s worth stating because the rest of the design depends on it.
  • Receiver PWM wires directly to all 4 VESC PPM inputs in parallel. Same as a stock 4WD build. The script does not sit in the throttle path.

Failure mode table

Failure Current mode Speed mode
Master loses power All 4 wheels keep running on PPM Slaves resume PPM in <0.5 s
Master script crashes All 4 wheels keep running on PPM Slaves resume PPM in <0.5 s
CAN bus disconnects All 4 wheels keep running on PPM Slaves resume PPM in <0.5 s
Receiver dies All 4 coast All 4 coast
Slave VESC loses power That wheel coasts; others continue That wheel coasts; others continue
Knob wire shorts/breaks No effect (knob unused in current mode) Speed cap jumps within bounded range
Button stuck pressed One toggle, then debounce holds steady Same

The worst case in speed mode is that the board reverts to current-mode coasting within 500 ms. Since speed mode is for low-traction surfaces, this is acceptable. The script never acts in current mode, so a script bug or master crash is invisible to the rider during normal riding.

The test that proves it

After installing, I ride at low speed and yank the master’s CAN H wire. All 4 wheels keep going on their own PPM. That’s the proof the architecture is right — if a wheel had stopped, the throttle wiring would be wrong and I’d fix it before continuing.

Speed Mode Specifics

For my hardware (190 KV motors, 48 V, 5.2:1 gear, 13″ wheels, 7 pole pairs), 8 mph at the wheel = 7,500 ERPM at the motor. That’s the script’s hard cap. The knob scales linearly from 300 ERPM (0.3 mph crawl) to 7,500 ERPM.

Ramp time isn’t set in code — I rely on each VESC’s local speed PID with Speed Kp = 0.004, Ki = 0.006 (Ki slightly higher than typical because hall sensors give clean feedback at zero RPM). The 50 Hz CAN command rate is fast enough that the rider’s throttle stick controls the ERPM target smoothly.

At centre stick the script stops sending CAN commands so the slaves time out and coast — otherwise the speed PID would fight to actively hold zero RPM, which feels wrong on a hill.

Why Vedder’s Built-in Traction Control Wasn’t Enough

VESC has a built-in slave-VESC traction control that targets the slowest wheel. That works for most cases but it doesn’t give you a top-speed limit, and it doesn’t synchronise to a single throttle-controlled RPM target. For pulling the board through wet grass or gravel where I want a guaranteed crawl speed regardless of grip, I needed the explicit RPM control with a knob.

What I’d Watch Out For

  • The 0.5 s coast on speed→failure transition is real. If you’re hooning at 7 mph in speed mode and the master dies, you’ll coast for half a second before the slaves’ PPM apps re-engage. On loose terrain that’s fine. On a steep grade it might not be — be aware of it.
  • can-cmd is rate-limited to 2 calls/sec per device in VESC LispBM. My script doesn’t use it (uses canset-rpm which has no rate limit), but if you adapt this design to write configuration over CAN you’ll hit that limit fast.
  • Test the failsafe. Yanking CAN H mid-ride is the only way to know the throttle is reaching all 4 VESCs independently. Don’t skip it.

Happy to share the full LispBM script and wiring guide if there’s interest. Open to feedback on the safety reasoning — particularly if anyone sees a failure mode I’ve missed.

Below is the same result in the format of instructions.

Detailed step-by-step guide

4WD VESC Mode Switcher — LISP Edition (Coast-Safe Architecture)

Complete Build & Configuration Guide

No microcontroller required — runs entirely on the master VESC

VESC LispBM · VESC Tool · CAN Bus


Overview

This guide builds a button-and-knob mode switcher that toggles your 4WD electric skateboard between torque control (current mode) and synchronised speed control (speed mode), using only the VESC’s built-in LispBM interpreter.

The architecture is built around one safety guarantee: in current mode, no failure of the script, the master VESC, or the CAN bus can affect the rider. Every VESC reads the throttle PWM independently and runs its own PPM app. The script does nothing in current mode — it only acts when speed mode is engaged.

In speed mode, the script overrides each VESC’s local control to lock all 4 wheels to the same RPM, with a knob-controlled top speed. If the script or master fails in speed mode, the slave VESCs’ own PPM apps regain control within 0.5 seconds and the board reverts to coasting current-mode behaviour — an acceptable degradation since speed mode is only used in low-traction conditions.

Failure mode summary

All VESCs are configured with Timeout Brake Current = 0, so any loss of control input results in coasting, never braking.

Failure Current mode Speed mode
Master loses power All 4 wheels keep running on PPM Slaves resume PPM in <0.5 s
Master script crashes All 4 wheels keep running on PPM Slaves resume PPM in <0.5 s
CAN disconnects All 4 wheels keep running on PPM Slaves resume PPM in <0.5 s
Slave VESC loses power That wheel coasts That wheel coasts
Receiver dies All 4 coast All 4 coast
Knob wire fails No effect Speed cap jumps within bounded range

Hardware Summary

Component Purpose
4× VESC (firmware 6.00+, FOC, hall sensors) Motor controllers
10kΩ Potentiometer (linear) Speed limit knob → master VESC ADC1
Momentary pushbutton Mode toggle → master VESC ADC2
10kΩ resistor Pull-up for the button line
100nF ceramic capacitor ADC noise filter on the pot wiper
Hookup wire + JST-PH connector Connects to master VESC COMM port

That is the entire BOM. No external microcontroller, no power supply, no level shifter.

NOTE: Your VESCs need firmware 6.00 or newer for LispBM. Update via VESC Tool first if needed.


Part 1 — Install VESC Tool

Step 1 — Download and Install

  1. Go to vesc-project.com and download the latest VESC Tool for Windows. Run the installer with default options.
  2. Launch VESC Tool.

Step 2 — Update VESC Firmware (if needed)

  1. Plug a VESC into your PC via USB.
  2. Click the plug icon in the top left toolbar. Select the COM port and click Connect.
  3. Go to the Firmware tab on the left sidebar.
  4. If the firmware shown is below 6.00, click Upload to flash the latest. Wait for the VESC to reboot.
  5. Move the USB cable to each of the other 3 VESCs and repeat.

NOTE: Updating firmware erases motor and app configurations. You will re-run motor detection in Part 3.


Part 2 — Wiring

Wire everything with the battery fully disconnected.

Power and Throttle

Connection Destination
Battery positive All 4 VESC power inputs
Battery negative All 4 VESC GND inputs
PWM receiver signal All 4 VESC PPM inputs in parallel
PWM receiver GND Common GND with all VESCs

NOTE: The throttle wires to all 4 VESCs in parallel — the same as a stock 4WD VESC build. This is the safety foundation. Every VESC has its own PPM source and runs its own PPM app. The master’s LispBM script overrides this only in speed mode.

CAN Bus (Master ↔ Slaves)

Daisy-chain all 4 VESCs together with twisted pairs.

Signal Connection
Master VESC CAN H VESC 2 CAN H → VESC 3 CAN H → VESC 4 CAN H
Master VESC CAN L VESC 2 CAN L → VESC 3 CAN L → VESC 4 CAN L

TIP: Twist the CAN H and CAN L wires together by hand even without a proper twisted-pair cable. Even a few twists per inch significantly reduces noise.

Master VESC COMM Port — Button and Knob

This is the only wiring beyond a stock 4WD build. Everything attaches to the master VESC’s COMM connector.

COMM Pin Function Wire To
Pin 1 GND Pot outer pin + button leg
Pin 2 +3.3V Pot outer pin (other side) + 10kΩ pull-up resistor
Pin 3 RX Not used
Pin 4 TX Not used
Pin 5 ADC1 Pot wiper (centre pin) + 100nF cap to GND
Pin 6 ADC2 Button (other leg) + pull-up resistor (other end)
Master VESC COMM Port:

  +3.3V (Pin 2) ────┬──── 10kΩ ─────┬──── ADC2 (Pin 6) ──── Button ──── GND (Pin 1)
                    │               │
                    │               └─── (this junction is the button-read line)
                    │
                    └──── 10kΩ POT outer
                             │
                             ├──── ADC1 (Pin 5) ──┐
                             │                   │
                             │              [100nF cap]
                             │                   │
                             └──── GND ──────────┴──── GND (Pin 1)

  POT WIPER     → ADC1
  POT outer pins → 3.3V and GND

How it works:

  • Pot: Acts as a voltage divider between 3.3V and GND. Wiper outputs 0V to 3.3V depending on knob position. The script reads this with (get-adc 0).
  • Button: ADC2 sits at 3.3V via the 10kΩ pull-up when the button is open. Pressing the button shorts ADC2 to GND, dropping it to ~0V. The script polls this with (get-adc 1).
  • 100nF capacitor: Filters ADC noise on the pot wiper. Place it physically as close to the VESC connector as possible.

NOTE: If your VESC has a different COMM connector pinout (some Stormcore variants differ), check your hardware’s documentation. The function names (ADC1, ADC2, 3.3V, GND) are universal — only the physical pin numbers may change.


Part 3 — Configure VESC Tool

Step 1 — Run Motor Setup Wizard on Each VESC

Move the USB cable between the 4 VESCs and run setup on each one.

  1. Connect the VESC via USB. Click the plug icon (top left) and connect.
  2. Go to the Setup tab and click Motor Setup Wizard.
  3. Follow the wizard. Enter 7 for pole pairs. Confirm hall sensor detection succeeds on all 6 positions. Complete the resistance and inductance measurements.
  4. In Motor Settings > General, set motor current max and battery current max to safe values for your motors. Do not exceed motor or VESC ratings.
  5. Click Write Motor Configuration.

Step 2 — Set Timeout Brake Current to Zero

This is the safety-critical setting that guarantees coast-on-failure behaviour.

  1. On each VESC in turn (USB connected), go to App Settings > General.
  2. Find Timeout Brake Current and set it to 0.0 A.
  3. Click Write App Configuration.

NOTE: With this set to 0, any loss of control input (PPM signal lost, CAN command stream stops, script crash) results in the motor coasting after the timeout period. Any non-zero value would cause active braking on failure, which is not acceptable for an off-road skateboard.

Step 3 — Configure PPM on All 4 VESCs

Every VESC runs the same PPM app — current control mode. Do this on each one.

  1. Go to App Settings > General. Set App to Use to PPM.
  2. Go to App Settings > PPM.
  3. Set Control Type to Current (or Current No Reverse with Brake if you do not want reverse from the throttle in current mode).
  4. Click Detect and move your throttle through its full range to capture min, centre, and max pulse widths.
  5. Set Positive Ramping Time to 0.3 and Negative Ramping Time to 0.3. This is current-mode feel — not used in speed mode.
  6. Click Write App Configuration.

NOTE: Configure this on the master VESC too, exactly like the slaves. The script will take over the master’s PPM input only when speed mode is engaged.

Step 4 — Assign CAN IDs

  1. On the master VESC: Set VESC ID to 1. Enable Send Status Over CAN. Write App Configuration.
  2. On VESC 2: Set ID to 2. Enable Send Status Over CAN. Write.
  3. On VESC 3: Set ID to 3. Enable Send Status Over CAN. Write.
  4. On VESC 4: Set ID to 4. Enable Send Status Over CAN. Write.

Step 5 — Tune the Speed PID on Each VESC

Each VESC runs its own speed PID independently when receiving CAN RPM commands.

  1. On each VESC in turn, go to Motor Settings > PID Controllers.
  2. Set:
Parameter Value
Speed Kp 0.004
Speed Ki 0.006
Speed Kd 0.0
  1. Click Write Motor Configuration.

TIP: Hall sensors give clean speed feedback all the way to zero RPM. This is why Ki can be slightly higher than the back-EMF-only default without causing oscillation at low speed.


Part 4 — Install the LispBM Script

The script runs only on the master VESC. Slaves run nothing.

Step 1 — Open the LispBM Editor

  1. Connect to the master VESC (ID 1) via USB.
  2. In VESC Tool, find the VESC Packages or Scripting > LispBM section in the left sidebar (location depends on VESC Tool version).
  3. The editor pane has Stream, Upload, and Run on Boot controls.

Step 2 — Paste the Script

;;; ─────────────────────────────────────────────────────────────────────────
;;;  4WD VESC Mode Switcher — Master VESC (ID 1)
;;;  Coast-safe architecture
;;;
;;;  CURRENT MODE (default):
;;;    Script does nothing. All 4 VESCs run their own PPM apps independently.
;;;    Any failure (script crash, master power loss, CAN disconnect) leaves
;;;    every VESC reading its own throttle. Rider feels nothing.
;;;
;;;  SPEED MODE (button engaged):
;;;    Master detaches its PPM app and computes synchronised RPM target from
;;;    throttle * knob limit. Drives itself with set-rpm and slaves with
;;;    canset-rpm at 50 Hz. Slave VESCs' PPM apps still receive throttle in
;;;    parallel - they're being overridden by the higher-priority CAN command.
;;;    If the script stops, slaves time out (Timeout Brake Current = 0 ->
;;;    coast), then their PPM apps resume control within 0.5 s.
;;;
;;;  Hardware: 190KV motors | 48V | 5.2:1 gear | 13" tires | 7 pole pairs
;;; ─────────────────────────────────────────────────────────────────────────

;; ── Slave VESC IDs ───────────────────────────────────────────────────────
(define slave-1 2)
(define slave-2 3)
(define slave-3 4)

;; ── Speed mode tuning ────────────────────────────────────────────────────
;; ERPM at 8 mph for this hardware = 7,500
(define knob-max-erpm 7500.0)
(define knob-min-erpm 300.0)    ; ~0.3 mph crawl when knob fully CCW

;; ── Throttle behaviour ───────────────────────────────────────────────────
(define ppm-deadband 0.05)      ; +/-5% deadband around centre stick

;; ── Button handling ──────────────────────────────────────────────────────
;; ADC2 voltage: ~3.3V released, ~0V pressed (10k pull-up)
(define btn-press-v   1.0)
(define btn-release-v 2.0)
(define btn-state 'released)
(define btn-debounce-ticks 0)

;; ── Mode state ───────────────────────────────────────────────────────────
(define mode 'current)

;; ── Knob ─────────────────────────────────────────────────────────────────
(defun knob-fraction ()
  (let ((v (get-adc 0)))
    (if (< v 0.0) 0.0
      (if (> v 3.3) 1.0
        (/ v 3.3)))))

(defun current-erpm-limit ()
  (+ knob-min-erpm
     (* (knob-fraction) (- knob-max-erpm knob-min-erpm))))

;; ── Button (debounced edge detection) ────────────────────────────────────
(defun read-button ()
  (let ((v (get-adc 1)))
    (if (< v btn-press-v) 'pressed
      (if (> v btn-release-v) 'released
        btn-state))))

(defun button-pressed-edge ()
  (let ((raw (read-button)))
    (if (eq raw btn-state)
        (progn (setq btn-debounce-ticks 0) nil)
      (progn
        (setq btn-debounce-ticks (+ btn-debounce-ticks 1))
        (if (>= btn-debounce-ticks 3)         ; 3 x 20ms = 60ms debounce
            (progn
              (setq btn-debounce-ticks 0)
              (setq btn-state raw)
              (eq raw 'pressed))
          nil)))))

(defun apply-deadband (x)
  (if (< (abs x) ppm-deadband) 0.0 x))

;; ── Mode entry / exit ────────────────────────────────────────────────────

;; Speed mode entry: detach master's PPM app so it stops driving the motor
;; from PPM. We will drive it directly with set-rpm.
(defun enter-speed-mode ()
  (app-ppm-detach 1)
  (setq mode 'speed)
  (print "-> SPEED"))

;; Current mode entry: re-attach master's PPM app. Script becomes inert.
;; Slaves' PPM apps were never detached - they resume immediately when our
;; canset-rpm commands stop arriving (after their 0.5s timeout, coast).
(defun enter-current-mode ()
  (app-ppm-detach 0)
  (setq mode 'current)
  (print "-> CURRENT"))

;; ── Speed mode driver ────────────────────────────────────────────────────
;; PPM x knob limit = ERPM target. All 4 wheels locked to same RPM.
;; At centre stick: stop sending CAN commands so slaves coast (timeout
;; brake = 0) instead of fighting the speed PID at zero.
(defun drive-speed-mode ()
  (let ((throttle (apply-deadband (get-ppm)))
        (limit    (current-erpm-limit)))
    (let ((target (* throttle limit)))
      (if (= target 0.0)
          ;; Centre stick - let everything coast.
          ;; Master: app-ppm-override 0 keeps master coasting
          ;; Slaves: skip CAN command, they time out and coast
          (app-ppm-override 0.0)
        (progn
          (set-rpm        target)
          (canset-rpm slave-1 target)
          (canset-rpm slave-2 target)
          (canset-rpm slave-3 target))))))

;; ── Main loop ────────────────────────────────────────────────────────────
(defun main-loop ()
  (loopwhile t
    (progn
      ;; Mode toggle on button edge
      (if (button-pressed-edge)
          (if (eq mode 'current)
              (enter-speed-mode)
            (enter-current-mode)))

      ;; Drive only when in speed mode. In current mode, do nothing -
      ;; the master's own PPM app is doing all the work.
      (if (eq mode 'speed) (drive-speed-mode))

      ;; 20 ms tick = 50 Hz control loop
      (sleep 0.02))))

;; ── Boot ─────────────────────────────────────────────────────────────────
(print "4WD Mode Switcher (coast-safe) starting...")
;; Always start in current mode - confirm PPM is attached
(app-ppm-detach 0)
(print "Default: CURRENT (script idle, all VESCs running own PPM)")
(main-loop)

Step 3 — Test, Then Make It Permanent

  1. With the wheels off the ground, click Stream to upload the script to RAM and run it. Watch the console:
    4WD Mode Switcher (coast-safe) starting...
    Default: CURRENT (script idle, all VESCs running own PPM)
    
  2. Apply gentle throttle. All 4 wheels should spin proportionally (this is current mode — every VESC’s own PPM app is doing the work). The script is doing nothing.
  3. Press the button. Console prints -> SPEED. Apply throttle — wheels should now hit the knob-set ERPM limit.
  4. Press the button again. Console prints -> CURRENT. Confirm full throttle range is restored.
  5. Once both modes work, click Upload to write the script to flash. Tick Run on Boot. Save.

After this the script runs automatically on every power-up. You can disconnect USB.

NOTE: Stream puts the script in RAM only — gone at power-off. Upload + Run on Boot puts it in flash so it persists. Both write to flash equally rarely (only when you click Upload), so neither causes per-button-press wear.


Part 5 — First Test

:warning: Safety requirement — Lift the board off the ground so all 4 wheels spin freely. Do not test on the ground until both modes have been verified.

Current Mode Test

  1. Power on the board. Console (if USB is connected) shows the boot message and Default: CURRENT.
  2. Apply gentle forward throttle. All 4 wheels spin proportionally.
  3. Apply reverse throttle (if your PPM control type allows it). All 4 wheels reverse.
  4. Release throttle. Wheels coast.

Failsafe Test (Important)

This is the test that verifies your safety architecture is working.

  1. With all 4 wheels spinning in current mode, disconnect the master VESC’s CAN H wire.
  2. The board should keep running normally — every VESC reads its own PPM independently.
  3. Reconnect CAN H. No change.
  4. Now power-cycle just the master VESC (kill its battery feed if you have a separate path; otherwise simulate with a temporary disconnect).
  5. The 3 slave VESCs should keep running on their own PPM. The master comes back, the script restarts, and the board returns to normal current mode.

If either test causes any wheel to stop, brake, or behave erratically, your wiring is wrong — the throttle PWM is probably not reaching all 4 VESCs. Fix this before proceeding.

Speed Mode Test

  1. Set the knob to roughly the middle position.
  2. Press the button. Console prints -> SPEED.
  3. Apply gentle throttle. Wheels ramp up smoothly to roughly half the speed cap.
  4. Confirm all 4 wheels spin at the same RPM. Full throttle should not exceed the knob-set ERPM limit.
  5. Apply reverse — wheels reverse up to the same cap.
  6. Release throttle to centre. Wheels coast (the script stops sending CAN commands at centre stick, slaves time out and coast).
  7. Turn the knob. Next throttle application reflects the new cap immediately.
  8. Press the button again. Console prints -> CURRENT. Full throttle range restored.

Verifying All 4 Wheels Sync

In speed mode at full throttle, all 4 wheels should be locked to the same RPM. If one wheel spins faster, freer, or stalls:

  • Confirm that VESC’s CAN ID matches slave-1, slave-2, or slave-3 in the script (2, 3, or 4)
  • Confirm Send Status Over CAN is enabled on that VESC
  • Confirm CAN H/L wiring is correct (not swapped, twisted pair if possible)

Quick Reference

Speed Calculations

Parameter Value
Motor KV 190 KV
Battery voltage 48 V nominal
Motor free-spin RPM at 48V 9,120 RPM
Gear ratio 5.2 : 1
Pole pairs 7
Tire diameter 13 inches
Max motor ERPM at 48V 63,840 ERPM
Wheel RPM at 8 mph 207 RPM
Motor RPM at 8 mph 1,076 RPM
ERPM at 8 mph 7,532 → rounded to 7,500 ERPM
Knob minimum speed 300 ERPM ≈ 0.3 mph
Speed mode loop rate 50 Hz (20 ms tick)

Master VESC COMM Pin Map

Pin Function Wired To
1 GND Pot, button, capacitor common
2 +3.3V Pot supply, pull-up resistor
5 ADC1 Pot wiper (with 100nF to GND)
6 ADC2 Button + 10kΩ pull-up to 3.3V

Behaviour Summary

Condition Behaviour
Power on Always boots in current mode
Button press Toggles between current and speed mode
Knob turned in speed mode Limit updates next throttle tick (~20 ms)
Master power loss in current mode All 4 wheels keep running on their own PPM
Master power loss in speed mode Slaves resume their PPM apps within 0.5 s
Master script crash Master’s PPM app is unaffected; in current mode, nothing changes; in speed mode, slaves resume PPM in 0.5 s
CAN disconnect in current mode No effect — every VESC runs independently
CAN disconnect in speed mode Slaves resume PPM in 0.5 s
Receiver dies All 4 lose PPM → all coast
Slave VESC loses power That wheel coasts; others continue

Why This Has No Flash Wear

  • The LispBM script is written to flash exactly once when you click Upload.
  • Every button press only mutates a local LispBM variable (mode).
  • All motor commands (set-rpm, canset-rpm, app-ppm-detach, app-ppm-override) are RAM-only firmware-internal state — not flash.
  • The script never calls conf-set, conf-store, or any other flash-writing function.

Why Coast Is Guaranteed in Current Mode

  • The master VESC’s LispBM script does literally nothing in current mode — it sleeps in a loop checking only the button.
    All 4 VESCs read the receiver PWM directly via their own PPM apps, in parallel.
    A complete master VESC failure (power loss, hardware death, script crash, CPU lockup) does not affect the throttle path on any slave VESC.
    Timeout Brake Current = 0 on every VESC ensures any loss of PPM signal results in coasting, not braking.

Asking a human who actually would know how to do this to read this and critique it is actual work.

If you are one of those people, DM me with your experience and a quote in dollars for you to write up a “rebuttal”

Thanks

1 Like