Re: [問題]dspic控制converter
: 最近在
用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
討論串 (同標題文章)
完整討論串 (本文為第 2 之 2 篇):