feat: LLC_48V v1 20260625
EPWM ok
This commit is contained in:
@@ -36,13 +36,14 @@ extern "C"
|
||||
#define VBUS_SET_H (VBUS_SET + 20) // burst mode in, 在過零區判斷
|
||||
#define VBUS_SET_L (VBUS_SET - 20) // burst mode out, 在過零區判斷
|
||||
// #define VBUS_SET_H2 370 // for skip mode
|
||||
#define VBUS_OVP 420 // 420V 電容
|
||||
#define VBUS_2ADC 149.15f // 4M + 27K
|
||||
#define VCOMP_2DUTY 0 // vbus_comp control duty
|
||||
#define V_COMP_MAX 16000 // (PFC_DUTY_MAX * 32) // 480 * 32 = 16360
|
||||
#define V_COMP_MIN 300 // (PFC_DUTY_MAX * 32) // 12 * 32 = 384
|
||||
#define V_INT_GAIN_BIT 9 // 7=/128, 9=/512 大約除 120 ~ 500 之間 (粗調用bit, 細調用整數)
|
||||
#define V_POR_GAIN_BIT 8 // 6=/64, 8=/256 大約除 60 ~ 250 之間
|
||||
#define VBUS_OVP 72
|
||||
#define VBUS_UVP 36
|
||||
#define VBUS_2ADC 24.81f // 100K + 4.2K
|
||||
#define VCOMP_2DUTY 0 // vbus_comp control duty
|
||||
#define V_COMP_MAX 16000 // (PFC_DUTY_MAX * 32) // 480 * 32 = 16360
|
||||
#define V_COMP_MIN 300 // (PFC_DUTY_MAX * 32) // 12 * 32 = 384
|
||||
#define V_INT_GAIN_BIT 9 // 7=/128, 9=/512 大約除 120 ~ 500 之間 (粗調用bit, 細調用整數)
|
||||
#define V_POR_GAIN_BIT 8 // 6=/64, 8=/256 大約除 60 ~ 250 之間
|
||||
#define VBUS_INT_MAX (V_COMP_MAX << V_INT_GAIN_BIT)
|
||||
#define VBUS_POR_MAX (V_COMP_MAX << (V_POR_GAIN_BIT - 1))
|
||||
//---------------------------------------------------------------
|
||||
|
||||
@@ -13,120 +13,38 @@
|
||||
//=============================================================================
|
||||
// Public Function Definition
|
||||
//=============================================================================
|
||||
#if 0
|
||||
static void
|
||||
_Pre_Proc(PWR_ModeTypeDef pwr_mode, PWR_WakeupTypeDef *pWakeup_type)
|
||||
{
|
||||
{ /* User terminates proprietary modules */
|
||||
sys_disable_systick();
|
||||
syslog_deinit();
|
||||
}
|
||||
|
||||
// Configure WDG to wake-up system
|
||||
WDG_InitTypeDef init = {0};
|
||||
uint32_t g_wakeup_msec = 5000;
|
||||
|
||||
SYSCFG_SetLSIAlwaysOn(true);
|
||||
|
||||
*pWakeup_type = PWR_Wakeup_WDG;
|
||||
|
||||
init.Counter = WDG_MSec2Counter(g_wakeup_msec);
|
||||
init.ResetMode = WDG_Reset_Disable;
|
||||
WDG_Init(&init);
|
||||
|
||||
WDG_Enable();
|
||||
|
||||
SYSCFG_SetICEPin2NormalIO(true);
|
||||
return;
|
||||
}
|
||||
//===========================================================================
|
||||
static void
|
||||
_Post_Proc(PWR_ModeTypeDef pwr_mode)
|
||||
{
|
||||
// Recover wake-up module
|
||||
SYSCFG_SetLSIAlwaysOn(false);
|
||||
__HAL_SYSCFG_RESET_GPIOA();
|
||||
__HAL_SYSCFG_RESET_GPIOB();
|
||||
WDG_DeInit();
|
||||
|
||||
/* Enable ICE I/O */
|
||||
SYSCFG_SetICEPin2NormalIO(false);
|
||||
|
||||
sys_config_systick(SYS_TICK_1_MS);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
//===================================================================================
|
||||
void gpio_init(void)
|
||||
{
|
||||
GPIO_InitTypeDef gpio_init = { 0 };
|
||||
|
||||
// PA12(vfb)(vcomp)
|
||||
// PA12, PWOK
|
||||
gpio_init.GPIO_Pin = GPIO_Pin_12;
|
||||
gpio_init.GPIO_Mode = GPIO_Mode_IN;
|
||||
gpio_init.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(GPIOA, &gpio_init);
|
||||
|
||||
// PA15(button)
|
||||
gpio_init.GPIO_Pin = GPIO_Pin_15;
|
||||
gpio_init.GPIO_Mode = GPIO_Mode_IN;
|
||||
gpio_init.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_Init(GPIOA, &gpio_init);
|
||||
|
||||
#if 0 // 取消了
|
||||
// PA5(TP1)
|
||||
// PA6(TP2)
|
||||
gpio_init.GPIO_Pin = GPIO_Pin_05;
|
||||
gpio_init.GPIO_Pin |= GPIO_Pin_06;
|
||||
gpio_init.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_Init(GPIOA, &gpio_init);
|
||||
#endif
|
||||
}
|
||||
//===================================================================================
|
||||
void opa_init(void)
|
||||
{
|
||||
// gpio
|
||||
GPIO_InitTypeDef gpio_init = { 0 };
|
||||
gpio_init.GPIO_Pin = GPIO_Pin_07 | GPIO_Pin_08; // Pin_09 is set as power_ok
|
||||
gpio_init.GPIO_Mode = GPIO_Mode_ANAL;
|
||||
gpio_init.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(GPIOA, &gpio_init);
|
||||
|
||||
// opa
|
||||
OPAMP_InitTypeDef opa_init = { 0 };
|
||||
opa_init.OPAMP_VinP = OPAMP_VinP_IO; // PA8
|
||||
opa_init.OPAMP_VinM = OPAMP_VinM_GND; // internal GND, PIN 留給 POWER_OK
|
||||
opa_init.OPAMP_Vout = OPAMP_Vout_IO; // PA7, 拉到 IO PA7,需要外部 500 ~ 1000pF 電容
|
||||
opa_init.OPAMP_Gain = OPAMP_PGAGain_15; // x1~x16 as needed, 使用 15 倍, 減少 RS 功耗
|
||||
OPAMP_Init(OPAMP0, &opa_init);
|
||||
OPAMP_Enable(OPAMP0);
|
||||
}
|
||||
//===================================================================================
|
||||
void adc_init(void)
|
||||
{
|
||||
// gpio
|
||||
GPIO_InitTypeDef gpio_init;
|
||||
gpio_init.GPIO_Pin = GPIO_Pin_10; // vbus = PA10(AIN4)
|
||||
gpio_init.GPIO_Pin |= GPIO_Pin_07; // iac = PA7(AIN9)
|
||||
gpio_init.GPIO_Pin |= GPIO_Pin_13; // vac = PA13(AIN7)
|
||||
gpio_init.GPIO_Pin |= GPIO_Pin_11; // vcr = PA11(AIN5)
|
||||
gpio_init.GPIO_Pin = GPIO_Pin_08; // PA8 AIN2 VBUS
|
||||
gpio_init.GPIO_Pin |= GPIO_Pin_09; // PA9 AIN3 IP_CS
|
||||
gpio_init.GPIO_Pin |= GPIO_Pin_10; // PA10 AIN4 VCOMP
|
||||
gpio_init.GPIO_Mode = GPIO_Mode_ANAL;
|
||||
GPIO_Init(GPIOA, &gpio_init);
|
||||
|
||||
// adc
|
||||
ADC_InitTypeDef adc_init = { 0 };
|
||||
ADC_StructInit(&adc_init);
|
||||
adc_init.SelChannels = ADC_Channel_04;
|
||||
adc_init.SelChannels |= ADC_Channel_09; // 量測外部 PA7
|
||||
// adc_init.SelChannels |= ADC_Channel_00; // 若是讀取 PGA0 輸出的 AIN0 通道, 要改成 ADC_Channel_00
|
||||
adc_init.SelChannels |= ADC_Channel_07;
|
||||
adc_init.SelChannels |= ADC_Channel_05;
|
||||
adc_init.SelChannels = ADC_Channel_02;
|
||||
adc_init.SelChannels |= ADC_Channel_03;
|
||||
adc_init.SelChannels |= ADC_Channel_04;
|
||||
adc_init.ClkPrescaler = ADC_ClkDiv_4; // 60M/4 = 15MHz, ADC max working clock is 16MHz
|
||||
adc_init.DataAlign = ADC_DataAlign_Right;
|
||||
adc_init.Mode = ADC_Mode_Scan; // Scan mode
|
||||
ADC_Init(ADC0, &adc_init);
|
||||
ADC_ExtTrigConfig(ADC0, ADC_ExtTrigSource_TIM0, ADC_ExtTrigMode_Enable); // tim0 trigger adc
|
||||
ADC_ExtTrigConfig(ADC0, ADC_ExtTrigSource_EPWM_CH1R, ADC_ExtTrigMode_Enable);
|
||||
|
||||
// ADC interrupt config
|
||||
sys_irq_attr_t irq_attr = {
|
||||
@@ -188,46 +106,6 @@ void llc_pwm_init(void)
|
||||
TIM_CtrlPWMOutputs(EPWM, ENABLE);
|
||||
EPWM->CCMR1_OUTPUT_b.OC1PE = 1; // Output Compare 1 preload enable
|
||||
}
|
||||
//===================================================================================
|
||||
void pfc_pwm_init(void) // single PWM for PFC
|
||||
{
|
||||
// gpio
|
||||
// PA2(TIM2_CH1)
|
||||
GPIO_InitTypeDef gpio_init = {
|
||||
.GPIO_Pin = GPIO_Pin_02,
|
||||
.GPIO_Mode = GPIO_Mode_AF,
|
||||
.GPIO_AF_Mode = GPIO_AF_5,
|
||||
};
|
||||
GPIO_Init(GPIOA, &gpio_init);
|
||||
|
||||
// tim
|
||||
TIM_TimeBaseInitTypeDef tim_init = {
|
||||
.TIM_Prescaler = 0,
|
||||
.TIM_CounterMode = TIM_CounterMode_Up,
|
||||
.TIM_Period = PFC_PERIOD,
|
||||
.TIM_ClockDivision = TIM_CKD_Div1,
|
||||
.TIM_RepetitionCounter = 0,
|
||||
};
|
||||
TIM_DeInit(TIM2);
|
||||
TIM_TimeBaseInit(TIM2, &tim_init);
|
||||
|
||||
TIM_ARRPreloadConfig(TIM2, ENABLE);
|
||||
|
||||
// pwm
|
||||
TIM_OCInitTypeDef pwm_init = {
|
||||
.TIM_OCMode = TIM_OCMode_PWM1,
|
||||
.TIM_OutputState = TIM_OutputState_Disable,
|
||||
.TIM_OCPolarity = TIM_OCPolarity_High,
|
||||
.TIM_OCIdleState = TIM_OCIdleState_Reset,
|
||||
.TIM_Pulse = 1,
|
||||
};
|
||||
TIM_OC1Init(TIM2, &pwm_init);
|
||||
|
||||
TIM_Cmd(TIM2, ENABLE); // enable PWM
|
||||
TIM_CtrlPWMOutputs(TIM2, ENABLE); // enable PWM output
|
||||
TIM2->CCMR1_OUTPUT_b.OC1PE = 1; // Output Compare 1 preload enable
|
||||
}
|
||||
|
||||
//===================================================================================
|
||||
void tim0_init(void)
|
||||
{
|
||||
@@ -255,19 +133,12 @@ void sysclk_init(void)
|
||||
void SYS_Config(void)
|
||||
{
|
||||
sysclk_init();
|
||||
// PWR_EnterDeepSleepMode(_Pre_Proc, _Post_Proc); // use WDG wake up 1 sec
|
||||
|
||||
gpio_init();
|
||||
opa_init();
|
||||
|
||||
adc_init();
|
||||
llc_pwm_init(); // 初始化但不輸出 EPWM_CH1
|
||||
pfc_pwm_init(); // 初始化但不輸出 TIM2_CH1
|
||||
|
||||
__NOP();
|
||||
__NOP();
|
||||
__NOP();
|
||||
__NOP();
|
||||
__NOP(); // timer shift between pfc and tim0
|
||||
llc_pwm_init();
|
||||
|
||||
tim0_init(); // trigger ADC, current loop frequency
|
||||
uart_init();
|
||||
}
|
||||
|
||||
@@ -24,23 +24,12 @@
|
||||
//=============================================================================
|
||||
// Structure Definition
|
||||
//=============================================================================
|
||||
typedef enum
|
||||
{
|
||||
KEY_IDLE = 0,
|
||||
KEY_DOWN,
|
||||
KEY_WAIT_RELEASE
|
||||
} KeyState_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STATE_INIT,
|
||||
STATE_STANDBY, // 等 AC brown-in
|
||||
STATE_PFC_SOFT_START, // 第一階段:PFC 透過最小 duty 提升 vbus,若 vbus 足夠,直接進入下一階段
|
||||
STATE_LLC_SOFT_START, // 第二階段:LLC 掃頻
|
||||
STATE_RUN_NORMAL, // 第三階段:二級都進入穩態閉環
|
||||
STATE_RUN_SKIP, // 第四階段:負載太小,暫時關閉 PFC
|
||||
STATE_FAULT, // 故障保護
|
||||
STATE_PAUSE // 暫停,測試用
|
||||
STATE_STOP,
|
||||
STATE_SS,
|
||||
STATE_RUN
|
||||
} SystemState_t;
|
||||
|
||||
typedef struct
|
||||
@@ -68,21 +57,17 @@ typedef struct
|
||||
// int32_t a1 = 128; // -A1(因為通常寫成 u[k] = ... + A1*u[k-1] + A2*u[k-2],這裡 a1 = 128 代表 A1 ≈ 1)
|
||||
// int32_t a2 = 0; // -A2(PID 特例時 a2 常為 0)
|
||||
|
||||
SystemState_t sys_state = STATE_INIT;
|
||||
SystemState_t sys_state = STATE_STOP;
|
||||
uint8_t is_zero_crossing = 0;
|
||||
static uint8_t last_is_zero_crossing = 0;
|
||||
|
||||
uint8_t llc_running = 0;
|
||||
uint8_t pfc_running = 0;
|
||||
uint8_t is_brown_in = 0; // 0: 關機/保護中, 1: 正常工作
|
||||
static uint8_t cur_loop_fun_en = 0;
|
||||
|
||||
// static volatile int32_t print1, print2;
|
||||
// static volatile int64_t print3;
|
||||
|
||||
static uint16_t iac = 0;
|
||||
static uint16_t vac = 0;
|
||||
static uint16_t vbus = 0;
|
||||
static uint16_t vcr = 0;
|
||||
static uint16_t ipcs = 0;
|
||||
static uint16_t vcomp = 0;
|
||||
|
||||
static int32_t vcr_x1_q14 = 0; // x[n-1]
|
||||
static int32_t vcr_y1_q14 = 0; // y[n-1]
|
||||
@@ -91,30 +76,25 @@ static int32_t cr_feed_forward_output_q14 = 0; // 最終輸出的 Q14 補償量
|
||||
uint32_t count1;
|
||||
|
||||
uint32_t vbus_ovp = (VBUS_OVP * 4096 / VBUS_2ADC / 3.3);
|
||||
uint32_t vbus_set = (VBUS_SET * 4096 / VBUS_2ADC / 3.3);
|
||||
uint32_t vbus_set_h = (VBUS_SET_H * 4096 / VBUS_2ADC / 3.3); // burst mode in
|
||||
uint32_t vbus_set_l = (VBUS_SET_L * 4096 / VBUS_2ADC / 3.3); // burst mode out
|
||||
uint32_t vbus_uvp = (VBUS_UVP * 4096 / VBUS_2ADC / 3.3);
|
||||
|
||||
uint32_t digi_vcomp_max = (LLC_PERIOD_MAX - LLC_PERIOD_MIN) << LLC_COMP_GAIN_BIT;
|
||||
int32_t vbus_comp2 = 0; // 過零點用
|
||||
uint16_t llc_ss_cnt = 0;
|
||||
//-----------------------------------------------
|
||||
KeyState_t key1State = KEY_IDLE;
|
||||
uint32_t key1Timer = 0;
|
||||
uint8_t key1_action = 0;
|
||||
uint8_t keyInput;
|
||||
//-----------------------------------------------
|
||||
|
||||
uint8_t power_on_cmd = 0;
|
||||
uint32_t vac_avg1;
|
||||
uint32_t vbus_avg = 0;
|
||||
uint32_t vcr_avg;
|
||||
static volatile uint16_t vac_pk1, vac_pk2;
|
||||
uint32_t vcomp_avg;
|
||||
|
||||
uint32_t static digital_vcomp = (LLC_PERIOD_MAX - LLC_PERIOD_MIN) << LLC_COMP_GAIN_BIT;
|
||||
uint16_t llc_period_ss = LLC_SS_MIN;
|
||||
uint16_t llc_run_arr = LLC_PERIOD_MIN;
|
||||
uint8_t v_loop_cnt = 0;
|
||||
uint8_t v_loop_cnt2 = 0;
|
||||
|
||||
uint8_t volatile tim0_trigger = 0;
|
||||
uint8_t volatile adc_trigger = 0;
|
||||
|
||||
// 全局或靜態變數(需在函數外或 static 保留狀態)
|
||||
static int32_t iac_err_1 = 0; // e[k-1]
|
||||
@@ -144,7 +124,7 @@ uint16_t capture_packet_gap_ms = 1000;
|
||||
void A_Para_Reset()
|
||||
{
|
||||
digital_vcomp = (LLC_PERIOD_MAX - LLC_PERIOD_MIN) << LLC_COMP_GAIN_BIT;
|
||||
vbus_set = (VBUS_SET * 4096 / VBUS_2ADC / 3.3);
|
||||
// vbus_set = (VBUS_SET * 4096 / VBUS_2ADC / 3.3);
|
||||
v_loop_cnt = 0;
|
||||
|
||||
iac_err_1 = 0;
|
||||
@@ -164,46 +144,6 @@ void A_Para_Reset()
|
||||
pfc_running = 0;
|
||||
llc_running = 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Key1_Scan()
|
||||
{
|
||||
keyInput = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15);
|
||||
|
||||
switch (key1State)
|
||||
{
|
||||
case KEY_IDLE:
|
||||
if (keyInput == 0)
|
||||
{ // 剛按下
|
||||
key1Timer = sys_get_tick(); // 紀錄時間
|
||||
key1State = KEY_DOWN;
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_DOWN:
|
||||
if (keyInput == 0)
|
||||
{
|
||||
if (sys_get_tick() - key1Timer >= DEBOUNCE_TIME)
|
||||
{
|
||||
key1State = KEY_WAIT_RELEASE; // 完成去抖
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
key1State = KEY_IDLE; // 回到 IDLE
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_WAIT_RELEASE:
|
||||
if (keyInput == 1)
|
||||
{ // 剛放開
|
||||
key1Timer = sys_get_tick();
|
||||
key1State = KEY_IDLE;
|
||||
key1_action = 1; // 執行動作
|
||||
Key_Action();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
void capture_start(void)
|
||||
{
|
||||
@@ -223,10 +163,10 @@ static inline void Capture_Sample_ISR(void)
|
||||
return;
|
||||
|
||||
// capture_buf[idx].timestamp = sys_get_tick();
|
||||
capture_buf[idx].iac = iac;
|
||||
// capture_buf[idx].vac = vac;
|
||||
// capture_buf[idx].vbus = vbus;
|
||||
// capture_buf[idx].vcr = vcr;
|
||||
// capture_buf[idx].iac = iac;
|
||||
// capture_buf[idx].vac = vac;
|
||||
// capture_buf[idx].vbus = vbus;
|
||||
// capture_buf[idx].vcr = vcr;
|
||||
|
||||
idx++;
|
||||
capture_idx = idx;
|
||||
@@ -259,38 +199,6 @@ static void Capture_Dump_IfReady(void)
|
||||
msg("capture done,count=%d\r\n", CAPTURE_BUF_SIZE);
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
void Key_Action()
|
||||
{
|
||||
if (power_on_cmd == 0)
|
||||
{
|
||||
power_on_cmd = 1;
|
||||
// A_Para_Reset();
|
||||
// Power_On();
|
||||
}
|
||||
else
|
||||
{
|
||||
power_on_cmd = 0;
|
||||
Power_Off();
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
void Power_On()
|
||||
{
|
||||
power_on_cmd = 1;
|
||||
llc_pwm_enable(); // LLC ON first
|
||||
pfc_pwm_enable();
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
void Power_Off()
|
||||
{
|
||||
power_on_cmd = 0;
|
||||
pfc_pwm_disable(); // PFC OF first
|
||||
sys_delay(2000); // discharge
|
||||
llc_pwm_disable();
|
||||
sys_state = STATE_PAUSE;
|
||||
A_Para_Reset();
|
||||
}
|
||||
//===================================================================================
|
||||
void llc_set_period(uint16_t val)
|
||||
{
|
||||
if (val > LLC_PERIOD_MAX) val = LLC_PERIOD_MAX; // 可以小,不能過大
|
||||
@@ -298,13 +206,6 @@ void llc_set_period(uint16_t val)
|
||||
EPWM->CCR1 = val >> 1;
|
||||
}
|
||||
//===================================================================================
|
||||
void pfc_set_duty(uint16_t val)
|
||||
{
|
||||
if (val > PFC_DUTY_MAX) val = PFC_DUTY_MAX;
|
||||
if (val < PFC_DUTY_MIN) val = PFC_DUTY_MIN;
|
||||
TIM2->CCR1 = val;
|
||||
}
|
||||
//===================================================================================
|
||||
void llc_pwm_enable()
|
||||
{
|
||||
REG_SET_BITS(EPWM->CCER, TIM_CCER_CC1E_Msk | TIM_CCER_CC1NE_Msk);
|
||||
@@ -315,16 +216,6 @@ void llc_pwm_disable()
|
||||
REG_CLR_BITS(EPWM->CCER, TIM_CCER_CC1E_Msk | TIM_CCER_CC1NE_Msk);
|
||||
}
|
||||
//===================================================================================
|
||||
void pfc_pwm_enable()
|
||||
{
|
||||
REG_SET_BITS(TIM2->CCER, TIM_CCER_CC1E_Msk);
|
||||
}
|
||||
//===================================================================================
|
||||
void pfc_pwm_disable()
|
||||
{
|
||||
REG_CLR_BITS(TIM2->CCER, TIM_CCER_CC1E_Msk);
|
||||
}
|
||||
//======================================================================================
|
||||
// Cr 1P1Z 回授,做負載驟變補償,執行頻率 10KHZ
|
||||
// 抓取 vcr 的動態變化趨勢,並在穩態時回歸平靜
|
||||
void Load_Loop_1P1Z(void)
|
||||
@@ -334,7 +225,7 @@ void Load_Loop_1P1Z(void)
|
||||
int32_t y0;
|
||||
|
||||
// 1. 讀取當前 vcr
|
||||
x0 = vcr_avg;
|
||||
// x0 = vcr_avg;
|
||||
|
||||
// 2. 執行 1P1Z 差分方程計算:
|
||||
temp_y0 = ((int64_t)CR_1P1Z_B0_Q14 * x0) + ((int64_t)CR_1P1Z_B1_Q14 * vcr_x1_q14) - ((int64_t)CR_1P1Z_A1_Q14 * vcr_y1_q14);
|
||||
@@ -358,7 +249,7 @@ void Load_Loop_1P1Z(void)
|
||||
void Vol_Loop_PFC_1P1Z(void)
|
||||
{
|
||||
// 1. 計算誤差
|
||||
int32_t vbus_err_n = (int32_t)vbus_set - (int32_t)vbus_avg;
|
||||
int32_t vbus_err_n; // = (int32_t)vbus_set - (int32_t)vbus_avg;
|
||||
|
||||
// --- 策略 A:動態增益調整 ---
|
||||
int32_t b0 = 139;
|
||||
@@ -368,15 +259,15 @@ void Vol_Loop_PFC_1P1Z(void)
|
||||
// vloop_p->b1 = -129;
|
||||
// vloop_p->a1 = -16383;
|
||||
/*
|
||||
if (vbus_err_n > 40 || vbus_err_n < -40) // ~ 20V
|
||||
if (vbus_err_n > 40 || vbus_err_n < -40) // ~ 20V
|
||||
{
|
||||
// 大誤差時(通常是剛啟動或大跳載),強化參數加快反應
|
||||
//b0 = 250;
|
||||
//b1 = -249;
|
||||
//b0 = 180; // 稍微調降強增益的力道
|
||||
//b1 = -178;
|
||||
b0 = 500;
|
||||
b1 = -499;
|
||||
// b0 = 250;
|
||||
// b1 = -249;
|
||||
// b0 = 180; // 稍微調降強增益的力道
|
||||
// b1 = -178;
|
||||
b0 = 500;
|
||||
b1 = -499;
|
||||
}
|
||||
// --- 策略 B:接近目標時微調零點 (抗過衝) ---
|
||||
else if (vbus_err_n < 20 && vbus_err_n > -20) // ~ 5V
|
||||
@@ -386,6 +277,7 @@ void Vol_Loop_PFC_1P1Z(void)
|
||||
b1 = -119; // 如果不能用浮點數,請維持 120 / -119,增加阻尼感
|
||||
}
|
||||
*/
|
||||
|
||||
// 2. 差分方程計算
|
||||
int64_t acc = (int64_t)b0 * vbus_err_n;
|
||||
acc += (int64_t)b1 * vbus_err_1;
|
||||
@@ -394,24 +286,24 @@ void Vol_Loop_PFC_1P1Z(void)
|
||||
int32_t y_n = (int32_t)acc;
|
||||
|
||||
#if 0 // 有問題
|
||||
// --- 策略 C:軟限制抗過衝 (Soft Clamping) ---
|
||||
// 預設最大限制 (Duty 300 << 14)
|
||||
int32_t current_max_limit = 4915200; // duty 300
|
||||
// --- 策略 C:軟限制抗過衝 (Soft Clamping) ---
|
||||
// 預設最大限制 (Duty 300 << 14)
|
||||
int32_t current_max_limit = 4915200; // duty 300
|
||||
|
||||
// 如果電壓誤差已經很小(例如剩 15V 就到達),甚至已經發生過衝 (err < 0)
|
||||
// 我們強制壓低 Duty 的允許上限,防止積分器帶著大 Duty 衝過頭
|
||||
if (vbus_err_n < 15)
|
||||
{
|
||||
// 這裡的 3276800 對應 Duty 200,您可以根據 800W 穩態時的 Duty 大約位置來設定
|
||||
// 核心目標是:不讓 Duty 在接近目標時還維持在 300 這麼高
|
||||
current_max_limit = 3276800; // duty 200
|
||||
}
|
||||
// 如果電壓誤差已經很小(例如剩 15V 就到達),甚至已經發生過衝 (err < 0)
|
||||
// 我們強制壓低 Duty 的允許上限,防止積分器帶著大 Duty 衝過頭
|
||||
if (vbus_err_n < 15)
|
||||
{
|
||||
// 這裡的 3276800 對應 Duty 200,您可以根據 800W 穩態時的 Duty 大約位置來設定
|
||||
// 核心目標是:不讓 Duty 在接近目標時還維持在 300 這麼高
|
||||
current_max_limit = 3276800; // duty 200
|
||||
}
|
||||
|
||||
// 如果發生明顯過衝 (電壓高於目標 5V 以上)
|
||||
if (vbus_err_n < -5)
|
||||
{
|
||||
current_max_limit = 1638400; // 強制壓低到 Duty 100 快速拉回
|
||||
}
|
||||
// 如果發生明顯過衝 (電壓高於目標 5V 以上)
|
||||
if (vbus_err_n < -5)
|
||||
{
|
||||
current_max_limit = 1638400; // 強制壓低到 Duty 100 快速拉回
|
||||
}
|
||||
#endif
|
||||
|
||||
// 3. 輸出限幅執行
|
||||
@@ -425,8 +317,8 @@ void Vol_Loop_PFC_1P1Z(void)
|
||||
vbus_comp_1 = y_n;
|
||||
|
||||
// 5. 輸出 Duty >> 14
|
||||
if (sys_state == STATE_PFC_SOFT_START || sys_state == STATE_RUN_SKIP) // 緩啟動期間直接控制 DUTY
|
||||
TIM2->CCR1 = (vbus_comp_1 >> 14); // 0 ~ 540
|
||||
// if (sys_state == STATE_PFC_SOFT_START || sys_state == STATE_RUN_SKIP) // 緩啟動期間直接控制 DUTY
|
||||
TIM2->CCR1 = (vbus_comp_1 >> 14); // 0 ~ 540
|
||||
|
||||
// 6. 輸出 comp >> 9 (變大 32 倍) (MAX ~ 18000) (540*32=17280)差不多,>> 9 應該是對的
|
||||
// if (sys_state == STATE_RUN_NORMAL) // 正常工作時間輸出 COMP 值
|
||||
@@ -437,7 +329,7 @@ void Vol_Loop_PFC_1P1Z(void)
|
||||
static void Vol_Loop_PFC_1P1Z_UI(void) // ZERO: 120HZ, POLE:0.1HZ, G:10
|
||||
{
|
||||
// 1. 計算誤差
|
||||
int32_t vbus_err_0 = (int32_t)vbus_set - (int32_t)vbus_avg;
|
||||
int32_t vbus_err_0; // = (int32_t)vbus_set - (int32_t)vbus_avg;
|
||||
|
||||
// 2. 2P2Z 運算 (Fixed-point Q14)
|
||||
struct bode_plot_param_t *vloop_p = &pfc_vloop_bode_plot_param;
|
||||
@@ -461,8 +353,8 @@ static void Vol_Loop_PFC_1P1Z_UI(void) // ZERO: 120HZ, POLE:0.1HZ, G:10
|
||||
vbus_comp_1 = y_n;
|
||||
|
||||
// 5. 輸出 Duty >> 14
|
||||
if (sys_state == STATE_PFC_SOFT_START || sys_state == STATE_RUN_SKIP) // 緩啟動期間直接控制 DUTY
|
||||
TIM2->CCR1 = (vbus_comp_1 >> 14); // 0 ~ 540
|
||||
// if (sys_state == STATE_PFC_SOFT_START || sys_state == STATE_RUN_SKIP) // 緩啟動期間直接控制 DUTY
|
||||
TIM2->CCR1 = (vbus_comp_1 >> 14); // 0 ~ 540
|
||||
|
||||
// 6. 輸出 comp >> 9 (變大 32 倍) (MAX ~ 18000) (540*32=17280)差不多,>> 9 應該是對的
|
||||
// if (sys_state == STATE_RUN_NORMAL) // 正常工作時間輸出 COMP 值
|
||||
@@ -472,8 +364,8 @@ static void Vol_Loop_PFC_1P1Z_UI(void) // ZERO: 120HZ, POLE:0.1HZ, G:10
|
||||
//========================================================================
|
||||
__attribute__((always_inline)) static inline void Cur_Loop_PFC_2P2Z(void) // 優化後 3.65us
|
||||
{
|
||||
if (sys_state != STATE_RUN_NORMAL)
|
||||
return;
|
||||
// if (sys_state != STATE_RUN_NORMAL)
|
||||
return;
|
||||
|
||||
// if (is_zero_crossing == 1) return; // 凍結積分,改善過零後上升緣的突波
|
||||
|
||||
@@ -482,7 +374,7 @@ __attribute__((always_inline)) static inline void Cur_Loop_PFC_2P2Z(void) // 優
|
||||
int32_t local_vac_avg1 = vac_avg1;
|
||||
|
||||
// 電流採樣處理
|
||||
int32_t local_iac = 3840 - iac; // OPA 電路的關係,實際值為 CURR_OFFSET - ADC
|
||||
int32_t local_iac; // = 3840 - iac; // OPA 電路的關係,實際值為 CURR_OFFSET - ADC
|
||||
if (local_iac < 0)
|
||||
local_iac = 0; // 避免負值
|
||||
|
||||
@@ -609,29 +501,24 @@ __INTERRUPT void isr_adc_handle(void)
|
||||
SAVE_IRQ_CSR_CONTEXT();
|
||||
ADC_ClearITFlag(ADC0);
|
||||
|
||||
// GPIO_SetBits(GPIOA, GPIO_Pin_06);
|
||||
|
||||
tim0_trigger = 1;
|
||||
adc_trigger = 1;
|
||||
|
||||
// get ADC value
|
||||
iac = ADC0->DAT9_b.DATA; // PA7, AIN9
|
||||
vac = ADC0->DAT7_b.DATA; // PA13, AIN7
|
||||
vbus = ADC0->DAT4_b.DATA; // PA10, AIN4
|
||||
vcr = ADC0->DAT5_b.DATA; // PA11, AIN5
|
||||
|
||||
if (cur_loop_fun_en) Cur_Loop_PFC_2P2Z(); // current loop
|
||||
vbus = ADC0->DAT4_b.DATA; // PA10, AIN4
|
||||
ipcs = ADC0->DAT9_b.DATA; // PA7, AIN9
|
||||
vcomp = ADC0->DAT7_b.DATA; // PA13, AIN7
|
||||
|
||||
// if (cur_loop_fun_en) Cur_Loop_PFC_2P2Z(); // current loop
|
||||
/*
|
||||
static uint8_t cnt = 0;
|
||||
if (cnt++ >= 10)
|
||||
{
|
||||
Capture_Sample_ISR();
|
||||
cnt = 0;
|
||||
}
|
||||
|
||||
// GPIO_ResetBits(GPIOA, GPIO_Pin_06);
|
||||
*/
|
||||
|
||||
RESTORE_IRQ_CSR_CONTEXT();
|
||||
return;
|
||||
}
|
||||
//============================================================================
|
||||
void reset_pid_parameters(void)
|
||||
@@ -644,41 +531,6 @@ void reset_pid_parameters(void)
|
||||
digital_vcomp = (LLC_PERIOD_MAX - LLC_PERIOD_MIN) << LLC_COMP_GAIN_BIT;
|
||||
}
|
||||
//================================================================================
|
||||
void Vac_Peak_Detector(void)
|
||||
{
|
||||
// 1. 峰值追蹤 (Peak Detector):只要不在過零區,就持續抓最大值
|
||||
if (vac >= VAC_ZERO)
|
||||
{
|
||||
is_zero_crossing = 0;
|
||||
last_is_zero_crossing = 0;
|
||||
if (vac > vac_pk1) vac_pk1 = vac; // 只有比目前紀錄大才更新,確保 vac_pk1 停在波峰
|
||||
}
|
||||
else
|
||||
{
|
||||
// 2. 進入過零區 (vac < 400)
|
||||
is_zero_crossing = 1;
|
||||
// 3. 邊緣觸發:只在從「非過零」進入「過零」的瞬間交接數據
|
||||
if (last_is_zero_crossing == 0 && vac_pk1 > VAC_ZERO_RISE)
|
||||
{
|
||||
vac_pk2 = vac_pk1; // 這裡的 vac_pk1 必定是剛才半周抓到的最高點
|
||||
|
||||
// --- 新增 Brown-in / Brown-out 判斷邏輯 ---
|
||||
if (is_brown_in == 0)
|
||||
{
|
||||
// 目前處於關閉狀態,檢查是否達到啟動門檻
|
||||
if (vac_pk2 >= VOLT_BROWN_IN) is_brown_in = 1; // 執行 Brown-in
|
||||
}
|
||||
else
|
||||
{
|
||||
// 目前處於啟動狀態,檢查是否低於欠壓門檻
|
||||
if (vac_pk2 < VOLT_BROWN_OUT) is_brown_in = 0; // 執行 Brown-out
|
||||
}
|
||||
|
||||
vac_pk1 = 0; // 交接完後立即清零,為下半周做準備
|
||||
last_is_zero_crossing = 1; // 剛過上升緣
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void uart_rx_task(void)
|
||||
{
|
||||
@@ -722,6 +574,16 @@ static void capture_continuous_task(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
//==============================================================================
|
||||
void Handle_UART_Monitor(void)
|
||||
{
|
||||
static uint32_t msg_timer2 = 0;
|
||||
if (sys_get_tick() - msg_timer2 >= 1000)
|
||||
{
|
||||
printf("%d %d %d", power_on_cmd, sys_state, vbus_comp2);
|
||||
// msg_timer2 = sys_get_tick();
|
||||
}
|
||||
}
|
||||
//=============================================================================
|
||||
// Public Function Definition
|
||||
//=============================================================================
|
||||
@@ -730,221 +592,16 @@ int main(void)
|
||||
struct bode_plot_param_t *cloop_p = &pfc_cloop_bode_plot_param;
|
||||
struct bode_plot_param_t *vloop_p = &pfc_vloop_bode_plot_param;
|
||||
|
||||
// 基礎硬體底層設定 (HIRC 60MHz, GPIO, ADC 採樣率 1Msps) [cite: 55, 127, 184]
|
||||
// system initial configuration
|
||||
SYS_Config();
|
||||
sys_delay(10); // delay 10ms
|
||||
|
||||
// read plot param from flash
|
||||
msg("read plot param from flash\r\n");
|
||||
read_bodeplot_params_from_flash(cloop_p, vloop_p, FLASH_PROG_ADDR_USER_CALI);
|
||||
print_bodeplot_params(cloop_p, vloop_p);
|
||||
|
||||
#if 0 // 單測 PFC 電壓環 (OK)
|
||||
|
||||
// Not used
|
||||
cloop_p->b0 = 0;
|
||||
cloop_p->b1 = 0;
|
||||
cloop_p->b2 = 0;
|
||||
cloop_p->a1 = 0;
|
||||
cloop_p->a2 = 0;
|
||||
|
||||
// 1P1Z 參數: Z=120HZ, P=0.1HZ, G=100 ?
|
||||
vloop_p->b0 = 139;
|
||||
vloop_p->b1 = -129;
|
||||
vloop_p->b2 = 0;
|
||||
vloop_p->a1 = -16383;
|
||||
vloop_p->a2 = 0;
|
||||
print_bodeplot_params(cloop_p, vloop_p);
|
||||
|
||||
cur_loop_fun_en = 0; // 關閉電流環,專測電壓環
|
||||
sys_state = STATE_PFC_SOFT_START;
|
||||
|
||||
while (1)
|
||||
{
|
||||
//uart_rx_task();
|
||||
|
||||
if (tim0_trigger == 1) // 100KHZ
|
||||
{
|
||||
tim0_trigger = 0;
|
||||
// --- 1. 高速信號濾波 (簡易位移算法減少算力消耗) ---
|
||||
vac_avg1 = (vac_avg1 - (vac_avg1 >> 3)) + (vac >> 3); // for current loop
|
||||
vbus_avg = (vbus_avg - (vbus_avg >> 4)) + (vbus >> 4); // for voltage loop
|
||||
vcr_avg = (vcr_avg - (vcr_avg >> 3)) + (vcr >> 3);
|
||||
if (vbus_avg > vbus_ovp) Power_Off(); // ovp
|
||||
|
||||
Vac_Peak_Detector();
|
||||
|
||||
if (power_on_cmd == 1)
|
||||
{
|
||||
if (pfc_running == 0)
|
||||
{
|
||||
pfc_pwm_enable();
|
||||
pfc_running = 1;
|
||||
}
|
||||
|
||||
if (++v_loop_cnt >= 10) // 10KHZ
|
||||
{
|
||||
//Vol_Loop_PFC_1P1Z_UI();
|
||||
Vol_Loop_PFC_1P1Z(); // 800W 板子會低 13V
|
||||
v_loop_cnt = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Key1_Scan();
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 // 單測 PFC 電流環 (OK)
|
||||
|
||||
// 2P2Z 參數: Z1=200, Z2=100000, P1=10, P2=20000, G=10000, fs=100K, bQ14, aQ14
|
||||
cloop_p->b0 = 3353681;
|
||||
cloop_p->b1 = -1577632;
|
||||
cloop_p->b2 = -1712512;
|
||||
cloop_p->a1 = -20114;
|
||||
cloop_p->a2 = 3737;
|
||||
|
||||
// Not used
|
||||
vloop_p->b0 = 0;
|
||||
vloop_p->b1 = 0;
|
||||
vloop_p->b2 = 0;
|
||||
vloop_p->a1 = 0;
|
||||
vloop_p->a2 = 0;
|
||||
print_bodeplot_params(cloop_p, vloop_p);
|
||||
|
||||
cur_loop_fun_en = 1; // 開啟電流環,專測電流環
|
||||
while (1)
|
||||
{
|
||||
//uart_rx_task();
|
||||
if (tim0_trigger == 1) // 100KHZ
|
||||
{
|
||||
tim0_trigger = 0;
|
||||
// --- 1. 高速信號濾波 (簡易位移算法減少算力消耗) ---
|
||||
vac_avg1 = (vac_avg1 - (vac_avg1 >> 3)) + (vac >> 3); // for current loop
|
||||
vbus_avg = (vbus_avg - (vbus_avg >> 4)) + (vbus >> 4); // for voltage loop
|
||||
// vcr_avg = (vcr_avg - (vcr_avg >> 3)) + (vcr >> 3);
|
||||
if (vbus > vbus_ovp) Power_Off(); // ovp
|
||||
|
||||
Vac_Peak_Detector();
|
||||
|
||||
if (power_on_cmd == 1)
|
||||
{
|
||||
if (is_zero_crossing == 1)
|
||||
{
|
||||
sys_state = STATE_RUN_NORMAL;
|
||||
// --- 關鍵修正:重新初始化電壓環內部狀態 ---
|
||||
// 給予一個極小的初始 COMP 值,讓它從輕載慢慢往上爬
|
||||
// vbus_comp_1 = (10 << 14); // 假設從一個極小的係數開始
|
||||
vbus_err_1 = 0; // 清除誤差歷史
|
||||
// vbus_comp2 = (vbus_comp_1 >> 9); // 讓電流環拿到的初始值是 10
|
||||
vbus_comp2 = 4000; // 2000 不足,2500 過壓
|
||||
// vset / 5700
|
||||
// vbus_comp2: 3000, 275V / 0.25A = 68W
|
||||
// vbus_comp2: 4000, 314V / 0.25A = 78W
|
||||
// vbus_comp2: 5000, 360V / 0.25A = 90W
|
||||
// vset >> 13 ( / 8192)
|
||||
// vbus_comp2: 3000, 256V / 0.25A = 64W
|
||||
// vbus_comp2: 4000, 267V / 0.25A = 66W
|
||||
// vbus_comp2: 5000, 293V / 0.25A = 73W
|
||||
|
||||
// vbus_comp2: 2000, 298V / 0.25A = 75W ?? 波形不對 ff 的問題
|
||||
// vbus_comp2: 1000, 398V / 0.25A = 75W ??
|
||||
}
|
||||
else if (sys_state == STATE_RUN_NORMAL)
|
||||
{
|
||||
if (pfc_running == 0)
|
||||
{
|
||||
pfc_pwm_enable();
|
||||
pfc_running = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Key1_Scan();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 // 測試 PFC 電壓環 + 電流環 (OK)
|
||||
TIM2->CCR1 = 12; // min duty
|
||||
sys_state = STATE_PFC_SOFT_START;
|
||||
|
||||
cur_loop_fun_en = 0; // 一開始關閉電流環,STATE_RUN_NORMAL再開電流環
|
||||
|
||||
// 2P2Z 參數: Z1=200, Z2=100000, P1=10, P2=20000, G=10000, fs=100K, bQ14, aQ14
|
||||
cloop_p->b0 = 3353681;
|
||||
cloop_p->b1 = -1577632;
|
||||
cloop_p->b2 = -1712512;
|
||||
cloop_p->a1 = -20114;
|
||||
cloop_p->a2 = 3737;
|
||||
|
||||
// 1P1Z 參數: Z=120HZ, P=0.1HZ, G=100 ?
|
||||
vloop_p->b0 = 139;
|
||||
vloop_p->b1 = -129;
|
||||
vloop_p->b2 = 0;
|
||||
vloop_p->a1 = -16383;
|
||||
vloop_p->a2 = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (tim0_trigger == 1) // 100KHZ
|
||||
{
|
||||
tim0_trigger = 0;
|
||||
// --- 1. 高速信號濾波 (簡易位移算法減少算力消耗) ---
|
||||
vac_avg1 = (vac_avg1 - (vac_avg1 >> 3)) + (vac >> 3); // for current loop
|
||||
vbus_avg = (vbus_avg - (vbus_avg >> 4)) + (vbus >> 4); // for voltage loop
|
||||
if (vbus > vbus_ovp) Power_Off(); // ovp
|
||||
|
||||
Vac_Peak_Detector();
|
||||
|
||||
if (power_on_cmd == 1)
|
||||
{
|
||||
if (sys_state == STATE_PFC_SOFT_START)
|
||||
{
|
||||
if (pfc_running == 0) {
|
||||
pfc_pwm_enable();
|
||||
pfc_running = 1;
|
||||
}
|
||||
|
||||
if (++v_loop_cnt >= 10) // 10KHZ
|
||||
{
|
||||
Vol_Loop_PFC_1P1Z_UI();
|
||||
//Vol_Loop_PFC_1P1Z();
|
||||
v_loop_cnt = 0;
|
||||
}
|
||||
|
||||
if (vbus_avg > vbus_set_l && is_zero_crossing == 1)
|
||||
{
|
||||
sys_state = STATE_RUN_NORMAL;
|
||||
// --- 關鍵修正:重新初始化電壓環內部狀態 ---
|
||||
// 給予一個極小的初始 COMP 值,讓它從輕載慢慢往上爬
|
||||
vbus_comp_1 = (10 << 14); // 假設從一個極小的係數開始
|
||||
vbus_err_1 = 0; // 清除誤差歷史
|
||||
vbus_comp2 = (vbus_comp_1 >> 9); // 讓電流環拿到的初始值是 10
|
||||
cur_loop_fun_en = 1; // 開啟電流環
|
||||
}
|
||||
}
|
||||
|
||||
else if (sys_state == STATE_RUN_NORMAL)
|
||||
{
|
||||
if (pfc_running == 0) {
|
||||
pfc_pwm_enable();
|
||||
pfc_running = 1;
|
||||
}
|
||||
|
||||
if (++v_loop_cnt >= 10) // 10KHZ
|
||||
{
|
||||
Vol_Loop_PFC_1P1Z_UI();
|
||||
//Vol_Loop_PFC_1P1Z();
|
||||
v_loop_cnt = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Key1_Scan();
|
||||
}
|
||||
#endif
|
||||
|
||||
// main loop
|
||||
// main loop ===============================================================================
|
||||
|
||||
/* PFC 電流環參數*/
|
||||
// Z1=200, Z2=100000, P1=10, P2=20000, G=8000
|
||||
@@ -959,92 +616,35 @@ int main(void)
|
||||
{
|
||||
uart_rx_task();
|
||||
|
||||
// 核心定時觸發:100kHz (由 TIMER0 旗標觸發) [cite: 318]
|
||||
if (tim0_trigger == 1)
|
||||
// 核心觸發:100kHz ~ 200KHz (由 EPWM 旗標觸發)
|
||||
if (adc_trigger == 1)
|
||||
{
|
||||
tim0_trigger = 0;
|
||||
adc_trigger = 0;
|
||||
|
||||
// 高速信號濾波 (簡易位移算法減少算力消耗) ---
|
||||
vac_avg1 = (vac_avg1 - (vac_avg1 >> 3)) + (vac >> 3); // for current loop
|
||||
vbus_avg = (vbus_avg - (vbus_avg >> 4)) + (vbus >> 4); // for voltage loop
|
||||
vcr_avg = (vcr_avg - (vcr_avg >> 3)) + (vcr >> 3);
|
||||
// 系統安全監控 (軟體第二道防護)
|
||||
// vbus ovp
|
||||
if (vbus_avg > vbus_ovp)
|
||||
vbus_avg = (vbus_avg - (vbus_avg >> 3)) + (vbus >> 3);
|
||||
vcomp_avg = (vcomp_avg - (vcomp_avg >> 3)) + (vcomp >> 3);
|
||||
|
||||
// vbus ovp, uvp, 超出工作電壓範圍就不工作
|
||||
if (vbus_avg > vbus_ovp || vbus_avg < vbus_uvp)
|
||||
{
|
||||
sys_state = STATE_FAULT;
|
||||
Power_Off();
|
||||
sys_state = STATE_STOP;
|
||||
}
|
||||
#if 0
|
||||
// vac over voltage
|
||||
if (vac_pk2 > 2600)
|
||||
else
|
||||
{
|
||||
sys_state = STATE_FAULT;
|
||||
Power_Off();
|
||||
if (sys_state == STATE_STOP) sys_state = STATE_SS;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
// vac brown out
|
||||
if (vac_pk2 < VOLT_BROWN_OUT && pfc_running == 1)
|
||||
{
|
||||
sys_state = STATE_FAULT;
|
||||
Power_Off();
|
||||
}
|
||||
#endif
|
||||
Vac_Peak_Detector(); // VAC 峰值偵測
|
||||
|
||||
#if 1
|
||||
// --- 2. 核心狀態機邏輯 -----------------------------------------------------------------------
|
||||
switch (sys_state)
|
||||
{
|
||||
case STATE_INIT: // 0
|
||||
// 等待約 100ms,並按下按鍵
|
||||
if (sys_get_tick() > 100 && power_on_cmd == 1)
|
||||
{
|
||||
sys_state = STATE_STANDBY;
|
||||
}
|
||||
case STATE_STOP: // 0
|
||||
llc_pwm_disable(); // 關閉 PWM
|
||||
A_Para_Reset(); // 重置參數
|
||||
break;
|
||||
|
||||
case STATE_STANDBY: // 1
|
||||
// Brown-in 判斷
|
||||
if (is_brown_in == 1)
|
||||
{
|
||||
sys_state = STATE_PFC_SOFT_START; // 先進 PFC SS
|
||||
TIM2->CCR1 = PFC_DUTY_MIN;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_PFC_SOFT_START: // 2
|
||||
// 若 vbus < 320 做 pre-charge
|
||||
if (pfc_running == 0)
|
||||
{
|
||||
pfc_pwm_enable();
|
||||
pfc_running = 1;
|
||||
}
|
||||
|
||||
if (++v_loop_cnt >= 10) // 10KHZ
|
||||
{
|
||||
Vol_Loop_PFC_1P1Z();
|
||||
// Vol_Loop_PFC_1P1Z();
|
||||
v_loop_cnt = 0;
|
||||
}
|
||||
|
||||
if (vbus_avg > vbus_set_h)
|
||||
{
|
||||
sys_state = STATE_LLC_SOFT_START;
|
||||
llc_period_ss = LLC_SS_MIN;
|
||||
pfc_pwm_disable();
|
||||
pfc_running = 0;
|
||||
TIM2->CCR1 = PFC_DUTY_MIN;
|
||||
// --- 關鍵修正:重新初始化電壓環內部狀態 ---
|
||||
// 給予一個極小的初始 COMP 值,讓它從輕載慢慢往上爬
|
||||
// vbus_comp_1 = (10 << 14); // 假設從一個極小的係數開始
|
||||
// vbus_err_1 = 0; // 清除誤差歷史
|
||||
// vbus_comp2 = (vbus_comp_1 >> 9); // 讓電流環拿到的初始值是 10
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_LLC_SOFT_START: // 3
|
||||
case STATE_SS: // 1
|
||||
// LLC 軟啟動:頻率由高往低掃描 (掃向 1倍諧振頻率)
|
||||
llc_period_ss++;
|
||||
llc_ss_cnt++;
|
||||
@@ -1056,72 +656,46 @@ int main(void)
|
||||
llc_running = 1;
|
||||
}
|
||||
|
||||
if (llc_ss_cnt >= LLC_SS_COUNT && is_zero_crossing == 1)
|
||||
if (llc_ss_cnt >= LLC_SS_COUNT)
|
||||
{
|
||||
sys_state = STATE_RUN_NORMAL;
|
||||
sys_state = STATE_RUN;
|
||||
// sys_state = STATE_PAUSE; // 測試用
|
||||
// 重要動作 =====================================
|
||||
vbus_comp_1 = YN_MIN; // 假設從一個極小的係數開始
|
||||
vbus_comp2 = (vbus_comp_1 >> 9);
|
||||
vbus_err_1 = 0; // 清除誤差歷史
|
||||
iac_err_2 = 0;
|
||||
iac_err_1 = 0;
|
||||
iac_comp_2 = YN_MIN;
|
||||
iac_comp_1 = YN_MIN;
|
||||
// 重要動作 =====================================
|
||||
// vbus_comp_1 = YN_MIN; // 假設從一個極小的係數開始
|
||||
// vbus_comp2 = (vbus_comp_1 >> 9);
|
||||
// vbus_err_1 = 0; // 清除誤差歷史
|
||||
// iac_err_2 = 0;
|
||||
// iac_err_1 = 0;
|
||||
// iac_comp_2 = YN_MIN;
|
||||
// iac_comp_1 = YN_MIN;
|
||||
// msg("%d %d %d %d \r\n", power_on_cmd, sys_state, vbus_comp_1, vbus_comp2);
|
||||
// 1 4 196608, = 12 << 14
|
||||
// E LOAD 抽太慢,導致 OVP ?? (是的)
|
||||
// 1 4 196608, = 12 << 14
|
||||
// E LOAD 抽太慢,導致 OVP ?? (是的)
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_RUN_NORMAL: // 4
|
||||
if (pfc_running == 0)
|
||||
case STATE_RUN: // 2
|
||||
// 根據電壓環、電流環調整頻率
|
||||
/*
|
||||
if (++v_loop_cnt >= 10) // 10KHZ
|
||||
{
|
||||
pfc_pwm_enable();
|
||||
pfc_running = 1;
|
||||
}
|
||||
|
||||
if (++v_loop_cnt >= 10)
|
||||
{
|
||||
// 先算前饋,再算主環,最後疊加
|
||||
Load_Loop_1P1Z(); // Cr 前饋
|
||||
Vol_Loop_PFC_1P1Z(); // PFC 電壓環
|
||||
// Vol_Loop_LLC(); // LLC 電壓環
|
||||
Vol_Loop_PFC_1P1Z();
|
||||
// Vol_Loop_PFC_1P1Z();
|
||||
v_loop_cnt = 0;
|
||||
}
|
||||
|
||||
if (++v_loop_cnt2 >= 5) // 好一點
|
||||
{
|
||||
Vol_Loop_LLC(); // LLC 電壓環
|
||||
v_loop_cnt2 = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
break;
|
||||
|
||||
case STATE_RUN_SKIP: // 5
|
||||
break;
|
||||
|
||||
case STATE_FAULT: // 6
|
||||
// 立即封鎖所有輸出
|
||||
pfc_pwm_disable();
|
||||
llc_pwm_disable();
|
||||
// 記錄故障代碼,等待手動重置
|
||||
break;
|
||||
|
||||
case STATE_PAUSE: // 7
|
||||
break;
|
||||
|
||||
} // switch case
|
||||
#endif
|
||||
|
||||
} // if tim0_trigger
|
||||
|
||||
// --- 3. 非即時任務 (UI、通訊、Data Log) ---
|
||||
Key1_Scan();
|
||||
Handle_UART_Monitor();
|
||||
// Capture_Dump_IfReady();
|
||||
|
||||
Capture_Dump_IfReady();
|
||||
|
||||
capture_continuous_task();
|
||||
// capture_continuous_task();
|
||||
} // while --------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user