[問題]dspic控制converter

看板Electronics作者 (sudyuid)時間14年前 (2011/09/16 18:22), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串1/2 (看更多)
最近在用dspic30F4011控制簡單的buck和boost converter 但是對dspic不太熟析 所以上網找了一些資料 其中找到了用dspic30F4011 寫PI控制buck converter 所以我就拿來實作看看不過有些問題 以下是網路上找到的程式 #include <p30F4011.h> #include <dsp.h> _FOSC(CSW_FSCM_OFF & XT_PLL16); // Failsafe clock off, Internal FRC with 16xPLL oscillator _FWDT(WDT_OFF); // Wathcdog timer disabled _FBORPOR(PBOR_OFF & MCLR_EN); // Brown-out reset disabled, MCLR reset enabled _FGS(CODE_PROT_OFF); // Code protect disabled #define PWM_Period 0x0257 // PTPER = (Fcy / Fpwm) - 1 #define PWM_Duty_Max 0x0438 // PWM Duty 最大值, 0.9 #define PWM_Duty_Min 0x0078 // PWM Duty 最小值, 0.1 #define PWM_Duty_Ref 0x012C // PWM Duty 參考準位, 0.25 #define Vref 0x018E // Vdd=3.4V 時的 Vref = 2.5V // 宣告PID 資料結構 tPID fooPID; fractional abcCoefficient[3] __attribute__ ((section (".xbss, bss, xmemory"))); fractional controlHistory[3] __attribute__ ((section (".ybss, bss, ymemory"))); fractional kCoeffs[] = {0,0,0}; // 宣告函數 void Init_PWM(void) ; void Init_ADC(void) ; void Set_PWM_Duty(void) ; void Compensator(void); // 宣告全域變數 unsigned int PWM_Duty ; int main(void) { Init_PWM() ; // 初始化PWM Init_ADC() ; // 初始化ADC ADCON1bits.ADON = 1 ; // 啟動ADC PTCONbits.PTEN = 1 ; // 啟動PWM fooPID.abcCoefficients = &abcCoefficient[0] ; // Set up pointer to derived coefficients fooPID.controlHistory = &controlHistory[0] ; // Set up pointer to controller history samples PIDInit(&fooPID) ; // Clear the controller history and the controller output kCoeffs[0] = Q15(0.5) ; // KP kCoeffs[1] = Q15(0.000) ; // KI kCoeffs[2] = Q15(0.0) ; // KD PIDCoeffCalc(&kCoeffs[0], &fooPID) ; // Derive the a,b, & c coefficients from the Kp, Ki & Kd fooPID.controlReference = Vref << 5 ; // 初始化參考電壓Vref 的值 while(1) { ADCON1bits.SAMP = 1 ; // start sampling while (ADCON1bits.SAMP) ; // Sample done? while (!ADCON1bits.DONE) ; // conversion done? Compensator() ; } } void Init_PWM(void) { PTCON = 0x0000 ; // Stop in Idle off, 1:1 Postscale and Prescale, Free Running Mode PTPER = PWM_Period ; // PTPER = Fcy / Fpwm - 1 PWMCON1 = 0x0110 ; // PWM1 independent, PWM1H Enable PWMCON2 = 0x0000 ; OVDCON = 0xFF00 ; // Output on PWMxx I/O pin is controlled by the PWM generator PDC1 = 0x0257 ; // Duty: (PDCx/2) / (PTPER+1) } void Init_ADC(void) { ADPCFG = 0xFFFE ; // AN0 Analog ADCON1 = 0x0000 ; // FORM: Integer ADCON1bits.SSRC = 0b111 ; // Auto convert ADCON2 = 0x0000 ; // VrefH=AVdd, VrefL=AVss, Do not scan, Converts CH0, Always MUXA ADCON3bits.SAMC = 16 ; // ADC SAMPLE TIME = 16 Tad ADCON3bits.ADRC = 0 ; // Use system clock ADCON3bits.ADCS = 4 ; // Conversion clock = 4 Tcy ADCSSL = 0x0000 ; // ADC scan no channel ADCHS = 0x0000 ; ADCHSbits.CH0NA = 0 ; // Channal 0 negative input is Vref- ADCHSbits.CH0SA = 0 ; // Channal 0 positive input is AN0 } void Set_PWM_Duty(void) { if(PWM_Duty > PWM_Duty_Max) PDC1 = PWM_Duty_Max ; else if(PWM_Duty < PWM_Duty_Min) PDC1 = PWM_Duty_Min ; else PDC1 = PWM_Duty ; } //取樣迴授訊號與補償器設計 void Compensator(void) { fooPID.measuredOutput = ADCBUF0 << 5 ; // Set PID measured input PID(&fooPID); // Call the PID controller using the new measured input if(fooPID.controlOutput > (0x7FFF - PWM_Duty_Ref)) // 處理可能造成的溢位 PWM_Duty = 0x7FFF; else if( (fooPID.controlOutput + PWM_Duty_Ref) < 0 ) PWM_Duty = 0x0000; else PWM_Duty = fooPID.controlOutput + PWM_Duty_Ref; Set_PWM_Duty(); // 限制Duty 最大值與最小值 } 1.因為看不太懂程式,所以我實作是這樣做的 假設buck情形時輸入60V輸出30V,輸出電壓經過分壓假設是3V ,我就先把3V拉進去dspic裡看輸出PWM的duty是不是0.5,有點像在湊答案= = 如果不是我就改他的Vref的值,這邊有點怪怪的Vref的值好像沒有一定的比例 所以一定要try很多次才能找到 這邊不太清楚為什麼... 2.找到了以後我就輸入60V,得到了30V的輸出電壓,我試著把輸入電壓變大或變小 但是輸出電壓沒有辦法追到我的命令,會跟著變大變小.所以說我就試著改 kCoeffs[0] = Q15(0.5) ; // KP kCoeffs[1] = Q15(0.000) ; // KI kCoeffs[2] = Q15(0.0) ; // KD 這三行裡Q15括號裡的值 但是示波器量出來的波形更怪 離我的命令值更遠 有時後電感還會發出淒厲的叫聲? 3.我另外還有想說把開關切換頻率降低,應此我改了 #define PWM_Period 0x0257 // PTPER = (Fcy / Fpwm) - 1 這行,但是改完以後,一開始輸出PWM的duty(燒錄晶片後 開始RUN的時候 不經過回授) 原本是0.9但是隨著我改變PWM_Period 的值PWM的DUTY也會跟著變...感覺怪怪的? 有沒有高手可以解決我的疑問 感恩~~~ -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 134.208.1.23
文章代碼(AID): #1ESoDvDb (Electronics)
文章代碼(AID): #1ESoDvDb (Electronics)