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