智能小车pid算法

合集下载

智能车PID的算法推荐

智能车PID的算法推荐

PID( Proportional Integral Derivative )控制是最早发展起来的控制策略之一,由于其算法简单、鲁棒性(稳定性)好和可靠性高,被广泛应用于工业过程控制,尤其适用于可建立精确数学模型的确定性控制系统。

模拟PID控制系统原理框图PID是一种线性控制器,它根据给定值r in(k)与实际输出值y out(k)的差值e(t)构成控制方案,利用运放实现模拟PID的一个例子:式中:以上为典型模拟PID应用例子。

关于各调节器的作用说明:♥比例调节器P1、起调节作用与输出量和给定量的差成正比,有差就有调节作用,所以他的调节结果总是有差存在,这种调节不可消除差,所以叫这种调节为有静差调节;2、但这种调节作用快,能很快减小误差,是最常用的一种调节器!3、积分I调节慢,所以PI是最常用的一种搭配!♥积分调节器I1、是给定量与输出量的差对时间的积分,在电路里就是用给定量与输出量的差给电容充电,只要时间足够长,电容器的电压总会到达给定量,使输出量与给定量的差为零;2、积分调节器是一种无静差调节器,意思是说可调节到给定值,做到精确、准确输出;♥微分控制调节器D1、,这种控制总是以输出量与给定量的差的变化率成正比,差变化越剧烈,调节作用越大,差变化越平稳,调节作用越弱;2、这种微分调节作用,使得输出量平稳而很少波动;3、这种微分调节作用,对输出量的变化、波动产生强烈的阻尼、抑制的作用,就像摩擦力的作用;数字式PID应用:增量式PID的算式为:如果换换成智能车里的方向控制就变为:Pwm_offset=PWMMiddle+PID_P*(error-last_error)+PID_I*(error)+PID_D*(error+pre_error-2*la st_error);其中:error=middle-offset,注意这个公式里的offset应该有正负之分,左右偏移的值互为相反。

这样自然就确定了最后的方向。

智能车PID的算法推荐

智能车PID的算法推荐

PID( Proportional Integral Derivative )控制是最早发展起来的控制策略之一,由于其算法简单、鲁棒性(稳定性)好和可靠性高,被广泛应用于工业过程控制,尤其适用于可建立精确数学模型的确定性控制系统。

模拟PID控制系统原理框图PID是一种线性控制器,它根据给定值r in(k)与实际输出值y out(k)的差值e(t)构成控制方案,利用运放实现模拟PID的一个例子:式中:以上为典型模拟PID应用例子。

关于各调节器的作用说明:♥比例调节器P1、起调节作用与输出量和给定量的差成正比,有差就有调节作用,所以他的调节结果总是有差存在,这种调节不可消除差,所以叫这种调节为有静差调节;2、但这种调节作用快,能很快减小误差,是最常用的一种调节器!3、积分I调节慢,所以PI是最常用的一种搭配!♥积分调节器I1、是给定量与输出量的差对时间的积分,在电路里就是用给定量与输出量的差给电容充电,只要时间足够长,电容器的电压总会到达给定量,使输出量与给定量的差为零;2、积分调节器是一种无静差调节器,意思是说可调节到给定值,做到精确、准确输出;♥微分控制调节器D1、,这种控制总是以输出量与给定量的差的变化率成正比,差变化越剧烈,调节作用越大,差变化越平稳,调节作用越弱;2、这种微分调节作用,使得输出量平稳而很少波动;3、这种微分调节作用,对输出量的变化、波动产生强烈的阻尼、抑制的作用,就像摩擦力的作用;数字式PID应用:增量式PID的算式为:如果换换成智能车里的方向控制就变为:Pwm_offset=PWMMiddle+PID_P*(error-last_error)+PID_I*(error)+PID_D*(error+pre_error-2*la st_error);其中:error=middle-offset,注意这个公式里的offset应该有正负之分,左右偏移的值互为相反。

这样自然就确定了最后的方向。

PID算法在智能车方向控制中的应用

PID算法在智能车方向控制中的应用

PID算法在智能车方向控制中的应用智能车是指能够感知、分析、决策和执行动作的汽车。

它可以通过集成传感器、图像识别、机器学习和控制算法来实现自主导航和安全驾驶。

在智能车的控制系统中,方向控制是一个重要的组成部分。

PID算法是智能车方向控制中常用的一种算法,它能够通过实时调整车辆转向角度来实现车辆的精确控制。

PID算法是一种反馈控制算法,它通过不断地对系统输出与期望输出的差异进行检测和调整,以实现控制系统的稳定。

PID算法由比例控制、积分控制和微分控制三个部分组成。

比例控制部分根据系统输出与期望输出的差异进行比例调整,积分控制部分根据系统输出与期望输出的累积差异进行积分调整,微分控制部分根据系统输出与期望输出的变化速率进行微分调整。

这三个部分共同作用,通过实时调整控制信号来达到期望输出。

在智能车的方向控制中,PID算法可以通过以下步骤应用:1.传感器数据获取:智能车通常配备了多种传感器,如惯性传感器、陀螺仪和激光雷达等,用于感知车辆的运动状态和周围环境。

PID算法需要读取传感器数据作为反馈信号。

2.设置期望输出:根据预定的路线或目标,可以设置一个期望的转向角度作为系统的期望输出。

3.计算误差:将传感器数据中获取的实际转向角度与期望转向角度进行比较,计算得出误差。

误差可以表示为实际转向角度减去期望转向角度的差异。

4.比例控制:根据误差的大小,比例控制部分会调整控制信号的大小,从而影响车辆的转向角度。

比例系数越大,车辆的响应速度越快,但可能会引起过冲或震荡现象。

5.积分控制:积分控制部分会通过累积误差来调整控制信号,从而消除系统的稳态误差。

积分系数越大,车辆的稳定性越好,但可能会引起过冲现象。

6.微分控制:微分控制部分会通过测量误差的变化率来调整控制信号,从而降低车辆的震荡现象。

微分系数越大,车辆的稳定性越好,但可能会引起过度补偿。

7.发送控制信号:根据比例控制、积分控制和微分控制的结果,生成控制信号并发送给车辆的转向系统,从而实现转向角度的调整。

PID算法

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控制算法在智能小车中的研究与应用

模糊PID控制算法在智能小车中的研究与应用

模糊PID控制算法在智能小车中的研究与应用一、本文概述随着科技的快速发展和智能化水平的提高,智能小车在各个领域的应用越来越广泛,如无人驾驶、物流运输、环境监测等。

然而,智能小车的运动控制是一个复杂的问题,需要解决路径规划、避障、速度控制等多个方面的问题。

其中,速度控制是智能小车运动控制的核心问题之一。

传统的PID控制算法在速度控制方面有着广泛的应用,但由于其对于系统参数变化的敏感性,使得其在实际应用中往往难以达到理想的控制效果。

因此,本文提出了一种基于模糊PID控制算法的智能小车速度控制方法,旨在提高智能小车的运动控制精度和稳定性。

本文首先对模糊PID控制算法的基本原理和特点进行了介绍,然后详细阐述了模糊PID控制算法在智能小车速度控制中的应用方法。

在此基础上,通过实验验证了模糊PID控制算法在智能小车速度控制中的有效性和优越性。

本文的研究工作不仅为智能小车的运动控制提供了一种新的方法,同时也为模糊PID控制算法在其他领域的应用提供了有益的参考。

接下来,本文将从模糊PID控制算法的基本原理、智能小车的运动控制模型、模糊PID控制算法在智能小车速度控制中的应用方法、实验结果与分析等方面展开详细的阐述。

二、模糊PID控制算法的基本原理模糊PID控制算法是一种结合了模糊逻辑和传统PID控制算法的控制策略。

该算法利用模糊逻辑处理PID控制中的非线性、不确定性和复杂性问题,从而提高了系统的鲁棒性和控制精度。

模糊逻辑是一种基于模糊集合和模糊推理的控制系统设计方法。

在模糊逻辑中,变量不再局限于具体的数值,而是可以在一定的范围内取任意值,这种变量被称为模糊变量。

模糊逻辑通过模糊集合和模糊运算,能够处理不确定性、非线性和不精确性等问题,使系统更加适应复杂环境。

PID控制算法是一种经典的闭环控制算法,由比例(P)、积分(I)和微分(D)三个部分组成。

PID控制器通过比较实际输出与期望输出的偏差,根据偏差的大小和方向,调整控制量以实现系统的稳定控制。

PID算法原理及调整规律

PID算法原理及调整规律

PID算法原理及调整规律一、PID算法简介在智能车竞赛中,要想让智能车根据赛道的不断变化灵活的行进,PID算法的采用很有意义。

首先必须明确PID算法是基于反馈的。

一般情况下,这个反馈就是速度传感器返回给单片机当前电机的转速。

简单的说,就是用这个反馈跟预设值进行比较,如果转速偏大,就减小电机两端的电压;相反,则增加电机两端的电压。

顾名思义,P指是比例(Proportion),I指是积分(Integral),D指微分(Differential)。

在电机调速系统中,输入信号为正,要求电机正转时,反馈信号也为正(PID算法时,误差=输入-反馈),同时电机转速越高,反馈信号越大。

要想搞懂PID算法的原理,首先必须先明白P,I,D各自的含义及控制规律:比例P:比例项部分其实就是对预设值和反馈值差值的发大倍数。

举个例子,假如原来电机两端的电压为U0,比例P为0.2,输入值是800,而反馈值是1000,那么输出到电机两端的电压应变为U0+0.2*(800-1000)。

从而达到了调节速度的目的。

显然比例P越大时,电机转速回归到输入值的速度将更快,及调节灵敏度就越高。

从而,加大P值,可以减少从非稳态到稳态的时间。

但是同时也可能造成电机转速在预设值附近振荡的情形,所以又引入积分I解决此问题。

积分I:顾名思义,积分项部分其实就是对预设值和反馈值之间的差值在时间上进行累加。

当差值不是很大时,为了不引起振荡。

可以先让电机按原转速继续运行。

当时要将这个差值用积分项累加。

当这个和累加到一定值时,再一次性进行处理。

从而避免了振荡现象的发生。

可见,积分项的调节存在明显的滞后。

而且I值越大,滞后效果越明显。

微分D:微分项部分其实就是求电机转速的变化率。

也就是前后两次差值的差而已。

也就是说,微分项是根据差值变化的速率,提前给出一个相应的调节动作。

可见微分项的调节是超前的。

并且D值越大,超前作用越明显。

可以在一定程度上缓冲振荡。

比例项的作用仅是放大误差的幅值,而目前需要增加的是“微分项”,它能预测误差变化的趋势,这样,具有比例+微分的控制器,就能够提前使抑制误差的控制作用等于零,甚至为负值,从而避免了被控量的严重超调。

小车循迹的pid算法

小车循迹的pid算法

小车循迹的pid算法小车循迹的PID算法引言:小车循迹是指通过感知地面上的黑线或者白线,使小车能够沿着线路行驶。

为了实现精确的循迹,PID算法被广泛应用于小车循迹控制中。

本文将介绍PID算法的原理和应用于小车循迹的具体实现。

一、PID算法原理PID算法是一种基于反馈控制的算法,其全称为比例-积分-微分控制算法。

其基本原理是通过不断调整输出信号,使系统的输出值尽量接近给定的目标值。

1. 比例控制(Proportional Control):比例控制是根据当前误差的大小来调整输出信号。

当误差较大时,输出信号也会相应增大;当误差较小时,输出信号也会相应减小。

这样可以实现系统的快速响应。

2. 积分控制(Integral Control):积分控制是根据误差的累积值来调整输出信号。

当误差持续存在时,积分项会逐渐增大,从而加大输出信号,以消除积累误差。

积分控制可以解决系统静差的问题。

3. 微分控制(Derivative Control):微分控制是根据误差的变化率来调整输出信号。

当误差的变化率较大时,输出信号也会相应增大;当误差的变化率较小时,输出信号也会相应减小。

微分控制可以提高系统的稳定性和抑制振荡。

二、PID算法在小车循迹中的应用小车循迹是指通过感知地面上的黑线或者白线,使小车能够沿着线路行驶。

PID算法可以根据当前的线路位置误差来调整小车的转向角度,从而实现循迹控制。

1. 感知线路:小车循迹需要通过感知地面上的黑线或者白线来判断当前的位置误差。

通常使用光敏电阻或红外传感器来感知地面的亮度,并将其转换为电信号。

2. 计算误差:根据感知到的线路信息,可以计算出当前的位置误差。

位置误差可以定义为小车当前位置与目标位置之间的距离差。

3. 调整转向角度:根据计算得到的位置误差,可以使用PID算法来调整小车的转向角度。

比例控制项可以根据位置误差的大小来调整转向角度;积分控制项可以消除积累误差,使小车能够更好地沿着线路行驶;微分控制项可以提高系统的稳定性,防止小车出现过大的震荡。

智能车PID的算法推荐

智能车PID的算法推荐

智能车PID的算法推荐智能车PID控制算法是一种常用的控制算法,它通过不断地调整车辆的控制量来实现目标状态与当前状态之间的误差最小化。

PID算法的名称源于它的三个部分:比例(P)、积分(I)和微分(D),而车辆的控制量则是根据这三个部分的权重参数进行计算。

比例项(P)是通过比较目标状态和当前状态的误差得到的,其控制效果是与误差成比例的。

当误差较大时,比例项会产生较大的输出,有助于加快系统响应速度;而当误差较小时,比例项的输出将减小,以减小振荡。

积分项(I)可以追踪已经发生的误差,得到误差的累积项。

它在误差持续存在时提供控制输出,可以在误差较小或者趋于零时,对系统进行微调以消除持久性误差。

微分项(D)是根据误差的变化率来调整系统的输出。

它可以提供一个反馈信号,预测误差的变化趋势,并制定适当的控制输出来减小误差的变化速度,以克服过冲或振荡的问题。

在实际应用中,选择合适的PID权重参数是非常重要的。

通常的做法是先设置P和D的值,然后逐渐增加I的值直到系统稳定。

这个过程可能需要多次试验和微调,以获得最佳的参数组合。

除了基本的PID算法,还有一些改进的PID算法可供选择,其中一些常用的包括:1.增量PID算法:在每个控制周期中,通过计算误差的变化量来更新控制量,以提高控制系统对于误差变化的敏感性。

2.自适应PID算法:根据系统当前状态和性能,动态调整PID参数,以适应不同的工况和外部扰动。

3.模糊PID算法:结合模糊逻辑和PID算法,通过定义模糊规则来调整PID参数,以更好地适应非线性和不确定性系统。

4.基于模型的PID算法:通过对系统动态建模,根据建模结果自动调整PID参数,以提高系统的控制精度和稳定性。

5.改进的积分项算法:针对积分项可能导致的问题(如积分饱和),进行改进和优化,以避免控制系统出现过度响应或不稳定的情况。

6.鲁棒PID算法:通过考虑外部扰动和模型不确定性,设计具有鲁棒性的PID控制器,以提高系统的抗干扰能力和稳定性。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
//矢量合成,X,Y 两个轴, x=0; y=0; //1 号光敏电阻,无 Y 轴,X 为负 x=x-Intensity*Light[0]; //2 号光敏电阻,X 为-0.707,Y 为 0.707,45 度 x=x-(Intensity *Light[1]*707)/1000; y=y+(Intensity *Light[1]*707)/1000; //3 号光敏电阻,X 为 0,Y 为正 y=y+Intensity * Light[2]; //4 号光敏电阻,X,Y 都为+0.707,45 度 x=x+(Intensity*Light[3]*707)/1000; y=y+(Intensity*Light[3]*707)/1000; //5 号光敏电阻,Y 为 0,X 为正 x=x+Intensity*Light[4]; y=y;
Temp_PID=Temp_PID*1/5;
//-1000~+1000 是左右满舵的输出,因此需要除以
0.5
/*单片机浮点运算非常慢,所以用乘 2 除 5 两次定点
运算来替代定点数要先乘后除,才能保证精度,同时要防止溢出,用起来比较麻烦,但 CPU
和内存开销小。*/
return (Temp_PID);
//开启串口 0 收发模块
U0TCTL |= SSEL0;
//选择 ACLK 作为串口波特率时钟源
U0BR1 = 0;
//
U0BR0 = 13;
//分频系数整数部分=13
U0MCTL = 0X6B;
//分频系数小数部分调制=5/8.(2400bps)
P3SEL |= BIT4 + BIT5;
U0CTL &=~ SWRST;
光的强弱,小车都能稳定地、以大概相同的速度寻光进入车库。
这个问题要是深究下去还有很多值得研究的地方:比如同时有若干个强光
源,小车现在的算法是朝着这些光源合成的几何中心进行,如果要实现朝着光最
强的那个光源行进该采用什么样的算法。
避障算法采用了检测发射红外 LED,读一体化接收头的数据判断障碍物的
位置。这里采用 38Khz 敏感的接收头。为了使小车的检测距离适中,还需调整
{flag_2 = 1;BarrierData[2]=5-i;} else BarrierData[2]=0; PIRE3_L; // 关闭 3 号传感器 } // 4 if(flag_3==0) { PIRE4_H ; // 打开 4 号传感器 Delay(34); // 延迟,等待数据稳定
if(IRE4_IN==0) // 如果接收到的信号为低电平,表明右前方有障碍物 {flag_3 = 1;BarrierData[3]=5-i;} else BarrierData[3]=0; PIRE4_L; // 关闭 4 号传感器 } // 5 if(flag_4==0) { Delay(34); PIRE5_H ; // 打开 5 号传感器 Delay(34); // 延迟,等待数据稳定
Last_Position[4]=Last_Position[3];
Last_Position[3]=Last_Position[2];
Last_Position[2]=Last_Position[1];
Last_Position[1]=Last_Position[0];
Last_Position[0]=Position;
//计算比例分量(P)=比例系数*本次位置差
Temp_D=D_coefficient*(Position-Last_Position[5]); //计算微分分量(D)=微分系数
*(本次位置差-前 3 次的位置差)
//注意由于采样比较快,用本次位置-前 3 次位置
才有足够大的控制量
Last_Position[6]=Last_Position[5];
//启动串口
IE1 |= URXIE0;
}
从串口读一个字节数据 char UART0_GetChar(unsigned char *Chr) {
if(UART_InpLen == 0) return (0); _DINT(); UART_InpLen--; *Chr = RX_BUFF[RX_IndexR]; if (++RX_IndexR >= RXBUF_SIZE) { RX_IndexR = 0; } _EINT(); return (1);
影响时设计的一个难点,引导小车的光源时 200W 的灯泡,在实际测试时,由于
白天和晚上环境光的不同,小车的实际 AD 采样值也有差异,会造成小车运行的
不稳定。
不过即使环境光再强烈,在题目要求的场地里也不及灯泡的亮度,该问题
解决方法是先大概感知周围环境的光强,再根据预设的值调整光强系数,自适应
调整电机转速,这样就能保证只要是 200W 的灯泡作为引导光源,无论周围环境
冲过黑线,黑线又偏右。然后控制过程反复,车身是在左右摇摆中向前行走的。
这种摇摆叫做“超调”,超调越大,控制越不稳定,容易出轨。
为了克服惯性,我们除了位置信息之外,还需要知道轨迹的变化趋势。我们
可以用黑线位置的微分值来提前得到变化趋势。用本次位置减去前次位置求出差
值,就大致知道偏移量的变化趋势。将该差值和比例相加后一起作为控制量,即
} }
3.2 寻光,避障算法
题目要求小车到达 C 点之后,在光源引导下避开障碍物进入车库,这就要 求小车同时完成寻光和避障的功能。如果只进行寻光,小车会撞上障碍物,如果 只进行避障,小车也许会离光源越来越远。理论上避障的优先级是要高于寻光的, 因为一旦接触上障碍便宣告失败。所以一旦检测到障碍物,小车会立刻执行避障 动作,一旦传感器环路没有检测到障碍小车就向光源靠拢,这样能够保证小车在 成功避障的条件下逐渐逼近光源,直到走出障碍区之后就能直奔光源而去。这种 算法小车执行寻光避障整体采用了状态机的切换,
if(IRE5_IN==0) // 如果接收到的信号为低电平,表明右前方有障碍物 {flag_4 = 1;BarrierData[4]=5-i;} else BarrierData[4]=0; PIRE5_L; // 关闭 5 号传感器 }
if(flag_0||flag_1||flag_2||flag_3||flag_4) {flag=1;} else flag=0;
}
3.3 串口通信
由于小车采用双核结构,所以就涉及到了两个单片机的通信问题。在整个进
行的过程中,由于两个单片机分工明确,需要通信的地方大概有如下几个地方:
1. 启动时,149 给 425 发送信号,开始计时;
2. 检测到金属时,425 发给 149 计数;
3. 检测到 C 点停车;
4. 车身入库后 149 发给 425 停车,停止计时。
if(Position==-128) return (No_black);
//错误处理(值得改进的地方)
else
{
Temp_I=Position;
for(k=0;k<5;k++)Temp_I+=Last_Position[k];
Temp_I*=I_coefficient;
Tห้องสมุดไป่ตู้mp_P=P_coefficient*Position;
由此可见,通信量并不是很大,而且通信距离不过十几个厘米,所以采用两
个单片机的串口直接相连的方式。全部收发均放在中断中执行,以下是串口
通信的部分程序:
149 串口初始化
UART_Init149()
{
U0CTL |= CHAR;
//异步通讯模式,8 位数据,无校验,1 位停止位
ME1 |= UTXE0 + URXE0;
//2 if(flag_1==0) { Delay(34);
PIRE2_H; // 打开 2 号传感器 Delay(34); // 延迟,等待数据稳定
if(IRE1_IN==0) // 如果接收到的信号为低电平,表明前方有障碍物 {flag_1 = 1;BarrierData[1]=5-i;}
else BarrierData[1]=0; PIRE2_L; } // 3 if(flag_2==0) { PIRE3_H ; // 打开 3 号传感器 Delay(34); // 延迟,等待数据稳定 if(IRE3_IN==0) // 如果接收到的信号为低电平,表明右前方有障碍物
3.1 寻迹算法
采用 PID(PD)控制算法,如果某时刻检测到黑线偏左,就要向左转弯;如果
检测到黑线偏右,就要向右转。偏得越多,就要向黑线方向打越大的转角。这就
是比例控制(P)。
遗憾的是,因为小车有惯性。假设黑线偏左,说明小车偏右了,需要左传舵,
等到小车回到中心的时候,停止转舵,可是小车的惯性会使车身继续左转,直到
通过红外 LED 的电流为 5mA 左右。
采用了 TA0 来发生红外线,不干扰 CPU 的运行:
void TimerAInit()
{ //设置数组,对应频率分别为 38,41,44,48,54,60,67
TACTL |= TASSEL_2 + TACLR + MC_1 ; //TIMER_A 时钟源选为 SMCLK,清 TAR
/*保存前 5 次的位置,以备用。
Temp_PID=Temp_P+Temp_D+Temp_I; //P 分量和 D 分量相加,得到控制量。
if(Temp_PID>5000) Temp_PID=5000; //防止控制量溢出
if(Temp_PID<-5000) Temp_PID=-5000; //控制量-5000~5000 作为左右满舵
可实现提前控制。这就叫做比例微分控制(PD 控制)
相关文档
最新文档