|
本帖最后由 kaixuan520 于 2019-7-12 10:04 編輯
位置式PID控制
位置式PID控制是指在積分環(huán)節(jié),對(duì)從0時(shí)刻到當(dāng)前時(shí)刻的所有偏差進(jìn)行積分,是非遞推式的全局積分。
增量式PID控制
和位置式PID控制不同,增量式PID控制將當(dāng)前時(shí)刻的控制量和上一時(shí)刻的控制量做差,以差值為新的控制量,是一種遞推式的算法。
增量式PID控制的主要優(yōu)點(diǎn)為:
①算式中不需要累加。控制增量Δu(k)的確定僅與最近3次的采樣值有關(guān),容易通過(guò)加權(quán)處理獲得比較好的控制效果;
②計(jì)算機(jī)每次只輸出控制增量,即對(duì)應(yīng)執(zhí)行機(jī)構(gòu)位置的變化量,故機(jī)器發(fā)生故障時(shí)影響范圍小、不會(huì)嚴(yán)重影響生產(chǎn)過(guò)程;
③手動(dòng)—自動(dòng)切換時(shí)沖擊小。當(dāng)控制從手動(dòng)向自動(dòng)切換時(shí),可以作到無(wú)擾動(dòng)切換[2] 。
由于增量式需要對(duì)控制量進(jìn)行記憶,所以對(duì)于不帶記憶裝置的系統(tǒng),只能使用位置式PID控制方式進(jìn)行控制。
公式:
S90712-08471440.jpg (104.42 KB, 下載次數(shù): 103)
下載附件
2019-7-12 08:48 上傳
上代碼:
使用定時(shí)器3作為PWM輸出,頻率為20KHz,調(diào)節(jié)占空比0-100%來(lái)改變電機(jī)速度
//TIM3初始化和輸出GPIO初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
GPIO_InitTypeDef GPIO_InitTypeStruct;
GPIO_InitTypeStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitTypeStruct.GPIO_Pin = GPIO_Pin_6;
GPIO_InitTypeStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitTypeStruct);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitTypeStruct;
TIM_TimeBaseInitTypeStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitTypeStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitTypeStruct.TIM_Period = 99;
TIM_TimeBaseInitTypeStruct.TIM_Prescaler = 35; //20KHz
TIM_TimeBaseInitTypeStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitTypeStruct);
TIM_OCInitTypeDef TIM_OCInitTypeStruct;
TIM_OCInitTypeStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitTypeStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitTypeStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitTypeStruct.TIM_Pulse = DutyCycle; //占空比
TIM_OC1Init(TIM3,&TIM_OCInitTypeStruct);
TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);
TIM_Cmd(TIM3,ENABLE);
//使用定時(shí)器1作輸入捕獲,PWM輸入模式,
//GPIO和定時(shí)器1初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitTypeStruct;
GPIO_InitTypeStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitTypeStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitTypeStruct.GPIO_Pin = GPIO_Pin_8;
GPIO_Init(GPIOA,&GPIO_InitTypeStruct);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitTypeStruct;
TIM_TimeBaseInitTypeStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitTypeStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitTypeStruct.TIM_Period = TIM1_ARR;
TIM_TimeBaseInitTypeStruct.TIM_Prescaler = TIM1_PSC;
TIM_TimeBaseInitTypeStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitTypeStruct);
TIM_ICInitTypeDef TIM_ICInitTypeStruct;
TIM_ICInitTypeStruct.TIM_Channel = TIM_Channel_1;
TIM_ICInitTypeStruct.TIM_ICFilter = 0x0f;//對(duì)輸入的脈沖進(jìn)行濾波
TIM_ICInitTypeStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitTypeStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitTypeStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_PWMIConfig(TIM1,&TIM_ICInitTypeStruct);
TIM_SelectInputTrigger(TIM1,TIM_TS_TI1FP1); //選擇輸入觸發(fā)方式
TIM_SelectSlaveMode(TIM1,TIM_SlaveMode_Reset); //設(shè)置從機(jī)模式
TIM_SelectMasterSlaveMode(TIM1,TIM_MasterSlaveMode_Enable);//
NVIC_InitTypeDef NVIC_InitTypeStruct;
NVIC_InitTypeStruct.NVIC_IRQChannel = TIM1_CC_IRQn;//輸入捕獲中斷線
NVIC_InitTypeStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitTypeStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitTypeStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitTypeStruct);
TIM_ITConfig(TIM1,TIM_IT_CC1,ENABLE);//使能通道1捕獲中斷
TIM_ClearITPendingBit(TIM1,TIM_IT_CC1);
TIM_Cmd(TIM1,ENABLE);
//通過(guò)輸入捕獲中斷函數(shù)來(lái)取得電機(jī)編碼器的頻率,占空比,周期,從而計(jì)算出速度
uint16_t IC1V;
uint16_t IC2V;
void TIM1_CC_IRQHandler(void)
{
TIM_ClearITPendingBit(TIM1,TIM_IT_CC1);
IC1V = TIM_GetCapture1(TIM1);//周期us
IC2V = TIM_GetCapture2(TIM1);//占空比
if(IC1V!=0)
{
IC1V+=1;
IC2V+=1;
float d1 = ((float)IC1V/1000);
float d2 = ((float)IC2V/1000);
float f = (float)IC1V/1000000;
DutyCycle = 100*d2/d1;//占空比
Frequency = 1/f; //計(jì)算出編碼器的頻率
Period = (float)IC1V/1000;//周期ms
} else {
Frequency = 0;
DutyCycle = 0;
}
}
//再使用一個(gè)100ms的定時(shí)器來(lái)每秒10次的數(shù)據(jù)采集和控制,定時(shí)器初始化就不貼了,具體看附件
float M_PWM = 0;
float M_Speed = 0;
uint8_t xi=0;
void TIM2_IRQHandler(void)//100ms定時(shí)器中斷
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)
{
//if(Frequency!=0) {
GPIOB->ODR ^= GPIO_Pin_5;
M_Speed = Frequency;
M_Speed /= 20;
Frequency = 0;
int value = Compute_PID((uint16_t)(M_Speed*100));//進(jìn)行PID計(jì)算,返回PWM占空比
int y = value;
float n = value/100;
M_PWM += n;
if(xi==0) {//沒(méi)500ms向串口發(fā)送一次數(shù)據(jù)
printf("當(dāng)前轉(zhuǎn)速:%0.2f\r\n",M_Speed);
printf("目標(biāo)轉(zhuǎn)速:%d\r\n",(uint16_t)PID_Struct->SetPoint/100);
printf("P:%0.4f,I:%0.4f,D:%0.4f,LE:%d,PE:%d,VO:%d,MO:%d\r\n",//PID相關(guān)參數(shù)信息,
PID_Struct->Proportion,PID_Struct->Integral,PID_Struct->Derivaltive,
PID_Struct->LastError,PID_Struct->PreError,y,(int)M_PWM);
printf("Period:%0.4fms, Frequency:%0.4fHz, DutyCycle:%0.4f%%\r\n",Period,Frequency,DutyCycle);//PWM輸出的周期,頻率,占空比
printf("\r\n\r\n");
}
xi++;
xi%= 5;
if(M_PWM>100)M_PWM = 100; //防止越過(guò)最大和最小控制量
if(M_PWM<0)M_PWM = 0;
TIM_SetCompare1(TIM3,(uint16_t)M_PWM);
//}
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}
PID算法結(jié)構(gòu)體
typedef struct {
int SetPoint; //設(shè)定值
long SumError; //累計(jì)誤差
double Proportion; //比例
double Integral; //積分
double Derivaltive; //微分
int LastError; //上次誤差
int PreError; //上上次誤差
} PID_S;
static PID_S PID_Struct_;
static PID_S *PID_Struct = &PID_Struct_;
//main:
/PID參數(shù)整定方法請(qǐng)轉(zhuǎn)各大論壇查找教程,這里不詳細(xì)介紹
PID_Struct->Proportion = 1.92;
PID_Struct->Integral = 1.65;
PID_Struct->Derivaltive = 0.116;
PID_Struct->SetPoint = 80*100;
//PID計(jì)算
int Compute_PID(uint16_t nowValue)
{
register int iError,Ouk;
iError = PID_Struct->SetPoint - nowValue;//當(dāng)前誤差
// PID_Struct ->SumError += iError;
Ouk = (PID_Struct->Proportion * iError)
- (PID_Struct->Integral * PID_Struct->LastError)
+ (PID_Struct->Derivaltive *PID_Struct->PreError);
PID_Struct->PreError = PID_Struct->LastError;
PID_Struct->LastError = iError;
return Ouk;
}
電路方面制作
電機(jī)使用12V掃地機(jī)器人的電機(jī),編碼器使用每圈20次脈沖的光電編碼器
使用LM393電壓比較器對(duì)光電編碼器輸出進(jìn)行穩(wěn)定和優(yōu)化
電路圖:
a.PNG (27.65 KB, 下載次數(shù): 118)
下載附件
2019-7-12 09:16 上傳
P90712-091716(1).jpg (1.76 MB, 下載次數(shù): 116)
下載附件
2019-7-12 09:18 上傳
P90712-091725(1).jpg (1.6 MB, 下載次數(shù): 101)
下載附件
2019-7-12 09:18 上傳
編碼器輸出波形圖:
P90712-092253(1).jpg (2.05 MB, 下載次數(shù): 109)
下載附件
2019-7-12 09:23 上傳
波形還是比較完美的
電機(jī)驅(qū)動(dòng)使用L298N,連接圖:
1562895548198.jpg (2.62 MB, 下載次數(shù): 114)
下載附件
2019-7-12 09:39 上傳
串口打印數(shù)據(jù):
b.PNG (67.89 KB, 下載次數(shù): 97)
下載附件
2019-7-12 09:38 上傳
視頻演示PWM輸出效果:https://share.weiyun.com/5idpKLF
增大阻力和調(diào)節(jié)速度都能快速回到設(shè)定值以下為附件信息
STM32源碼:
PID_直流調(diào)速.rar
(349.35 KB, 下載次數(shù): 157)
2019-7-12 09:42 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
PID學(xué)習(xí)資料:
PID算法.zip
(1.81 MB, 下載次數(shù): 113)
2019-7-12 09:46 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
評(píng)分
-
查看全部評(píng)分
|