[P1] ESC abstraction layer — pluggable motor controller backends #388

Closed
opened 2026-03-04 10:32:37 -05:00 by seb · 0 comments
Owner

Problem

The firmware currently hardcodes the hoverboard ESC (EFeru FOC) UART protocol. With VESC support coming (#383), we need a clean abstraction so ESC backends are pluggable.

Design

C function pointer vtable pattern:

typedef struct {
    const char *name;
    void (*init)(void);
    void (*send)(int16_t speed, int16_t steer);
    void (*estop)(void);
    bool (*get_telemetry)(esc_telemetry_t *out);  // optional
} esc_backend_t;

Backends to support:

  1. Hoverboard (EFeru FOC) — current implementation, wrap existing hoverboard.c
  2. VESC (UART) — from #383, using VESC UART/pyvesc protocol
  3. Future: PWM/DShot, ODrive, direct BLDC FOC, etc.

Selection:

  • Compile-time #define ESC_BACKEND in config.h
  • Or runtime selection via Jetson command over UART

Implementation

  1. Create include/esc_backend.h with the vtable struct + esc_telemetry_t
  2. Refactor hoverboard.cesc_hoverboard.c implementing the vtable
  3. Create esc_vesc.c stub (filled in by #383)
  4. Update motor_driver.c to call through vtable instead of hoverboard_send() directly
  5. Add esc_backend_register() / esc_backend_get() for runtime swap

Acceptance Criteria

  • motor_driver.c has zero direct references to hoverboard_send()
  • Hoverboard backend passes existing balance tests unchanged
  • VESC backend stub compiles and links
  • Adding a new backend requires only one new .c file + registration
  • Config selects backend at compile time (runtime optional)

Dependencies

  • Blocks #383 (VESC should implement this interface)
  • #362/#356 (UART wiring) needed for Jetson-side runtime selection
## Problem The firmware currently hardcodes the hoverboard ESC (EFeru FOC) UART protocol. With VESC support coming (#383), we need a clean abstraction so ESC backends are pluggable. ## Design C function pointer vtable pattern: ```c typedef struct { const char *name; void (*init)(void); void (*send)(int16_t speed, int16_t steer); void (*estop)(void); bool (*get_telemetry)(esc_telemetry_t *out); // optional } esc_backend_t; ``` ### Backends to support: 1. **Hoverboard (EFeru FOC)** — current implementation, wrap existing `hoverboard.c` 2. **VESC (UART)** — from #383, using VESC UART/pyvesc protocol 3. Future: PWM/DShot, ODrive, direct BLDC FOC, etc. ### Selection: - Compile-time `#define ESC_BACKEND` in `config.h` - Or runtime selection via Jetson command over UART ## Implementation 1. Create `include/esc_backend.h` with the vtable struct + `esc_telemetry_t` 2. Refactor `hoverboard.c` → `esc_hoverboard.c` implementing the vtable 3. Create `esc_vesc.c` stub (filled in by #383) 4. Update `motor_driver.c` to call through vtable instead of `hoverboard_send()` directly 5. Add `esc_backend_register()` / `esc_backend_get()` for runtime swap ## Acceptance Criteria - [ ] `motor_driver.c` has zero direct references to `hoverboard_send()` - [ ] Hoverboard backend passes existing balance tests unchanged - [ ] VESC backend stub compiles and links - [ ] Adding a new backend requires only one new `.c` file + registration - [ ] Config selects backend at compile time (runtime optional) ## Dependencies - Blocks #383 (VESC should implement this interface) - #362/#356 (UART wiring) needed for Jetson-side runtime selection
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: seb/saltylab-firmware#388
No description provided.