|
- /**
- ******************************************************************************
- * @file PID_Control.h
- * @author willieon
- * @version V0.1
- * @date January-2015
- * @brief PID控制算法頭文件
- * 定義結(jié)構(gòu)體類型以及聲明函數(shù)
- * #define IF_THE_INTEGRAL_SEPARATION 0/1 為積分分離標(biāo)志
- ******************************************************************************
- **/
-
- #ifndef __PID_CONTROL_H__
- #define __PID_CONTROL_H__
-
- #define IF_THE_INTEGRAL_SEPARATION 0
- //#define IF_THE_INTEGRAL_SEPARATION 1 //是否積分分離 0-不分離,1 -分離
-
- typedef struct
- {
- double SetPoint; // 設(shè)定目標(biāo) Desired Value
- double Proportion; // 比例常數(shù) Proportional Const
- double Integral; // 積分常數(shù) Integral Const
- double Derivative; // 微分常數(shù) Derivative Const
- double LastError; // Error[-1]
- double PrevError; // Error[-2]
- double SumError; // Sums of Errors
- }PID;
-
- #if IF_THE_INTEGRAL_SEPARATION //是否積分分離預(yù)編譯開始
-
- double PIDCalc(double NextPoint ,double SepLimit, PID *pp); //帶積分分離的PID運(yùn)算
-
- #else
-
- double PIDCalc( double NextPoint, PID *pp); //不帶積分分離的PID運(yùn)算
-
- #endif //是否積分分離預(yù)編譯結(jié)束
-
- void PIDInit (double SetPoint, double Proportion, double Integral, double Derivative, PID *pp);
-
- #endif
復(fù)制代碼
- /**
- ******************************************************************************
- * @file PID_Control.c
- * @author willieon
- * @version V0.1
- * @date January-2015
- * @brief PID控制算法函數(shù)代碼
- *
- *
- ******************************************************************************
- **/
-
- #include "PID_Control.h"
- #include "math.h"
-
- /*************************************************************************************
- * 名 稱: double PIDCalc( PID *pp, double NextPoint ,double SepLimit)
- * 功 能: PID控制運(yùn)算
- * 入口參數(shù): PID *pp - 定義的運(yùn)算所需變量的結(jié)構(gòu)體
- * NextPoint - 負(fù)反饋輸入值
- * SepLimit - 積分分離上限
- * 出口參數(shù): 返回PID控制量
- * 說 明: 默認(rèn)不進(jìn)行積分分離,如果用戶需要使用積分分離,需在PID_Control.h中
- * 將 #define IF_THE_INTEGRAL_SEPARATION 0 改為
- * #define IF_THE_INTEGRAL_SEPARATION 1
- * 調(diào)用方法: 進(jìn)行積分分離時(shí)入口參數(shù)為3個(gè),具體方法如下:
- * PID PIDControlStruct ; //定義PID運(yùn)算結(jié)構(gòu)體
- * PIDInit(50, 0.24, 0.04, 0.2, &PIDControlStruct);//結(jié)構(gòu)體初始化,注意&符號(hào)不能省
- * ControlData = PIDCalc(ReadData, 200, &PIDControlStruct); //控制量 = PIDCalc(反饋值,積分分離上限,PID運(yùn)算結(jié)構(gòu)體)
- *
- ***************************************************************************************
- */
-
- #if IF_THE_INTEGRAL_SEPARATION
-
- double PIDCalc(double NextPoint ,double SepLimit, PID *pp)
- {
- double dError, Error,Flag;
- Error = pp->SetPoint - NextPoint; // 偏差
- if(abs(Error) > SepLimit) //當(dāng)偏差大于分離上限積分分離
- {
- Flag = 0;
- }
- else //當(dāng)偏差小于分離上限,積分項(xiàng)不分離
- {
- Flag = 1;
- pp->SumError += Error; // 積分
- }
- dError = pp->LastError - pp->PrevError; // 當(dāng)前微分
- pp->PrevError = pp->LastError;
- pp->LastError = Error;
- return (
- pp->Proportion * Error // 比例項(xiàng)
- + Flag * pp->Integral * pp->SumError // 積分項(xiàng)
- + pp->Derivative * dError // 微分項(xiàng)
- );
- }
-
- #else
-
- double PIDCalc( double NextPoint, PID *pp)
- {
- double dError, Error;
- Error = pp->SetPoint - NextPoint; // 偏差
- pp->SumError += Error; // 積分
- dError = pp->LastError - pp->PrevError; // 當(dāng)前微分
- pp->PrevError = pp->LastError;
- pp->LastError = Error;
- return (pp->Proportion * Error // 比例項(xiàng)
- + pp->Integral * pp->SumError // 積分項(xiàng)
- + pp->Derivative * dError // 微分項(xiàng)
- );
- }
-
- #endif
-
-
- /*************************************************************************************
- * 名 稱: double PIDCalc( PID *pp, double NextPoint ,double SepLimit)
- * 功 能: PID初始化設(shè)定
- * 入口參數(shù): PID *pp - 定義的運(yùn)算所需變量的結(jié)構(gòu)體
- * SetPoint - 設(shè)定的目標(biāo)值
- * Proportion,Integral ,Derivative - P,I,D系數(shù)
- * 出口參數(shù): 無
- * 說 明:
- * 調(diào)用方法: PID PIDControlStruct ; //定義PID運(yùn)算結(jié)構(gòu)體
- * PIDInit(50, 0.24, 0.04, 0.2, &PIDControlStruct);//結(jié)構(gòu)體初始化,注意&符號(hào)不能省
- * 因?yàn)楹瘮?shù)需要傳入一個(gè)指針,需要對(duì)結(jié)構(gòu)體取首地址傳給指針
- *
- ***************************************************************************************
- */
-
-
- void PIDInit (double SetPoint, double Proportion, double Integral, double Derivative, PID *pp)
- {
- pp -> SetPoint = SetPoint; // 設(shè)定目標(biāo) Desired Value
- pp -> Proportion = Proportion; // 比例常數(shù) Proportional Const
- pp -> Integral = Integral; // 積分常數(shù) Integral Const
- pp -> Derivative = Derivative; // 微分常數(shù) Derivative Const
- pp -> LastError = 0; // Error[-1]
- pp -> PrevError = 0; // Error[-2]
- pp -> SumError = 0; // Sums of Errors
-
- //memset ( pp,0,sizeof(struct PID)); //need include "string.h"
- }
復(fù)制代碼
好了,現(xiàn)在把卡爾曼濾波和PID算法聯(lián)合起來,在VS平臺(tái)中運(yùn)行實(shí)驗(yàn)
- #include "kalman.h"
-
- #include "stdio.h"
- #include "stdlib.h"
- #include "PID_Control.h"
-
- void main(void)
-
- {
- KalmanCountData k;
- PID PIDControlStruct;
- Kalman_Filter_Init(&k);
- PIDInit(50, 1, 0.04, 0.2, &PIDControlStruct);
- int m,n;
-
- double out;
-
- for(int a = 0;a<80;a++)
- {
- m = 1+ rand() %100;
- n = 1+ rand() %100;
- Kalman_Filter((float)m,(float)n,&k);
- out = PIDCalc(k.Angle_Final, &PIDControlStruct);
- printf("%3d and %3d is %6f -pid- %6f\r\n",m,n,k.Angle_Final,out);
-
- }
- }
復(fù)制代碼
寫到此處,我覺得,自平衡小車的兩座大山應(yīng)該對(duì)讀者來說不是問題了,只要會(huì)調(diào)用函數(shù),會(huì)做參數(shù)整定,就完全可以解決數(shù)據(jù)采集和數(shù)據(jù)融合以及控制了。
好吧!我承認(rèn)我的代碼是仿照 STM32的庫的風(fēng)格寫的,真心覺得這種代碼風(fēng)格很NB。學(xué)習(xí)ing!
代碼本人測(cè)試過,如果有不足之處望不吝賜教!請(qǐng)直接跟帖討論
我最近在做的平衡車,硬件清單:
香蕉電機(jī)+輪子 6.4元*2
STM32F103C8Tb 最小系統(tǒng)板 31.5元*1
newwayL298N 光耦隔離電機(jī)驅(qū)動(dòng)板 30元 *1
MPU6050姿態(tài)傳感器 9.3元*1
LM2596S DC-DC 降壓電源模塊 3.2元*1
藍(lán)牙4.0 BLE從模塊串口通信+直驅(qū)模式 CC2540 CC2541 RF-BM-S02 23元*1
光電測(cè)速傳感器模塊 4.8元*2
小車底盤用自己的小雕刻機(jī)雕的亞克力板,感覺可以用薄的鋁板做中間層,這樣底層放光電測(cè)速和姿態(tài)傳感器+薄鋁底板+電動(dòng)機(jī)驅(qū)動(dòng)板+鋁底板+STM32主控,可以屏蔽一部分干擾,在inventor里面建模畫好圖!
之前沒有用帶光耦隔離的驅(qū)動(dòng),速度一快STM32就死機(jī),后來換光耦隔離才解決!
|
|