Add active VESC probing so the Orin binary protocol reports CAN RX health: - vesc_can_ping(): sends CAN_PACKET_PING (17) to each VESC at startup - vesc_can_rx_task: handles CAN_PACKET_PONG (18) → sets g_vesc_alive[i] - g_can_bus_active: set on any extended CAN frame received - STATUS flags now include bit4=can_bus_active, bit5=vesc_a_alive, bit6=vesc_b_alive - Test script decodes and reports twai_state, can_bus_active, vesc_a/b_alive - Fix cosmetic: VESC IDs 56=LEFT 68=RIGHT (was wrong 61/79 in print line) Confirmed diagnostic: can_bus_active=False — VESCs ACK SET_RPM commands (TWAI stays RUNNING) but broadcast zero data frames. Root cause: VESC CAN Status Message Mode is Disabled. Fix: set mode ≥ 1 in VESC Tool. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
44 lines
1.8 KiB
C
44 lines
1.8 KiB
C
#pragma once
|
||
/* vesc_can.h — VESC CAN TWAI driver for ESP32-S3 BALANCE (bd-66hx)
|
||
*
|
||
* VESC extended CAN ID: (packet_type << 8) | vesc_node_id
|
||
* Physical layer: TWAI peripheral → SN65HVD230 → 500 kbps shared bus
|
||
*/
|
||
|
||
#include <stdint.h>
|
||
#include <stdbool.h>
|
||
#include "freertos/FreeRTOS.h"
|
||
#include "freertos/queue.h"
|
||
|
||
/* ── VESC packet types ── */
|
||
#define VESC_PKT_SET_RPM 3u
|
||
#define VESC_PKT_STATUS 9u /* int32 erpm, int16 I×10, int16 duty×1000 */
|
||
#define VESC_PKT_PING 17u /* CAN_PACKET_PING: data[0]=requester_id */
|
||
#define VESC_PKT_PONG 18u /* CAN_PACKET_PONG: data[0]=vesc_id, data[1]=hw */
|
||
#define VESC_PKT_STATUS_4 16u /* int16 T_fet×10, T_mot×10, I_in×10 */
|
||
#define VESC_PKT_STATUS_5 27u /* int32 tacho, int16 V_in×10 */
|
||
|
||
#define VESC_CAN_ID_SELF 1u /* our ESP32 CAN node ID (for PING replies) */
|
||
|
||
/* ── VESC telemetry snapshot ── */
|
||
typedef struct {
|
||
int32_t erpm; /* electrical RPM (STATUS) */
|
||
int16_t current_x10; /* phase current A×10 (STATUS) */
|
||
int16_t voltage_x10; /* bus voltage V×10 (STATUS_5) */
|
||
int16_t temp_mot_x10; /* motor temp °C×10 (STATUS_4) */
|
||
uint32_t last_rx_ms; /* esp_timer ms of last STATUS frame */
|
||
} vesc_state_t;
|
||
|
||
/* ── Globals ── */
|
||
extern vesc_state_t g_vesc[2]; /* index 0=VESC_ID_A, 1=VESC_ID_B */
|
||
extern volatile bool g_can_bus_active; /* true after any extended CAN frame received */
|
||
extern volatile bool g_vesc_alive[2]; /* true after PONG from each VESC */
|
||
|
||
/* ── API ── */
|
||
void vesc_can_init(void);
|
||
void vesc_can_send_rpm(uint8_t vesc_id, int32_t erpm);
|
||
void vesc_can_ping(uint8_t vesc_id);
|
||
|
||
/* RX task — pass tx_queue as arg; forwards STATUS frames to Orin over serial */
|
||
void vesc_can_rx_task(void *arg); /* arg = QueueHandle_t orin_tx_queue */
|