小型双轮差速底盘三灰度循迹功能的实现

news2024/11/25 23:18:37

1. 功能说明

       在小型双轮差速底盘样机前方安装3个 灰度传感器 ,实现机器人沿下图所指定的跑道路线进行运动的效果。

 2. 使用样机

本实验使用的样机为R023样机。

3. 功能实现

3.1 电子硬件

     在这个示例中,我们采用了以下硬件,请大家参考:

主控板Basra(兼容Arduino Uno)
扩展板

Bigfish2.1扩展板

传感器灰度传感器
电池7.4V锂电池

电路连接说明:

① 左轮直流电机连在D9,D10接口上;

② 右轮直流电机连在D5,D6接口上;

③ 3个灰度传感器从左至右连接在A0,A4,A3端口上。

 3.2 编程框架

      本实验的编程框架用到了有限状态机。有限状态机(Finite-state machine)简称FSM,表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。它把复杂的控制逻辑分解成有限个稳定状态,在每个状态上判断事件。由于有限状态机有有限个状态,因此可以在实际中实现。有限状态机可以广泛的应用于机器人多个传感器触发组合状态的判断,大大提高检测效率。

状态表

      机器人的传感器触发一般用条件判断来做。

      这时机器人程序的一般思路是:

如果

机器人的某几个传感器触发了;

机器人的某几个电机做个什么事;

做多久;

如果

机器人的另外某几个传感器触发了;

机器人的某几个电机做个什么事;

做多久;

所以我们总是要用到大量的 if 语句,比如双轮小车的某个功能:

如果

机器人的1号传感器触发了;

机器人的左侧电机顺时针转;

机器人的右侧电机逆时针转;

持续5秒;

如果

机器人的2号传感器触发了;

机器人的左侧电机逆时针转;

机器人的右侧电机顺时针转;

持续5秒;

否则

都不转

用伪码写出来就是:

if {   Sensor(端口a,触发);//传感器触发时此句为真,否则为假 }

{

    Motor(L,顺);

    Motor(R,逆);

    Delay 5;

}

if {   Sensor(端口b,触发); }

{

    Motor(L,逆);

    Motor(R,顺);

    Delay 5;

}

else

{

    Motor(L,停);

    Motor(R,停);

}

在只有一个传感器的情况下,我们假设这是个开关量传感器。那么我们可以得到一个状态表格:

状态序号传感器1
11
20

这个传感器有两个状态。

而当有两个传感器时,则有四个状态。

状态序号传感器1传感器2
111
210
301
400

如果我们用 if 语句写这四个状态,就显得比较长。

状态序号传感器1传感器2伪码

1

1

1

if

{
    Sensor(1,1);
    Sensor(2,1);
    ……
}

2

1

0

if

{
    Sensor(1,1);
    Sensor(2,0);
    ……
}

3

0

1

if

{
    Sensor(1,0);
    Sensor(2,1);
    ……
}

4

0

0

else

  ……

      在编程的时候,状态罗列的越全,机器人的bug就越少。但是随着传感器的增多,状态数量按2的N次幂增加,大量的if语句使执行效率变得很低,经常出现识别不灵的情况。我们需要换一种高效写法。

      多个确定数量的传感器的触发组合,符合有限状态机的概念,有限状态机一般是用Switch语句来实现。如:

switch(s)

{

case 1 : {动作1;}break;

case 2 : {动作2;}break;

case 3 : {动作3;}break;

case 4 : Act_Stop();break;

default:;break;

}

      不难发现,这段语句实现的关键,就是识别出上页表中的1、2、3、4,四个状态序号。

      那么问题就来了:我们如何让机器人知道自己传感器的触发组合对应于1、2、3、4的哪个序号呢?

二进制状态表

      下面,我们把每组传感器返回值看成一个二进制数值。

 结果我们发现了一种新的、可计算的编码方式:

新序号

传感器1

传感器2
000
101
210
311

      于是,只要我们知道了传感器们的触发状态,也就知道了序号;知道了序号,也就知道了传感器们的触发状态。用这个序号去写switch语句,再合适不过了。下面我们要做的是,用一种算法,让机器人能够返回自己接收到的传感器组合值的二进制数据。

算法精解

我们可以使用以下算法来实现:

  • 首先设置一个变量s,这个s,将存储传感器组的二进制状态序号。
    • 我们还需要用到一个重要的运算符“<<”,这个运算符的意义是:左移

如:1<<n,意思是1向左移动n位,空出来的数位用0填补。

如:1<<1,结果就是10;1<<2,结果就是100;101<<1,结果就是1010

  • 只要让机器人依次返回各个传感器的状态数值,最早获取的,移到最左;第二获得的,移到“倒数第二左”,……,以此类推。即可获得。

 如两个传感器均触发:

先获得1号的数值(真)并左移0位,得

01

再获得2号的数值(真)并左移1位,得

10

两数值取“或”,即可得11

数学问题解决了,很容易就可以转化为程序语句:

s=0;

for(i=0;i<2;i++) //因为此例中有2个传感器,i取2

{

s=s|(Servo(i+1,触发判断)<<i);//获得传感器值,移位,或运算

}

于是switch语句可以写为:

switch(s)

{

case 0x00 : {动作0;}break; //序号也可以写作16进制数值

case 0x01 : {动作1;}break;

case 0x02 : {动作2;}break;

case 0x03 : {动作3;}break;

default:;break;

}

策略表

下面我们以本实验中的“小型双轮差速底盘-3灰度循迹”程序为例,再来推导一遍。

传感器触发情况、小车行驶状态、对应行为策略表如下:

传感器1传感器2传感器3序号小车状态动作
0000都没触发,可能是跑偏了后退,转向
0011小车左偏左轮逆时针转,向右调整
0102小车正中左轮逆时针转,右轮顺时针转,前进
0113在这个行进方向上不可能
1004小车右偏右轮顺时针转,向左调整
1015在此跑道上不可能
1106遇到转角

右轮顺时针转,左转

1117

在此跑道上不可能

伪码如下:

s=0;

for(i=0;i<3;i++)

{

s=s|(Input(i+1,1)<<i);

}

switch(s)

{

case 0x00 : 停;break;

case 0x01 : {Motor(L,逆);Motor(R,停);}break;

case 0x02 : {Motor(L,逆);Motor(R,顺);}break;

case 0x04 : {Motor(L,停);Motor(R,顺);}break;

case 0x06 : {Motor(L,停);Motor(R,顺);}break;

default:;break;

}

       这段代码中的动作,完全由策略表分析获得,因此,当状态比较多时,用户要学会利用策略表进行分析,从而确定机器人的动作策略,而不是凭空想象。

3.3 编写程序

编程环境:Arduino 1.8.19

编写并烧录以下程序(Track_Car.ino),该程序将实现演示视频中的动作。

/*------------------------------------------------------------------------------------

  版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.

           Distributed under MIT license.See file LICENSE for detail or copy at

           https://opensource.org/licenses/MIT

           by 机器谱 2023-02-09 https://www.robotway.com/                                   

------------------------------------------------------------------------------------*/

int pin[3] = {A0, A3, A4};           //按车头前进方向,从右至左定义,后面经过公式计算,会转化为从左至右的顺序

int s;

void setup()

{

  pinMode( 5 , OUTPUT);

  pinMode( 6 , OUTPUT);

  pinMode( 9 , OUTPUT);

  pinMode( 10 , OUTPUT);

}



void loop()

{

   s = 0;

        for(int i=0; i<3; i++)                 //循环获取三个传感器的值

        {

            s|= (!digitalRead(pin[i]) << i);   //经过左移运算和或运算后,按照A0、A3、A4的顺序产生一个三位2进制数值,表示3个传感器的组合触发状态

        }

        switch (s)

        {

          case 0x00: //三个均未触发

          back();

          Left();

          break;

          case 0x01: //右侧传感器触发,直线上摆动或遇到右转弯

          Right();

          break;

          case 0x02: //中间传感器触发,直线上直行

          Forwards();

          break;

          case 0x04: //左侧传感器触发,直线上摆动或遇到左转弯

          Left();

          break;

          case 0x06: //左侧两个触发,遇到左转弯

          Left();

          break;

          default:;break;

        }

  }

void Left()

{

digitalWrite( 5 , LOW );

digitalWrite( 6 , HIGH);

digitalWrite( 9 , HIGH );

digitalWrite( 10 , LOW );

}



void Right()

{

digitalWrite( 5 , HIGH );

digitalWrite( 6 , LOW );

digitalWrite( 9 , LOW );

digitalWrite( 10 , HIGH );

}



void Forwards()

{

digitalWrite( 5 , HIGH );

digitalWrite( 6 , LOW );

digitalWrite( 9 , HIGH );

digitalWrite( 10 , LOW );

}



void back()

{

digitalWrite( 5 , LOW );

digitalWrite( 6 , HIGH );

digitalWrite( 9 , LOW );

digitalWrite( 10 , HIGH );

}

4. 资料内容

3灰度循迹-例程源代码


​资料内容下载详见小型双轮差速底盘

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/401223.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

likeshop社区团购v1.5.1更新

likeshop社区团购系统适用于初创业或者个人创业者&#xff0c;希望以低成本、高效益的方式开展本地电商业务&#xff0c;或者已经拥有线下实体店或实体店经验的商家&#xff0c;希望将线上业务扩展到社区团购平台&#xff0c;提升线上业务的营收。 likeshop社区团购V1.5.1版本…

第十五章 opengl之高级OpenGL(模板测试)

OpenGL模板测试模板函数物体轮廓模板测试 当片段着色器处理完一个片段后&#xff0c;模板测试就会开始执行。类似于深度测试&#xff0c;模板测试也可能会丢弃片段。被保留的片段会进入深度测试&#xff0c;可能会丢弃更多的片段。 模板测试是根据模板缓冲来进行的。一个模板缓…

什么是ChatGPT?

目录前言一、什么是GPT&#xff1f;二、什么是ChatGPT&#xff1f;三、ChatGPT应用场景四、ChatGPT未来展望五、OpenAI介绍前言 3月3号&#xff0c;早上6:30就有人发消息给我&#xff0c;来问我有关GPT API的事件。 那是因为3月2号&#xff0c;OpenAI 发布了ChatGPT 3.5的开放…

提高办公效率的免费网站有哪些

收藏一些免费好用的网站&#xff0c;在我们工作中需要用到的时候可以直接使用&#xff0c;提高我们的工作效率。小编就和大家分享10个可以提高我们办公效率的免费网站。 1.羽兔网软件下载-以设计类软件为主的免费软件下载网站 很多小白都不知道怎么下载软件&#xff0c;往往搜…

【Python】AES加解密代码,文章还有加密串等你来解密,等你来挑战

&#x1f366;&#x1f366;写这篇AES文章也是有件趣事&#xff0c;有位小伙伴发了段密文&#xff0c;看看谁解密速度快&#xff0c;学过Python的小伙伴一下子就解开来了&#xff0c;内容也挺有趣的。 &#x1f35f;&#x1f35f;原来加解密也可以这么有趣&#xff0c;虽然看起…

【专项训练】字典树和并查集

字典树和并查集 二叉搜索树查询效率更高 前缀推后面,这种情况怎么办,选什么数据结构呢 每个节点不存单词本身!他只存到下一个路径上面,这个路径代表的字符! Trie树是多叉树! 任何一个节点,他代表的单词是走过的这条边 统计频次 208. 实现 Trie (前缀树)

ViewBinding 和 DataBinding的使用

1.ViewBinding:视图绑定 通过视图绑定功能&#xff0c;您可以更轻松地编写可与视图交互的代码。在模块中启用视图绑定之后&#xff0c;系统会为该模块中的每个 XML 布局文件生成一个绑定类。绑定类的实例包含对在相应布局中具有 ID 的所有视图的直接引用。在大多数情况下&…

容器方式搭建免费的表白网站--阿狸心图--背景音乐《英文歌》(2023.310更新)

效果图 源码 源文件:https://download.csdn.net/download/zhanremo3062/87554456 目录结构 ├── ali2 │ ├── css │ │ └── all.min.css │ ├── fonts │ │ └── RuiHeiXiTi.otf │ ├── img │ │ ├── 14915.jpg . . . │ ├── index.html │ ├──…

【JVM】字节码指令

文章目录1. 方法的执行流程1.1 常量池载入运行时常量池1.2 方法字节码载入方法区1.3 main线程开始运行&#xff0c;分配栈帧内存1.4 执行引擎开始执行字节码2. 条件判断2.1 源码分析3. 循环控制指令3.1 源码分析1. 方法的执行流程 原始Java代码 public class Demo3_1 {public…

vue el-switch 列表开关状态显示有误 全部关闭的问题

后台使用int类型传状态status的值 但是前端列表展示的开关状态是未开启&#xff0c;实际上&#xff0c;后台传的都是开启的状态 结果应该是这样 确定后台传的status值 在 el-switch 标签中是否使用了正确的值判断&#xff0c;比如 后台用的是字符串、布尔 或者是 数值类型&…

2-7 SpringCloud快速开发入门: Eureka 注册中心高可用集群搭建

接上一章节Eureka 服务注册中心发现与消费服务&#xff0c;这里讲讲Eureka 注册中心高可用集群搭建 Eureka 注册中心高可用集群搭建 Eureka 注册中心高可用集群就是各个注册中心相互注册 Eureka Server的高可用实际上就是将自己作为服务向其他服务注册中心注册自己&#xff0c…

LeetCode——203. 移除链表元素

对于初学链表的学者来学&#xff0c;链表是比较困难的&#xff0c;这部分对指针结构体的要求比较高。我们通过练习是掌握知识的重要途经203. 移除链表元素 - 力扣&#xff08;LeetCode&#xff09;我们在数组中去除某元素是遍历一遍数组&#xff0c;如果某位置是要去除的元素&a…

[Linux]应用部署部分流程命令备忘

备忘一下常用的Linxu应用部署命令&#xff0c;Java应用版。 目录1、环境查询1.1、端口占用查询1.2、环境变量查询与设置设置局部用户定义变量设置全局环境变量删除环境变量2、执行命令保存日志并查看3、查看java应用内存使用情况1、环境查询 1.1、端口占用查询 lsof -i 命令 …

leetcode-每日一题-2379(简单,字符串)

久违的简单题......给你一个长度为 n 下标从 0 开始的字符串 blocks &#xff0c;blocks[i] 要么是 W 要么是 B &#xff0c;表示第 i 块的颜色。字符 W 和 B 分别表示白色和黑色。给你一个整数 k &#xff0c;表示想要 连续 黑色块的数目。每一次操作中&#xff0c;你可以选择…

NGINX学习笔记(三):一篇搞懂NGINX的常用配置之LOCATION指令

写在前面 NGINX主配置文件 /etc/nginx/nginx.conf 是一个纯文本类型的文件&#xff0c;整个配置文件是以区块的形式组织&#xff0c;通常每一个区块以一对大括号{}来表示开始与结束。 提示&#xff1a;若编译安装则nginx.conf 位于编译时所指定目录。 我是手动编译安装的&…

【LeetCode】剑指 Offer(20)

目录 题目&#xff1a;剑指 Offer 38. 字符串的排列 - 力扣&#xff08;Leetcode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 写在最后&#xff1a; 题目&#xff1a;剑指 Offer 38. 字符串的…

一文读懂无线信道传播的各种特性

通过无线信道传播的信号沿着大量不同的路径到达目的地&#xff0c;这些不同路径称为多径。图 1 是一位沿公路驾车的典型移动用户的图形。该图描述了从发射机到接收机的众多信号路径中的三条。这些路径源自环境中物体对辐射能的散射、反射和衍射或者媒介中的折射。各种传播机制对…

mac系统手册(帮助/说明)

文章目录1. mac自带的帮助文档2. Mac使用技巧&#xff08;提示&#xff09;2.1 聚焦搜索2.2 截图&#xff08;录制屏幕&#xff09;2.3 调出右键菜单2.4 快速查看2.5 翻译2.5.1 词典解释2.5.2 翻译&#xff08;字、词和句&#xff09;3. macOS使用手册3.1 在聚焦中进行计算和转…

C51---串口发送字符串

1.Code: #include "reg52.h" #include "intrins.h" sfr AUXR 0x8E; void UartInit(void) //9600bps11.0592MHz { PCON & 0x7F; //波特率不倍速 SCON 0x50; //8位数据,可变波特率 AUXR & 0xBF; //定时器…

100种思维模型之认知资源思维模型-030

我们常说&#xff0c;一个人永远也赚不到自己认知以外的钱&#xff0c;这话的确很有道理&#xff0c;被无数人所推崇。 由此&#xff0c;不难看出&#xff0c;认知在我们的生活起着多么关键的作用。 你的认知层次越高&#xff0c;范围越广&#xff0c;就意味着你这个人所处的阶…