sl-firmware 291dd689f8 feat: remove all STM32/Mamba/BlackPill references — ESP32-S3 only
Archive STM32 firmware to legacy/stm32/:
- src/, include/, lib/USB_CDC/, platformio.ini, test stubs, flash_firmware.py
- test/test_battery_adc.c, test_hw_button.c, test_pid_schedule.c, test_vesc_can.c, test_can_watchdog.c
- USB_CDC_BUG.md

Rename: stm32_protocol → esp32_protocol, mamba_protocol → balance_protocol,
  stm32_cmd_node → esp32_cmd_node, stm32_cmd_params → esp32_cmd_params,
  stm32_cmd.launch.py → esp32_cmd.launch.py,
  test_stm32_protocol → test_esp32_protocol, test_stm32_cmd_node → test_esp32_cmd_node

Content cleanup across all files:
- Mamba F722S → ESP32-S3 BALANCE
- BlackPill → ESP32-S3 IO
- STM32F722/F7xx → ESP32-S3
- stm32Mode/Version/Port → esp32Mode/Version/Port
- STM32 State/Mode labels → ESP32 State/Mode
- Jetson Nano → Jetson Orin Nano Super
- /dev/stm32 → /dev/esp32
- stm32_bridge → esp32_bridge
- STM32 HAL → ESP-IDF

docs/SALTYLAB.md:
- Update "Drone FC Details" to describe ESP32-S3 BALANCE board (Waveshare ESP32-S3 Touch LCD 1.28)
- Replace verbose "Self-Balancing Control" STM32 section with brief note pointing to SAUL-TEE-SYSTEM-REFERENCE.md

TEAM.md: Update Embedded Firmware Engineer role to ESP32-S3 / ESP-IDF

No new functionality — cleanup only.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 08:41:26 -04:00

123 lines
5.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* pid_schedule.h — Speed-dependent PID gain scheduling (Issue #550)
*
* Maps robot velocity to PID gain triplets (Kp, Ki, Kd) using a lookup
* table with linear interpolation between adjacent entries. The table
* supports 1PID_SCHED_MAX_BANDS entries, each associating a velocity
* breakpoint (m/s) with gains that apply AT that velocity.
*
* HOW IT WORKS:
* 1. Each entry in the table defines: {speed_mps, kp, ki, kd}.
* The table is sorted by speed_mps ascending (pid_schedule_set_table
* sorts automatically).
*
* 2. pid_schedule_get_gains(speed_mps, ...) finds the two adjacent entries
* that bracket the query speed and linearly interpolates:
* t = (speed - bands[i-1].speed_mps) /
* (bands[i].speed_mps - bands[i-1].speed_mps)
* kp = bands[i-1].kp + t * (bands[i].kp - bands[i-1].kp)
* Speeds below the first entry or above the last entry clamp to the
* nearest endpoint (no extrapolation).
* The query speed is ABS(motor_speed) — scheduling is symmetric.
*
* 3. Default 3-entry table (loaded when flash has no valid schedule):
* Band 0: speed=0.00 m/s kp=40.0 ki=1.5 kd=1.2 (stopped — tight)
* Band 1: speed=0.30 m/s kp=35.0 ki=1.0 kd=1.0 (slow — balanced)
* Band 2: speed=0.80 m/s kp=28.0 ki=0.5 kd=0.8 (fast — relaxed)
*
* 4. pid_schedule_apply(balance, speed_mps) interpolates and writes the
* result directly into balance->kp/ki/kd. Call from the main loop at
* the same rate as the balance PID update (1 kHz) or slower (100 Hz
* for scheduling, 1 kHz for PID execution — gains change slowly enough).
*
* 5. Flash persistence: pid_schedule_flash_save() calls pid_flash_save_all()
* which erases sector 7 once and writes both the single-PID record at
* PID_FLASH_STORE_ADDR and the schedule at PID_SCHED_FLASH_ADDR.
*
* 6. JLINK interface (Issue #550):
* 0x0C SCHED_GET — no payload; triggers TLM_SCHED response
* 0x0D SCHED_SET — upload new table (num_bands + N×16-byte entries)
* 0x0E SCHED_SAVE — save current table + single PID to flash
* 0x85 TLM_SCHED — table dump response to SCHED_GET
*/
#ifndef PID_SCHEDULE_H
#define PID_SCHEDULE_H
#include <stdint.h>
#include <stdbool.h>
#include "pid_flash.h" /* pid_sched_entry_t, PID_SCHED_MAX_BANDS */
#include "balance.h" /* balance_t */
/* ---- Default gain table ---- */
/* Motor ESC range is ±1000 counts; 1000 counts ≈ full drive.
* Speed scale: MOTOR_CMD_MAX=1000 → ~0.8 m/s max tangential velocity.
* Adjust PID_SCHED_SPEED_SCALE if odometry calibration changes this. */
#define PID_SCHED_SPEED_SCALE 0.0008f /* motor_cmd counts → m/s: 1000 × 0.0008 = 0.8 m/s */
/* ---- API ---- */
/*
* pid_schedule_init() — load table from flash (via pid_flash_load_schedule).
* Falls back to the built-in 3-band default if flash is empty or invalid.
* Call once after flash init during system startup.
*/
void pid_schedule_init(void);
/*
* pid_schedule_get_gains(speed_mps, *kp, *ki, *kd) — interpolate gains.
* |speed_mps| is used (scheduling is symmetric for forward/reverse).
* Clamps to table endpoints; does not extrapolate outside the table range.
*/
void pid_schedule_get_gains(float speed_mps, float *kp, float *ki, float *kd);
/*
* pid_schedule_apply(b, speed_mps) — compute interpolated gains and write
* them into b->kp, b->ki, b->kd. b->integral is reset to 0 when the
* active band changes to avoid integrator windup on transitions.
*/
void pid_schedule_apply(balance_t *b, float speed_mps);
/*
* pid_schedule_set_table(entries, n) — replace the active gain table.
* Entries are copied and sorted by speed_mps ascending.
* n is clamped to [1, PID_SCHED_MAX_BANDS].
* Does NOT automatically save to flash — call pid_schedule_flash_save().
*/
void pid_schedule_set_table(const pid_sched_entry_t *entries, uint8_t n);
/*
* pid_schedule_get_table(out_entries, out_n) — copy current table out.
* out_entries must have room for PID_SCHED_MAX_BANDS entries.
*/
void pid_schedule_get_table(pid_sched_entry_t *out_entries, uint8_t *out_n);
/*
* pid_schedule_get_num_bands() — return current number of table entries.
*/
uint8_t pid_schedule_get_num_bands(void);
/*
* pid_schedule_flash_save(kp_single, ki_single, kd_single) — save the
* current schedule table PLUS the caller-supplied single-PID values to
* flash in one atomic sector erase (pid_flash_save_all).
* Must NOT be called while armed (sector erase takes ~1s).
* Returns true on success.
*/
bool pid_schedule_flash_save(float kp_single, float ki_single, float kd_single);
/*
* pid_schedule_active_band_idx() — index (0-based) of the lower bracket
* entry used in the most recent interpolation. Useful for telemetry.
* Returns 0 if speed is below the first entry.
*/
uint8_t pid_schedule_active_band_idx(void);
/*
* pid_schedule_get_default_table(out_entries, out_n) — fill the 3-band
* default table into caller's buffer. Used for factory-reset.
*/
void pid_schedule_get_default_table(pid_sched_entry_t *out_entries, uint8_t *out_n);
#endif /* PID_SCHEDULE_H */