diff --git a/pec930_sdk-v1.0.1/Examples/template/LLC_48V/inc/main.h b/pec930_sdk-v1.0.1/Examples/template/LLC_48V/inc/main.h index 2249dde..0116921 100644 --- a/pec930_sdk-v1.0.1/Examples/template/LLC_48V/inc/main.h +++ b/pec930_sdk-v1.0.1/Examples/template/LLC_48V/inc/main.h @@ -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)) //--------------------------------------------------------------- diff --git a/pec930_sdk-v1.0.1/Examples/template/LLC_48V/src/init.c b/pec930_sdk-v1.0.1/Examples/template/LLC_48V/src/init.c index b3c38c7..32592a8 100644 --- a/pec930_sdk-v1.0.1/Examples/template/LLC_48V/src/init.c +++ b/pec930_sdk-v1.0.1/Examples/template/LLC_48V/src/init.c @@ -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(); } diff --git a/pec930_sdk-v1.0.1/Examples/template/LLC_48V/src/main.c b/pec930_sdk-v1.0.1/Examples/template/LLC_48V/src/main.c index 6b5d54c..8b5f540 100644 --- a/pec930_sdk-v1.0.1/Examples/template/LLC_48V/src/main.c +++ b/pec930_sdk-v1.0.1/Examples/template/LLC_48V/src/main.c @@ -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;