PID算法巡线
- 格式:doc
- 大小:99.00 KB
- 文档页数:10
割草机器人基于PID控制算法的巡线方法摘要:智能割草机人巡线行走回充电站是一个运动控制的难点,本文介绍了利用经典的PID算法,结合信号采集模块,设计控制算法,通过对测试结果数据分析,对PID参数实时调整,得到了一个完美的工况参数,达到了割草机器人完美沿着边界线行走的结果。
关键词:智能割草机器人;PID算法;巡线运动控制;0 引言随着半导体的发展,智能割草机器人已经在很大比例上取代了传统的人工手推式燃油割草机。
它有着自动运行、自助回充、自动进行路径规划的特点,极大的降低了人的参与。
在欧美市场,智能割草机器人已经取代了传统割草机百分之四十多的市场。
智能智能割草机器人由中央控制单元、电机驱动单元、边界信号采集单元、信号发射单元、安全检测单元、充电单元、UI单元及APP和服务器等模块组成的一个复杂的系统。
1智能割草机的工作原理目前市场上主流的智能割草机大多都是预埋线的方案。
从大的模块上分,这个系统由机器人小车系统、边界信号发射基站和具有导电性能的边界线三部分组成。
首先边界信号发射模块通过一根导线连接形成一个闭环,机器人只能在这根导线围成的圈里面工作。
边界线的形状是根据实际的草地形状随机延伸,是不规则的。
规律性的边界信号通过这根导线发射出去。
机器内部的边界信号采集单元实时的采集数据,把采集到的数据传送给主控单元,主控单元根据信号的状态来发送命令给驱动单元,驱动单元驱动行走电机和割草电机的运行。
我们定义采集到第一个信号是下降沿,此信号采集模块在边界线圈内部,如果采集到的第一个信号是上升沿,则此信号采集模块在边界线圈的外部。
机器的前端安装有3个信号采集模块,3个信号头把感应接收到的信号放大处理后,判断出来自己的位置是位于线圈内部还是线圈外部。
如果3个信号头都在边界线圈内部,则主控发命令使驱动模块驱动电机前进,割草电机转动作业。
当信号头传输给主控的状态是在边界线外时,主控模块发送停机命令。
机器停下来后,重新检测信号是否在界外,如果是,机器做后退转弯的逻辑,转到边界线圈内来继续工作。
1.Arduino 智能小车寻迹原理寻迹采用的主要原理就是红外探测法,即利用红外线在不同颜色的物体表面具有不同的反射性质的特点Arduino 单片机就是以是否收到反射回来的红外光为依据来确定黑线的位置和小车的行走路线。
红外探测器探测距离有限,一般最大不应超过15cm。
对于发射和接收红外线的红外探头,可以自己制作或直接采用集成式红外探头2.Arduino 寻迹模块简介3.Arduino pwm 调速4.PID算法5.PID 算法与寻迹6.代码:.#include "pid.h"....#ifdef ARDUINO_DEBUG..int debugLeftSpeed;..int debugRightSpeed;..uint8_t debugIrs = 0;..#endif....const float motorSpeed = 140; //小车输出速度..const int IR_PIN[] = {A0, A1, A2, A3, A4}; //寻迹板引脚定义..const int IN_A1 = 7; //..const int IN_A2 = 6; //..const int IN_B1 = 5; //..const int IN_B2 = 4; //..const int _pwmLeftPin = 10;//左边 pwm 引脚..const int _pwmRightPin = 11;//右边 pwm 引脚..pid_t pid;..float pidValue = 0; //pid 值..bool turnFlag = false;....void setup(void)..{..int i;....//设置引脚功能..pinMode(IN_A1, OUTPUT); ..pinMode(IN_A2, OUTPUT); ..pinMode(IN_B1, OUTPUT); ..pinMode(IN_B2, OUTPUT); ....//设置寻迹板引脚为 INPUT..for (i = 0; i < 5; i++) { .pinMode(IR_PIN[i], INPUT);..}......pid.sampleTime = SAMPLE_TIME;//初始化采样时间..pid.Kp = KP_VALUE;..pid.Ki = KI_VALUE;..pid.Kd = KD_VALUE;..pid.error = 0;..pid.previous_error = 0;....Serial.begin(115200);//设置波特率..delay(5000);//延时 5s....analogWrite(_pwmLeftPin, motorSpeed );.analogWrite(_pwmRightPin, motorSpeed ); ....goForward();//小车向前行驶....return;..}........../**..获取寻迹板红外数据..*/..uint8_t getIrData(void)..{..int i, j;..uint8_t level;..uint8_t temp;..uint8_t irs[9] = {0};....//获取10组数据..for (j = 0; j < 9; j ++) {....for (i = 0; i < 5; i++) {..level = digitalRead(IR_PIN[i]); ..if (level) {..bitSet(irs[j], i);//设置对应位为1 ..} else {..bitClear(irs[j], i);//设置对应为0 .}..}..}....//对所有的数据进行排序..for (i = 0; i < 9 - 1; i ++) {..for (j = 0; j < 9 - i - 1; j ++) { ..if (irs[j] > irs[j + 1]) {..temp = irs[j];..irs[j] = irs[j + 1];..irs[j + 1] = temp;..}..}..}...#ifdef ARDUINO_DEBUG..debugIrs = irs[4];..#endif....//返回中间值..return irs[4];..}..../**..计算误差值..@param irs :获取的寻迹传感器的值..*/..int calcErrorByIrsValue(uint8_t irs) ..{..int curError = pid.error;....switch (irs) {..case B11110: curError = -8; break; ....case B10000:..case B11000: curError = -7; break; ....case B11100: curError = -6; break; ..case B11101: curError = -4; break; ..case B11001: curError = -2; break; ....case B00000:..case B11011: curError = 0; break; ...case B10011: curError = 2; break;..case B10111: curError = 4; break;..case B00111: curError = 6; break;....case B00011:..case B00001: curError = 7; break;....case B01111: curError = 8; break;..case B11111: curError = pid.error > 0 ? 9 : - 9; break; ..}....return curError;..}...../**..排序函数..*/..void _sortData(int *p, int n)..{..int temp;..int i, j;....for (i = 0; i < n - 1; i ++) {..for (j = 0; j < n - i - 1; j ++) { ..if (p[j] > p[j + 1]) {..temp = p[j];..p[j] = p[j + 1];..p[j + 1] = temp;..}..}..}....return;..}....../**..计算误差值..*/..void calcCurrentError(void) ..{..int i;..uint8_t irs;.float sum = 0;..int errorData[10];....//获取 10组数据..for (i = 0; i < 10; i ++) {..irs = getIrData();..errorData[i] = calcErrorByIrsValue(irs); ..}...._sortData(errorData, 10);....for (i = 1; i < 10 - 1; i ++) {..sum += errorData[i];..}...pid.error = sum / 8;....return;..}....void turnRight(void)..{..digitalWrite(IN_A1, LOW); ..digitalWrite(IN_A2, HIGH); ..digitalWrite(IN_B1, HIGH); ..digitalWrite(IN_B2, LOW); ..}....void turnLeft(void)..{..digitalWrite(IN_A1, HIGH); ..digitalWrite(IN_A2, LOW); ..digitalWrite(IN_B1, LOW); ..digitalWrite(IN_B2, HIGH); ..}....void goForward(void)..{..digitalWrite(IN_A1, HIGH); ..digitalWrite(IN_A2, LOW); ..digitalWrite(IN_B1, HIGH); ..digitalWrite(IN_B2, LOW); ..}.../**..小车控制函数..@param pidValue : 计算出来的 pid 值..@param turnFlag : 方向标志..*/..void motorControl(float pidValue, bool turnFlag)..{....int leftMotorSpeed = 0;..int rightMotorSpeed = 0;....//根据 pid 的值调整小车左右电机的速度..leftMotorSpeed = constrain((motorSpeed + pidValue), -255, 255); ..rightMotorSpeed = constrain((motorSpeed - pidValue), -255, 255); ...//当转弯标志被设置时,则需要使用左边与右边的轮子正转与反转来调整,提高调整速度..if (turnFlag) {..//按照较大的 pwm 值进行调整,速度最快,左边速度与右边速度一致..if (abs(leftMotorSpeed) > abs(rightMotorSpeed)) {..leftMotorSpeed = abs(leftMotorSpeed);..rightMotorSpeed = leftMotorSpeed;..} else {..rightMotorSpeed = abs(rightMotorSpeed);..leftMotorSpeed = rightMotorSpeed;..}..} else {..//当速度为正时,则取原值,当速度为负时,则取相反数,保持 pwm 的值为正值..leftMotorSpeed = leftMotorSpeed > 0 ? leftMotorSpeed : -leftMotorSpeed; ..rightMotorSpeed = rightMotorSpeed > 0 ? rightMotorSpeed : -rightMotorSpeed; ..}....analogWrite(_pwmLeftPin, leftMotorSpeed ); ..analogWrite(_pwmRightPin, rightMotorSpeed); ....#ifdef ARDUINO_DEBUG..debugLeftSpeed = leftMotorSpeed ;..debugRightSpeed = rightMotorSpeed;..#endif....return;..}..../***..计算 pid 的值.*/..bool calculatePid(float *pValue)..{..float P = 0;..static float I = 0 ;..float D = 0 ;..static unsigned long lastTime = 0; ..unsigned long now = millis();..int timeChange = now - lastTime; ....//没有到达采样时间..if (timeChange < pid.sampleTime) { ..return false;..}...P = pid.error;//错误值..I = I + pid.error;//积累误差..D = pid.error - pid.previous_error;//计算错误的变化率....*pValue = (pid.Kp * P) + (pid.Ki * I) + (pid.Kd * D) + 1; ..*pValue = constrain(*pValue, -motorSpeed,motorSpeed);....pid.previous_error = pid.error;..lastTime = now;....return true;..}....#if ARDUINO_DEBUG..void print_debug()..{..int i;..String irs2bin = String(debugIrs, 2); ..int len = irs2bin.length();..if (len < 5) {..for (i = 0; i < 5 - len; i++) {..irs2bin = "0" + irs2bin;..}..}....Serial.print("IRS : ");..Serial.print(irs2bin);..Serial.print(" ML:");..Serial.print(debugLeftSpeed);..Serial.print(" MR:");..Serial.print(debugRightSpeed);..Serial.print(" ERROR:");..Serial.print(pid.error, OCT);..Serial.println();..}..#endif..../**..计算运动方向..*/..void calcDirection(void)..{....if (pid.error >= 7 && pid.error <= 9) {..turnLeft();..turnFlag = true;..} else if (pid.error >= -9 && pid.error <= -7) { ..turnRight();..turnFlag = true;..} else {..goForward();..turnFlag = false;..}....return;..}....void loop(void)..{..bool ok;..float pidValue;....//计算错误值..calcCurrentError();..//计算 pid 的值..ok = calculatePid(&pidValue);..if (ok) {..calcDirection();//计算小车运动方向..motorControl(pidValue, turnFlag);//控制电机..}....//delay(500);....#if ARDUINO_DEBUG ..print_debug(); ..delay(1000); ..#endif....return;..}.。
#include <PID_v1.h>double Setpoint, Input, Output;void PID_MY();double Kp=5, Ki=0.8, Kd=5;void fun1();void fun2();int num1,num2,num3,num4,num5,num6,num7,num8;//8路循迹PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd,P_ON_M, DIRECT);int pinI1=26;//定义I1接口int pinI2=27;//定义I2接口int pinI3=28;int pinI4=29;int pinI5=30;//定义I1接口int pinI6=31;//定义I2接口int pinI7=32; //一high一LOW 正转int pinI8=33;int P1=2;//定义EA(PWM调速)接口int P2=3;//定义EA(PWM调速)接口int P3=4;//定义EA(PWM调速)接口int P4=5;//定义EA(PWM调速)接口//1,3左同侧电机,对应PWM1void FORWARD(int PWM1,int PWM2);void BACK(int PWM1,int PWM2);void LEFT(int PWM1,int PWM2);void RIGHT(int PWM1,int PWM2);void STOP();void PID_my();void input_hong();void hong();void setup(){pinMode(pinI1,OUTPUT);pinMode(pinI2,OUTPUT);pinMode(pinI3,OUTPUT);pinMode(pinI4,OUTPUT);pinMode(pinI5,OUTPUT);pinMode(pinI6,OUTPUT);pinMode(pinI7,OUTPUT);pinMode(pinI8,OUTPUT);pinMode(P1,OUTPUT);pinMode(P2,OUTPUT);pinMode(P3,OUTPUT);pinMode(P4,OUTPUT);//initialize the variables we're linked to Input=0;Setpoint = 0;//turn the PID onmyPID.SetMode(AUTOMATIC);myPID.SetSampleTime(10);myPID.SetOutputLimits(-255, 255);attachInterrupt(4, fun1,RISING);//当电平上升时,触发中断函数,21 attachInterrupt(3, fun2,RISING);//22pinMode(P1,OUTPUT);pinMode(P2,OUTPUT);pinMode(pinI1,OUTPUT);pinMode(pinI2,OUTPUT);pinMode(pinI3,OUTPUT);pinMode(pinI4,OUTPUT);//马达pinMode(19,INPUT); //1pinMode(20,INPUT); //8pinMode(48,INPUT); //2pinMode(46,INPUT); //3pinMode(44,INPUT); //4pinMode(36,INPUT); //5pinMode(38,INPUT); //6pinMode(40,INPUT); //7delay(4000);PID_MY();}void loop() {}void PID_MY(){int PWM1,PWM2;while(1){hong();input_hong();//根据红外输入inputpute();if(Output>=0){PWM1=255;PWM2=(int)(255-Output);}else{PWM1=(int)(255+Output);PWM2=255;}FORWARD(PWM1,PWM2);if(num5==HIGH&&num6==HIGH&&num7==HIGH){LEFT(255,255);delay(100);}if(num3==HIGH&&num4==HIGH&&num5==HIGH&&num6==HIGH) {detachInterrupt(3);detachInterrupt(4);FORWARD(255,255);delay(500);STOP();return;}}}void input_hong(){if(num2==HIGH)Input = -16;else if(num3==HIGH) Input = -8;else if(num4==HIGH) Input = -0.5;else if(num5==HIGH) Input = 1.5;else if(num6==HIGH) Input = 8;else if(num7==HIGH) Input = 16;}void hong(){num1=digitalRead(20); num2=digitalRead(36);num3=digitalRead(38);num4=digitalRead(40);num5=digitalRead(44);num6=digitalRead(46);num7=digitalRead(48);num8=digitalRead(21);// 用num1-8保存从左到右8个传感器的状态 }void fun1(){do{num4=digitalRead(44);RIGHT(255,255);}while(num4!=HIGH);}void fun2(){do{num5=digitalRead(36);LEFT(255,255);}while(num5!=HIGH);}void FORWARD(int PWM1,int PWM2){analogWrite(P1,PWM1);digitalWrite(pinI1,LOW);digitalWrite(pinI2,HIGH);analogWrite(P2,PWM2);digitalWrite(pinI3,LOW);digitalWrite(pinI4,HIGH);analogWrite(P3,PWM1);digitalWrite(pinI5,LOW);digitalWrite(pinI6,HIGH);analogWrite(P4,PWM2);digitalWrite(pinI7,LOW);digitalWrite(pinI8,HIGH);}void BACK(int PWM1,int PWM2) {analogWrite(P1,PWM1);digitalWrite(pinI1,HIGH);digitalWrite(pinI2,LOW);analogWrite(P2,PWM2);digitalWrite(pinI3,HIGH);digitalWrite(pinI4,LOW);analogWrite(P3,PWM1);digitalWrite(pinI5,HIGH);digitalWrite(pinI6,LOW);analogWrite(P4,PWM2);digitalWrite(pinI7,HIGH);}void LEFT(int PWM1,int PWM2) {analogWrite(P1,PWM1);digitalWrite(pinI2,LOW);digitalWrite(pinI1,HIGH);analogWrite(P2,PWM2);digitalWrite(pinI4,HIGH);digitalWrite(pinI3,LOW);analogWrite(P3,PWM1);digitalWrite(pinI6,LOW);digitalWrite(pinI5,HIGH);analogWrite(P4,PWM2);digitalWrite(pinI7,LOW);digitalWrite(pinI8,HIGH);}void RIGHT(int PWM1,int PWM2) {analogWrite(P1,PWM1);digitalWrite(pinI2,HIGH);digitalWrite(pinI1,LOW);analogWrite(P2,PWM2);digitalWrite(pinI4,LOW);analogWrite(P3,PWM1); digitalWrite(pinI6,HIGH); digitalWrite(pinI5,LOW); analogWrite(P4,PWM2); digitalWrite(pinI8,LOW); digitalWrite(pinI7,HIGH); }void STOP(){digitalWrite(pinI1,HIGH); digitalWrite(pinI2,HIGH); digitalWrite(pinI3,HIGH); digitalWrite(pinI4,HIGH); digitalWrite(pinI5,HIGH); digitalWrite(pinI6,HIGH); digitalWrite(pinI7,HIGH); digitalWrite(pinI8,HIGH); }。
基于PID算法的巡线小车的设计与实现作者:任翠平来源:《电子技术与软件工程》2016年第12期本文描述了如何使用PID算法实现小车巡线的运动,针对依靠直流电机驱动双轮小车平台,依靠引导线进行运动的特点,设计了基于PID驱动算法与加权平均扫描法,实现对小车的巡线控制。
在算法中对比,整合PID的三个参数,使在小车巡线过程中协调发挥作用,实现在离散状态下小车巡线的精确控制。
通过实践表明该算法具有适应性强,控制精度高,调整误差小的优点。
【关键词】PID 算法巡线加权平均扫描1 引言PID技术广泛应用于各种领域,其因为结构简单,参数明确,容易实现,其P(Pro-portional)是比例项,I(Integral)是积分项,D(Derivative)是微分项。
PID能够精确控制各种被控对象,比如在控制小车巡线方面。
在实际应用中可以采用P,PI,PD或PID等控制形式,同时约可以加入人工智能模糊控制,在使用PID时要根据被控对象的系统响应变化特点作出选择和调整。
PID算法的原理是根据设定值r(t)与输出值c(t)之间的偏差e(t)=r(t)-c(t),通过线性组合按照比例,积分,微分运算后生存控制变量,及时控制小车巡线运动。
PID系统结构如图1所示。
其中,u(t)为输出项;为比例放大系数;为积分时间;为微分时间; e(t)为误差值;为控制量基准值。
比例放大系数能加快系统响应速度,但容易产生超调现象,在机器人巡线行走过程中会出现左右搬动现象;积分时间参数主要作用是消除系统的稳态误差;微分时间参数作用是改善系统的动态性能,对误差趋势能够进行提前干预。
2 双轮巡线小车结构设2.1 小车位置判定在PID算法设计中,构建比例因子是最重要的。
第一步就是确定比例采样方法,构建比例方法。
在小车运动巡线过程中,在小车前端的7路颜色传感器不断反馈扫描的信息给CPU,7路颜色传感器从左到右依次为P1,P2,P3,P4,P5,P6,P7,P4传感器只要引导走直线,P1和p7,P2和P6,P3和P5分别为一组,通过不同组的传感器反馈回的信息能实时判定小车的位置状态,通过不同组反馈的位置信息与P4传感器位置偏差e(t),通过比例因子就可以构建PID算法中比例控制项了。
技术解析——单颜色传感器巡线中的PID控制器1PID控制器是什么?百度百科:工业生产过程中,对于生产装置的温度、压力、流量、液位等工艺变量常常要求维持在一定的数值上,或按一定的规律变化,以满足生产工艺的要求。
PID控制器是根据PID控制原理对整个控制系统进行偏差调节,从而使被控变量的实际值与工艺要求的预定值一致。
不同的控制规律适用于不同的生产过程,必须合理选择相应的控制规律,否则PID控制器将达不到预期的控制效果。
PID控制器(Proportion Integration Differentiation.比例-积分-微分控制器),由比例单元 P、积分单元 I 和微分单元 D 组成。
通过Kp, Ki和Kd三个参数的设定。
PID控制器主要适用于基本线性和动态特性不随时间变化的系统。
简单点说,PID控制器可以将某一参数,维持稳定,适用于基本线性和动态特性不随时间变化的系统中。
2黑线附近的灰度值是否为线性系统?下面以黑色胶带轨迹、原木桌面巡线环境为例,进行验证(一)黑线附近灰度值采集删除test文件,车体以3的功率直行4秒,每0.08秒采集一次传感器灰度值并存在文件中。
(程序运行前保证车身垂直于黑线,且距离黑线一定距离)运行程序后,打开程序块内存浏览器找到对应的test.rtf文件选中上传并将文件扩展名改为xls(表格)打开表格→选中数据→插入→折线图黑线附近灰度值变化情况:OA段,传感器红色光圈未接触黑线;AB段,传感器红色光圈慢慢进入黑线范围;BC段,传感器红色光圈完全处于黑线中;CD段,传感器红色光圈慢慢离开黑线范围。
AB段为一条直线段,因此可以得出:传感器红色光圈慢慢进入黑线范围的过程中,灰度值随距离线性变化。
3PID控制器原理分析及程序编写(一)P控制器——比例控制黑线附近的灰度值随着距离线性改变,因此可以根据传感器检测到的灰度值与目标灰度值的差值控制车体转弯的幅度。
转向度 = kp*(灰度值-目标值)定义比例因子kp、直行功率Ep、目标灰度值huidu,将传感器灰度值减去目标灰度值乘以比例因子kp的积作为转向度。
循迹小车pid算法原理PID算法是一种常用的控制算法,用于调节被控对象的输出使其达到给定的目标值。
循迹小车是指能够在预定轨迹上行驶的小车,通常是通过图像或者传感器来感知自己的位置并做出相应的调整,PID算法在循迹小车的控制中起到了重要的作用。
PID算法的全称是比例-积分-微分算法,它根据当前控制误差的大小来调整控制器的输出,以使系统的输出达到期望值。
PID算法的原理可以简单概括为以下三部分:1.比例控制:根据当前的误差,调整控制器的输出。
比例控制的目的是使系统对误差的响应更为迅速,其输出与误差成正比。
比例控制能够解决系统的静态误差,但对于系统的超调和振荡等问题并没有很好的处理能力。
2.积分控制:根据误差的累积值来调整控制器的输出。
积分控制能够解决系统的稳态误差,通过累积误差可以逐渐消除系统的静态误差。
积分控制可以使系统对稳态误差更加敏感,但对于系统的超调和振荡等问题并没有很好的抑制能力。
3.微分控制:根据误差的变化率来调整控制器的输出。
微分控制能够使系统对误差的变化趋势做出反应,通过减小误差的变化率可以使系统更加稳定。
微分控制对于系统的超调和振荡等问题有一定的抑制作用,但对于系统的静态误差并没有很好的解决能力。
在循迹小车的控制中,PID算法可以通过如下方式应用:1.传感器获取车辆当前位置信息。
2.计算当前位置与期望位置之间的误差。
3.根据误差的大小来调整控制器的输出,得到轮速或转角的控制信号。
4.根据控制信号调整车辆的轮速或转弯角度,使车辆朝期望位置行驶。
5.重复步骤1-4,使车辆持续追踪期望轨迹。
在具体实现中,需要根据系统的特性和需求来调节PID算法中比例、积分和微分的参数。
通常可以通过实验或者系统模拟来找到合适的参数值,以使系统达到较好的控制效果。
总结起来,PID算法通过比例、积分和微分三部分的组合来调节控制器的输出,使系统跟踪期望值。
在循迹小车中,PID算法可以根据当前位置与期望位置的差异来调整车辆的轮速或转弯角度,使车辆持续沿着期望轨迹行驶。
灰度循迹PID参数1. 灰度循迹简介灰度循迹是指通过对地面上的灰度进行感知和分析,实现机器人沿着预定轨迹行驶的技术。
它广泛应用于自动驾驶、智能机器人等领域。
PID控制是灰度循迹中常用的控制算法,通过调整PID参数,可以使机器人更加精确地跟随预定轨迹。
2. PID控制原理PID控制是一种闭环控制算法,由比例(P)、积分(I)和微分(D)三个部分组成。
它通过不断地根据误差信号调整输出信号,使得系统的输出能够迅速、平稳地接近设定值。
•比例(P)控制:根据当前误差的大小,按比例调整输出信号。
比例控制可以使系统快速响应,但可能导致系统产生超调和震荡。
•积分(I)控制:根据过去误差的累积值,按比例调整输出信号。
积分控制可以消除稳态误差,但可能导致系统响应过慢和超调。
•微分(D)控制:根据当前误差的变化率,按比例调整输出信号。
微分控制可以使系统对误差变化快速响应,但可能导致系统对噪声敏感。
PID控制的输出信号计算公式为:Output = Kp * Error + Ki * Integral(Error) + Kd * Derivative(Error)其中,Kp、Ki和Kd分别为比例、积分和微分参数,Error为当前误差,Integral(Error)为误差的累积值,Derivative(Error)为误差的变化率。
3. 灰度循迹PID参数调整方法调整PID参数是灰度循迹中的关键步骤,合理的参数设置可以使机器人更加准确地跟随预定轨迹。
下面介绍几种常用的PID参数调整方法。
3.1 手动调整法手动调整法是一种简单直观的调整方法,适用于对系统有一定了解的情况。
具体步骤如下:1.将积分和微分参数设为0,只调整比例参数。
2.将机器人放在预定轨迹上,观察机器人的行驶情况。
3.如果机器人偏离轨迹,增大比例参数;如果机器人超调或震荡,减小比例参数。
4.重复步骤2和步骤3,直到机器人能够稳定地跟随轨迹。
5.根据需要,适量增加积分和微分参数,以进一步调整系统的性能。
机器人PID巡线技术PID技术一直是大家很感兴趣的话题。
要用好PID控制,并不是一件容易的事,需要有相当的高等数学基础和控制技术基础,这对很多乐高机器人爱好者来说,是一个难题。
J. Sluka (原文作者)没有从专业的角度去解释PID,而是以非常浅显的方式写出了这篇“A PID Controller For Lego Mindstorms Robots”(用于乐高机器人的PID控制器),向缺乏专业基础的人士,解释如何在乐高机器人里使用PID控制器。
另,虽然原文用了一种非常简单的方法来说明PID控制器的用法,但是对于那些小学、初中没毕业的同学来说,还是有些过于复杂,所以,我并不建议乐友门盲目跟风(感觉会用PID就高端一点)学习PID。
在我看来,先有一定的数学基础后,再回头学习此篇更为适合!PS:在这篇文章里所有的代码都不是真正的程序代码,只是作者对编程的示意,或者说是用类似程序代码的方式对编程的内容进行解释。
作者希望读者能自行选择程序语言,自己完成PID 控制器的编程。
PID控制器是一种常用的控制技术,常用于多种机械装置(如车辆、机器人、火箭)中。
用数学方式来描述PID控制器是非常复杂的。
本文描述了如何在使用NXT-G编程的LEGO机器人上创建PID控制器。
文中将以实例来说明如何创建PID来完成机器人巡线任务。
PID 创建完成后,经过简单的修改就可以应用到其他地方,如,让机器人跑直线,做两轮平衡机器人。
其实学过微积分的人很容易理解PID的典型描述,本文是写给那些对PID几乎没有任何概念的读者,比如参加FLL比赛的3~8年级的孩子们。
考虑到大家可能不了解微积分,因此我尽量不使用微积分,从非常低的起点开始建造整个概念。
先来看看一个适于巡线的机器人是什么样的结构。
看下图,这个机器人用两个马达驱动,分别与车轮A、C连接,前端装有垂直向下的光电传感器,红圈标出的部分就是光电传感器能“看到”的部分。
带箭头的大长方形表示机器人的其余部分,箭头指示机器人的运动方向。
基于PID控制算法的自动巡线机器人的设计与实现
郭政堃;王颜辉;姚志广;李睿智
【期刊名称】《自动化应用》
【年(卷),期】2024(65)4
【摘要】自动巡线移动机器人能在各种环境下独立执行巡线任务,适用于工业、农业、物流等领域。
传统机器人在复杂或需快速响应的环境中效率低。
为此,采用PID(比例-积分-微分)控制算法优化机器人的路径追踪和运动控制,提高巡线的准确性和稳定性。
通过硬件和软件的综合设计,实现了一款基于PID算法的高效、稳定的自动巡线机器人,其设计的有效性通过装配、调试和实验得到了验证,为自动巡线机器人在各行业的应用提供了理论和实践基础,有助于扩大自动化技术的应用范围和提高效率。
【总页数】3页(P54-56)
【作者】郭政堃;王颜辉;姚志广;李睿智
【作者单位】山西能源学院机电工程系
【正文语种】中文
【中图分类】TP242
【相关文献】
1.基于模糊PID控制的智能巡线机器人的设计与研究
2.基于51型单片机的自动巡线轮式机器人控制系统设计
3.基于RTOS的机器人巡线控制算法
4.基于DSP和模
糊控制的巡线机器人控制系统设计与实现5.基于PID算法的巡线小车的设计与实现
因版权原因,仅展示原文概要,查看原文内容请购买。
FLL机器人比赛中的巡线摘要本文从搭建和编程两个方面阐述了目前FLL机器人比赛中常见的PID 巡线的使用方法。
搭建中讨论了车体重心的要求,光电传感器位置的要求。
在算法中讨论了P算法、I算法和D算法的不同作用。
关键词PID;巡线;结构;FLL;机器人;算法巡线是FLL竞赛中一项非常重要的支撑技能。
有了它机器人就能在场地上准确定位,完成任务;有了它机器人就能充分利用场地上的线路,提高速度和准确性。
在一般的教材中提到的往往是由传感器判断黑白位置,控制器控制左右轮交替前进的方式,该方式车体摆动较大,定位的精度不够,所以在比赛中失误较多。
为了能够达到比赛精度,我们往往采用的是PID算法巡线。
1 巡线对车体结构的要求巡线要稳定车体结构是基础,在搭建车体时往往要注意以下几点。
光电(颜色)传感器要放置在驱动轮的前面(前后以机器人运行的方向为准),至于左右位置是根据任务需要来设计,甚至在车体的驱动轮之外。
传感器的高度一般是离场地1.5~2.5cm[1]。
太低了,光线值的变化太小,车体的摆动较大,甚至脱线;太高了,容易受环境光的影响,不具有通用性。
车体的重心在驱动轮和从动轮之间偏驱动轮的三分之一处比较合理,如太靠近驱动轮则车体在前进和后退的过程中因为惯性的原因会造成车体的抬头和点头现象,形成误差;如太靠近从动轮,驱动轮会出现打滑现象,造成较大的误差。
重心在高度上宜低不宜高。
2 PID巡线的P算法有了稳定的好的车体,下面就欠缺好的算法了。
机器人在巡线的时候巡的是黑白的交界线,用我们的肉眼看这条分界线是黑白分明,黑色的光线暗而白色的光线亮。
实际上光线不论从暗到明还是从明到暗都不是跳跃的而是线型变化的。
我们利用这个线型的变化值来确定机器人的位置,来确定驱动轮电机的功率,从而修正位置。
通常我们用于驱动的电机都习惯是B和C(因为程序默认B和C),依照前进的方向,左侧的为B电机,右侧的为C电机。
假定黑色路线的平均光线值为5,白色部分的光线值为55,那么平均值30我们就可以看成是黑白分界线的值,换句话说就是传感器测出的值为30,那么我们就确定传感器的位置在分界线上,值越小就越靠近黑线里面,值越大离黑线就越远。
FLL机器人比赛中PID巡线的使用方法作者:王彦祺来源:《中国科技博览》2018年第10期[摘要]PID巡线技术是FLL机器人比赛过程中十分常见的一种巡线技术,与此占据同等重要地位的还有基础小车的搭建。
本文将主要对FLL机器人比赛过程中的PID巡线技术使用方法及基础小车的搭建等内容进行研究分析。
[关键词]FLL机器人比赛;PID巡线;使用方法中图分类号:S988 文献标识码:A 文章编号:1009-914X(2018)10-0385-01随着教育环境的改变以及教育观念的进步,机器人竞赛在近几年来得到了越来越多人的关注,不仅竞赛的次数增加而且种类显著。
经过研究发现机器人竞赛的举办可以使青少年发现与解决问题的能力得到提升,正好符合了当前的素质教育理念[1]。
为了适应这一趋势,不少大学也纷纷开设了机器人专业。
机器人教育不仅与学生的天性相符合,也使得教育事业领域得到拓展。
FLL机器人比赛是众多机器人比赛当中最为复杂的一种,也更加考验青少年的能力要求。
该项赛事过程中机器人的搭建以及PID巡线的使用都会对最终的结果产生直接影响。
1、PID巡线使用方法在FLL机器人比赛过程中,巡线是十分重要的技能,想要提高机器人的定位准确度,更好的完成任务,就必须要认识到PID巡线的重要性。
有了巡线的帮助,机器人可以对比赛场地上的各种线路进行充分的利用,进而使其准确度与速度都得到相应提升。
常规教材当中所起到的,黑白位置的控制与判断是由传感器来完成的,同时对左右轮交替前进的方式展开相应的控制。
但是采用这种方式,会使车体发生很大的摆动,精度也得不到较好的控制,这最终会导致在比赛过程中出现很多失误[2]。
为了使机器人比赛的精度得到进一步的提升,需要在FLL机器人比赛过程中使用PID巡线方法。
1.1 PID当中的P算法分析机器人在具体工作过程中所开展的巡线活动主要是对黑白交界线来进行巡视,我们使用自己的眼睛所开拿到的分界线是黑白分明,与颜色比较亮的光线相比,黑色的光线比较暗一些,实际上不管光线具体的变化规律是怎样的,或许是从明到暗也或许是从暗到明,根据现行变化的值来对机器人的位置进行确定,从而更好的对驱动轮电机的功率进行确定,实现位置的修正。
巡线小车源程序(M S P430-P I D) -CAL-FENGHAI-(2020YEAR-YICAI)_JINGBIAN巡线小车源程序(MSP430,PID)首先是各种宏定义的头文件[cpp]view plaincopy1"myhead.h"2#ifndef xxxx_xxx3#define xxxx_xxx4#define P 435#define I 0.016#define D 1007#define LeftMotorTurnNeg {P3OUT|=BIT0;P3OUT&=~BIT1;}8#define LeftMotorTurnPos {P3OUT&=~BIT0;P3OUT|=BIT1;}9#define RightMotorTurnNeg {P3OUT|=BIT3;P3OUT&=~BIT2;}10#define RightMotorTurnPos {P3OUT&=~BIT3;P3OUT|=BIT2;}11#define LeftPwmOut TACCR112#define RightPwmOut TACCR213#define F 1000014#define T (8000000/F)15#define BASIC 10016#define simpletime (unsigned int)517#define LEFT 10018#define RIGHT 10019#endif接下来就是点击驱动的头文件[cpp]view plaincopy20"Motor.h"21#ifndef Motor22#define Motor23#include "myhead.h"24#include "msp430x14x.h"25void MotorLeft(float left)26{27 LeftMotorTurnPos//正转28if(left<0)29 {30 LeftMotorTurnNeg//反转31 left=-left;32 }33 LeftPwmOut=(int)(left*T/100); 34}35void MotorRight(float right)36{37 RightMotorTurnPos//正转38if(right<0)39 {40 RightMotorTurnNeg//41 right=-right;42 }43 RightPwmOut=(int)(right*T/100); 44}45void DriveMotor(float PIDout)46{47float left=BASIC+PIDout;48float right=BASIC-PIDout;49if(left>100)left=100;50if(left<-100)left=-100;51if(right>100)right=100;52if(right<-100)right=-100;53 MotorLeft(left);54 MotorRight(right);//工作正常55}56#endif再下来是主文件[cpp]view plaincopy57”main.c"5859#include "Motor.h"60float lasterror,sumerror;61float Sensor[]={-4,-3,-2,-1,0,1,2,3,4};62int flag;63void delay(int time)64{}65void timer_inti()66{67 TACTL=TASSEL_2+MC_1+TAR+ID_0;//SMCLK,增计数模式,清零,不分频;允许定时器溢出中断68 TACCR0=8000000/F;//其中F为PWM的频率69 TACCTL1=OUTMOD_7;70 TACCTL2=OUTMOD_7;7172 TBCTL=TASSEL_2+MC_1+TBR+ID_0+CNTL_0;//SMCLK,增计数模式,清零,不分频;允许定时器溢出中断,16WEI73 TBCCTL0|=CCIE;74 TBCCR0=8000*simpletime;//控制采样时间75 _EINT();76}77void IO_inti()78{79 P1DIR=BIT3+BIT2;//用于定时器输出80 P1SEL=BIT3+BIT2;8182 P3DIR=0X7f;//用作传感器输入跟电机驱动83 P5DIR=0X00;//用于传感器输入8485 P6DIR=0XFF;//用于流水灯输出,纯粹调试用8687 P2DIR|=BIT4;//外部中断,用于壁障88 P2IE=BIT4;89 P2IES=BIT4;9091}92void PID_inti()93{94 sumerror=0;95 lasterror=0;96 flag=0;97}98void Crystal()//晶振启振程序99{100 BCSCTL1&=~XT2OFF;101do102 {103int i;104 IFG1&=~OFIFG;105for(i=255;i>=0;i--);106 }while(IFG1&OFIFG);107 BCSCTL2=SELM_2+DIVM_0+SELS+DIVS_0;//SMCLK=MCLK=XT2;DIV=0; 108}109float PID_Cal(float error)110{111float derror=error-lasterror;//微分df112 sumerror+=error;//积分113 lasterror=error;114return P*error+I*sumerror+D*derror; 115}116float Sensor_Read()//左边传感器压线往左偏117{118static float ans=0;119float sum=0;120int i,sensor=0,num=0;121 sensor=P5IN;//3.7 5.7 5.6 5.5.....5.0122 sensor=((P3IN&BIT7)<<1)|sensor;123for(i=0;i<9;i++)124 {125if(!(sensor&(1<<i)))126 {127 sum+=Sensor[i];128 num++;129 }130 }131if(num!=0&&num<=4)ans=sum/num;132if(ans<0)133 {134 P6OUT=0x80;135 P6OUT|=(int)(-(ans-0.5));136 }137else138 {139 P6OUT=(int)(ans+0.5);140 }141142return ans;//运行找正常143}144void AvoidDetection(float left,float right)//壁障函数145{146int sensor=0;147 MotorLeft(left);148 MotorRight(right);149 delay(200);150do{151 MotorLeft(right);152 MotorRight(left);153 sensor=P3IN&BIT7;//3.7 5.7 5.6 5.5.....5.0154 sensor=(sensor<<1)|P5IN;155 }while(sensor==0x1ff);//当在空白的时候,一只往里面拐。
PID算法巡线制模型:你控制一个人让他以PID控制的方式走110步后停下。
(1)P比例控制,就是让他走110步,他按照一定的步伐走到一百零几步(如108步)或100多步(如112步)就停了。
说明:P比例控制是一种最简单的控制方式。
其控制器的输出与输入误差信号成比例关系。
当仅有比例控制时系统输出存在稳态误差(Steady-state error)。
(2)PI积分控制,就是他按照一定的步伐走到112步然后回头接着走,走到108步位置时,然后又回头向110步位置走。
在110步位置处来回晃几次,最后停在110步的位置。
说明:在积分I控制中,控制器的输出与输入误差信号的积分成正比关系。
对一个自动控制系统,如果在进入稳态后存在稳态误差,则称这个控制系统是有稳态误差的或简称有差系统(System with Steady-state Error)。
为了消除稳态误差,在控制器中必须引入“积分项”。
积分项对误差取决于时间的积分,随着时间的增加,积分项会增大。
这样,即便误差很小,积分项也会随着时间的增加而加大,它推动控制器的输出增大使稳态误差进一步减小,直到等于零。
因此,比例+积分(PI)控制器,可以使系统在进入稳态后无稳态误差。
(3)PD微分控制,就是他按照一定的步伐走到一百零几步后,再慢慢地向110步的位置靠近,如果最后能精确停在110步的位置,就是无静差控制;如果停在110步附近(如109步或111步位置),就是有静差控制。
说明:在微分控制D中,控制器的输出与输入误差信号的微分(即误差的变化率)成正比关系。
自动控制系统在克服误差的调节过程中可能会出现振荡甚至失稳,其原因是由于存在有较大惯性组件(环节)或有滞后(delay)组件,具有抑制误差的作用,其变化总是落后于误差的变化。
解决的办法是使抑制误差作用的变化“超前”,即在误差接近零时,抑制误差的作用就应该是零。
这就是说,在控制器中仅引入“比例P”项往往是不够的,比例项的作用仅是放大误差的幅值,而目前需要增加的是“微分项”,它能预测误差变化的趋势。
PID算法巡线制模型:你控制一个人让他以PID控制的方式走110步后停下。
(1)P比例控制,就是让他走110步,他按照一定的步伐走到一百零几步(如108步)或100多步(如112步)就停了。
说明:P比例控制是一种最简单的控制方式。
其控制器的输出与输入误差信号成比例关系。
当仅有比例控制时系统输出存在稳态误差(Steady-state error)。
(2)PI积分控制,就是他按照一定的步伐走到112步然后回头接着走,走到108步位置时,然后又回头向110步位置走。
在110步位置处来回晃几次,最后停在110步的位置。
说明:在积分I控制中,控制器的输出与输入误差信号的积分成正比关系。
对一个自动控制系统,如果在进入稳态后存在稳态误差,则称这个控制系统是有稳态误差的或简称有差系统(System with Steady-state Error)。
为了消除稳态误差,在控制器中必须引入“积分项”。
积分项对误差取决于时间的积分,随着时间的增加,积分项会增大。
这样,即便误差很小,积分项也会随着时间的增加而加大,它推动控制器的输出增大使稳态误差进一步减小,直到等于零。
因此,比例+积分(PI)控制器,可以使系统在进入稳态后无稳态误差。
(3)PD微分控制,就是他按照一定的步伐走到一百零几步后,再慢慢地向110步的位置靠近,如果最后能精确停在110步的位置,就是无静差控制;如果停在110步附近(如109步或111步位置),就是有静差控制。
说明:在微分控制D中,控制器的输出与输入误差信号的微分(即误差的变化率)成正比关系。
自动控制系统在克服误差的调节过程中可能会出现振荡甚至失稳,其原因是由于存在有较大惯性组件(环节)或有滞后(delay)组件,具有抑制误差的作用,其变化总是落后于误差的变化。
解决的办法是使抑制误差作用的变化“超前”,即在误差接近零时,抑制误差的作用就应该是零。
这就是说,在控制器中仅引入“比例P”项往往是不够的,比例项的作用仅是放大误差的幅值,而目前需要增加的是“微分项”,它能预测误差变化的趋势。
这样,具有比例+微分的控制器,就能够提前使抑制误差的控制作用等于零,甚至为负值,从而避免了被控量的严重超调。
所以对有较大惯性或滞后的被控对象,比例P+微分D(PD)控制器能改善系统在调节过程中的动态特性。
小明接到这样一个任务:有一个水缸有点漏水(而且漏水的速度还不一定固定不变),要求水面高度维持在某个位置,一旦发现水面高度低于要求位置,就要往水缸里加水。
小明接到任务后就一直守在水缸旁边,时间长就觉得无聊,就跑到房里看小说了,每30分钟来检查一次水面高度。
水漏得太快,每次小明来检查时,水都快漏完了,离要求的高度相差很远,小明改为每3分钟来检查一次,结果每次来水都没怎么漏,不需要加水,来得太频繁做的是无用功。
几次试验后,确定每10分钟来检查一次。
这个检查时间就称为采样周期。
开始小明用瓢加水,水龙头离水缸有十几米的距离,经常要跑好几趟才加够水,于是小明又改为用桶加,一加就是一桶,跑的次数少了,加水的速度也快了,但好几次将缸给加溢出了,不小心弄湿了几次鞋,小明又动脑筋,我不用瓢也不用桶,老子用盆,几次下来,发现刚刚好,不用跑太多次,也不会让水溢出。
这个加水工具的大小就称为比例系数。
小明又发现水虽然不会加过量溢出了,有时会高过要求位置比较多,还是有打湿鞋的危险。
他又想了个办法,在水缸上装一个漏斗,每次加水不直接倒进水缸,而是倒进漏斗让它慢慢加。
这样溢出的问题解决了,但加水的速度又慢了,有时还赶不上漏水的速度。
于是他试着变换不同大小口径的漏斗来控制加水的速度,最后终于找到了满意的漏斗。
漏斗的时间就称为积分时间。
小明终于喘了一口,但任务的要求突然严了,水位控制的及时性要求大大提高,一旦水位过低,必须立即将水加到要求位置,而且不能高出太多,否则不给工钱。
小明又为难了!于是他又开努脑筋,终于让它想到一个办法,常放一盆备用水在旁边,一发现水位低了,不经过漏斗就是一盆水下去,这样及时性是保证了,但水位有时会高多了。
他又在要求水面位置上面一点将水缸要求的水平面处凿一孔,再接一根管子到下面的备用桶里这样多出的水会从上面的孔里漏出来。
这个水漏出的快慢就称为微分时间。
看到几个问采样周期的帖子,临时想了这么个故事。
微分的比喻一点牵强,不过能帮助理解就行了,呵呵,入门级的,如能帮助新手理解下PID,于愿足矣。
故事中小明的试验是一步步独立做,但实际加水工具、漏斗口径、溢水孔的大小同时都会影响加水的速度,水位超调量的大小,做了后面的实验后,往往还要修改改前面PID算法解释很多同学都不清楚PID是个什么东西,因为很多不是自动化的学生。
他们开口就要资料,要程序。
这是明显的学习方法不对,起码,首先,你要理解PID是个什么东西。
本文以通俗的理解,以小车纵向控制举例说明PID的一些理解。
首先,为什么要做PID?由于外界原因,小车的实际速度有时不稳定,这是其一,要让小车以最快的时间达达到既定的目标速度,这是其二。
速度控制系统是闭环,才能满足整个系统的稳定要求,必竟速度是系统参数之一,这是其三.小车调速肯定不是线性的,外界因素那么多,没人能证明是线性的。
如果是线性的,直接用P就可以了。
比如在PWM=60%时,速度是2M/S,那么你要它3M/S,就把PWM提高到90%。
因为90/60=3/2,这样一来太完美了。
完美是不可能的。
那么不是线性的,要怎么怎么控制PWM使速度达到即定的速度呢?即要快,又要准,又要狠。
(即快准狠)系统这个速度的调整过程就必须通过某个算法调整,一般PID就是这个所用的算法。
可能你会想到,如果通过编码器测得现在的速度是2.0m/s,要达到2.3m/s的速度,那么我把pwm增大一点不就行了吗?是的,增大pwm多少呢?必须要通过算法,因为PWM和速度是个什么关系,对于整个系统来说,谁也不知道。
要一点一点的试,加个1%,不够,再加1%还是不够,那么第三次你还会加1%吗?很有可能就加2%了。
通过PID三个参数得到一个表达式:△PWM=a *△V1+b *△V2+c *△V3,a b c是通过PID的那个长长的公式展开,然后约简后的数字,△V1 ,△V2 ,△V3 此前第一次调整后的速度差,第二次调整后的速度差,第三次。
一句话,PID要使当前速度达到目标速度最快,需要建立如何调整pwm和速度之间的关系。
输入输出是什么:输入就是前次速度,前前次速度,前前前次速度。
输出就是你的PWM应该增加或减小多少。
为了避免教科书公式化的说明,本文用口语化和通俗的语言描述。
虽然不一定恰当,但意思差不多,就是那个事。
如果要彻头彻尾地弄PID,建议多调试,写几个仿真程序PID一般有两种:位置式PID和增量式PID。
在小车里一般用增量式,为什么呢?位置式PID的输出与过去的所有状态有关,计算时要对e(每一次的控制误差)进行累加,这个计算量非常大,而明没有必要。
而且小车的PID控制器的输出并不是绝对数值,而是一个△,代表增多少,减多少。
换句话说,通过增量PID算法,每次输出是PWM要增加多少或者减小多少,而不是PWM的实际值。
下面均以增量式PID说明。
这里再说一下P、I、D三个参数的作用。
P=Proportion,比例的意思,I是Integral,积分,D是Differential微分。
打个比方,如果现在的输出是1,目标输出是100,那么P的作用是以最快的速度达到100,把P理解为一个系数即可;而I呢?大家学过高数的,0的积分才能是一个常数,I就是使误差为0而起调和作用;D呢?大家都知道微分是求导数,导数代表切线是吧,切线的方向就是最快到至高点的方向。
这样理解,最快获得最优解,那么微分就是加快调节过程的作用了。
公式本来需要推导的,我就不来这一套了。
直接贴出来:看看最后的结果:△Uk=A*e(k)+B*e(k-1)+C*e(k-2)这里KP是P的值,TD是D的值,1/Ti是I的值,都是常数,哦,还有一个T,T是采样周期,也是已知。
而A 、B、C是由P I D换算来的,按这个公式,就可以简化计算量了,因为P I D 是常数,那么A B C可以用一个宏表示。
这样看来,只需要求e(k) e(k-1) e(k-2)就可以知道△Uk的值了,按照△Uk来调节PWM的大小就OK了。
PID三个参数的确定有很多方法,不在本文讨论范围内。
采样周期也是有据可依的,不能太大,也不能太小。
PID实际编程的过程的,要注意的东西还是有几点的。
PID这东西可以做得很深。
1 PID的诊定。
凑试法,临界比例法,经验法。
2 T的确定,采样周期应远小于过程的扰动信号的周期,在小车程序中一般是ms级别。
3 目标速度何时赋值问题,如何更新新的目标速度?这个问题一般的人都乎略了。
目标速度肯定不是个恒定的,那么何时改变目标速度呢?4 改变了目标速度,那么e(k) e(k-1) e(k-2)怎么改变呢?是赋0还是要怎么变?5 是不是PID要一直开着?6 error为多少时就可以当速度已达到目标?7 PID的优先级怎么处理,如果和图像采集有冲突怎么办?8 PID 的输入是速度,输出是PWM,按理说PWM产生速度,但二者不是同一个东西,有没有问题?9 PID计算如何优化其速度?指针,汇编,移位?都可以试!1.//*****************************************************2.//定义PID结构体3.//*****************************************************4.typedef struct PID5.{6.int SetPoint; //设定目标Desired Value7.double Proportion; //比例常数Proportional Const8.double Integral; //积分常数Integral Const9.double Derivative; //微分常数Derivative Const10.int LastError; //Error[-1]11.int PrevError; //Error[-2]12.} PID;13.//*****************************************************14.//定义相关宏15.//*****************************************************16.#define P_DATA 10017.#define I_DATA 0.618.#define D_DATA 119.#define HAVE_NEW_VELOCITY 0X0120.//*****************************************************21.//声明PID实体22.//*****************************************************23.static PID sPID;24.static PID *sptr = &sPID;25.//*****************************************************26.//PID参数初始化27.//*****************************************************28.void IncPIDInit(void)29.{30.sptr->LastError = 0; //Error[-1]31.sptr->PrevError = 0; //Error[-2]32.sptr->Proportion = P_DATA; //比例常数Proportional Const33.sptr->Integral = I_DATA; //积分常数Integral Const34.sptr->Derivative = D_DATA; //微分常数Derivative Const35.sptr->SetPoint =100; 目标是10036.}37.//*****************************************************38.//增量式PID控制设计39.//*****************************************************40.int IncPIDCalc(int NextPoint)41.{42. int iError, iIncpid; //当前误差43. iError = sptr->SetPoint - NextPoint; //增量计算44. iIncpid = sptr->Proportion * iError //E[k]项45.- sptr->Integral * sptr->LastError //E[k-1]项46.+ sptr->Derivative * sptr->PrevError; //E[k-2]项47.sptr->PrevError = sptr->LastError; //存储误差,用于下次计算48.sptr->LastError = iError;49.return(iIncpid); //返回增量值50.}51.Int g_CurrentVelocity;52.Int g_Flag;53.54.void main(void)55.{56.DisableInterrupt57.InitMCu();58.IncPIDInit();59.g_CurrentVelocity=0; //全局变量也初始化60.g_Flag=0; //全局变量也初始化61.EnableInterrupt;62. While(1)63.{64. if (g_Flag& HAVE_NEW_VELOCITY)65. {66.PWMOUT+= IncPIDCalc(CurrentVelocity);67. g_Flag&=~ HAVE_NEW_VELOCITY;68.}69.}70.}71.//****************************************72.//采样周期T73.//****************************************74.Interrrupt TIME void75.{76. CurrentVelocity =GetCurrentVelocity;77. g_Flag|= HAVE_NEW_VELOCITY;78.}PID算法巡线例程1./* Techbricks.nl Line Follower2.Based on a PID controller, using the NXT 2.0 color sensor3.NXC firmware 1.284.www.techbricks.nlst modified03/03/2010 */ 6.7./* Proportional gain, straight forward reaction of the controllerrger values typically mean faster response since the larger the error,9.the larger the proportional term compensation.10.An excessively large proportional gain will lead to process instability andoscillation.*/11.#define Kproportional 612.13./* Integral gain, improves the controller accuracyrger values imply steady state errors are eliminated more quickly.15.The trade-off is larger overshoot: any negative error integrated during transientresponse16.must be integrated away by positive error before reaching steady state.*/17.#define Kintegral 0.000218.19./* Derivative gain, improves the controller speedrger values decrease overshoot, but slow down transient response21.and may lead to instability due to signal noise amplification in the differentiationof the error.*/22.#define Kderivative 10023.24.// Sample time, determined the reaction rate25.#define dt 2526.27.// NXT 2.0 Color sensor connected to port 2.28.#define COLORSENSOR SENSOR_229.30.task main()31.{32.int error = 0;33.float previous_error = 0;34.float setpoint = 0;35.float actual_position = 0;36.float proportional = 0;37.int integral = 0;38.float derivative = 0;39.float output = 0;40.float left = 0;41.float right = 0;42.43.// Set the motor speed.44.float speed=50;45.46.// Set the color sensor light on.47.SetSensorColorFull(IN_2);48.49.// Read the value from the light sensor at the start position. The sensor must be placeabove the black line.50.TextOut(1,LCD_LINE1,"Setpoint");51.setpoint = COLORSENSOR;52.NumOut(50,LCD_LINE1,setpoint);53.54.// never ending loop.55.while (true)56.{57.// Read the actual color sensor value.58.actual_position = COLORSENSOR;59.TextOut(1,LCD_LINE2,"Actual");60.NumOut(50,LCD_LINE2,actual_position);61.62.// Calculate the error, the differance between the setpoint and actual position.63.error = setpoint - actual_position;64.// Play a sound when the sensor is off the line65.if (error <> 0) PlayTone(TONE_B7, 1);66.67.// Proportional term makes a change to the output that is proportional to the currenterror value.68.proportional = Kproportional * error;69.70.// Integrate, sum of errors71.integral = integral + error;72.73.// Derivative, rate of change of the process error is calculated by determining theslope of the error over time.74.derivative = (error - previous_error) / dt;75.76.// Calculate sum of Proportional, Integral and Derivative.77.output = proportional + Kintegral * dt * integral + Kderivative * derivative;78.79.// save error value for period.80.previous_error = error;81.82.// Controll left motor83.left = speed - output;84.85.// Controll right motor86.right = speed + output;87.88.// Adjust the left and right motor value.89.if (left > 100) left = 100;90.if (left < -100) left = -100;91.if (right > 100) right = 100;92.if (right < -100) right = -100;93.94.if (left < 0 )95.{96.OnFwd(OUT_A,-left);97.TextOut(1,LCD_LINE4,"Left Rev");98.NumOut(55,LCD_LINE4,-left);99.}100.else101.{102.OnRev(OUT_A,left);103.TextOut(1,LCD_LINE4,"Left Fwd"); 104.NumOut(55,LCD_LINE4,left);105.}106.107.if (right < 0 )108.{109. OnFwd(OUT_B,-right);110. TextOut(1,LCD_LINE5,"Right Rev"); 111. NumOut(55,LCD_LINE5,-right); 112.}113. else114.{115. OnRev(OUT_B,right);116. TextOut(1,LCD_LINE5,"Right Fwd"); 117. NumOut(55,LCD_LINE5,right);118. }119.120.// Wait sample time.121.Wait(dt);122.}123.}目前工业自动化水平已成为衡量各行各业现代化水平的一个重要标志。