1 Commits

Author SHA1 Message Date
aiden c846ad9793 小改動 2026-06-10 11:36:25 +08:00
4 changed files with 114 additions and 72 deletions
@@ -32,7 +32,7 @@ extern "C"
#define YN_MAX (PFC_DUTY_MAX << 14) #define YN_MAX (PFC_DUTY_MAX << 14)
#define YN_MIN (PFC_DUTY_MIN << 14) #define YN_MIN (PFC_DUTY_MIN << 14)
// VBUS 參數 // VBUS 參數
#define VBUS_SET 340 // unit: volt (Transformer N = 14) #define VBUS_SET 350 // unit: volt (Transformer N = 14)
#define VBUS_SET_H (VBUS_SET + 20) // burst mode in, 在過零區判斷 #define VBUS_SET_H (VBUS_SET + 20) // burst mode in, 在過零區判斷
#define VBUS_SET_L (VBUS_SET - 20) // burst mode out, 在過零區判斷 #define VBUS_SET_L (VBUS_SET - 20) // burst mode out, 在過零區判斷
// #define VBUS_SET_H2 370 // for skip mode // #define VBUS_SET_H2 370 // for skip mode
@@ -192,7 +192,7 @@ void adc_config(void)
// ---------------------------------------------- // ----------------------------------------------
// vcr = PA11 = ADC_Channel_05 (未使用) // vcr = PA11 = ADC_Channel_05 (未使用)
// vfb = PA12 = ADC_Channel_06 (使用 GPIO) // vfb = PA12 = ADC_Channel_06 (使用 GPIO)
init1.SelChannels = ADC_Channel_04 | ADC_Channel_07 | ADC_Channel_09; // | ADC_Channel_05; init1.SelChannels = ADC_Channel_04 | ADC_Channel_07 | ADC_Channel_09 | ADC_Channel_05;
// init1.SelChannels = ADC_Channel_09 ;// OP_O 指定到 PA7 時,ADC 需要用 CH_09 讀取 // init1.SelChannels = ADC_Channel_09 ;// OP_O 指定到 PA7 時,ADC 需要用 CH_09 讀取
init1.ClkPrescaler = ADC_ClkDiv_4; // 60M/4 = 15M,接近 1MSPS (1us 轉換時間), 最快速度 init1.ClkPrescaler = ADC_ClkDiv_4; // 60M/4 = 15M,接近 1MSPS (1us 轉換時間), 最快速度
init1.DataAlign = ADC_DataAlign_Right; init1.DataAlign = ADC_DataAlign_Right;
@@ -16,8 +16,8 @@
#define CR_1P1Z_A1_Q14 -5803 #define CR_1P1Z_A1_Q14 -5803
// 前饋輸出限制(請根據您主環 Q14 格式的數值範圍調整) // 前饋輸出限制(請根據您主環 Q14 格式的數值範圍調整)
// 假設最大前饋量限制為實數值 50.0 -> 50.0 * 16384 = 819200 // 假設最大前饋量限制為實數值 50.0 -> 50.0 * 16384 = 819200
#define CR_FF_MAX_Q14 819200 // 50 duty << 14 #define CR_FF_MAX_Q14 1638400 //819200 // 50 duty << 14
#define CR_FF_MIN_Q14 -819200 #define CR_FF_MIN_Q14 -1638400 //-819200
//============================================================================= //=============================================================================
// Macro Definition // Macro Definition
@@ -328,7 +328,7 @@ void Load_Loop_1P1Z(void)
int32_t y0; int32_t y0;
// 1. 讀取當前 vcr // 1. 讀取當前 vcr
x0 = vcr; x0 = vcr_avg;
// 2. 執行 1P1Z 差分方程計算: // 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); 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);
@@ -342,32 +342,35 @@ void Load_Loop_1P1Z(void)
// 定點數安全限幅 (Saturation) // 定點數安全限幅 (Saturation)
if (y0 > CR_FF_MAX_Q14) if (y0 > CR_FF_MAX_Q14)
y0 = CR_FF_MAX_Q14; // 868352 = 53 duty y0 = CR_FF_MAX_Q14;
else if (y0 > -CR_FF_MIN_Q14) else if (y0 > -CR_FF_MIN_Q14)
y0 = -CR_FF_MIN_Q14; y0 = -CR_FF_MIN_Q14;
cr_feed_forward_output_q14 = y0; cr_feed_forward_output_q14 = y0;
} }
//========================================================================== //==========================================================================
void Vol_Loop_PFC_1P1Z(void) // TEST OK void Vol_Loop_PFC_1P1Z(void)
{ {
// 1. 計算誤差 // 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:動態增益調整 --- // --- 策略 A:動態增益調整 ---
// int32_t b0 = 135; int32_t b0 = 139;
// int32_t b1 = -134; int32_t b1 = -129;
int32_t b0 = 180;
int32_t b1 = -175;
// if (vbus_err_n > 30 || vbus_err_n < -30) // vloop_p->b0 = 139;
if (vbus_err_n > 80 || vbus_err_n < -80) // ~ 20V // vloop_p->b1 = -129;
// vloop_p->a1 = -16383;
/*
if (vbus_err_n > 40 || vbus_err_n < -40) // ~ 20V
{ {
// 大誤差時(通常是剛啟動或大跳載),強化參數加快反應 // 大誤差時(通常是剛啟動或大跳載),強化參數加快反應
b0 = 250; //b0 = 250;
b1 = -240; //b1 = -249;
// b0 = 180; // 稍微調降強增益的力道 //b0 = 180; // 稍微調降強增益的力道
// b1 = -175; //b1 = -178;
b0 = 500;
b1 = -499;
} }
// --- 策略 B:接近目標時微調零點 (抗過衝) --- // --- 策略 B:接近目標時微調零點 (抗過衝) ---
else if (vbus_err_n < 20 && vbus_err_n > -20) // ~ 5V else if (vbus_err_n < 20 && vbus_err_n > -20) // ~ 5V
@@ -376,14 +379,35 @@ void Vol_Loop_PFC_1P1Z(void) // TEST OK
b0 = 120; b0 = 120;
b1 = -119; // 如果不能用浮點數,請維持 120 / -119,增加阻尼感 b1 = -119; // 如果不能用浮點數,請維持 120 / -119,增加阻尼感
} }
*/
// 2. 差分方程計算 // 2. 差分方程計算
int64_t acc = (int64_t)b0 * vbus_err_n; int64_t acc = (int64_t)b0 * vbus_err_n;
acc += (int64_t)b1 * vbus_err_1; acc += (int64_t)b1 * vbus_err_1;
acc += ((int64_t)16384 * vbus_comp_1) >> 14; // 16384 = 1 >> 14 acc += ((int64_t)16383 * vbus_comp_1) >> 14; // 16384 = 1 >> 14
int32_t y_n = (int32_t)acc; int32_t y_n = (int32_t)acc;
#if 0 // 有問題
// --- 策略 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
}
// 如果發生明顯過衝 (電壓高於目標 5V 以上)
if (vbus_err_n < -5)
{
current_max_limit = 1638400; // 強制壓低到 Duty 100 快速拉回
}
#endif
// 3. 輸出限幅執行 // 3. 輸出限幅執行
if (y_n > YN_MAX) if (y_n > YN_MAX)
y_n = YN_MAX; y_n = YN_MAX;
@@ -395,12 +419,13 @@ void Vol_Loop_PFC_1P1Z(void) // TEST OK
vbus_comp_1 = y_n; vbus_comp_1 = y_n;
// 5. 輸出 Duty >> 14 // 5. 輸出 Duty >> 14
// if (sys_state == STATE_PFC_SOFT_START || sys_state == STATE_RUN_SKIP) // 緩啟動期間直接控制 DUTY if (sys_state == STATE_PFC_SOFT_START || sys_state == STATE_RUN_SKIP) // 緩啟動期間直接控制 DUTY
TIM2->CCR1 = (vbus_comp_1 >> 14); // 0 ~ 540 TIM2->CCR1 = (vbus_comp_1 >> 14); // 0 ~ 540
// 6. 輸出 comp >> 9 (變大 32 倍) (MAX ~ 18000) (540*32=17280)差不多,>> 9 應該是對的 // 6. 輸出 comp >> 9 (變大 32 倍) (MAX ~ 18000) (540*32=17280)差不多,>> 9 應該是對的
// if (sys_state == STATE_RUN_NORMAL) // 正常工作時間輸出 COMP 值 // if (sys_state == STATE_RUN_NORMAL) // 正常工作時間輸出 COMP 值
vbus_comp2 = (vbus_comp_1 >> 9); vbus_comp2 = (vbus_comp_1 >> 9) + (cr_feed_forward_output_q14 << 1); // 太大會直接 OVP
//vbus_comp2 = (vbus_comp_1 >> 9);
} }
//============================================================= //=============================================================
static void Vol_Loop_PFC_1P1Z_UI(void) // ZERO: 120HZ, POLE:0.1HZ, G:10 static void Vol_Loop_PFC_1P1Z_UI(void) // ZERO: 120HZ, POLE:0.1HZ, G:10
@@ -430,8 +455,8 @@ static void Vol_Loop_PFC_1P1Z_UI(void) // ZERO: 120HZ, POLE:0.1HZ, G:10
vbus_comp_1 = y_n; vbus_comp_1 = y_n;
// 5. 輸出 Duty >> 14 // 5. 輸出 Duty >> 14
// if (sys_state == STATE_PFC_SOFT_START || sys_state == STATE_RUN_SKIP) // 緩啟動期間直接控制 DUTY if (sys_state == STATE_PFC_SOFT_START || sys_state == STATE_RUN_SKIP) // 緩啟動期間直接控制 DUTY
TIM2->CCR1 = (vbus_comp_1 >> 14); // 0 ~ 540 TIM2->CCR1 = (vbus_comp_1 >> 14); // 0 ~ 540
// 6. 輸出 comp >> 9 (變大 32 倍) (MAX ~ 18000) (540*32=17280)差不多,>> 9 應該是對的 // 6. 輸出 comp >> 9 (變大 32 倍) (MAX ~ 18000) (540*32=17280)差不多,>> 9 應該是對的
// if (sys_state == STATE_RUN_NORMAL) // 正常工作時間輸出 COMP 值 // if (sys_state == STATE_RUN_NORMAL) // 正常工作時間輸出 COMP 值
@@ -607,7 +632,7 @@ __INTERRUPT void isr_adc_handle(void)
iac = ADC0->DAT9_b.DATA; // PA7, AIN9 iac = ADC0->DAT9_b.DATA; // PA7, AIN9
vac = ADC0->DAT7_b.DATA; // PA13, AIN7 vac = ADC0->DAT7_b.DATA; // PA13, AIN7
vbus = ADC0->DAT4_b.DATA; // PA10, AIN4 vbus = ADC0->DAT4_b.DATA; // PA10, AIN4
// vcr = ADC0->DAT5_b.DATA; // PA11, AIN5 vcr = ADC0->DAT5_b.DATA; // PA11, AIN5
if (cur_loop_fun_en) Cur_Loop_PFC_2P2Z(); // current loop if (cur_loop_fun_en) Cur_Loop_PFC_2P2Z(); // current loop
@@ -637,9 +662,10 @@ void Handle_UART_Monitor(void)
static uint32_t msg_timer = 0; static uint32_t msg_timer = 0;
if (sys_get_tick() - msg_timer >= 1000) // msg_out = 1, print if (sys_get_tick() - msg_timer >= 1000) // msg_out = 1, print
{ {
// printf("%d %d %d\r\n", vac_pk1, vac_pk2, is_brown_in); printf("%d\r\n", vac);
// printf("%d %d %d %d %d %d", power_on_cmd, sys_state, vbus_comp2, print1, print2, print3); // printf("%d %d %d %d %d %d", power_on_cmd, sys_state, vbus_comp2, print1, print2, print3);
msg("%d %d %d", power_on_cmd, sys_state, vbus_comp2); //msg("%d %d %d", power_on_cmd, sys_state, vac_pk2);
//msg("%d %d %d", iac, vac, vbus);
// 電壓環輸出最大 COMP,但是電流環輸出最小 DUTY // 電壓環輸出最大 COMP,但是電流環輸出最小 DUTY
msg_timer = sys_get_tick(); msg_timer = sys_get_tick();
} }
@@ -729,6 +755,21 @@ int main(void)
// 基礎硬體底層設定 (HIRC 60MHz, GPIO, ADC 採樣率 1Msps) [cite: 55, 127, 184] // 基礎硬體底層設定 (HIRC 60MHz, GPIO, ADC 採樣率 1Msps) [cite: 55, 127, 184]
SYS_Config(); SYS_Config();
//pfc_set_duty(15);
//pfc_pwm_enable();
//while(1);
//llc_set_period(600);
//llc_pwm_enable();
//while(1);
/*
while(1)
{
Handle_UART_Monitor();
}
*/
// PFC 電流環參數 // PFC 電流環參數
bode_plot_param_read_from_flash(bplot_p, FLASH_PROG_ADDR_USER_CALI); bode_plot_param_read_from_flash(bplot_p, FLASH_PROG_ADDR_USER_CALI);
@@ -743,11 +784,11 @@ int main(void)
// vloop_p->a1 = -16383; // vloop_p->a1 = -16383;
/*********************************************************************/ /*********************************************************************/
/* PFC 電流環參數*/ /* PFC 電流環參數*/
// bplot_p->b0 = 12368803; //bplot_p->b0 = 3353681;
// bplot_p->b1 = -19162610; //bplot_p->b1 = -1577632;
// bplot_p->b2 = 7037429; //bplot_p->b2 = -1712512;
// bplot_p->a1 = -20921; //bplot_p->a1 = -20921;
// bplot_p->a2 = 4545; //bplot_p->a2 = 4545;
/*********************************************************************/ /*********************************************************************/
#if 0 // 單測 PFC 電壓環 (OK) #if 0 // 單測 PFC 電壓環 (OK)
@@ -763,9 +804,11 @@ int main(void)
} }
cur_loop_fun_en = 0; // 關閉電流環,專測電壓環 cur_loop_fun_en = 0; // 關閉電流環,專測電壓環
sys_state = STATE_PFC_SOFT_START;
while (1) while (1)
{ {
uart_rx_task(); //uart_rx_task();
if (tim0_trigger == 1) // 100KHZ if (tim0_trigger == 1) // 100KHZ
{ {
@@ -774,7 +817,7 @@ int main(void)
vac_avg1 = (vac_avg1 - (vac_avg1 >> 3)) + (vac >> 3); // for current loop vac_avg1 = (vac_avg1 - (vac_avg1 >> 3)) + (vac >> 3); // for current loop
vbus_avg = (vbus_avg - (vbus_avg >> 4)) + (vbus >> 4); // for voltage loop vbus_avg = (vbus_avg - (vbus_avg >> 4)) + (vbus >> 4); // for voltage loop
vcr_avg = (vcr_avg - (vcr_avg >> 3)) + (vcr >> 3); vcr_avg = (vcr_avg - (vcr_avg >> 3)) + (vcr >> 3);
if (vbus > vbus_ovp) Power_Off(); // ovp if (vbus_avg > vbus_ovp) Power_Off(); // ovp
Vac_Peak_Detector(); Vac_Peak_Detector();
@@ -788,8 +831,8 @@ int main(void)
if (++v_loop_cnt >= 10) // 10KHZ if (++v_loop_cnt >= 10) // 10KHZ
{ {
Vol_Loop_PFC_1P1Z_UI(); //Vol_Loop_PFC_1P1Z_UI();
// Vol_Loop_PFC_1P1Z(); Vol_Loop_PFC_1P1Z(); // 800W 板子會低 13V
v_loop_cnt = 0; v_loop_cnt = 0;
} }
} }
@@ -797,29 +840,24 @@ int main(void)
Key1_Scan(); Key1_Scan();
// Handle_UART_Monitor(); //Handle_UART_Monitor();
if (is_full == 1)
{
sys_delay(10);
Handle_UART_Log();
}
} }
#endif #endif
#if 0 // 單測 PFC 電流環 (OK) #if 0 // 單測 PFC 電流環 (OK)
/* PFC 電流環參數*/ /* PFC 電流環參數*/
// Z1=200, Z2=1000000, P1=10, P2=20000, G=10000 // Z1=200, Z2=1000000, P1=10, P2=20000, G=10000
bplot_p->b0 = 4192101; bplot_p->b0 = 3353681;
bplot_p->b1 = -1972040; bplot_p->b1 = -1577632;
bplot_p->b2 = -2140640; bplot_p->b2 = -1712512;
bplot_p->a1 = -20114; bplot_p->a1 = -20114;
bplot_p->a2 = 3737; bplot_p->a2 = 3737;
cur_loop_fun_en = 1; // 開啟電流環,專測電流環 cur_loop_fun_en = 1; // 開啟電流環,專測電流環
while (1) while (1)
{ {
uart_rx_task(); //uart_rx_task();
if (tim0_trigger == 1) // 100KHZ if (tim0_trigger == 1) // 100KHZ
{ {
tim0_trigger = 0; tim0_trigger = 0;
@@ -841,7 +879,7 @@ int main(void)
// vbus_comp_1 = (10 << 14); // 假設從一個極小的係數開始 // vbus_comp_1 = (10 << 14); // 假設從一個極小的係數開始
vbus_err_1 = 0; // 清除誤差歷史 vbus_err_1 = 0; // 清除誤差歷史
// vbus_comp2 = (vbus_comp_1 >> 9); // 讓電流環拿到的初始值是 10 // vbus_comp2 = (vbus_comp_1 >> 9); // 讓電流環拿到的初始值是 10
vbus_comp2 = 3000; vbus_comp2 = 4000; // 2000 不足,2500 過壓
// vset / 5700 // vset / 5700
// vbus_comp2: 3000, 275V / 0.25A = 68W // vbus_comp2: 3000, 275V / 0.25A = 68W
// vbus_comp2: 4000, 314V / 0.25A = 78W // vbus_comp2: 4000, 314V / 0.25A = 78W
@@ -883,12 +921,12 @@ int main(void)
vloop_p->a1 = -16383; vloop_p->a1 = -16383;
} }
{ {
bplot_p->b0 = 4192101; bplot_p->b0 = 3353681;
bplot_p->b1 = -1972040; bplot_p->b1 = -1577632;
bplot_p->b2 = -2140640; bplot_p->b2 = -1712512;
bplot_p->a1 = -20114; bplot_p->a1 = -20114;
bplot_p->a2 = 3737; bplot_p->a2 = 3737;
} }
while(1) while(1)
{ {
@@ -913,8 +951,8 @@ int main(void)
if (++v_loop_cnt >= 10) // 10KHZ if (++v_loop_cnt >= 10) // 10KHZ
{ {
//Vol_Loop_PFC_1P1Z_UI(); Vol_Loop_PFC_1P1Z_UI();
Vol_Loop_PFC_1P1Z(); //Vol_Loop_PFC_1P1Z();
v_loop_cnt = 0; v_loop_cnt = 0;
} }
@@ -939,8 +977,8 @@ int main(void)
if (++v_loop_cnt >= 10) // 10KHZ if (++v_loop_cnt >= 10) // 10KHZ
{ {
//Vol_Loop_PFC_1P1Z_UI(); Vol_Loop_PFC_1P1Z_UI();
Vol_Loop_PFC_1P1Z(); //Vol_Loop_PFC_1P1Z();
v_loop_cnt = 0; v_loop_cnt = 0;
} }
} }
@@ -955,11 +993,11 @@ int main(void)
/* PFC 電流環參數*/ /* PFC 電流環參數*/
// Z1=200, Z2=100000, P1=10, P2=20000, G=8000 // Z1=200, Z2=100000, P1=10, P2=20000, G=8000
// bplot_p->b0 = 3353681; bplot_p->b0 = 3353681;
// bplot_p->b1 = -1577632; bplot_p->b1 = -1577632;
// bplot_p->b2 = -1712512; bplot_p->b2 = -1712512;
// bplot_p->a1 = -20114; bplot_p->a1 = -20114;
// bplot_p->a2 = 3737; bplot_p->a2 = 3737;
cur_loop_fun_en = 1; // 開啟電流環,專測電流環 cur_loop_fun_en = 1; // 開啟電流環,專測電流環
while (1) while (1)
@@ -977,26 +1015,27 @@ int main(void)
vcr_avg = (vcr_avg - (vcr_avg >> 3)) + (vcr >> 3); vcr_avg = (vcr_avg - (vcr_avg >> 3)) + (vcr >> 3);
// 系統安全監控 (軟體第二道防護) // 系統安全監控 (軟體第二道防護)
// vbus ovp // vbus ovp
if (vbus > vbus_ovp) if (vbus_avg > vbus_ovp)
{ {
sys_state = STATE_FAULT; sys_state = STATE_FAULT;
Power_Off(); Power_Off();
} }
#if 0
// vac over voltage // vac over voltage
if (vac_pk2 > 2600) if (vac_pk2 > 2600)
{ {
sys_state = STATE_FAULT; sys_state = STATE_FAULT;
Power_Off(); Power_Off();
} }
#endif
#if 0
// vac brown out // vac brown out
if (vac_pk2 < VOLT_BROWN_OUT && pfc_running == 1) if (vac_pk2 < VOLT_BROWN_OUT && pfc_running == 1)
{ {
sys_state = STATE_FAULT; sys_state = STATE_FAULT;
Power_Off(); Power_Off();
} }
#endif
Vac_Peak_Detector(); // VAC 峰值偵測 Vac_Peak_Detector(); // VAC 峰值偵測
#if 1 #if 1
@@ -1030,11 +1069,12 @@ int main(void)
if (++v_loop_cnt >= 10) // 10KHZ if (++v_loop_cnt >= 10) // 10KHZ
{ {
Vol_Loop_PFC_1P1Z_UI(); Vol_Loop_PFC_1P1Z();
//Vol_Loop_PFC_1P1Z();
v_loop_cnt = 0; v_loop_cnt = 0;
} }
if (vbus_avg > vbus_set_l) if (vbus_avg > vbus_set_h)
{ {
sys_state = STATE_LLC_SOFT_START; sys_state = STATE_LLC_SOFT_START;
llc_period_ss = LLC_SS_MIN; llc_period_ss = LLC_SS_MIN;
@@ -1089,18 +1129,20 @@ int main(void)
if (++v_loop_cnt >= 10) if (++v_loop_cnt >= 10)
{ {
// 先算前饋,再算主環,最後疊加 // 先算前饋,再算主環,最後疊加
// Load_Loop_1P1Z(); // Cr 前饋 Load_Loop_1P1Z(); // Cr 前饋
Vol_Loop_PFC_1P1Z(); // PFC 電壓環 Vol_Loop_PFC_1P1Z(); // PFC 電壓環
// Vol_Loop_LLC(); // LLC 電壓環 //Vol_Loop_LLC(); // LLC 電壓環
v_loop_cnt = 0; v_loop_cnt = 0;
} }
if (++v_loop_cnt2 >= 15)
if (++v_loop_cnt2 >= 5) // 好一點
{ {
Vol_Loop_LLC(); // LLC 電壓環 Vol_Loop_LLC(); // LLC 電壓環
v_loop_cnt2 = 0; v_loop_cnt2 = 0;
} }
break; break;
case STATE_RUN_SKIP: // 5 case STATE_RUN_SKIP: // 5
@@ -1,5 +1,5 @@
adapter speed 5000 adapter speed 1000
reset_config srst_only reset_config srst_only
adapter srst pulse_width 100 adapter srst pulse_width 100