PID算法巡线
基于模糊PID控制的智能巡线机器人的设计与研究

作者简介 : 叶振 捷 (9 8一) 男 , 程 师 , 事 变 电运 行 方 面 的 研 究 与 16 , 工 从 管理 工 作 。
收 稿 日期 :0 8— 5— 2 8 3 20 0 2 ( 20)
过这个过程 , 监测终端才 能和 G S G N建立 一条 逻辑 通道 , 才能
文 章 编 号 :6 1 0 1 2 0 ) 6— 0 9— 2 17 —14 ( 08 0 0 2 0
5 结束 语
.
GR P S无线通信方 式作 为先进 的通 信技术 , 电力系统 生 在 产监控中的应用有其独特 的优势 。本 文结 合 G R P S技术 、 入 嵌 式技术和 It nt ne e 技术实现 电力 系统远 程监控 , r 保证 了实时性 与可靠性 。本系统监测管理 中心软件选用 Mi oot i u c sfVs l r a C+ +. 6 0作为 开发工具 , 用模块 化设计 , 之具有最 大 的灵 活 采 使
I lu x i x是 一 个 完 全 免 费 的 、 Cn 开放 的 系统 , 以根 据 用 户 的 不 同 可
要求 对 操 作 系 统 进 行 裁 减 , 以节 省 不 必 要 的 开 销 ; 外 , 此 I lu x i x的开发资源丰富 , Cn 拥有 丰富的驱 动程 序和应用程序 。 4 2 GP S通 信 协 议 部 分 、 . R GR P S核心 网络是基 于 I P技术 的 , 因此监测 终端 需要利用 T P I 议来完成 G R C /P协 P S业 务数 据 的装 帧和拆 帧 , 以及 保 证 数 据在 网络中的安全可靠传输 。 由数 据采集模 块送 来 的数 据 按 照 T P的格式封装 C C F P数据包 , 然后 加上 I P报头 和报 尾封 装成 I P数据报 。由于处理器与 G R 模 块的通信遵 循 P P协 PS P 议, 因而需要将 l P数据报按 照 P P的帧格 式封 装成 P P帧 , P 然 后通过 串 口传给 G R P S模块 。 P P链 路 链 路 创建 过程 分 成 三 个 阶 段 : P
割草机器人基于PID控制算法的巡线方法

割草机器人基于PID控制算法的巡线方法摘要:智能割草机人巡线行走回充电站是一个运动控制的难点,本文介绍了利用经典的PID算法,结合信号采集模块,设计控制算法,通过对测试结果数据分析,对PID参数实时调整,得到了一个完美的工况参数,达到了割草机器人完美沿着边界线行走的结果。
关键词:智能割草机器人;PID算法;巡线运动控制;0 引言随着半导体的发展,智能割草机器人已经在很大比例上取代了传统的人工手推式燃油割草机。
它有着自动运行、自助回充、自动进行路径规划的特点,极大的降低了人的参与。
在欧美市场,智能割草机器人已经取代了传统割草机百分之四十多的市场。
智能智能割草机器人由中央控制单元、电机驱动单元、边界信号采集单元、信号发射单元、安全检测单元、充电单元、UI单元及APP和服务器等模块组成的一个复杂的系统。
1智能割草机的工作原理目前市场上主流的智能割草机大多都是预埋线的方案。
从大的模块上分,这个系统由机器人小车系统、边界信号发射基站和具有导电性能的边界线三部分组成。
首先边界信号发射模块通过一根导线连接形成一个闭环,机器人只能在这根导线围成的圈里面工作。
边界线的形状是根据实际的草地形状随机延伸,是不规则的。
规律性的边界信号通过这根导线发射出去。
机器内部的边界信号采集单元实时的采集数据,把采集到的数据传送给主控单元,主控单元根据信号的状态来发送命令给驱动单元,驱动单元驱动行走电机和割草电机的运行。
我们定义采集到第一个信号是下降沿,此信号采集模块在边界线圈内部,如果采集到的第一个信号是上升沿,则此信号采集模块在边界线圈的外部。
机器的前端安装有3个信号采集模块,3个信号头把感应接收到的信号放大处理后,判断出来自己的位置是位于线圈内部还是线圈外部。
如果3个信号头都在边界线圈内部,则主控发命令使驱动模块驱动电机前进,割草电机转动作业。
当信号头传输给主控的状态是在边界线外时,主控模块发送停机命令。
机器停下来后,重新检测信号是否在界外,如果是,机器做后退转弯的逻辑,转到边界线圈内来继续工作。
PID算法

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;..}.。
PID自动控制巡线arduino

#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算法的巡线小车的设计与实现

基于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移动机器人的循线控制

[收稿日期] 2009-07-09 [作者简介] 唐建东(1970—),男,四川遂宁人,深圳职业技术学院电子信息工程学院讲师.
第9 卷第4期
唐建东:基于数字PID移动机器人的循线控制
57
表1 移动机器人循线状态
移动机器人的循线物理模型移动机器人车体采用双轮驱动自动行进中为实现对白色标识线的跟踪在车体前后部分别安装了两个光电循线检测装置每个循线检测装置上有5个检测点来判断车体相对于白线的位置循线检测装置将检测到白线且偏离车体中心最大的检测点的编号作为反馈信号并提供给控制器控制器再据此来调整左右轮转速给定使得车体快速平稳的趋近白线最终达到沿白线正中行进的目的
1 移动机器人的循线物理模型
移动机器人车体采用双轮驱动,自动行进中为实 现对白色标识线的跟踪,在车体前、后部分别安装了两 个光电循线检测装置(每个循线检测装置上有5个检测 点)来判断车体相对于白线的位置,循线检测装置将检 测到白线且偏离车体中心最大的检测点的编号作为反馈 信号,并提供给控制器,控制器再据此来调整左、右轮 转速给定,使得车体快速平稳的趋近白线,最终达到沿 白线正中行进的目的。白线检测点的数量有限,前、后 循线检测装置各有5个检测点,因而检测到的位置反馈 是离散的、任意时刻的,可能只有1个或2个检测点位于 白线上方。对移动机器人循线检测装置5个检测点依次 编码,其循线状态见表1。 2 移动机器人的数字PID控制算法
如图1所示,本实例的三点曲线拟合方程为:
在软件中的检验点,输入数值7,软件自动给出其 估计值23.695966,而在7点的精确值是24.8,绝对误差 是1.104034,相对误差是0.0445175。 4 结 果
技术解析——单颜色传感器巡线中的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算法的全称是比例-积分-微分算法,它根据当前控制误差的大小来调整控制器的输出,以使系统的输出达到期望值。
PID算法的原理可以简单概括为以下三部分:1.比例控制:根据当前的误差,调整控制器的输出。
比例控制的目的是使系统对误差的响应更为迅速,其输出与误差成正比。
比例控制能够解决系统的静态误差,但对于系统的超调和振荡等问题并没有很好的处理能力。
2.积分控制:根据误差的累积值来调整控制器的输出。
积分控制能够解决系统的稳态误差,通过累积误差可以逐渐消除系统的静态误差。
积分控制可以使系统对稳态误差更加敏感,但对于系统的超调和振荡等问题并没有很好的抑制能力。
3.微分控制:根据误差的变化率来调整控制器的输出。
微分控制能够使系统对误差的变化趋势做出反应,通过减小误差的变化率可以使系统更加稳定。
微分控制对于系统的超调和振荡等问题有一定的抑制作用,但对于系统的静态误差并没有很好的解决能力。
在循迹小车的控制中,PID算法可以通过如下方式应用:1.传感器获取车辆当前位置信息。
2.计算当前位置与期望位置之间的误差。
3.根据误差的大小来调整控制器的输出,得到轮速或转角的控制信号。
4.根据控制信号调整车辆的轮速或转弯角度,使车辆朝期望位置行驶。
5.重复步骤1-4,使车辆持续追踪期望轨迹。
在具体实现中,需要根据系统的特性和需求来调节PID算法中比例、积分和微分的参数。
通常可以通过实验或者系统模拟来找到合适的参数值,以使系统达到较好的控制效果。
总结起来,PID算法通过比例、积分和微分三部分的组合来调节控制器的输出,使系统跟踪期望值。
在循迹小车中,PID算法可以根据当前位置与期望位置的差异来调整车辆的轮速或转弯角度,使车辆持续沿着期望轨迹行驶。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
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.}目前工业自动化水平已成为衡量各行各业现代化水平的一个重要标志。