PID 控制线跟随机器人
组件和用品
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
应用和在线服务
|
关于这个项目
概览
大多数漫游者自主机器人需要的一项功能是线路跟随。该项目的目的是构建一个跟随机器人并开始以有趣的方式学习 PID 控制器。
零件
机器人通过两个电机、Rosbot 基板和一个 5 通道传感器正常运行。与其他产品不同的是,您无需购买额外的 H 桥电机驱动器或各种组件,因为 Rosbot 基板内置了 2 个 H 桥双驱动器。只需将电机连接到 Rosbot 基板,它就会提供比 Arduino Uno 更大的功率。
- 机器人的框架: KittenBot 阳极氧化铝机箱
具有大量安装孔(4.8 毫米乐高机械组)的酷炫而坚固的机箱,您绝对可以将此机箱重新用于其他有趣的项目。
- 机器人的大脑 :RosBot 底板
基于 Arduino UNO 的主板,带有 2 个板载双 H 桥电机驱动器。
- 机器人的眼睛 :5 通道红外跟踪跟踪传感器
5通道红外探测器,更准确、更稳定。
第一步:组装
这个机器人相当容易组装,按照说明操作,大约需要 15 分钟。
首先,将电机连接到底盘的两侧,只需插入橡胶轮即可。
将 5 通道红外传感器安装到机箱前部。
将您的 Rosbot 底板连接到底盘上,然后机器人就可以接线了。
第 2 步:拧干
以下是 5 通道红外传感器的连接:
- VCC 至 5V
- GND 到 RosBot 的 GND
- T1-T4 至 A0-A3 引脚
- T5 连接 SDA
直流电机只需转到引脚 A+A- 和引脚 B+B-。
编码
在代码中,我们有一个状态机来指示每个可能的传感器阵列输出。机器人根据传感器阵列输出向某个方向移动。
void stateMachine(int a) { switch (a) { case B00000:outlineCnt++;休息;案例 B11111:outlineCnt++;休息;案例 B00010:案例 B00110:outlineCnt =0; pixel.setPixelColor(2, pixel.Color(0, 50, 0));偏差 =1;休息;案例 B00001:案例 B00011:outlineCnt =0; pixel.setPixelColor(2, pixel.Color(0, 200, 0));偏差 =2;休息;情况 B00100:outlineCnt =0; pixel.setPixelColor(2, pixel.Color(0, 0, 20));偏差 =0;休息;案例 B01000:案例 B01100:outlineCnt =0; pixel.setPixelColor(2, pixel.Color(50, 0, 0));偏差 =-1;休息;案例 B10000:案例 B11000:outlineCnt =0; pixel.setPixelColor(2, pixel.Color(200, 0, 0));偏差 =-2;休息;默认值:Serial.println(a,BIN);大纲Cnt++;休息; }
我们已经设置了误差值、比例项、积分项和导数项。
float Kp =25;float Ki =0.15;float Kd =1200;float error, errorLast, erroInte;float calcPid(float input) { float errorDiff;浮动输出;错误 =错误 * 0.7 + 输入 * 0.3; // 过滤器 //错误 =输入; errorDiff =错误 - errorLast;错误输入 =约束(错误输入 + 错误,-50, 50);输出 =Kp * 错误 + Ki * erroInte + Kd * errorDiff;串行打印(错误); Serial.print(' '); Serial.print(errorInte); Serial.print(' '); Serial.print(errorDiff); Serial.print(' '); Serial.println(输出); errorLast =错误;返回输出;
操纵这些值以找到最适合您的机器人的值。
代码
- 巡线机器人
线跟随机器人Arduino
在代码中,我们包含来自 Adafruit 的 NeoPixel,但这是可选的。#include#define S_NULL 0#define S_ONTRACE 1Adafruit_NeoPixel pixel =Adafruit_NeoPixel(4, 4, NEO_GRB + NEO_KHZ800);int doDcSpeed( spdL, int spdR) { spdR =-spdR;如果(spdL <0){analogWrite(5, 0);模拟写入(6,-spdL); } else {analogWrite(5, spdL);模拟写入(6, 0); } if (spdR <0) {analogWrite(9, 0);模拟写入(10,-spdR); } else {analogWrite(9, spdR);模拟写入(10, 0); }}int bias =0;int outlineCnt =0;void stateMachine(int a) { switch (a) { case B00000:outlineCnt++;休息;案例 B11111:outlineCnt++;休息;案例 B00010:案例 B00110:outlineCnt =0; pixel.setPixelColor(2, pixel.Color(0, 50, 0));偏差 =1;休息;案例 B00001:案例 B00011:outlineCnt =0; pixel.setPixelColor(2, pixel.Color(0, 200, 0));偏差 =2;休息;情况 B00100:outlineCnt =0; pixel.setPixelColor(2, pixel.Color(0, 0, 20));偏差 =0;休息;案例 B01000:案例 B01100:outlineCnt =0; pixel.setPixelColor(2, pixel.Color(50, 0, 0));偏差 =-1;休息;案例 B10000:案例 B11000:outlineCnt =0; pixel.setPixelColor(2, pixel.Color(200, 0, 0));偏差 =-2;休息;默认值:Serial.println(a,BIN);大纲Cnt++;休息; } pixel.setPixelColor(0, pixel.Color(outlineCnt * 10, 0, 0));如果(outlineCnt> 10){ doDcSpeed(0,0); }其他{浮动FF =150;浮动 ctrl =calcPid(bias); doDcSpeed(ff-ctrl,ff+ctrl); } pixel.show();}float Kp =25;float Ki =0.15;float Kd =1200;float error, errorLast, erroInte;float calcPid(float input) { float errorDiff;浮动输出;错误 =错误 * 0.7 + 输入 * 0.3; // 过滤器 //错误 =输入; errorDiff =错误 - errorLast;错误输入 =约束(错误输入 + 错误,-50, 50);输出 =Kp * 错误 + Ki * erroInte + Kd * errorDiff;串行打印(错误); Serial.print(' '); Serial.print(errorInte); Serial.print(' '); Serial.print(errorDiff); Serial.print(' '); Serial.println(输出); errorLast =错误;返回输出;}int echoTrace() { int ret =0; int a[5]; for (int i =0; i <5; i++) { a[i] =constrain((1025 - analogRead(A0 + i)) / 10 - 4, 0, 20);如果 (a[i]> 2) ret +=(0x1 < LinefollowRobot
https://github.com/KittenBot/LinefollowRobot
示意图
制造工艺