[英]wiringPi library of Raspberry Pi 2 to rotate bidirectional DC servo motor
[英]Motor PI regulator structure code
我實際上正在基於freeRTOS的機器人項目上工作。 PI控制器控制機器人的車輪速度時遇到一些問題。
#define To 100 // 100 ms
#define Te 5 // 5 ms
#define Kp 0.01
#define Ti 10 //0.1*To
#define Ki 0.05/10 //Te/ti
void corrNum(int consigneVitesse) // takes speed as parameter
{
int eL,eR = 0; errors left and right
float cdeL = 0 ;
float UpL = 0 ;
int dutyL = 0 ;
float cdeR = 0 ;
float UpR = 0 ;
int dutyR = 0 ;
float UiL= 0 ;
float UiR = 0 ;
if(consigneVitesse)
{
tickL = quadEncoder_GetSpeedL();
tickR = quadEncoder_GetSpeedR();
eL = (int)(consigneVitesse - tickL);
eR = (int)(consigneVitesse - tickR);
UpL = Kp*eL ;
UpR = Kp*eR ;
UiL= UiL + Kp*Ki*eL ;
UiR= UiR + Kp*Ki*eR ;
UiL_prev = UiL ;
UiR_prev = UiR ;
cdeL = UpL + UiL ;
cdeR = UpR + UiR ;
dutyL = cdeL < 100 && cdeL > -100 ? (int)cdeL +100 : 200 ;
dutyR = cdeR < 100 && cdeR > -100 ? (int)cdeR +100 : 200 ;
motorLeft_SetDuty(dutyL);
motorRight_SetDuty(dutyR);
HAL_Delay(5); // sampling period 5 ms
term_printf("MOTOR LEFT ::::::> CMD : %d SPEED : %d Err : %d DUTY : %d\n\r",consigneVitesse,tickL,eL,dutyL`enter code here`);
term_printf("MOTOR RIGHT ::::::> CMD : %d SPEED : %d Err : %d DUTY : %d \n\r",consigneVitesse,tickR,eR,dutyR);;
tickL = 0 ;
tickR = 0;
}
else
{
motorLeft_SetDuty(100);
motorRight_SetDuty(100);
}
}`
問題是,當誤差達到0.0而不是穩定時,它就會開始振盪。
目前尚不清楚您如何在此解決方案中使用FreeRTOS-片段中沒有FreeRTOS調用,非RTOS HAL_delay()
和時間關鍵控制循環中的終端輸出將無濟於事-您只能輸出57個字符5毫秒內-您沒有時間輸出文本。
錯誤信號的計算錯誤是編碼器提供的相對位置而不是速度; 您必須根據位置隨時間的變化來計算速度。
您應該將任務分配給控制回路,並使用RTOS時序來確保高效而准確的調度。 該任務應相對於其他任務以足夠高的優先級運行,以確保無抖動定時。
以下應視為偽代碼; 我不熟悉FreeRTOS API,因此OS調用不是真實的,並且我沒有處理實例化任務本身,也沒有處理擴展和其他您沒有提供足夠信息的細節-建議這樣做您應該從中獲取的控制器結構-而不是逐字記錄實際的代碼:
typedef enum
{
LEFT = 0,
RIGHT = 1
} tMotorId
volatile static struct
{
float integral ;
int speed ;
int previous_position ;
} motor_ctrl_data[2] = {{0,0},{0,0}} ;
void setSpeed( tMotorId id, int speed )
{
motor_ctrl_data[id] = speed ;
}
void motor_ctrl_task()
{
// Configure RTOS time for 5ms update period
OS_TIMER timer = creatTimer( 5 ) ;
startTimer( timer ) ;
// Get initial encoder counts
motor_ctrl_data[LEFT].previous_position = getEncoder(LEFT) ;
motor_ctrl_data[RIGHT].previous_position = getEncoder(RIGHT) ;
// PI control loop
for(;;)
{
// Loop update timer wait
waitTimer( timer ) ;
// For each motor
for( int m = 0; m < 2; m++ )
{
// Calculate speed
int speed = getEncoder[m] - motor_ctrl_data[m].previous_position ;
// Calculate speed error
int error = motor_ctrl_data[m].speed - speed[m] ;
// Calculate error integral
motor_ctrl_data[m].integral += error[m] ;
motorDuty( LEFT, Kp * error + Ki * motor_ctrl_data[m].integral ) ;
}
}
}
當然,這本身並不能解決振盪,但是至少是一種控制器結構能夠控制給定的適當系數。 要調整環路,請設置Ki = 0並增加Kp,直到電機盡可能快地運動而沒有振盪。 這不會使您達到目標速度,因為在目標上誤差為零,因此僅Kp無法工作。 然后開始增加Ki直到達到目標速度。 即使是很小的Ki,最終也能達到目標速度,但動態響應會很慢。 太多,您將獲得超調或振盪。
根據電動機的動態響應,您可能需要進行其他調整,例如積分限制或死區補償。 您甚至可以從微分項中受益,但是對於簡單的速度控制器而言,這通常是不必要的,並且通常很難調整。
如果需要輸出調試數據,請讓循環將調試數據寫入共享變量(例如,如果使用上述建議的結構,則在motor_ctrl_data
中),並以較低的優先級任務以終端輸出可以維持的速率異步打印它們。
蒂姆·韋斯科特(Tim Wescott)的文章“ 沒有博士學位的PID ”可能是有用的讀物。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.