feat: complete dual-seat whole-vehicle orchestration
This commit is contained in:
@@ -179,6 +179,7 @@ static uint8_t s_diagnosticPeriodicId = 0u;
|
||||
static bool s_motorPeriodicPending = false;
|
||||
static bool s_diagnosticPeriodicPending = false;
|
||||
static bool s_dynamicStatusPending = true;
|
||||
static bool s_firmwareIdPending = true;
|
||||
static uint8_t s_systemAlive = 0u;
|
||||
static uint8_t s_diagnosticAlive[SEAT_MOVE_MOTOR_COUNT];
|
||||
static uint32_t s_nextStartMs = 0u;
|
||||
@@ -186,6 +187,7 @@ static uint32_t s_nextSystemStatusMs = 0u;
|
||||
static uint32_t s_nextMotorPollMs = 0u;
|
||||
static uint32_t s_nextDiagnosticPollMs = 0u;
|
||||
static uint32_t s_nextDynamicStatusMs = 0u;
|
||||
static uint32_t s_nextFirmwareIdMs = 0u;
|
||||
static uint8_t s_hilArmedCase = 0u;
|
||||
static uint16_t s_hilArmToken = 0u;
|
||||
static uint32_t s_hilArmExpiresMs = 0u;
|
||||
@@ -242,6 +244,7 @@ static bool SeatMove_SendMotorStatus(uint8_t motor);
|
||||
static bool SeatMove_SendDiagnostic(uint8_t motor);
|
||||
static bool SeatMove_SendCurrentDiagnostic(uint8_t motor);
|
||||
static bool SeatMove_SendDynamicStatus(void);
|
||||
static bool SeatMove_SendFirmwareIdentity(void);
|
||||
static void SeatMove_ServiceFeedback(void);
|
||||
|
||||
bool SeatMoveApplication_Init(void)
|
||||
@@ -282,10 +285,12 @@ bool SeatMoveApplication_Init(void)
|
||||
s_nextMotorPollMs = now;
|
||||
s_nextDiagnosticPollMs = now;
|
||||
s_nextDynamicStatusMs = now;
|
||||
s_nextFirmwareIdMs = now;
|
||||
s_systemStatusPending = true;
|
||||
s_motorStatusPendingMask = SEAT_MOVE_ACTIVE_MOTOR_MASK;
|
||||
s_diagnosticPendingMask = SEAT_MOVE_ACTIVE_MOTOR_MASK;
|
||||
s_dynamicStatusPending = true;
|
||||
s_firmwareIdPending = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1818,6 +1823,22 @@ static bool SeatMove_SendDynamicStatus(void)
|
||||
data1);
|
||||
}
|
||||
|
||||
static bool SeatMove_SendFirmwareIdentity(void)
|
||||
{
|
||||
/* Bytes 0..3 are ASCII "SMV8". Keeping the persistent-store protocol
|
||||
* name in the identity makes accidental matches with unrelated bench
|
||||
* firmware very unlikely without consuming an actuator command ID. */
|
||||
uint32_t data0 = (uint32_t)0x53u |
|
||||
((uint32_t)0x4Du << 8u) |
|
||||
((uint32_t)0x56u << 16u) |
|
||||
((uint32_t)0x38u << 24u);
|
||||
uint32_t data1 = (uint32_t)SEAT_MOVE_FIRMWARE_REVISION |
|
||||
((uint32_t)SEAT_MOVE_FIRMWARE_BUILD_ID << 8u) |
|
||||
((uint32_t)SEAT_MOVE_MOTOR_COUNT << 16u) |
|
||||
((uint32_t)SEAT_MOVE_CAN_PROTOCOL_VERSION << 24u);
|
||||
return BspSeatMoveCan_Send(SEAT_MOVE_CAN_FIRMWARE_ID_ID, data0, data1);
|
||||
}
|
||||
|
||||
static void SeatMove_ServiceFeedback(void)
|
||||
{
|
||||
uint32_t now = Motor_GetTimeMs();
|
||||
@@ -1833,6 +1854,11 @@ static void SeatMove_ServiceFeedback(void)
|
||||
s_dynamicStatusPending = true;
|
||||
s_nextDynamicStatusMs = now + SEAT_MOVE_DYNAMIC_STATUS_PERIOD_MS;
|
||||
}
|
||||
if(SeatMove_TimeReached(now, s_nextFirmwareIdMs))
|
||||
{
|
||||
s_firmwareIdPending = true;
|
||||
s_nextFirmwareIdMs = now + 500u;
|
||||
}
|
||||
if(!s_motorPeriodicPending &&
|
||||
SeatMove_TimeReached(now, s_nextMotorPollMs))
|
||||
{
|
||||
@@ -1881,6 +1907,19 @@ static void SeatMove_ServiceFeedback(void)
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(s_firmwareIdPending)
|
||||
{
|
||||
if(SeatMove_SendFirmwareIdentity())
|
||||
{
|
||||
s_firmwareIdPending = false;
|
||||
g_seatMoveFeedbackTxCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_seatMoveFeedbackTxFailureCount++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
for(motor = 0u; motor < SEAT_MOVE_MOTOR_COUNT; motor++)
|
||||
{
|
||||
uint8_t bit = (uint8_t)(1u << motor);
|
||||
|
||||
@@ -33,11 +33,14 @@
|
||||
#define SEAT_MOVE_M0_DEFAULT_DUTY_PERCENT (90u)
|
||||
#define SEAT_MOVE_M1_DEFAULT_DUTY_PERCENT (90u)
|
||||
#define SEAT_MOVE_M2_DEFAULT_DUTY_PERCENT (90u)
|
||||
#define SEAT_MOVE_M3_DEFAULT_DUTY_PERCENT (90u)
|
||||
/* The connected loaded legrest leaves its hard stop more reliably at the
|
||||
* empirically verified diagnostic PWM than at maximum PWM. It is selected
|
||||
* only after a supervised endpoint-departure attempt produced no Hall edge. */
|
||||
#define SEAT_MOVE_M3_BREAKAWAY_DUTY_PERCENT (60u)
|
||||
#define SEAT_MOVE_M3_DEFAULT_DUTY_PERCENT (50u)
|
||||
/* M3 is the loaded legrest linkage. The standalone angle-test firmware
|
||||
* proves sustained Hall travel at 50% duty, while the former 90% command
|
||||
* makes the connected actuator stop driving after roughly 70 pulses even
|
||||
* though the ECU continues to request PWM. Keep normal and endpoint-
|
||||
* departure motion on the same verified bench duty so absolute requests do
|
||||
* not trip that internal/mechanical protection window. */
|
||||
#define SEAT_MOVE_M3_BREAKAWAY_DUTY_PERCENT (50u)
|
||||
|
||||
/* A Hall target is discrete and the connected actuator can physically stop
|
||||
* up to four pulses short because of its limit contact and gear backlash. If
|
||||
@@ -79,6 +82,12 @@
|
||||
#define SEAT_MOVE_CAN_DIAGNOSTIC_ID (0x303u)
|
||||
#define SEAT_MOVE_CAN_CURRENT_DIAGNOSTIC_ID (0x304u)
|
||||
#define SEAT_MOVE_CAN_DYNAMIC_STATUS_ID (0x306u)
|
||||
/* Repository-image identity. The legacy four-bit revision in 0x301 is
|
||||
* already at 15, so 0x307 carries an independently incremented build ID.
|
||||
* This lets the headless runtime distinguish the current image from an older
|
||||
* revision-15 image or from a temporary standalone motor-test image. */
|
||||
#define SEAT_MOVE_CAN_FIRMWARE_ID_ID (0x307u)
|
||||
#define SEAT_MOVE_FIRMWARE_BUILD_ID (16u)
|
||||
/* The self-healing hook is accepted only by this bench-demo image and only
|
||||
* after a short-lived token arm exchange. */
|
||||
#define SEAT_MOVE_CAN_HIL_SELF_HEAL_REQUEST_ID (0x2F0u)
|
||||
@@ -174,6 +183,7 @@
|
||||
(SEAT_MOVE_CAN_DIAGNOSTIC_ID > 0x7FFu) || \
|
||||
(SEAT_MOVE_CAN_CURRENT_DIAGNOSTIC_ID > 0x7FFu) || \
|
||||
(SEAT_MOVE_CAN_DYNAMIC_STATUS_ID > 0x7FFu) || \
|
||||
(SEAT_MOVE_CAN_FIRMWARE_ID_ID > 0x7FFu) || \
|
||||
(SEAT_MOVE_CAN_HIL_SELF_HEAL_REQUEST_ID > 0x7FFu) || \
|
||||
(SEAT_MOVE_CAN_HIL_SELF_HEAL_RESPONSE_ID > 0x7FFu))
|
||||
#error "Seat movement CAN identifiers must be 11-bit standard IDs."
|
||||
@@ -183,6 +193,10 @@
|
||||
#error "The firmware revision must fit in the 0x301 high nibble."
|
||||
#endif
|
||||
|
||||
#if (SEAT_MOVE_FIRMWARE_BUILD_ID > 0xFFu)
|
||||
#error "The firmware build ID must fit in the 0x307 build byte."
|
||||
#endif
|
||||
|
||||
#if (SEAT_MOVE_DEBUG_SESSION_BREG_INDEX >= SRSS_BACKUP_NUM_BREG)
|
||||
#error "The selected debug-session backup register is not available."
|
||||
#endif
|
||||
|
||||
@@ -3618,8 +3618,7 @@ static uint8_t Motor_CalibrationProbeMotion(
|
||||
uint32_t *travelEdges)
|
||||
{
|
||||
uint32_t index = (uint32_t)mode;
|
||||
uint32_t verifyEdges = (mode == MOTOR_MODE_3_LINEAR_TRACK) ?
|
||||
2ul : MOTOR_HOME_PROBE_VERIFY_EDGES;
|
||||
uint32_t verifyEdges = MOTOR_HOME_PROBE_VERIFY_EDGES;
|
||||
uint32_t rawTotalStart;
|
||||
uint32_t rawTotalEnd;
|
||||
uint32_t savedIntrStatus;
|
||||
@@ -3890,9 +3889,6 @@ uint8_t Motor_Calibrate(motor_mode_t mode,
|
||||
uint32_t measuredEdges = 0ul;
|
||||
uint32_t probeEdges = 0ul;
|
||||
uint32_t preloadEdges = 0ul;
|
||||
uint32_t homeProbeVerifyEdges =
|
||||
(mode == MOTOR_MODE_3_LINEAR_TRACK) ?
|
||||
2ul : MOTOR_HOME_PROBE_VERIFY_EDGES;
|
||||
uint8_t probeAttempt = 0u;
|
||||
#if (MOTOR_DIAGNOSTIC_LOG_ENABLE != 0u)
|
||||
uint32_t firstNearPulses = 0ul;
|
||||
@@ -3960,7 +3956,7 @@ uint8_t Motor_Calibrate(motor_mode_t mode,
|
||||
firstNearEdges = measuredEdges;
|
||||
#endif
|
||||
if((status == MOTOR_API_SUCCESS) &&
|
||||
(measuredEdges < homeProbeVerifyEdges))
|
||||
(measuredEdges < MOTOR_HOME_PROBE_VERIFY_EDGES))
|
||||
{
|
||||
/* Do not turn a non-start into a fake Hall zero. A genuine
|
||||
* already-near condition is proved by moving across several Hall
|
||||
@@ -3969,11 +3965,11 @@ uint8_t Motor_Calibrate(motor_mode_t mode,
|
||||
* cycle to leave a mechanical hard stop. Retry the departure,
|
||||
* but still require real Hall edges before accepting the home.
|
||||
* This improves endpoint breakaway without weakening the open
|
||||
* Hall / disconnected-motor diagnostic. The loaded M3 linkage
|
||||
* is accepted after two filtered raw Hall edges: the real bench
|
||||
* repeatedly produces one complete Hall pulse before its bounded
|
||||
* probe stops, while an open/disconnected Hall still produces
|
||||
* zero. The other axes retain the four-edge proof. */
|
||||
* Hall / disconnected-motor diagnostic. Keep the same four-edge
|
||||
* proof on M3 as the other axes: accepting a single complete Hall
|
||||
* pulse can make a temporarily stuck legrest look like a real
|
||||
* mechanical endpoint and incorrectly rewrite its position to
|
||||
* Hall=0 before the linkage is fully lowered. */
|
||||
for(probeAttempt = 0u; probeAttempt < 3u; probeAttempt++)
|
||||
{
|
||||
status = Motor_CalibrationProbeMotion(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@@ -6,7 +6,10 @@ import json
|
||||
import os
|
||||
import time
|
||||
|
||||
import zcanpro
|
||||
try:
|
||||
import zcanpro
|
||||
except ImportError: # protocol helpers are also reused by the headless runtime
|
||||
zcanpro = None
|
||||
|
||||
|
||||
SEAT_RX_IDS = (0x301, 0x302, 0x303, 0x304, 0x305, 0x306, 0x4FA)
|
||||
@@ -138,6 +141,8 @@ def command_payload(opcode, motor, direction, sequence, param_a=0,
|
||||
|
||||
class HilSession(object):
|
||||
def __init__(self, group_name):
|
||||
if zcanpro is None:
|
||||
raise RuntimeError("HilSession must run inside ZCANPRO")
|
||||
self.group_name = group_name
|
||||
self.stop_requested = False
|
||||
self.results = []
|
||||
|
||||
Reference in New Issue
Block a user