forked from achamaikin/CCSModuleSW30Web
Add PSU fast discharge API for DC precharge step-down (v1.0.23).
Policy/executor hooks, event-driven OFF/ON state machine, and release binaries. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -13,3 +13,17 @@
|
|||||||
#define FAKE_EVREQ_VOLTAGE_V 500u
|
#define FAKE_EVREQ_VOLTAGE_V 500u
|
||||||
#define FAKE_PSU_VOLTAGE_V 300u
|
#define FAKE_PSU_VOLTAGE_V 300u
|
||||||
#define FAKE_PSU_CURRENT_0P1A 10u
|
#define FAKE_PSU_CURRENT_0P1A 10u
|
||||||
|
|
||||||
|
/* Fast discharge: PSU off/on cycle on step-down setpoint (unloaded bus). */
|
||||||
|
#define PSD_ENABLE 1u
|
||||||
|
#define PSD_MAX_CMD_CURRENT_0P1A 20u /* 2.0 A */
|
||||||
|
#define PSD_MAX_MEASURED_CURRENT_0P1A 30u /* 3.0 A */
|
||||||
|
#define PSD_MEASURED_LATCH_MS 500u
|
||||||
|
#define PSD_MIN_VOLTAGE_STEP_V 50u
|
||||||
|
#define PSD_DISCHARGE_MARGIN_V 15u
|
||||||
|
#define PSD_DEBOUNCE_MS 2000u
|
||||||
|
#define PSD_MAX_PER_SESSION 4u
|
||||||
|
#define PSD_OFF_TIMEOUT_MS 10000u /* как PSU_WAIT_ACK_OFF */
|
||||||
|
#define PSD_ON_TIMEOUT_MS 10000u
|
||||||
|
#define PSD_ON_RETRY_MS 500u /* повтор SET+ON в ON_WAIT */
|
||||||
|
#define PSD_PRECHARGE_TOLERANCE_V 40u /* ~±10% for 350 V precharge window */
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ extern "C" {
|
|||||||
/* USER CODE BEGIN EC */
|
/* USER CODE BEGIN EC */
|
||||||
#define FW_VERSION_MAJOR 1
|
#define FW_VERSION_MAJOR 1
|
||||||
#define FW_VERSION_MINOR 0
|
#define FW_VERSION_MINOR 0
|
||||||
#define FW_VERSION_PATCH 19
|
#define FW_VERSION_PATCH 23
|
||||||
/* USER CODE END EC */
|
/* USER CODE END EC */
|
||||||
|
|
||||||
/* Exported macro ------------------------------------------------------------*/
|
/* Exported macro ------------------------------------------------------------*/
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "power_setpoint_policy.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PSD_TRY_IDLE = 0,
|
||||||
|
PSD_TRY_APPLIED_NORMAL,
|
||||||
|
PSD_TRY_START_FAST_DISCHARGE,
|
||||||
|
} PowerSetpointTryResult_t;
|
||||||
|
|
||||||
|
void PowerSetpoint_Init(void);
|
||||||
|
void PowerSetpoint_OnCommand(uint16_t voltage_V, uint16_t current_0p1A);
|
||||||
|
void PowerSetpoint_UpdateDeliveryLatch(void);
|
||||||
|
uint8_t PowerSetpoint_HasPending(void);
|
||||||
|
uint8_t PowerSetpoint_IsBusy(void);
|
||||||
|
PowerSetpointTryResult_t PowerSetpoint_TryApply(void);
|
||||||
|
void PowerSetpoint_GetFastDischargeTarget(PowerSetpoint_t *target);
|
||||||
|
void PowerSetpoint_OnFastDischargeComplete(void);
|
||||||
|
void PowerSetpoint_OnFastDischargeAbort(void);
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "charger_config.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t voltage_V;
|
||||||
|
uint16_t current_0p1A;
|
||||||
|
} PowerSetpoint_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
POWER_SETPOINT_NORMAL,
|
||||||
|
POWER_SETPOINT_FAST_DISCHARGE,
|
||||||
|
} PowerSetpointAction_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t dc_contactor_closed;
|
||||||
|
uint8_t psu_hv_enabled;
|
||||||
|
uint16_t measured_voltage_V;
|
||||||
|
uint16_t measured_current_0p1A;
|
||||||
|
uint8_t power_delivery_active;
|
||||||
|
uint8_t enable_output;
|
||||||
|
uint8_t psu_state_connected;
|
||||||
|
uint8_t psu_cont_fault;
|
||||||
|
uint8_t psu_fault;
|
||||||
|
uint8_t fast_discharge_count;
|
||||||
|
uint32_t last_fast_discharge_ms;
|
||||||
|
uint32_t now_ms;
|
||||||
|
} PowerPathContext_t;
|
||||||
|
|
||||||
|
PowerSetpointAction_t PowerSetpoint_Decide(
|
||||||
|
const PowerSetpoint_t *applied,
|
||||||
|
const PowerSetpoint_t *next,
|
||||||
|
const PowerPathContext_t *ctx);
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
void PSU_Init();
|
void PSU_Init();
|
||||||
void PSU_Enable(uint8_t addr, uint8_t enable);
|
void PSU_Enable(uint8_t addr, uint8_t enable);
|
||||||
|
void PSU_SetVoltageCurrent(uint8_t addr, uint16_t voltage, uint16_t current);
|
||||||
void PSU_ReadWrite(void);
|
void PSU_ReadWrite(void);
|
||||||
|
|
||||||
// --- Состояние силового модуля (DC30, один PSU) ---
|
// --- Состояние силового модуля (DC30, один PSU) ---
|
||||||
@@ -16,6 +17,11 @@ typedef enum{
|
|||||||
PSU_WAIT_ACK_ON, // ждём подтверждение включения модуля (напряжение выше порога)
|
PSU_WAIT_ACK_ON, // ждём подтверждение включения модуля (напряжение выше порога)
|
||||||
PSU_CONT_WAIT_ACK_ON, // включаем DC-контактор и ждём подтверждение
|
PSU_CONT_WAIT_ACK_ON, // включаем DC-контактор и ждём подтверждение
|
||||||
PSU_CONNECTED, // модуль включён, DC-контактор замкнут
|
PSU_CONNECTED, // модуль включён, DC-контактор замкнут
|
||||||
|
PSU_FAST_DISCHARGE_OFF,
|
||||||
|
PSU_FAST_DISCHARGE_WAIT, /* ждём подтверждение выключения (как PSU_WAIT_ACK_OFF) */
|
||||||
|
PSU_FAST_DISCHARGE_SET, /* задать целевое U/I при выключенном модуле */
|
||||||
|
PSU_FAST_DISCHARGE_ON, /* команда включения после set */
|
||||||
|
PSU_FAST_DISCHARGE_ON_WAIT, /* ждём подтверждение включения (как PSU_WAIT_ACK_ON) */
|
||||||
PSU_CURRENT_DROP, // снижение тока перед отключением
|
PSU_CURRENT_DROP, // снижение тока перед отключением
|
||||||
PSU_WAIT_ACK_OFF, // ждём подтверждение выключения модуля (напряжение ниже порога)
|
PSU_WAIT_ACK_OFF, // ждём подтверждение выключения модуля (напряжение ниже порога)
|
||||||
PSU_CONT_WAIT_ACK_OFF, // выключаем DC-контактор и ждём подтверждение
|
PSU_CONT_WAIT_ACK_OFF, // выключаем DC-контактор и ждём подтверждение
|
||||||
|
|||||||
@@ -0,0 +1,196 @@
|
|||||||
|
#include "power_setpoint_executor.h"
|
||||||
|
|
||||||
|
#include "charger_config.h"
|
||||||
|
#include "charger_control.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "psu_control.h"
|
||||||
|
#include "serial.h"
|
||||||
|
|
||||||
|
static PowerSetpoint_t applied;
|
||||||
|
static PowerSetpoint_t pending;
|
||||||
|
static PowerSetpoint_t fd_target;
|
||||||
|
static uint8_t setpoint_dirty;
|
||||||
|
static uint8_t fd_active;
|
||||||
|
static uint8_t power_delivery_latched;
|
||||||
|
static uint8_t fast_discharge_count;
|
||||||
|
static uint32_t last_fast_discharge_ms;
|
||||||
|
static uint32_t measured_high_current_since_ms;
|
||||||
|
|
||||||
|
static uint8_t session_ended_state(CONN_State_t state)
|
||||||
|
{
|
||||||
|
return (state == Unknown) || (state == Unplugged) || (state == Finished) ||
|
||||||
|
(state == FinishedEV) || (state == FinishedEVSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PowerSetpoint_Init(void)
|
||||||
|
{
|
||||||
|
applied.voltage_V = PSU_MIN_VOLTAGE;
|
||||||
|
applied.current_0p1A = 0u;
|
||||||
|
pending = applied;
|
||||||
|
fd_target = applied;
|
||||||
|
setpoint_dirty = 0u;
|
||||||
|
fd_active = 0u;
|
||||||
|
power_delivery_latched = 0u;
|
||||||
|
fast_discharge_count = 0u;
|
||||||
|
last_fast_discharge_ms = 0u;
|
||||||
|
measured_high_current_since_ms = 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PowerSetpoint_OnCommand(uint16_t voltage_V, uint16_t current_0p1A)
|
||||||
|
{
|
||||||
|
#if PSD_ENABLE
|
||||||
|
pending.voltage_V = voltage_V;
|
||||||
|
pending.current_0p1A = current_0p1A;
|
||||||
|
setpoint_dirty = 1u;
|
||||||
|
#else
|
||||||
|
(void)voltage_V;
|
||||||
|
(void)current_0p1A;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void PowerSetpoint_UpdateDeliveryLatch(void)
|
||||||
|
{
|
||||||
|
#if PSD_ENABLE
|
||||||
|
uint32_t now = HAL_GetTick();
|
||||||
|
|
||||||
|
if (!CONN.EnableOutput || !CONN.EvConnected || session_ended_state(CCS_EvseState)) {
|
||||||
|
power_delivery_latched = 0u;
|
||||||
|
fast_discharge_count = 0u;
|
||||||
|
last_fast_discharge_ms = 0u;
|
||||||
|
measured_high_current_since_ms = 0u;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CONN.WantedCurrent > PSD_MAX_CMD_CURRENT_0P1A) {
|
||||||
|
power_delivery_latched = 1u;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CCS_EvseState == Charging) {
|
||||||
|
power_delivery_latched = 1u;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CONN.MeasuredCurrent >= PSD_MAX_MEASURED_CURRENT_0P1A) {
|
||||||
|
if (measured_high_current_since_ms == 0u) {
|
||||||
|
measured_high_current_since_ms = now;
|
||||||
|
} else if ((now - measured_high_current_since_ms) >= PSD_MEASURED_LATCH_MS) {
|
||||||
|
power_delivery_latched = 1u;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
measured_high_current_since_ms = 0u;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t PowerSetpoint_HasPending(void)
|
||||||
|
{
|
||||||
|
#if PSD_ENABLE
|
||||||
|
return setpoint_dirty;
|
||||||
|
#else
|
||||||
|
return 0u;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t PowerSetpoint_IsBusy(void)
|
||||||
|
{
|
||||||
|
#if PSD_ENABLE
|
||||||
|
if (!fd_active) {
|
||||||
|
return 0u;
|
||||||
|
}
|
||||||
|
switch (PSU0.state) {
|
||||||
|
case PSU_FAST_DISCHARGE_OFF:
|
||||||
|
case PSU_FAST_DISCHARGE_WAIT:
|
||||||
|
case PSU_FAST_DISCHARGE_SET:
|
||||||
|
case PSU_FAST_DISCHARGE_ON:
|
||||||
|
case PSU_FAST_DISCHARGE_ON_WAIT:
|
||||||
|
return 1u;
|
||||||
|
default:
|
||||||
|
return 0u;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return 0u;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static PowerPathContext_t build_context(void)
|
||||||
|
{
|
||||||
|
PowerPathContext_t ctx;
|
||||||
|
|
||||||
|
ctx.dc_contactor_closed = PSU0.CONT_enabled;
|
||||||
|
ctx.psu_hv_enabled = PSU0.PSU_enabled;
|
||||||
|
ctx.measured_voltage_V = CONN.MeasuredVoltage;
|
||||||
|
ctx.measured_current_0p1A = (uint16_t)CONN.MeasuredCurrent;
|
||||||
|
ctx.power_delivery_active = power_delivery_latched;
|
||||||
|
ctx.enable_output = CONN.EnableOutput;
|
||||||
|
ctx.psu_state_connected = (PSU0.state == PSU_CONNECTED) ? 1u : 0u;
|
||||||
|
ctx.psu_cont_fault = PSU0.cont_fault;
|
||||||
|
ctx.psu_fault = PSU0.psu_fault;
|
||||||
|
ctx.fast_discharge_count = fast_discharge_count;
|
||||||
|
ctx.last_fast_discharge_ms = last_fast_discharge_ms;
|
||||||
|
ctx.now_ms = HAL_GetTick();
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
PowerSetpointTryResult_t PowerSetpoint_TryApply(void)
|
||||||
|
{
|
||||||
|
#if PSD_ENABLE
|
||||||
|
PowerPathContext_t ctx;
|
||||||
|
PowerSetpointAction_t action;
|
||||||
|
|
||||||
|
if (!setpoint_dirty || fd_active) {
|
||||||
|
return PSD_TRY_IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = build_context();
|
||||||
|
action = PowerSetpoint_Decide(&applied, &pending, &ctx);
|
||||||
|
|
||||||
|
if (action == POWER_SETPOINT_FAST_DISCHARGE) {
|
||||||
|
fd_target = pending;
|
||||||
|
fd_active = 1u;
|
||||||
|
setpoint_dirty = 0u;
|
||||||
|
log_printf(LOG_INFO, "Fast discharge trigger %u->%u I=%u\n",
|
||||||
|
(unsigned)applied.voltage_V,
|
||||||
|
(unsigned)fd_target.voltage_V,
|
||||||
|
(unsigned)fd_target.current_0p1A);
|
||||||
|
return PSD_TRY_START_FAST_DISCHARGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PSU0.ready) {
|
||||||
|
return PSD_TRY_IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PSU_SetVoltageCurrent(0, pending.voltage_V, pending.current_0p1A);
|
||||||
|
applied = pending;
|
||||||
|
setpoint_dirty = 0u;
|
||||||
|
return PSD_TRY_APPLIED_NORMAL;
|
||||||
|
#else
|
||||||
|
return PSD_TRY_IDLE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void PowerSetpoint_GetFastDischargeTarget(PowerSetpoint_t *target)
|
||||||
|
{
|
||||||
|
if (target != 0) {
|
||||||
|
*target = fd_target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PowerSetpoint_OnFastDischargeComplete(void)
|
||||||
|
{
|
||||||
|
#if PSD_ENABLE
|
||||||
|
applied = fd_target;
|
||||||
|
fd_active = 0u;
|
||||||
|
fast_discharge_count++;
|
||||||
|
last_fast_discharge_ms = HAL_GetTick();
|
||||||
|
log_printf(LOG_INFO, "Fast discharge complete, V=%u\n", (unsigned)CONN.MeasuredVoltage);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void PowerSetpoint_OnFastDischargeAbort(void)
|
||||||
|
{
|
||||||
|
#if PSD_ENABLE
|
||||||
|
fd_active = 0u;
|
||||||
|
pending = fd_target;
|
||||||
|
setpoint_dirty = 1u;
|
||||||
|
log_printf(LOG_WARN, "Fast discharge aborted, V=%u\n", (unsigned)CONN.MeasuredVoltage);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
#include "power_setpoint_policy.h"
|
||||||
|
|
||||||
|
PowerSetpointAction_t PowerSetpoint_Decide(
|
||||||
|
const PowerSetpoint_t *applied,
|
||||||
|
const PowerSetpoint_t *next,
|
||||||
|
const PowerPathContext_t *ctx)
|
||||||
|
{
|
||||||
|
#if !PSD_ENABLE
|
||||||
|
(void)applied;
|
||||||
|
(void)next;
|
||||||
|
(void)ctx;
|
||||||
|
return POWER_SETPOINT_NORMAL;
|
||||||
|
#else
|
||||||
|
uint16_t delta_v;
|
||||||
|
|
||||||
|
if (applied == 0 || next == 0 || ctx == 0) {
|
||||||
|
return POWER_SETPOINT_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next->voltage_V >= applied->voltage_V) {
|
||||||
|
return POWER_SETPOINT_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
delta_v = (uint16_t)(applied->voltage_V - next->voltage_V);
|
||||||
|
if (delta_v < PSD_MIN_VOLTAGE_STEP_V) {
|
||||||
|
return POWER_SETPOINT_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (applied->current_0p1A > PSD_MAX_CMD_CURRENT_0P1A ||
|
||||||
|
next->current_0p1A > PSD_MAX_CMD_CURRENT_0P1A) {
|
||||||
|
return POWER_SETPOINT_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->measured_current_0p1A >= PSD_MAX_MEASURED_CURRENT_0P1A) {
|
||||||
|
return POWER_SETPOINT_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->measured_voltage_V <= (uint16_t)(next->voltage_V + PSD_DISCHARGE_MARGIN_V)) {
|
||||||
|
return POWER_SETPOINT_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->power_delivery_active) {
|
||||||
|
return POWER_SETPOINT_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ctx->enable_output) {
|
||||||
|
return POWER_SETPOINT_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ctx->psu_state_connected) {
|
||||||
|
return POWER_SETPOINT_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ctx->dc_contactor_closed) {
|
||||||
|
return POWER_SETPOINT_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ctx->psu_hv_enabled) {
|
||||||
|
return POWER_SETPOINT_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->psu_cont_fault || ctx->psu_fault) {
|
||||||
|
return POWER_SETPOINT_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->fast_discharge_count >= PSD_MAX_PER_SESSION) {
|
||||||
|
return POWER_SETPOINT_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->last_fast_discharge_ms != 0u &&
|
||||||
|
(ctx->now_ms - ctx->last_fast_discharge_ms) < PSD_DEBOUNCE_MS) {
|
||||||
|
return POWER_SETPOINT_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return POWER_SETPOINT_FAST_DISCHARGE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
+148
-9
@@ -6,6 +6,7 @@
|
|||||||
#include "charger_control.h"
|
#include "charger_control.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "isr_opt.h"
|
#include "isr_opt.h"
|
||||||
|
#include "power_setpoint_executor.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -41,6 +42,24 @@ static uint32_t PSU_StateTime(void){
|
|||||||
return HAL_GetTick() - PSU0.statetick;
|
return HAL_GetTick() - PSU0.statetick;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void PSU_FastDischarge_PushTarget(void)
|
||||||
|
{
|
||||||
|
PowerSetpoint_t fd_sp;
|
||||||
|
|
||||||
|
PowerSetpoint_GetFastDischargeTarget(&fd_sp);
|
||||||
|
PSU_SetVoltageCurrent(0, fd_sp.voltage_V, fd_sp.current_0p1A);
|
||||||
|
PSU_Enable(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PSU_FastDischarge_AbortToConnected(void)
|
||||||
|
{
|
||||||
|
PowerSetpoint_OnFastDischargeAbort();
|
||||||
|
if (!PSU0.PSU_enabled) {
|
||||||
|
PSU_FastDischarge_PushTarget();
|
||||||
|
}
|
||||||
|
PSU_SwitchState(PSU_CONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
ISR_FAST void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan){
|
ISR_FAST void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan){
|
||||||
|
|
||||||
static CAN_RxHeaderTypeDef RxHeader;
|
static CAN_RxHeaderTypeDef RxHeader;
|
||||||
@@ -154,6 +173,7 @@ void PSU_Init(){
|
|||||||
PSU0.hv_tick = 0;
|
PSU0.hv_tick = 0;
|
||||||
|
|
||||||
PSU_Enable(0, 0);
|
PSU_Enable(0, 0);
|
||||||
|
PowerSetpoint_Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PSU_Enable(uint8_t addr, uint8_t enable){
|
void PSU_Enable(uint8_t addr, uint8_t enable){
|
||||||
@@ -258,20 +278,34 @@ void PSU_ReadWrite(){
|
|||||||
}
|
}
|
||||||
CONN.RequestedPower = CONN.RequestedCurrent * CONN.RequestedVoltage / 10;
|
CONN.RequestedPower = CONN.RequestedCurrent * CONN.RequestedVoltage / 10;
|
||||||
|
|
||||||
if(PSU0.ready){
|
#if PSD_ENABLE
|
||||||
if (CONN.RequestedVoltage == FAKE_EVREQ_VOLTAGE_V) {
|
{
|
||||||
PSU_SetVoltageCurrent(0, (uint16_t)FAKE_PSU_VOLTAGE_V, (uint16_t)FAKE_PSU_CURRENT_0P1A);
|
uint8_t block_setpoint = PowerSetpoint_HasPending() || PowerSetpoint_IsBusy();
|
||||||
}else{
|
|
||||||
PSU_SetVoltageCurrent(0, CONN.RequestedVoltage, CONN.RequestedCurrent); // Normal mode
|
if (PSU0.ready && !block_setpoint) {
|
||||||
|
if (CONN.RequestedVoltage == FAKE_EVREQ_VOLTAGE_V) {
|
||||||
|
PSU_SetVoltageCurrent(0, (uint16_t)FAKE_PSU_VOLTAGE_V, (uint16_t)FAKE_PSU_CURRENT_0P1A);
|
||||||
|
} else {
|
||||||
|
PSU_SetVoltageCurrent(0, CONN.RequestedVoltage, CONN.RequestedCurrent); // Normal mode
|
||||||
|
}
|
||||||
|
ED_Delay(CAN_DELAY);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (PSU0.ready) {
|
||||||
|
PSU_SetVoltageCurrent(0, CONN.RequestedVoltage, CONN.RequestedCurrent); // Normal mode
|
||||||
ED_Delay(CAN_DELAY);
|
ED_Delay(CAN_DELAY);
|
||||||
if(CONN.MeasuredVoltage > 490){
|
}
|
||||||
if(PSU0.hv_tick == 0){
|
#endif
|
||||||
|
|
||||||
|
if (PSU0.ready) {
|
||||||
|
if (CONN.MeasuredVoltage > 490) {
|
||||||
|
if (PSU0.hv_tick == 0) {
|
||||||
PSU0.hv_tick = HAL_GetTick();
|
PSU0.hv_tick = HAL_GetTick();
|
||||||
}else if((HAL_GetTick() - PSU0.hv_tick) >= 10000){
|
} else if ((HAL_GetTick() - PSU0.hv_tick) >= 10000) {
|
||||||
PSU0.hv_mode = 1;
|
PSU0.hv_mode = 1;
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
PSU0.hv_tick = 0;
|
PSU0.hv_tick = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -284,6 +318,18 @@ void PSU_ReadWrite(){
|
|||||||
void PSU_Task(void){
|
void PSU_Task(void){
|
||||||
static uint32_t psu_on_tick = 0;
|
static uint32_t psu_on_tick = 0;
|
||||||
static uint32_t cont_ok_tick = 0;
|
static uint32_t cont_ok_tick = 0;
|
||||||
|
static uint32_t fd_on_last_cmd_ms = 0;
|
||||||
|
PowerSetpointTryResult_t psd_result;
|
||||||
|
|
||||||
|
#if PSD_ENABLE
|
||||||
|
PowerSetpoint_UpdateDeliveryLatch();
|
||||||
|
if (PowerSetpoint_HasPending()) {
|
||||||
|
psd_result = PowerSetpoint_TryApply();
|
||||||
|
if (psd_result == PSD_TRY_START_FAST_DISCHARGE) {
|
||||||
|
PSU_SwitchState(PSU_FAST_DISCHARGE_OFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Обновляем ONLINE/READY по таймауту
|
// Обновляем ONLINE/READY по таймауту
|
||||||
if((HAL_GetTick() - can_lastpacket) > PSU_ONLINE_TIMEOUT){
|
if((HAL_GetTick() - can_lastpacket) > PSU_ONLINE_TIMEOUT){
|
||||||
@@ -403,6 +449,99 @@ void PSU_Task(void){
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PSU_FAST_DISCHARGE_OFF:
|
||||||
|
if (!CONN.EnableOutput || !PSU0.ready || PSU0.cont_fault || PSU0.psu_fault) {
|
||||||
|
log_printf(LOG_WARN, "Fast discharge abort -> stop\n");
|
||||||
|
PowerSetpoint_OnFastDischargeAbort();
|
||||||
|
PSU_SwitchState(PSU_CURRENT_DROP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PSU_Enable(0, 0);
|
||||||
|
PSU_SwitchState(PSU_FAST_DISCHARGE_WAIT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PSU_FAST_DISCHARGE_WAIT: {
|
||||||
|
PowerSetpoint_t fd_sp;
|
||||||
|
|
||||||
|
if (!CONN.EnableOutput || !PSU0.ready || PSU0.cont_fault || PSU0.psu_fault) {
|
||||||
|
log_printf(LOG_WARN, "Fast discharge abort -> stop\n");
|
||||||
|
PowerSetpoint_OnFastDischargeAbort();
|
||||||
|
PSU_SwitchState(PSU_CURRENT_DROP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Как PSU_WAIT_ACK_OFF: 0–20 V на телеметрии = модуль выключен */
|
||||||
|
if (!PSU0.PSU_enabled) {
|
||||||
|
PowerSetpoint_GetFastDischargeTarget(&fd_sp);
|
||||||
|
log_printf(LOG_INFO, "Fast discharge off ack, V=%u -> set %u\n",
|
||||||
|
(unsigned)CONN.MeasuredVoltage, (unsigned)fd_sp.voltage_V);
|
||||||
|
PSU_SwitchState(PSU_FAST_DISCHARGE_SET);
|
||||||
|
} else if (PSU_StateTime() > PSD_OFF_TIMEOUT_MS) {
|
||||||
|
log_printf(LOG_WARN, "Fast discharge off timeout, V=%u\n",
|
||||||
|
(unsigned)CONN.MeasuredVoltage);
|
||||||
|
PSU_FastDischarge_AbortToConnected();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PSU_FAST_DISCHARGE_SET: {
|
||||||
|
PowerSetpoint_t fd_sp;
|
||||||
|
|
||||||
|
if (!CONN.EnableOutput || !PSU0.ready || PSU0.cont_fault || PSU0.psu_fault) {
|
||||||
|
log_printf(LOG_WARN, "Fast discharge abort -> stop\n");
|
||||||
|
PowerSetpoint_OnFastDischargeAbort();
|
||||||
|
PSU_SwitchState(PSU_CURRENT_DROP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PowerSetpoint_GetFastDischargeTarget(&fd_sp);
|
||||||
|
PSU_SetVoltageCurrent(0, fd_sp.voltage_V, fd_sp.current_0p1A);
|
||||||
|
PSU_SwitchState(PSU_FAST_DISCHARGE_ON);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PSU_FAST_DISCHARGE_ON:
|
||||||
|
if (!CONN.EnableOutput || !PSU0.ready || PSU0.cont_fault || PSU0.psu_fault) {
|
||||||
|
log_printf(LOG_WARN, "Fast discharge abort -> stop\n");
|
||||||
|
PowerSetpoint_OnFastDischargeAbort();
|
||||||
|
PSU_SwitchState(PSU_CURRENT_DROP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PSU_Enable(0, 1);
|
||||||
|
fd_on_last_cmd_ms = HAL_GetTick();
|
||||||
|
PSU_SwitchState(PSU_FAST_DISCHARGE_ON_WAIT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PSU_FAST_DISCHARGE_ON_WAIT: {
|
||||||
|
PowerSetpoint_t fd_sp;
|
||||||
|
uint16_t v_low;
|
||||||
|
|
||||||
|
if (!CONN.EnableOutput || !PSU0.ready || PSU0.cont_fault || PSU0.psu_fault) {
|
||||||
|
log_printf(LOG_WARN, "Fast discharge abort -> stop\n");
|
||||||
|
PowerSetpoint_OnFastDischargeAbort();
|
||||||
|
PSU_SwitchState(PSU_CURRENT_DROP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PowerSetpoint_GetFastDischargeTarget(&fd_sp);
|
||||||
|
v_low = (fd_sp.voltage_V > PSD_PRECHARGE_TOLERANCE_V) ?
|
||||||
|
(uint16_t)(fd_sp.voltage_V - PSD_PRECHARGE_TOLERANCE_V) : 0u;
|
||||||
|
|
||||||
|
if (PSU0.PSU_enabled && CONN.MeasuredVoltage >= v_low) {
|
||||||
|
PowerSetpoint_OnFastDischargeComplete();
|
||||||
|
PSU_SwitchState(PSU_CONNECTED);
|
||||||
|
} else {
|
||||||
|
if ((HAL_GetTick() - fd_on_last_cmd_ms) >= PSD_ON_RETRY_MS) {
|
||||||
|
PSU_FastDischarge_PushTarget();
|
||||||
|
fd_on_last_cmd_ms = HAL_GetTick();
|
||||||
|
}
|
||||||
|
if (PSU_StateTime() > PSD_ON_TIMEOUT_MS) {
|
||||||
|
log_printf(LOG_WARN, "Fast discharge on timeout, V=%u (target %u)\n",
|
||||||
|
(unsigned)CONN.MeasuredVoltage, (unsigned)fd_sp.voltage_V);
|
||||||
|
PSU_FastDischarge_AbortToConnected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case PSU_CURRENT_DROP:
|
case PSU_CURRENT_DROP:
|
||||||
// снижаем ток до нуля перед отключением DC
|
// снижаем ток до нуля перед отключением DC
|
||||||
CONN.RequestedCurrent = 0;
|
CONN.RequestedCurrent = 0;
|
||||||
|
|||||||
+10
-4
@@ -7,6 +7,7 @@
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "isr_opt.h"
|
#include "isr_opt.h"
|
||||||
#include "psu_control.h"
|
#include "psu_control.h"
|
||||||
|
#include "power_setpoint_executor.h"
|
||||||
#include "serial_control.h"
|
#include "serial_control.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -533,15 +534,20 @@ ISR_FAST static void apply_command(uint8_t cmd, const uint8_t* payload, uint16_t
|
|||||||
}
|
}
|
||||||
case CMD_E2M_SET_OUTPUT_VOLTAGE: {
|
case CMD_E2M_SET_OUTPUT_VOLTAGE: {
|
||||||
const e2m_set_output_t* p = (const e2m_set_output_t*)payload;
|
const e2m_set_output_t* p = (const e2m_set_output_t*)payload;
|
||||||
|
uint16_t psu_voltage_V;
|
||||||
|
uint16_t psu_current_0p1A;
|
||||||
if (p->voltage_V == FAKE_EVREQ_VOLTAGE_V) {
|
if (p->voltage_V == FAKE_EVREQ_VOLTAGE_V) {
|
||||||
fake_500_voltage_mode = 1u;
|
fake_500_voltage_mode = 1u;
|
||||||
CONN.RequestedVoltage = FAKE_PSU_VOLTAGE_V;
|
psu_voltage_V = FAKE_PSU_VOLTAGE_V;
|
||||||
CONN.WantedCurrent = FAKE_PSU_CURRENT_0P1A;
|
psu_current_0p1A = FAKE_PSU_CURRENT_0P1A;
|
||||||
} else {
|
} else {
|
||||||
fake_500_voltage_mode = 0u;
|
fake_500_voltage_mode = 0u;
|
||||||
CONN.RequestedVoltage = p->voltage_V;
|
psu_voltage_V = p->voltage_V;
|
||||||
CONN.WantedCurrent = p->current_0p1A;
|
psu_current_0p1A = p->current_0p1A;
|
||||||
}
|
}
|
||||||
|
CONN.RequestedVoltage = psu_voltage_V;
|
||||||
|
CONN.WantedCurrent = psu_current_0p1A;
|
||||||
|
PowerSetpoint_OnCommand(psu_voltage_V, psu_current_0p1A);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_E2M_ISOLATION_CONTROL: {
|
case CMD_E2M_ISOLATION_CONTROL: {
|
||||||
|
|||||||
Binary file not shown.
+3701
-3557
File diff suppressed because it is too large
Load Diff
+3700
-3556
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,8 @@ C_SRCS += \
|
|||||||
../Core/Src/gpio.c \
|
../Core/Src/gpio.c \
|
||||||
../Core/Src/main.c \
|
../Core/Src/main.c \
|
||||||
../Core/Src/meter.c \
|
../Core/Src/meter.c \
|
||||||
|
../Core/Src/power_setpoint_executor.c \
|
||||||
|
../Core/Src/power_setpoint_policy.c \
|
||||||
../Core/Src/psu_control.c \
|
../Core/Src/psu_control.c \
|
||||||
../Core/Src/rgb_controller.c \
|
../Core/Src/rgb_controller.c \
|
||||||
../Core/Src/rtc.c \
|
../Core/Src/rtc.c \
|
||||||
@@ -46,6 +48,8 @@ C_DEPS += \
|
|||||||
./Core/Src/gpio.d \
|
./Core/Src/gpio.d \
|
||||||
./Core/Src/main.d \
|
./Core/Src/main.d \
|
||||||
./Core/Src/meter.d \
|
./Core/Src/meter.d \
|
||||||
|
./Core/Src/power_setpoint_executor.d \
|
||||||
|
./Core/Src/power_setpoint_policy.d \
|
||||||
./Core/Src/psu_control.d \
|
./Core/Src/psu_control.d \
|
||||||
./Core/Src/rgb_controller.d \
|
./Core/Src/rgb_controller.d \
|
||||||
./Core/Src/rtc.d \
|
./Core/Src/rtc.d \
|
||||||
@@ -75,6 +79,8 @@ OBJS += \
|
|||||||
./Core/Src/gpio.o \
|
./Core/Src/gpio.o \
|
||||||
./Core/Src/main.o \
|
./Core/Src/main.o \
|
||||||
./Core/Src/meter.o \
|
./Core/Src/meter.o \
|
||||||
|
./Core/Src/power_setpoint_executor.o \
|
||||||
|
./Core/Src/power_setpoint_policy.o \
|
||||||
./Core/Src/psu_control.o \
|
./Core/Src/psu_control.o \
|
||||||
./Core/Src/rgb_controller.o \
|
./Core/Src/rgb_controller.o \
|
||||||
./Core/Src/rtc.o \
|
./Core/Src/rtc.o \
|
||||||
@@ -99,7 +105,7 @@ Core/Src/%.o Core/Src/%.su Core/Src/%.cyclo: ../Core/Src/%.c Core/Src/subdir.mk
|
|||||||
clean: clean-Core-2f-Src
|
clean: clean-Core-2f-Src
|
||||||
|
|
||||||
clean-Core-2f-Src:
|
clean-Core-2f-Src:
|
||||||
-$(RM) ./Core/Src/adc.cyclo ./Core/Src/adc.d ./Core/Src/adc.o ./Core/Src/adc.su ./Core/Src/board.cyclo ./Core/Src/board.d ./Core/Src/board.o ./Core/Src/board.su ./Core/Src/can.cyclo ./Core/Src/can.d ./Core/Src/can.o ./Core/Src/can.su ./Core/Src/charger_control.cyclo ./Core/Src/charger_control.d ./Core/Src/charger_control.o ./Core/Src/charger_control.su ./Core/Src/cp.cyclo ./Core/Src/cp.d ./Core/Src/cp.o ./Core/Src/cp.su ./Core/Src/crc.cyclo ./Core/Src/crc.d ./Core/Src/crc.o ./Core/Src/crc.su ./Core/Src/debug.cyclo ./Core/Src/debug.d ./Core/Src/debug.o ./Core/Src/debug.su ./Core/Src/dma.cyclo ./Core/Src/dma.d ./Core/Src/dma.o ./Core/Src/dma.su ./Core/Src/fire_alarm.cyclo ./Core/Src/fire_alarm.d ./Core/Src/fire_alarm.o ./Core/Src/fire_alarm.su ./Core/Src/gpio.cyclo ./Core/Src/gpio.d ./Core/Src/gpio.o ./Core/Src/gpio.su ./Core/Src/main.cyclo ./Core/Src/main.d ./Core/Src/main.o ./Core/Src/main.su ./Core/Src/meter.cyclo ./Core/Src/meter.d ./Core/Src/meter.o ./Core/Src/meter.su ./Core/Src/psu_control.cyclo ./Core/Src/psu_control.d ./Core/Src/psu_control.o ./Core/Src/psu_control.su ./Core/Src/rgb_controller.cyclo ./Core/Src/rgb_controller.d ./Core/Src/rgb_controller.o ./Core/Src/rgb_controller.su ./Core/Src/rtc.cyclo ./Core/Src/rtc.d ./Core/Src/rtc.o ./Core/Src/rtc.su ./Core/Src/serial.cyclo ./Core/Src/serial.d ./Core/Src/serial.o ./Core/Src/serial.su ./Core/Src/serial_control.cyclo ./Core/Src/serial_control.d ./Core/Src/serial_control.o ./Core/Src/serial_control.su ./Core/Src/serial_handler.cyclo ./Core/Src/serial_handler.d ./Core/Src/serial_handler.o ./Core/Src/serial_handler.su ./Core/Src/sma_filter.cyclo ./Core/Src/sma_filter.d ./Core/Src/sma_filter.o ./Core/Src/sma_filter.su ./Core/Src/soft_rtc.cyclo ./Core/Src/soft_rtc.d ./Core/Src/soft_rtc.o ./Core/Src/soft_rtc.su ./Core/Src/stm32f1xx_hal_msp.cyclo ./Core/Src/stm32f1xx_hal_msp.d ./Core/Src/stm32f1xx_hal_msp.o ./Core/Src/stm32f1xx_hal_msp.su ./Core/Src/stm32f1xx_it.cyclo ./Core/Src/stm32f1xx_it.d ./Core/Src/stm32f1xx_it.o ./Core/Src/stm32f1xx_it.su ./Core/Src/syscalls.cyclo ./Core/Src/syscalls.d ./Core/Src/syscalls.o ./Core/Src/syscalls.su ./Core/Src/sysmem.cyclo ./Core/Src/sysmem.d ./Core/Src/sysmem.o ./Core/Src/sysmem.su ./Core/Src/system_stm32f1xx.cyclo ./Core/Src/system_stm32f1xx.d ./Core/Src/system_stm32f1xx.o ./Core/Src/system_stm32f1xx.su ./Core/Src/tim.cyclo ./Core/Src/tim.d ./Core/Src/tim.o ./Core/Src/tim.su ./Core/Src/usart.cyclo ./Core/Src/usart.d ./Core/Src/usart.o ./Core/Src/usart.su
|
-$(RM) ./Core/Src/adc.cyclo ./Core/Src/adc.d ./Core/Src/adc.o ./Core/Src/adc.su ./Core/Src/board.cyclo ./Core/Src/board.d ./Core/Src/board.o ./Core/Src/board.su ./Core/Src/can.cyclo ./Core/Src/can.d ./Core/Src/can.o ./Core/Src/can.su ./Core/Src/charger_control.cyclo ./Core/Src/charger_control.d ./Core/Src/charger_control.o ./Core/Src/charger_control.su ./Core/Src/cp.cyclo ./Core/Src/cp.d ./Core/Src/cp.o ./Core/Src/cp.su ./Core/Src/crc.cyclo ./Core/Src/crc.d ./Core/Src/crc.o ./Core/Src/crc.su ./Core/Src/debug.cyclo ./Core/Src/debug.d ./Core/Src/debug.o ./Core/Src/debug.su ./Core/Src/dma.cyclo ./Core/Src/dma.d ./Core/Src/dma.o ./Core/Src/dma.su ./Core/Src/fire_alarm.cyclo ./Core/Src/fire_alarm.d ./Core/Src/fire_alarm.o ./Core/Src/fire_alarm.su ./Core/Src/gpio.cyclo ./Core/Src/gpio.d ./Core/Src/gpio.o ./Core/Src/gpio.su ./Core/Src/main.cyclo ./Core/Src/main.d ./Core/Src/main.o ./Core/Src/main.su ./Core/Src/meter.cyclo ./Core/Src/meter.d ./Core/Src/meter.o ./Core/Src/meter.su ./Core/Src/power_setpoint_executor.cyclo ./Core/Src/power_setpoint_executor.d ./Core/Src/power_setpoint_executor.o ./Core/Src/power_setpoint_executor.su ./Core/Src/power_setpoint_policy.cyclo ./Core/Src/power_setpoint_policy.d ./Core/Src/power_setpoint_policy.o ./Core/Src/power_setpoint_policy.su ./Core/Src/psu_control.cyclo ./Core/Src/psu_control.d ./Core/Src/psu_control.o ./Core/Src/psu_control.su ./Core/Src/rgb_controller.cyclo ./Core/Src/rgb_controller.d ./Core/Src/rgb_controller.o ./Core/Src/rgb_controller.su ./Core/Src/rtc.cyclo ./Core/Src/rtc.d ./Core/Src/rtc.o ./Core/Src/rtc.su ./Core/Src/serial.cyclo ./Core/Src/serial.d ./Core/Src/serial.o ./Core/Src/serial.su ./Core/Src/serial_control.cyclo ./Core/Src/serial_control.d ./Core/Src/serial_control.o ./Core/Src/serial_control.su ./Core/Src/serial_handler.cyclo ./Core/Src/serial_handler.d ./Core/Src/serial_handler.o ./Core/Src/serial_handler.su ./Core/Src/sma_filter.cyclo ./Core/Src/sma_filter.d ./Core/Src/sma_filter.o ./Core/Src/sma_filter.su ./Core/Src/soft_rtc.cyclo ./Core/Src/soft_rtc.d ./Core/Src/soft_rtc.o ./Core/Src/soft_rtc.su ./Core/Src/stm32f1xx_hal_msp.cyclo ./Core/Src/stm32f1xx_hal_msp.d ./Core/Src/stm32f1xx_hal_msp.o ./Core/Src/stm32f1xx_hal_msp.su ./Core/Src/stm32f1xx_it.cyclo ./Core/Src/stm32f1xx_it.d ./Core/Src/stm32f1xx_it.o ./Core/Src/stm32f1xx_it.su ./Core/Src/syscalls.cyclo ./Core/Src/syscalls.d ./Core/Src/syscalls.o ./Core/Src/syscalls.su ./Core/Src/sysmem.cyclo ./Core/Src/sysmem.d ./Core/Src/sysmem.o ./Core/Src/sysmem.su ./Core/Src/system_stm32f1xx.cyclo ./Core/Src/system_stm32f1xx.d ./Core/Src/system_stm32f1xx.o ./Core/Src/system_stm32f1xx.su ./Core/Src/tim.cyclo ./Core/Src/tim.d ./Core/Src/tim.o ./Core/Src/tim.su ./Core/Src/usart.cyclo ./Core/Src/usart.d ./Core/Src/usart.o ./Core/Src/usart.su
|
||||||
|
|
||||||
.PHONY: clean-Core-2f-Src
|
.PHONY: clean-Core-2f-Src
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user