小型双轮差速底盘寻迹功能的实现
1. 功能说明
寻迹机器人是一种能够跟踪特定物体或线路的机器人。它们通常具有以下功能和特点:
① 传感器:寻迹机器人配备了用于感知环境的传感器,如摄像头、灰度传感器等。这些传感器可以探测地面上的标记、颜色、纹理或其他特定特征,以确定要跟踪的目标。
② 自主导航:寻迹机器人通常具备自主导航能力,可以根据目标物体的位置和运动轨迹进行移动和调整。它们可能使用轮式、履带或其他移动机构来在地面上移动。
③ 跟踪精度:寻迹机器人通常被设计为能够实时跟踪目标物体,并尽可能准确地保持距离和方向。一些高级寻迹机器人还可以通过预测目标物体的运动来提高跟踪的精度。
④ 应用场景:寻迹机器人可以应用于多种场景,如工业生产线上的零部件跟踪、物流仓库中的货物识别与追踪、安防领域中的行人监控等。它们在自动化、智能化和效率提升方面具有广泛的应用前景。
本文示例将实现R023样机小型双轮差速底盘机器人沿直线寻迹行走的一个功能。
2. 结构装配
按照下图所示方式进行安装:
3. 电子硬件
在这个示例中,我们采用了以下硬件,请大家参考:
主控板 | Basra主控板(兼容Arduino Uno) |
扩展板 | Bigfish2.1扩展板 |
传感器 | 灰度传感器 |
电池 | 7.4V锂电池 |
按照下图所示方式进行电路连接:
4. 功能实现
编程环境:Arduino 1.8.19
① 下面提供一个控制轮子转动方向和速度的参考例程(Test1.ino):
/*------------------------------------------------------------------------------------版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.Distributed under MIT license.See file LICENSE for detail or copy athttps://opensource.org/licenses/MITby 机器谱 2023-07-14 https://www.robotway.com/------------------------------*/#include <Servo.h>//调用舵机库Servo myservo;//声明一个舵机类void setup()//Arduino的设置函数{myservo.attach(4);//绑定控制舵机的引脚}void loop()//Arduino的循环函数{for(int i=0; i<180; i++){//通过调节i值控制舵机的运行参数myservo.write(i);//输出控制舵机的运行参数delay(500);//延时}}
② 下面提供一个控制轮子前进、停止、左转、右转、左微调、右微调的参考例程(Test2.ino):
/*------------------------------------------------------------------------------------版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.Distributed under MIT license.See file LICENSE for detail or copy athttps://opensource.org/licenses/MITby 机器谱 2023-07-14 https://www.robotway.com/------------------------------*/#include <Servo.h>#define middle1 88//定义对应舵机的中间值,即停止转动的值#define middle2 88//此值需要测量,各个舵机不一定相同Servo myservo[2];//定义一个舵机类数组void setup(){myservo[0].attach(4);myservo[1].attach(3);}void loop(){Left();//调用左转函数delay(1000);Right();delay(1000);Forwards();delay(1000);stop();delay(1000);}void Left()//左转函数{myservo[0].write(middle1);myservo[1].write(middle2 + 20);}void Right()//右转函数{myservo[0].write(middle1 - 20);myservo[1].write(middle2);}void Forwards()//前进函数{myservo[0].write(middle1 - 20);myservo[1].write(middle2 + 20);}void stop()//后退函数{myservo[0].write(middle1);myservo[1].write(middle2);}
③ 下面提供一个将灰度传感器数据显示到LED点阵上的参考例程(Test3.ino):
/*------------------------------------------------------------------------------------版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.Distributed under MIT license.See file LICENSE for detail or copy athttps://opensource.org/licenses/MITby 机器谱 2023-07-14 https://www.robotway.com/------------------------------*/#include <LedControl.h>//调用点阵库函数#include <Servo.h>LedControl lc=LedControl(12,11,13,1);//声明点阵类,并设置对应的引脚int pin[3] = {A0, A4, A3};//设置传感器的对应的三个引脚byte value;//声明传感器值变量void setup(){LedInit();//初始化点阵}/************************************************************************************此程序用到了for与switch的配合框架,可用于多传感器的实时处理,请细细体会!具体解析:for循环中使用了位处理,这样的结果就是value的一个数据位对应一个传感器的状态,此程序value的类型为byte,则可支持8个传感器,如果要使用更多传感器可定义int等。传感器触发时返回值为0,因此value值与传感器触发的状态对应关系以A0触发为例:A0传感器触发-->二进制:00000110-->十六进制:0x06-->对应case 0x06;所以这样做的好处就是当传感器的状态发生改变时程序可以快速的到达指定的处理方式**************************************************************************************/void loop(){value = 0;for(int i=0; i<3; i++){//通过循环检测,读取传感器的状态值value |= (digitalRead(pin[i]) << i);//通过位处理得到结果值,digitalRead()用于读取数字值}switch (value) {//根据结果值进行相应的事件处理case 0x00://全部触发LedOn(0);//点亮相应的点阵LedOn(1);LedOn(2);break;case 0x01://触发右边两个LedOn(1);LedOn(2);break;case 0x03://触发右边一个LedOn(2);break;case 0x04://触发左边两个LedOn(0);LedOn(1);break;case 0x05://触发中间一个LedOn(1);break;case 0x06://触发左边一个LedOn(0);break;default:;}}void LedOn(int key)//根据参数点亮相应的点阵LED{lc.clearDisplay(0);for(int i=0; i<2; i++){for(int j=3*key; j<3*key+2; j++){lc.setLed(0, i, j, true);}}}void LedInit() //点阵初始化函数{lc.shutdown(0,false);lc.setIntensity(0,8);lc.clearDisplay(0);}
④ 下面提供一个小车行走直线的参考例程(Test4.ino):
/*------------------------------------------------------------------------------------版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.Distributed under MIT license.See file LICENSE for detail or copy athttps://opensource.org/licenses/MITby 机器谱 2023-07-14 https://www.robotway.com/------------------------------*/#include <Servo.h>#define middle1 88#define middle2 88Servo myservo[2];int pin[3] = {A0, A4, A3};byte value;byte value_his = 0;//记录上一次的传感器值void setup(){myservo[0].attach(4);myservo[1].attach(3);}void loop(){value = 0;for(int i=0; i<3; i++){value |= (digitalRead(pin[i]) << i);}if(value == 0x07){//当传感器都没有触发时默认为上一次的值value = value_his;}switch (value) {case 0x00://全部触发Forwards();break;case 0x01://触发右边两个while(digitalRead(pin[1])){//通过while循环使小车回到跑道中间Right();}break;case 0x03://触发右边一个while(digitalRead(pin[1])){Right();}break;case 0x04://触发左边两个while(digitalRead(pin[1])){Left();}break;case 0x05://触发中间一个Forwards();break;case 0x06://触发左边一个while(digitalRead(pin[1])){Left();}break;default:stop();}value_his = value;}void Left(){myservo[0].write(middle1);myservo[1].write(middle2 + 20);}void Right(){myservo[0].write(middle1 - 20);myservo[1].write(middle2);}void Forwards(){myservo[0].write(middle1 - 20);myservo[1].write(middle2 + 20);}void stop(){myservo[0].write(middle1);myservo[1].write(middle2);}
⑤ 下面提供一个小车识别十字路口的参考例程(Test5.ino):
/*------------------------------------------------------------------------------------版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.Distributed under MIT license.See file LICENSE for detail or copy athttps://opensource.org/licenses/MITby 机器谱 2023-07-14 https://www.robotway.com/------------------------------*/#include <Servo.h>#include <LedControl.h>#define middle1 88#define middle2 88Servo myservo[2];LedControl lc=LedControl(12,11,13,1);int pin[3] = {A0, A4, A3};byte value;byte value_his = 0;int time[3];//用于记录传感器的触发时间void setup(){LedInit();myservo[0].attach(4);myservo[1].attach(3);}void loop(){value = 0;for(int i=0; i<3; i++){value |= (digitalRead(pin[i]) << i);if(!digitalRead(pin[i])){time[i] = millis();//调用mills函数可以得到此时单片机的运行时间}}if(TimeDeal()){if(millis() > 1000){//用于排除刚开机时的误判LedDis();//十字路口显示}}if(value == 0x07){//当传感器都没有触发时默认为上一次的值value = value_his;}switch (value) {case 0x00://全部触发Forwards();break;case 0x01://触发右边两个while(digitalRead(pin[1])){Right();}break;case 0x03://触发右边一个while(digitalRead(pin[1])){Right();}break;case 0x04://触发左边两个while(digitalRead(pin[1])){Left();}break;case 0x05://触发中间一个Forwards();break;case 0x06://触发左边一个while(digitalRead(pin[1])){Left();}break;default:stop();}value_his = value;lc.clearDisplay(0);}void Left(){myservo[0].write(middle1);myservo[1].write(middle2 + 20);}void Right(){myservo[0].write(middle1 - 20);myservo[1].write(middle2);}void Forwards(){myservo[0].write(middle1 - 20);myservo[1].write(middle2 + 20);}void stop(){myservo[0].write(middle1);myservo[1].write(middle2);}bool TimeDeal()//十字路口识别函数{if(millis() > 500){if((abs(time[1] - time[0]) < 100) && (abs(time[1] - time[2]) < 100)){//当中间传感器与另外两个传感器触发的时间小于100毫秒时判定为十字路口return true;}elsereturn false; }}void LedDis()//十字路口显示函数{for(int i=3; i<5; i++){for(int j=0; j<8; j++){lc.setLed(0, i, j, true);}}for(int i=3; i<5; i++){for(int j=0; j<8; j++){lc.setLed(0, j, i, true);}}}void LedInit(){lc.shutdown(0,false); //start the 8*8 ledlc.setIntensity(0,8);lc.clearDisplay(0);}
⑥ 下面提供一个小车实现寻迹的完整程序(TrackingCar.ino):
/*------------------------------------------------------------------------------------版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.Distributed under MIT license.See file LICENSE for detail or copy athttps://opensource.org/licenses/MITby 机器谱 2023-07-14 https://www.robotway.com/------------------------------*/#include <LedControl.h>#include <Servo.h>#define middle1 88#define middle2 88LedControl lc=LedControl(12,11,13,1);Servo myservo[2];int pin[3] = {A0, A4, A3};int time[3];byte value;byte value_his = 0;int flag = 0;int times = 0;void setup(){LedInit();Serial.begin(9600);//串口,用于调试myservo[0].attach(4);myservo[1].attach(3);}void loop(){value = 0;for(int i=0; i<3; i++){value |= (digitalRead(pin[i]) << i);if(!digitalRead(pin[i])){time[i] = millis();}}if(TimeDeal()){times++;Serial.print(times);}else{if(times > 1){Serial.println();flag += 1;Serial.println(flag);}times = 0;}if(flag == 3){while(1){stop();}}if(value == 0x07){value = value_his;}switch (value) {case 0x00://全部触发LedOn(0);LedOn(1);LedOn(2);Forwards();//delay(500);break;case 0x01://触发右边两个LedOn(1);LedOn(2);while(digitalRead(pin[1])){Right();}break;case 0x03://触发右边一个LedOn(2);while(digitalRead(pin[1])){Right();}break;case 0x04://触发左边两个LedOn(0);LedOn(1);while(digitalRead(pin[1])){Left();}break;case 0x05://触发中间一个LedOn(1);Forwards();break;case 0x06://触发左边一个LedOn(0);while(digitalRead(pin[1])){Left();}break;default:stop();}value_his = value;lc.clearDisplay(0);}bool TimeDeal(){if(millis() > 500){if((abs(time[1] - time[0]) < 100) && (abs(time[1] - time[2]) < 100)){return true;}elsereturn false; }}void Left(){myservo[0].write(middle1);myservo[1].write(middle2 + 20);}void Right(){myservo[0].write(middle1 - 20);myservo[1].write(middle2);}void Forwards(){myservo[0].write(middle1 - 20);myservo[1].write(middle2 + 20);}void stop(){myservo[0].write(middle1);myservo[1].write(middle2);}void LedOn(int key){for(int i=0; i<2; i++){for(int j=3*key; j<3*key+2; j++){lc.setLed(0, i, j, true);}}}void LedInit(){lc.shutdown(0,false); //start the 8*8 ledlc.setIntensity(0,8);lc.clearDisplay(0);}
程序源代码资料内容详见 小型双轮差速底盘-寻迹与路口
相关文章:

小型双轮差速底盘寻迹功能的实现
1. 功能说明 寻迹机器人是一种能够跟踪特定物体或线路的机器人。它们通常具有以下功能和特点: ① 传感器:寻迹机器人配备了用于感知环境的传感器,如摄像头、灰度传感器等。这些传感器可以探测地面上的标记、颜色、纹理或其他特定特征…...

第七篇:k8s集群使用helm3安装Prometheus Operator
安装Prometheus Operator 目前网上主要有两种安装方式,分别为:1. 使用kubectl基于manifest进行安装 2. 基于helm3进行安装。第一种方式比较繁琐,需要手动配置yaml文件,特别是需要配置pvc相关内容时,涉及到的yaml文件太…...

Chrome 75不支持保存成mhtml的解决方法
在Chrome 75之前,可以设置chrome://flags -> save as mhtml来保存网页为mhtml。 升级新版,发现无法另存为/保存网页为MHTML了。 在网上搜索无果后,只得从chromium项目的commits中查找,原来chrome搞了个"Chrome Flag Owner…...

工程监测振弦采集仪应用于岩土工程监测案例
振弦采集仪是一种用于测量地面或岩土中振动参数的仪器,可以对地基、土壤和岩体的性质及其变化进行监测。在岩土工程监测中,振弦传感器被广泛应用于测量土体或岩体的振动情况,以了解地震或其他自然灾害的影响。 以下是一个振弦采集仪应用岩土工…...

配置HDFS单机版,打造数据存储的强大解决方案
目录 简介:步骤:安装java下载安装hadoop配置hadoop-env.sh配置 core-site.xml配置hdfs-site.xml初始化hdfs文件系统启动hdfs服务验证hdfs 结论: 简介: Hadoop分布式文件系统(HDFS)是Hadoop生态系统中的一个…...

U盘删除的文件怎么找回?4个简单方法分享!
“在u盘里不小心删除的文件到底还能不能找回来呀?真的好着急啊!这个u盘对我来说真的很重要,怎么恢复里面的数据呢?请各位大佬帮帮我吧!” 作为一个便捷的存储工具,u盘逐渐获得大众的青睐。在互联网时代&…...

【雕爷学编程】MicroPython动手做(27)——物联网之掌控板小程序2
知识点:什么是掌控板? 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片,支持WiFi和蓝牙双模通信,可作为物联网节点,实现物联网应用。同时掌控板上集成了OLED…...

形参动态内存开辟和柔性数组
//柔性数组 //定义:结构体最后一个成员允许是未知大小的数组 // 优点;在开辟空间时,连续开辟,便于释放空间,不会因多次开辟,导致释放空间出错 // 开辟空间时,节省动态开辟次数,节省空间&am…...

【LLM系列之指令微调】长话短说大模型指令微调的“Prompt”
1 指令微调数据集形式“花样”太多 大家有没有分析过 prompt对模型训练或者推理的影响?之前推理的时候,发现不加训练的时候prompt,直接输入模型性能会变差的,这个倒是可以理解。假如不加prompt直接训练,是不是测试的时…...

MacOS使用brew如何下载Nginx
首先,第一步切换源: 切换 brew.git 仓库地址: cd "$(brew --repo)" git remote set-url origin https://mirrors.aliyun.com/homebrew/brew.git 替换 homebrew-core.git 仓库地址: cd "$(brew --repo)/Library/Taps/home…...

linux ftp
使用ftp连接本机进行文件传输 1、下载vsftpd服务器程序 apt install vsftpd 2、使用tcp抓包 tcpdump -nt -i lo port 20 在FTP连接到本地主机(127.0.0.1)时,数据可能通过本地回环接口(loopback interface)传输&…...

你知道HTTP与HTTPS有什么区别吗?
作者:Insist-- 个人主页:insist--个人主页 作者会持续更新网络知识和python基础知识,期待你的关注 目录 一、什么是HTTP? 二、什么是HTTPS? 三、HTTPS 的工作原理 1、客户端发起 HTTPS 请求 2、服务端的配置 3、…...

keil使用printf函数重定串口输出,程序卡在Reset_Handler
最近在做国产芯片GD32F103项目,使用printf()函数重定向USART0串口输出,发现程序没有运行,单步调试发现,程序卡在startup_gd32f10x.s文件的Reset_Handler处,记录一下解决方法。 解决办法: 1、引用头文件#in…...

Redis预热 雪崩 击穿 穿透
redis预热 在Redis中,预热是指在实际的负载之前,提前将数据加载到内存中,以便在请求到来时能够快速响应。预热可以减少冷启动时的延迟,并提高系统的性能。 有几种方法可以进行Redis的预热: 使用持久化机制࿱…...

Shell脚本学习-MySQL单实例和多实例启动脚本
已知MySQL多实例启动命令为: mysqld_safe --defaults-file/data/3306/my.cnf & 停止命令为: mysqladmin -uroot -pchang123 -S /data/3306/mysql.sock shutdown 请完成mysql多实例的启动脚本的编写: 问题分析: 要想写出脚…...

vue3搭建(vite+create-vue)
目录 前提条件 输入命令 对于Add an End-to-End Testing Solution nightwatch和Cypress 和 Playwright 运行 前提条件 熟悉命令行已安装 16.0 或更高版本的 Node.js (node -v查看版本) 输入命令 npm init vuelatest 这一指令将会安装并执行 create-…...

服务器中了360后缀勒索病毒怎么解决,360后缀勒索病毒解密数据恢复
某医药公司是一家小型企业,拥有自己的服务器存储重要数据和文件。某天早上,IT管理员发现企业服务器中了360后缀的勒索病毒,所有数据文件都被加密了。这个病毒的入侵让公司业务受到严重影响,企业立即启动了勒索病毒解密数据恢复的措…...

3000字详解:风控核心岗位及核心价值
01、信贷场景中所谓风控是什么? 从一个小故事说起: “风控是什么?” “你走过大桥么?” “桥上有栏杆么?” “有” “你过桥时会扶栏杆么” “一般不扶” “那栏杆是不是没必要有呢” “那还是得有啊…...

fiddler 手机抓包(含https) 完整流程
第一部分:下载并安装fiddler 一.使用任一浏览器搜索【fiddler下载安装】,并下载fiddler 安装包。 二.fiddler安装包下载成功后,将下载的fiddler压缩包解压到自定义文件夹【fiddler】或者解压到当前文件夹下,双击文件夹中的【fidd…...

ChatGPT学python——制作自己的AI模型(一)初步了解
前言 「作者主页」:雪碧有白泡泡 「个人网站」:雪碧的个人网站 「推荐专栏」: ★java一站式服务 ★ ★前端炫酷代码分享 ★ ★ uniapp-从构建到提升★ ★ 从0到英雄,vue成神之路★ ★ 解决算法,一个专栏就够了★ ★ 架…...

多赛道出海案例,亚马逊云科技为企业提供全新解决方案实现高速增长
数字化浪潮之下,中国企业的全球化步伐明显提速。从“借帆出海”到“生而全球化”,中国企业实现了从低端制造出口,向技术创新和品牌先导的升级。为助力中国企业业务高效出海,亚马逊云科技于2023年6月9日在深圳大中华喜来登酒店举办…...

异步消息传递技术 JMS AMQP MQTT
广泛使用的三种异步消息传递技术:JMS AMQP MQTT JMS AMQP MQTT JMS(Java Message Service):一个类似JDBC的规范,提供了与消息服务相关的API接口 JMS消息模型: P2P 点对点模型:消息发到一个队…...

利用Python实现汉译英的三种方法
一、前言 有道翻译API(主要推荐) 百度翻译API(需要申请key与密钥,每月100万免费字符) 谷歌翻译API(需要梯子,而且不稳定,不推荐) 二、代码 1、判断文本是否存在中文…...

磁盘均衡器:HDFS Disk Balancer
HDFS Disk Balancer 背景产生的问题以及解决方法 hdfs disk balancer简介HDFS Disk Balancer功能数据传播报告 HDFS Disk Balancer开启相关命令 背景 相比较于个人PC,服务器一般可以通过挂载多块磁盘来扩大单机的存储能力在Hadoop HDFS中,DataNode负责最…...

蔚小理新势力互联网造车在CAN FD硬件主框架及后装控制方案开发
在国内,新势力造车影响已经非常之大,整个造车大潮中,新整车企业蔚来汽车、小鹏汽车、理想汽车无一例外选择了CAN FD作为主要的车载通信总线,特斯拉推出了引领汽车EE架构集中化的趋势,即使在车载以太网EE架构快速发展的…...

左叶子之和
404. 左叶子之和 简单(有点意思 第一次我也写错了 先自己递归去写 如果不行看答案 我感觉还是蛮不错的) 示例 1: 输入: root [3,9,20,null,null,15,7] 输出: 24 解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15…...

Java版知识付费平台免费搭建 Spring Cloud+Spring Boot+Mybatis+uniapp+前后端分离实现知识付费平台qt
Java版知识付费源码 Spring CloudSpring BootMybatisuniapp前后端分离实现知识付费平台 提供职业教育、企业培训、知识付费系统搭建服务。系统功能包含:录播课、直播课、题库、营销、公司组织架构、员工入职培训等。 提供私有化部署,免费售…...

LeetCode343. 整数拆分
343. 整数拆分 文章目录 [343. 整数拆分](https://leetcode.cn/problems/integer-break/)一、题目二、题解方法一:动态规划方法改良 一、题目 给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k > 2 ),并使这些整…...

单机,集群和分布式概念
单机的局限性: 1.受限于硬件资源,单机所能承受的用户并发量太少; 2.一个系统有多个模块,任意模块的修改都会导致整个项目代码重新编译、部署; 3.系统中,有些模块是CPU密集型,有些模块是I/O密…...

小目标检测(1)——大恒(DaHeng)相机操作与控制编程
文章目录 引言正文相关开发库的介绍编程准备配置引用头文件GalaxyIncludes.h配置lib文件 具体编程过程初始化和反初始化枚举设备开关设备 属性控制属性控制器种类 图像采集控制和图像处理采单帧回调采集图像处理流对象属性控制 获取设备事件获取掉线事件通知 样例程序分析补充&…...