forked from achamaikin/CCSModuleSW30Web
Add charging-phase PSU sudden-off diagnostics (v1.0.28).
Observability only: log can_lost/output_lost and status flags during Charging, without changing PSU recovery behavior. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+1
-1
@@ -105,7 +105,7 @@ void debug_buffer_send(void)
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
#define LOG_BUFFER_SIZE 128
|
||||
#define LOG_BUFFER_SIZE 256
|
||||
uint8_t log_buffer[LOG_BUFFER_SIZE];
|
||||
|
||||
// Кастомный printf с приоритетом лога
|
||||
|
||||
@@ -27,6 +27,7 @@ PSU_t PSU0;
|
||||
#define PSU_ONLINE_TIMEOUT 500 // Таймаут для определения состояния (мс)
|
||||
#define PSU_STARTUP_DELAY 4000 // Задержка 2 секунды перед включением
|
||||
#define PSU_DIAG_LOG_MS 2000u
|
||||
#define PSU_SUDDEN_OFF_DEBOUNCE_MS 200u
|
||||
|
||||
uint32_t can_lastpacket;
|
||||
|
||||
@@ -34,8 +35,13 @@ extern CAN_HandleTypeDef hcan2;
|
||||
|
||||
static uint16_t psu_last_can_v;
|
||||
static uint16_t psu_last_can_i_0p1A;
|
||||
static uint8_t psu_last_good_s0;
|
||||
static uint8_t psu_last_good_s1;
|
||||
static uint8_t psu_last_good_s2;
|
||||
|
||||
static void PSU_SendCmd(uint8_t source, uint8_t destination, uint8_t cmd, void *data);
|
||||
static void PSU_LogActiveStatusFlags(LogLevel_t level);
|
||||
static void PSU_MonitorStatusAndUnexpectedOff(void);
|
||||
|
||||
static const char *PSU_StateName(PSU_State_t state)
|
||||
{
|
||||
@@ -65,6 +71,11 @@ static void PSU_LogPeriodicDiag(void)
|
||||
uint32_t now = HAL_GetTick();
|
||||
uint8_t block_setpoint;
|
||||
|
||||
/* Periodic PSU telemetry only while session is in Charging. */
|
||||
if (CONN.connState != Charging) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((now - last_log_ms) < PSU_DIAG_LOG_MS) {
|
||||
return;
|
||||
}
|
||||
@@ -110,6 +121,174 @@ static void PSU_LogPeriodicDiag(void)
|
||||
(unsigned long)(can_lastpacket ? (now - can_lastpacket) : 9999u));
|
||||
}
|
||||
|
||||
static void PSU_LogActiveStatusFlags(LogLevel_t level)
|
||||
{
|
||||
PSU_Status0_t s0 = PSU0.status0.bits;
|
||||
PSU_Status1_t s1 = PSU0.status1.bits;
|
||||
PSU_Status2_t s2 = PSU0.status2.bits;
|
||||
|
||||
log_printf(level,
|
||||
"PSU flags%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
|
||||
s0.shortCircuitFault ? " sc" : "",
|
||||
s0.unevenFlowAlarm ? " uneven" : "",
|
||||
s0.internalCommunicationFault ? " int_comm" : "",
|
||||
s0.inputBusLineFault ? " in_bus" : "",
|
||||
s0.lockProtection ? " lock" : "",
|
||||
s0.dischargeFault ? " disch" : "",
|
||||
s0.eepromFault ? " eeprom" : "",
|
||||
s1.dcSideOffStatus ? " dc_off" : "",
|
||||
s1.moduleFaultAlarm ? " fault" : "",
|
||||
s1.moduleProtectionAlarm ? " prot" : "",
|
||||
s1.fanFaultAlarm ? " fan" : "",
|
||||
s1.overTempAlarm ? " ot" : "",
|
||||
s1.outputOverVoltageAlarm ? " oov" : "",
|
||||
s1.outputOverCurrentAlarm ? " ooc" : "",
|
||||
s1.canCommunicationInterruptAlarm ? " can_int" : "",
|
||||
s2.powerLimitStatus ? " plim" : "",
|
||||
s2.moduleAddressDuplicate ? " addr_dup" : "",
|
||||
s2.severeUnevenFlowFault ? " uneven_hi" : "",
|
||||
s2.threePhaseInputPhaseLossAlarm ? " ph_loss" : "",
|
||||
s2.threePhaseInputUnbalanceAlarm ? " unbal" : "",
|
||||
s2.inputUnderVoltageAlarm ? " uv" : "",
|
||||
s2.inputOverVoltageAlarm ? " ov" : "",
|
||||
s2.pfcSideOffStatus ? " pfc_off" : "");
|
||||
}
|
||||
|
||||
/*
|
||||
* Observability only: does not change PSU/contactor state machine.
|
||||
* Armed only in CONN Charging phase:
|
||||
* - status bit edges while output is requested
|
||||
* - PSU_enabled 1->0 while CONNECTED + EnableOutput (sudden disable)
|
||||
*
|
||||
* Note: PSU_enabled is derived from V >= PSU_VOLTAGE_THRESHOLD, not from
|
||||
* the module enable command bit.
|
||||
*/
|
||||
static void PSU_MonitorStatusAndUnexpectedOff(void)
|
||||
{
|
||||
static uint8_t prev_s0;
|
||||
static uint8_t prev_s1;
|
||||
static uint8_t prev_s2;
|
||||
static uint8_t prev_enabled;
|
||||
static uint8_t inited;
|
||||
static uint8_t sudden_latched;
|
||||
static uint32_t sudden_cand_ms;
|
||||
|
||||
uint32_t now = HAL_GetTick();
|
||||
uint8_t in_charging;
|
||||
uint8_t watch_status;
|
||||
uint8_t expect_on;
|
||||
|
||||
in_charging = (CONN.connState == Charging);
|
||||
watch_status = in_charging && (CONN.EnableOutput != 0) && (PSU0.online != 0) &&
|
||||
((PSU0.state == PSU_CONNECTED) ||
|
||||
(PSU0.state == PSU_WAIT_ACK_ON) ||
|
||||
(PSU0.state == PSU_CONT_WAIT_ACK_ON));
|
||||
|
||||
expect_on = in_charging && (CONN.EnableOutput != 0) && (PSU0.state == PSU_CONNECTED);
|
||||
|
||||
if (!inited) {
|
||||
prev_s0 = PSU0.status0.raw;
|
||||
prev_s1 = PSU0.status1.raw;
|
||||
prev_s2 = PSU0.status2.raw;
|
||||
prev_enabled = PSU0.PSU_enabled;
|
||||
inited = 1u;
|
||||
return;
|
||||
}
|
||||
|
||||
if (watch_status) {
|
||||
if ((PSU0.status0.raw != prev_s0) ||
|
||||
(PSU0.status1.raw != prev_s1) ||
|
||||
(PSU0.status2.raw != prev_s2)) {
|
||||
log_printf(LOG_WARN,
|
||||
"PSU status change s0=0x%02x->0x%02x s1=0x%02x->0x%02x s2=0x%02x->0x%02x\n",
|
||||
(unsigned)prev_s0, (unsigned)PSU0.status0.raw,
|
||||
(unsigned)prev_s1, (unsigned)PSU0.status1.raw,
|
||||
(unsigned)prev_s2, (unsigned)PSU0.status2.raw);
|
||||
PSU_LogActiveStatusFlags(LOG_WARN);
|
||||
}
|
||||
}
|
||||
|
||||
prev_s0 = PSU0.status0.raw;
|
||||
prev_s1 = PSU0.status1.raw;
|
||||
prev_s2 = PSU0.status2.raw;
|
||||
|
||||
if (!expect_on) {
|
||||
sudden_cand_ms = 0u;
|
||||
if ((CONN.EnableOutput == 0) ||
|
||||
(CONN.connState != Charging) ||
|
||||
(PSU0.state == PSU_READY) ||
|
||||
(PSU0.state == PSU_UNREADY) ||
|
||||
(PSU0.state == PSU_OFF_PAUSE) ||
|
||||
(PSU0.state == PSU_WAIT_ACK_OFF) ||
|
||||
(PSU0.state == PSU_CONT_WAIT_ACK_OFF) ||
|
||||
(PSU0.state == PSU_CURRENT_DROP)) {
|
||||
sudden_latched = 0u;
|
||||
}
|
||||
prev_enabled = PSU0.PSU_enabled;
|
||||
return;
|
||||
}
|
||||
|
||||
if (PSU0.PSU_enabled) {
|
||||
sudden_cand_ms = 0u;
|
||||
sudden_latched = 0u;
|
||||
prev_enabled = 1u;
|
||||
return;
|
||||
}
|
||||
|
||||
if (sudden_latched) {
|
||||
prev_enabled = 0u;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!prev_enabled) {
|
||||
sudden_cand_ms = 0u;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Falling edge of PSU_enabled while still CONNECTED + EnableOutput + Charging */
|
||||
if (!PSU0.online) {
|
||||
log_printf(LOG_ERR,
|
||||
"PSU suddenly disabled while charging reason=can_lost "
|
||||
"V=%u I=%d cont=%u s0=0x%02x s1=0x%02x s2=0x%02x can_age=%lums\n",
|
||||
(unsigned)PSU0.outputVoltage,
|
||||
(int)PSU0.outputCurrent,
|
||||
(unsigned)PSU0.CONT_enabled,
|
||||
(unsigned)psu_last_good_s0,
|
||||
(unsigned)psu_last_good_s1,
|
||||
(unsigned)psu_last_good_s2,
|
||||
(unsigned long)(can_lastpacket ? (now - can_lastpacket) : 9999u));
|
||||
PSU_LogActiveStatusFlags(LOG_ERR);
|
||||
sudden_latched = 1u;
|
||||
sudden_cand_ms = 0u;
|
||||
prev_enabled = 0u;
|
||||
return;
|
||||
}
|
||||
|
||||
if (sudden_cand_ms == 0u) {
|
||||
sudden_cand_ms = now;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((now - sudden_cand_ms) < PSU_SUDDEN_OFF_DEBOUNCE_MS) {
|
||||
return;
|
||||
}
|
||||
|
||||
log_printf(LOG_ERR,
|
||||
"PSU suddenly disabled while charging reason=output_lost "
|
||||
"V=%u I=%d cont=%u s0=0x%02x s1=0x%02x s2=0x%02x can_age=%lums\n",
|
||||
(unsigned)PSU0.outputVoltage,
|
||||
(int)PSU0.outputCurrent,
|
||||
(unsigned)PSU0.CONT_enabled,
|
||||
(unsigned)PSU0.status0.raw,
|
||||
(unsigned)PSU0.status1.raw,
|
||||
(unsigned)PSU0.status2.raw,
|
||||
(unsigned long)(can_lastpacket ? (now - can_lastpacket) : 9999u));
|
||||
PSU_LogActiveStatusFlags(LOG_ERR);
|
||||
sudden_latched = 1u;
|
||||
sudden_cand_ms = 0u;
|
||||
prev_enabled = 0u;
|
||||
}
|
||||
|
||||
static void PSU_HvControl(void)
|
||||
{
|
||||
if (CONN.EnableOutput == 0u) {
|
||||
@@ -235,6 +414,9 @@ ISR_FAST void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan){
|
||||
PSU0.status0.raw = PSU_04.modularForm0;
|
||||
PSU0.status1.raw = PSU_04.modularForm1;
|
||||
PSU0.status2.raw = PSU_04.modularForm2;
|
||||
psu_last_good_s0 = PSU0.status0.raw;
|
||||
psu_last_good_s1 = PSU0.status1.raw;
|
||||
psu_last_good_s2 = PSU0.status2.raw;
|
||||
}
|
||||
if(CanId.command==0x06){
|
||||
memcpy(&PSU_06, RxData, 8);
|
||||
@@ -515,6 +697,9 @@ void PSU_Task(void){
|
||||
PSU0.ready = 0;
|
||||
}
|
||||
|
||||
/* Before state transitions so CONNECTED+can_lost is still visible */
|
||||
PSU_MonitorStatusAndUnexpectedOff();
|
||||
|
||||
switch(PSU0.state){
|
||||
case PSU_UNREADY:
|
||||
PSU0.enableOutput = 0;
|
||||
|
||||
Reference in New Issue
Block a user