Re: [問題]dspic控制converter

看板Electronics作者 (joy)時間14年前 (2011/09/16 21:53), 編輯推噓1(100)
留言1則, 1人參與, 最新討論串2/2 (看更多)
: 最近在 用dspic30F4011控制簡單的buck和boost converter : 但是對dspic不太熟析 所以上網找了一些資料 其中找到了用dspic30F4011 : 寫PI控制buck converter 所以我就拿來實作看看不過有些問題 : 以下是網路上找到的程式 建議不要這樣學數位控制 看別人寫好的程式 會很難懂 這樣的PID程式真的不是很好 寫的亂 有些程式動作又隱藏起來 建議先看三個範例程式 1.AD 了解類比轉數位:拿DC source灌入 0~5V 看ADCBUF 會在0~0x7FFF間 數位一般都是16bits 拿一半給正值 0x0x7FFF 一半給負值0xFFFF~0x8000 2.PWM 調整頻率和duty 用示波器觀察變化 3.中斷 設定計算頻率 設成PWM切換頻率 可以寫個小程式輸出PWM來用示波器觀察 : #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很多次才能找到 這邊不太清楚為什麼... 若你要分壓成3V (0x7fff << 5 )x(3/5) = 0x0265 = Vref : 2.找到了以後我就輸入60V,得到了30V的輸出電壓,我試著把輸入電壓變大或變小 : 但是輸出電壓沒有辦法追到我的命令,會跟著變大變小.所以說我就試著改 : kCoeffs[0] = Q15(0.5) ; // KP : kCoeffs[1] = Q15(0.000) ; // KI : kCoeffs[2] = Q15(0.0) ; // KD : 這三行裡Q15括號裡的值 但是示波器量出來的波形更怪 離我的命令值更遠 : 有時後電感還會發出淒厲的叫聲? 好慘 覺得這樣做不好 有程式碼隱藏起來 fooPID.controlOutput 這樣整個程式沒辦法看 電源領域的程式都偏簡單 不難學 建議還是從基本學起 電感在叫可能是飽和了 看看波型吧 : 3.我另外還有想說把開關切換頻率降低,應此我改了 : #define PWM_Period 0x0257 // PTPER = (Fcy / Fpwm) - 1 : 這行,但是改完以後,一開始輸出PWM的duty(燒錄晶片後 開始RUN的時候 不經過回授) : 原本是0.9但是隨著我改變PWM_Period 的值PWM的DUTY也會跟著變...感覺怪怪的? : 有沒有高手可以解決我的疑問 感恩~~~ duty是(PWM high的時間 / 頻率) 你改大 自然duty變小 觀察示波器可以發現 PWM high的時間沒有改變 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 219.84.57.118

09/19 15:04, , 1F
電感在叫,應該是震盪,程式還沒好就開重載也很怪
09/19 15:04, 1F
文章代碼(AID): #1ESrI-lq (Electronics)
文章代碼(AID): #1ESrI-lq (Electronics)