亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

基于人工智能 (AI) 的直线跟随机器人

组件和用品

Arduino Nano
× 1
Seeed 无线蓝牙射频收发器主从
× 1
亚马逊网络服务IR红外传感器模块反射光电
× 1
索尼连续旋转伺服
× 1
Android 4.8 伏电池
× 1

应用和在线服务

Arduino IDE

关于这个项目

在开发了基于 Arduino 的拾放机器人之后,我们的想法是开发一个基于人工智能 AI 的跟随机器人。开发一个简单的跟随机器人对初学者来说是件好事,因为它需要在我最近的项目中添加某种红外传感器而不是伺服电机。 “我的想法是在 测试我的技能 高级级别”。

虽然这是一项艰巨的任务,但某种在线研究对我帮助很大。

为什么需要基于人工智能的跟随机器人?

当谈到人工智能 最新的技术有可能改变世界环境,从而有效地人类生活。通过将智能赋予我们的机器人来理解现实生活中的问题并相应地解决它,这个梦想可以实现,这个梦想只能通过人工智能 这就是为什么每个人都在谈论它。

  • 可用于装配/生产线。
  • 载客巴士。

虽然我的原型机器人可能有点智能,但这只是我将项目转向 AI 的开始。 因此,在这里我将尝试用一种非常简单的语言逐步解释使用人工智能的线跟踪机器人的开发。由于缺乏资源,我不会构建机器人,但我可以很好地解释如何通过进行某种研究来构建它。我将尝试提供可在您的 Arduino IDE 上运行的准确代码,以便您可以很容易地开发出你的第一个人工智能机器人。

你可以从这里在 Patreon 上支持我 :http://bit.ly/31NfQ6A

“您可以在此视频的说明中找到美国最便宜的价格设备,只需点击 视频 。”

现在让我们进入项目“基于人工智能的线跟随机器人!”。

红外线传感器的使用

我们的 项目包括7个红外传感器,如图所示。

  • 5 用于 PID 控制
  • 1 用于左侧检测
  • 另一个用于右侧检测。

5 PID 控制传感器的作用 :这5个传感器将分别用于产生高或低(1、0)的数字输出。

传感器相对于黑线居中,只有该传感器会产生 HIGH(1)。该传感器的类似结果可能是:-

  • 10000
  • 11000
  • 01000
  • 01100
  • 00100
  • 00110
  • 00010
  • 00011
  • 00001
  • 00000
  • 11111

现在来另外两个传感器左右可能的结果是

最左传感器:模拟输出高或低

最左传感器:模拟输出高或低

要存储 5 个传感器的值,让我们创建一个数组变量。

在LFSensor[5]={1,1,1,1,1}; 

为了存储左右传感器的值,我们将使用整数

int farleft_sensor=0; 

众所周知,我们有 5 个传感器,可用于存储机器人在阵列中采用的左右路径。所以

LFSensor[0] =digitalRead(lineFollowSensor0);
LFSensor[1] =digitalRead(lineFollowSensor1);
LFSensor[2] =digitalRead(lineFollowSensor2);
LFSensor[ 3] =digitalRead(lineFollowSensor3);
LFSensor[4] =digitalRead(lineFollowSensor4);
farRightSensor =analogRead(farRightSensorPin);
farLeftSensor =analogRead(farLeftSensorPin);

迷宫左手规则:

观看 这个视频了解迷宫左手规则

简而言之,左手法则 可以描述为:

  • 将左手放在墙上。
  • 开始向前走
  • 在每个十字路口和整个迷宫中,让左手触碰左侧的墙壁。
  • 最终,您将到达迷宫的尽头。你可能不会走最短、最直接的路,但你会到达那里。

所以,这里的关键是识别交叉点 ,根据上述规则定义要采取的课程。具体来说,在我们这种 2D 迷宫中,我们可以找到 8 种不同类型的交叉点(见上图):

看图,我们可以知道在路口可能的动作是:

在“十字架 "

  • 向左走,或
  • 向右转,或
  • 直截了当
  • 在“十字架 “向左走,或向右走,或直走

在“T ":

  • 向左走,或
  • 向右转
  • 在“T ":向左,或向右

在“只有权利 ":

  • 向右转
  • 在“只有权利 ":向右转

在“仅左侧 ":

  • 向左走
  • 在“仅左 ":向左移动

在“直行或向左 ":

  • 向左走,或
  • 直截了当
  • 在“直行或向左 ":向左走,或直走

在“直行或右行 ":

  • 向右转,或
  • 直截了当
  • 在“直行或右行 ":向右走,或直走

在“死胡同 ":

  • 回去(“掉头”)
  • 处于“死胡同 ":Go back ("U turn")

在“迷宫尽头 ":

  • 停止
  • 在“迷宫尽头 ":停止

但是,应用“左手规则”,每个动作将减少到一个选项:

  • 在“十字路口”:向左走
  • 在“T”处:向左移动
  • 在“只靠右边”:向右移动
  • 在“仅左”处:向左移动
  • 在“直行或向左”处:向左走
  • 在“直行或向右”处:直行
  • 在“死胡同”:回去(“掉头”)
  • 在“迷宫尽头”:停止

我们就快到了! “冷静点!”

当机器人到达“死胡同”或“迷宫尽头”时,很容易识别它们,因为它们不存在模棱两可的情况(我们已经在 Line Follower Robot 上实现了这些动作,还记得吗?)。问题是当机器人找到“LINE”时,例如,因为一条线可以是“Cross”(1)或“T”(2)。此外,当它到达“左转或右转”时,可以是简单的转弯(选项 3 或 4)或直行的选项(5 或 6)。为了准确地发现机器人是什么类型的交叉路口,必须采取额外的步骤:机器人必须“多跑一英寸”,然后看看接下来会发生什么(例如,参见上面的第二张图片)。

因此,就流程而言,现在可以将可能的操作描述为:

在“死胡同”:

  • 回去(“掉头”)
  • 在“死胡同”:回去(“掉头”)

在“LINE”:

  • 多跑一英寸
  • 如果有一条线:它是一个“十字”==>转到左边
  • 如果没有线:它是一个“T”==>转到左边
  • 如果还有另一行:它是“迷宫尽头”==>停止
  • 在“LINE”处:多跑一英寸 如果有一条线:它是一个“十字”==>转到左如果没有线:它是一个“T”==>转到左如果有另一条线:它是“迷宫尽头”==> 停止

在“右转”处:

  • 多跑一英寸
  • 如果有一条线:它是直的或右的 ==> 直行
  • 如果没有线:它是一个 Right Only ==> Go to RIGHT
  • 在“右转”时:多跑一英寸 如果有一条线:它是直的或右的 ==> 直走如果没有线:它是一条正确的 ==> 转到右

在“左转”处:

  • 多跑一英寸
  • 如果有一条线:它是直线或左==>转到左
  • 如果没有一行:它是一个LEFT Only ==> Go to LEFT
  • 在“左转”处:多跑一英寸 如果有一条线:它是一条直线或向左 ==> 转到左边如果没有线:它是一条只向左 ==> 转到左边

请注意,实际上,如果是“LEFT TURN”,您可以跳过测试,因为无论如何您都会向左走。只是为了清楚起见,我让解释变得更通用。在真正的代码中,我会跳过这个测试。

以下是制作此项目时可能会遇到的一些问题。

相关话题

Arduino 驱动程序问题解决

观看 此视频用于解决 Arduino 驱动程序问题:


代码

  • RoBot_Maze_Solve_2
  • 功能
  • 通用功能。
  • 传感器功能
  • RobotDefines.h
  • 电机功能
RoBot_Maze_Solve_2C/C++
/*----------------------------------------- ---------------------7个传感器智能机器人-迷宫解算器和线跟随器,通过BT==>可编程PID控制器基于纳米鼠标机器人的基本运动,由开发Michael Backus (http://www.akrobotnerd.com/)==> 线路跟随基于 http://samvrit.tk/tutorials/pid-control-arduino-line-follower-robot/?ckattempt=1==>感谢 Patrick McCabe 提供的路径解决代码,请访问 patrickmccabemakes.com!!Marcelo Jose Rovai - 2016 年 4 月 23 日 - 访问:http://mjrobot.org---------------- -------------------------------------------------- -*/#include #include "robotDefines.h"String command;String device;// BT Module#include SoftwareSerial BT1(10, 11); // El pin 10 es Rx y el pin 11 es Tx//----------------------------------- ----------void setup() { Serial.begin(9600); BT1.开始(9600); pinMode(ledPin,输出); pinMode(buttonPin, INPUT_PULLUP); // 线跟随传感器 pinMode(lineFollowSensor0, INPUT); pinMode(lineFollowSensor1, INPUT); pinMode(lineFollowSensor2, INPUT); pinMode(lineFollowSensor3, INPUT); pinMode(lineFollowSensor4, INPUT); // 舵机 leftServo.attach(5); rightServo.attach(3); BT1.print("检查要发送给机器人的PID常数"); Serial.print("检查要发送给机器人的PID常数"); BT1.println('\n'); while (digitalRead(buttonPin) &&!mode) { checkBTcmd(); // 验证是否收到了来自 BT 遥控器的命令 manualCmd();命令 =""; } checkPIDvalues();模式 =停止;状态 =0; // 第一遍}void loop() { ledBlink(1); BT1.println("开始第一遍"); Serial.println("开始第一遍"); readLFSsensors();迷宫解决(); // 第一遍解迷宫 ledBlink(2); BT1.println("第一遍结束"); Serial.println("结束第一遍"); while (digitalRead(buttonPin) &&!mode) { checkBTcmd(); // 验证是否收到了来自 BT 遥控器的命令 manualCmd();命令 =""; } BT1.println("开始第二遍"); Serial.println("开始第二遍");路径索引 =0;状态 =0;迷宫优化(); //尽可能快地运行迷宫 ledBlink(3); BT1.println("第二遍结束"); Serial.println("第二遍结束"); while (digitalRead(buttonPin) &&!mode) { checkBTcmd(); // 验证是否收到了来自 BT 遥控器的命令 manualCmd();命令 ="";模式=停止;状态 =0; // 第一次通过 pathIndex =0;路径长度 =0;}
函数C/C++
void mazeSolve(void){ while (!status) { readLFSsensors(); switch (mode) { case NO_LINE:motorStop(); goAndTurn (左, 180); recIntersection('B');休息;案例 CONT_LINE:runExtraInch(); readLFSsensors();如果(模式!=CONT_LINE){goAndTurn(左,90); recIntersection('L');} // 或者它是一个“T”或“Cross”)。在这两种情况下,转到 LEFT else mazeEnd();休息; case RIGHT_TURN:runExtraInch(); readLFSsensors(); if (mode ==NO_LINE) {goAndTurn (RIGHT, 90); recIntersection('R');} else recIntersection('S');休息; case LEFT_TURN:goAndTurn (LEFT, 90); recIntersection('L');休息;案例FOLLOWING_LINE:followLine();休息; } }}//-------------------------------------------- void recIntersection(char 方向){ path[pathLength] =方向; // 将交集存储在路径变量中。路径长度++;简化路径(); // 简化学习路径。}//---------------------------------------- ------void mazeEnd(void){ motorStop(); BT1.print("结束 ==> 路径:"); for(int i=0;i "); Serial.println(pathLength);状态 =1; mode =STOPPED;}//------------------------------------------- ---void followingLine(void){ //readLFSsensors();计算PID();电机PID控制(); }//---------------------------------------------- -------------------------------------------// 路径简化。策略是每当我们遇到一个//序列xBx时,我们可以通过切掉死胡同来简化它。例如,LBL -> S,因为单个 S 绕过了由 LBL 表示的死胡同 //。 pathLength <3 || path[pathLength-2] !='B') return;整数总角度 =0;国际我; for(i=1;i<=3;i++) { switch(path[pathLength-i]) { case 'R':totalAngle +=90;休息; case 'L':totalAngle +=270;休息;案例'B':总角度+=180;休息; } } // 获取角度为 0 到 360 度之间的数字。总角度 =总角度 % 360; // 用一个回合替换所有这些回合。 switch(totalAngle) { case 0:path[pathLength - 3] ='S';休息;案例 90:路径[路径长度 - 3] ='R';休息; case 180:path[pathLength - 3] ='B';休息;案例270:路径[路径长度 - 3] ='L';休息; } // 路径现在缩短了两步。路径长度 -=2; } //---------------------------------------------- -----------------------------------------------void mazeOptimization ( void){ while (!status) { readLFSsensors();开关(模式){ case FOLLOWING_LINE:followLine();休息; case CONT_LINE:if (pathIndex>=pathLength) mazeEnd();否则{迷宫转弯(路径[路径索引]);路径索引++;}中断; case LEFT_TURN:if (pathIndex>=pathLength) mazeEnd();否则{迷宫转弯(路径[路径索引]);路径索引++;}中断; case RIGHT_TURN:if (pathIndex>=pathLength) mazeEnd();否则{迷宫转弯(路径[路径索引]);路径索引++;}中断; } } }//----------------------------------------- --------void mazeTurn (char dir) { switch(dir) { case 'L':// 向左转 goAndTurn (LEFT, 90);休息; case 'R':// 右转 goAndTurn (RIGHT, 90);休息; case 'B':// 返回 goAndTurn (RIGHT, 800);休息; case 'S':// 直接运行 runExtraInch();休息; }}
GeneralFunctions.C/C++
void ledBlink(int times){ for (int i =0; i 0) { Serial.print("从 BT 收到的命令 ==> "); Serial.println(设备);命令 =设备;设备=""; //重置变量BT1.flush(); }//---------------------------------------------- --------------------------void manualCmd(){ switch (command[0]) { case 'g':mode =FOLLOWING_LINE;休息; case 's':motorStop(); //关闭两个电机 break;案例'f':motorForward();休息; case 'r':motorTurn(RIGHT, 30);电机停止();休息; case 'l':motorTurn(LEFT, 30);电机停止();休息; case 'b':motorBackward();休息; case 'p':Kp =命令[2];休息;案例“我”:Ki =命令[2];休息;案例“d”:Kd =命令[2];休息; }}//---------------------------------------------- --------------------------void sendBTdata (int data) // 发送数据到 BT{ digitalWrite (ledPin, HIGH); BT1.print("来自Arduino的数据"); BT1.打印(数据); BT1.print("xx"); BT1.println('\n');数字写入(ledPin,低);}//---------------------------------------- ----------------void calculatePID(){ P =错误; I =I + 错误; D =错误前一个错误; PID值=(Kp*P)+(Ki*I)+(Kd*D); previousError =error;}//------------------------------------------- -------------void checkPIDvalues(){ BT1.print("PID:"); BT1.print(Kp); BT1.print(" - "); BT1.print(Ki); BT1.print(" - "); BT1.println(Kd); Serial.print("PID:"); Serial.print(Kp); Serial.print(" - "); Serial.print(Ki); Serial.print(" - "); Serial.println(Kd); }//---------------------------------------------- void testLineFollowSensors(){ int LFS0 =digitalRead(lineFollowSensor0); int LFS1 =digitalRead(lineFollowSensor1); int LFS2 =digitalRead(lineFollowSensor2); int LFS3 =digitalRead(lineFollowSensor3); int LFS4 =digitalRead(lineFollowSensor4); Serial.print ("LFS:L 0 1 2 3 4 R ==> "); Serial.print (LFS0); Serial.print(""); Serial.print (LFS1); Serial.print(""); Serial.print (LFS2); Serial.print(""); Serial.print (LFS3); Serial.print(""); Serial.print (LFS4); Serial.print (" ==> "); Serial.print("P:"); Serial.print (P); Serial.print("我:"); Serial.print (I); Serial.print("D:"); Serial.print (D); Serial.print(" PID:"); Serial.println (PIDvalue);}
sensorFuntionsC/C++
//----------------------------------------- ----------------/* 读取线传感器值 Sensor Array Error Value0 0 0 0 1 4 0 0 0 1 1 3 0 0 0 1 0 2 0 0 1 1 0 1 0 0 1 0 0 0 0 1 1 0 0 -1 0 1 0 0 0 -2 1 1 0 0 0 -3 1 0 0 0 0 -4 1 1 1 1 1 0 机器人找到连续线 - 测试是否有交叉点或结束of maze0 0 0 0 0 0 机器人找不到线:转 180o*/void readLFSsensors(){ LFSensor[0] =digitalRead(lineFollowSensor0); LFSensor[1] =digitalRead(lineFollowSensor1); LFSensor[2] =digitalRead(lineFollowSensor2); LFSensor[3] =digitalRead(lineFollowSensor3); LFSensor[4] =digitalRead(lineFollowSensor4); farRightSensor =analogRead(farRightSensorPin); farLeftSensor =analogRead(farLeftSensorPin); if ((LFSensor[0]==1 )&&(LFSensor[1]==1 )&&(LFSensor[2]==1 )&&(LFSensor[3]==1 )&&(LFSensor[4]==1 )) {模式 =CONT_LINE; error =0;} else if((LFSensor[0]==0 )&&(farRightSensor  "); Serial.print (farRightSensor); Serial.print("模式:"); Serial.print(模式); Serial.print(“错误:”); Serial.println(错误); }//---------------------------------------------- ------------void readLateralSensors(void){ }
RobotDefines.hC/C++
int mode =0;#define STOPPED 0#define FOLLOWING_LINE 1#define NO_LINE 2#define CONT_LINE 3#define POS_LINE 4#define RIGHT_TURN 5#define LEFT_TURN 6const int power =250;const int iniMotorPower =250;const int =0;float adjTurn =8;int extraInch =200;int adjGoAndTurn =800;const int ledPin =13;const int buttonPin =9;// LFSensor 更靠左为“0”const int lineFollowSensor0 =12; const int lineFollowSensor1 =18; const int lineFollowSensor2 =17; const int lineFollowSensor3 =16;const int lineFollowSensor4 =19;const int farRightSensorPin =0; //模拟引脚A0const int farLeftSensorPin =1; //模拟引脚A0const int THRESHOLD =150;int farRightSensor =0;int farLeftSensor =0;int LFSensor[5]={0, 0, 0, 0, 0};// PID控制器float Kp=50;float Ki=0;float Kd=0;float error=0, P=0, I=0, D=0, PIDvalue=0;float previousError=0, previousI=0;#define RIGHT 1#define LEFT -1Servo leftServo;Servo rightServo; //------------------------------------------------ -//特定迷宫阶段2(优化)定义和变量unsigned char dir; // 路径变量将存储机器人走过的路径:// 'L' 代表左// 'R' 代表右// 'S' 代表直线(直行穿过一个路口)// 'B' 代表后面(掉头)char path[100] ="";unsigned char pathLength =0; // pathint pathIndex =0;unsigned int status =0;的长度// 求解 =0;到达终点 =1
MotorFuntionsC/C++
void motorStop(){ leftServo.writeMicroseconds(1500); rightServo.writeMicroseconds(1500);延迟(200);}//------------------------------------------- --- void motorForward(){ leftServo.writeMicroseconds(1500 - (power+adj)); rightServo.writeMicroseconds(1500 + power);}//-------------------------------------- -------void motorBackward(){ leftServo.writeMicroseconds(1500 + power); rightServo.writeMicroseconds(1500 - power);}//-------------------------------------- -------void motorFwTime (unsigned int time){ motorForward();延迟时间); motorStop();}//---------------------------------------- --void motorBwTime (unsigned int time){ motorBackward();延迟时间); motorStop();}//---------------------------------------- -----void motorTurn(int direction, int degree){ leftServo.writeMicroseconds(1500 - (iniMotorPower+adj)*direction); rightServo.writeMicroseconds(1500 - iniMotorPower*direction);延迟(round(adjTurn*degrees+20)); motorStop();}//---------------------------------------- --------void motorPIDcontrol(){ int leftMotorSpeed =1500 - (iniMotorPower+adj) - PIDvalue; int rightMotorSpeed =1500 + iniMotorPower - PID 值; // 电机速度不应超过最大 PWM 值 constrain(leftMotorSpeed, 1000, 2000);约束(rightMotorSpeed, 1000, 2000); leftServo.writeMicroseconds(leftMotorSpeed); rightServo.writeMicroseconds(rightMotorSpeed); //Serial.print (PIDvalue); //Serial.print (" ==> Left, Right:"); //Serial.print (leftMotorSpeed); //Serial.print(""); //Serial.println (rightMotorSpeed);}//-------------------------------------- -------------void runExtraInch(void){ motorPIDcontrol();延迟(额外英寸); motorStop();}//---------------------------------------- --------void goAndTurn(int 方向,int 度数){ motorPIDcontrol();延迟(adjGoAndTurn); motorTurn(方向,度数);}

示意图


制造工艺

  1. 人造雪
  2. 基于树莓派的避墙机器人——FabLab NerveCentre
  3. 具有基于视觉的避障功能的移动机器人
  4. 'Artistic' Robot At NPE
  5. 自动化:重新设计的机器人生产线
  6. 博世将人工智能添加到工业 4.0
  7. SCARA 机器人生产线扩展
  8. 人工智能是小说还是时尚?
  9. 人工智能帮助机器人通过触摸识别物体
  10. 人工智能机器人
  11. 人工智能的优缺点
  12. 大数据与人工智能