一起来开发一个磁条机器人(五)

一起来开发一个磁条机器人(五) MOmo 2023-04-23 09:44:59 725

描述

这一篇介绍磁条机器人的算法思路,并开源部分代码

算法核心思路

磁条机器人的算法核心思路很简单,我愿意称之为“消息触发型”,意思就是机器人接收消息再通过代码进行判断和操作。

当然了,整体代码还是要分几部分去实现。以下几个小节来概述

消息处理

指令处理
上位机发送过来的命令,需要将命令解析,并对命令进行处理,令机器人做出相应的改变。

磁条信号处理
磁传感器的数据,由算法来判断磁条现在和机器人的位姿状态,改变左右电机的转速

RFID模块信息处理
RFID读到卡片后会产生中断信号,算法根据读到的卡片信息,来做相应的改变

超声信息处理
超声模块不停的将正前方距离数据返回,算法根据数值大小,判断机器人是否遇到障碍物

状态维护

机器人自身信息
需要维护的数据信息有很多,这些信息都需要在运行过程中被维护,包括机器人自身的状态、上一时刻的状态、左右电机的当前转速,设置的最大转速、运行方向、收到的命令、是否有目标点、目标点卡号等等。
不一一列出,这些在代码中或通过全局常量或通过struct进行动态调整,总之将全部的信息维护好很重要,这样即使出现问题我们可以知道机器人究竟发生了什么。

状态切换
机器人在运行过程中,最重要的就是状态。机器人出现问题,我们常问的也是,机器人现在是什么状态啊。因此机器人状态机的切换是尤为关键的。
机器人遇到什么状况转换成什么状态机,除了改变算法中的一些变量,另外一个要做的就是改变状态灯。这让我们能够很好的判断机器人的宏观运行状态。
为此我们另开一个小节,专门来讲一下我算法设置的机器人状态

状态介绍

我的算法中,将机器人状态分为4类,分别是READY,BLOCK,RUNNING,DERAILED,它们分别代表的顾名思义就是准备运行、有障碍、正常运行、脱轨。机器人在运行过程中的全部状态,都可以分为这四类。

(以下涉及到的命令会在之后的篇章中做出解释)

READY
含义:机器人准备好去运行
状态转入:机器人开机后,到达指定目标后,接收到stop命令后,会进入READY状态
状态转出:在这一状态下,机器人收到start和to两种命令后,会转到状态RUNNING
灯:机器人常亮青色灯

BLOCK
含义:机器人被障碍物卡住
状态转入:目前只有超声传感器的数据能令机器人进入BLOCK状态
状态转出:前方障碍物消除后,BLOCK状态会自动恢复到阻塞之前的状态,不用人为干预
灯:机器人常亮黄色灯

RUNNING
含义:机器人正常运行
状态转入:收到start和to的前进命令后,而当前的状态为READY时,才会进入RUNNING;或由BLOCK恢复
状态转出:会因障碍物转为BLOCK,会因脱轨转为DERAILED,会因到达目标转为READY
灯:机器人常亮绿色灯

DERAILED
含义:机器人脱轨
状态转入:目前只有磁条传感器的数据能令机器人进入DERAILED 状态,只要磁传感器返回数据证证明没有检测到磁条,READY、BLOCK和RUNNING状态都可以转为DERAILED状态
状态转出:状态不可自动恢复,只有通过开关机将状态转为READY;或者经人为处理矫正后发送命令“start”命令,可以转为RUNNING
灯:机器人常亮红色灯

添加代码文件

添加.h文件
点击菜单栏中的魔法棒

在弹出的窗口找到“Include Paths”,在文件编辑框最后有一个“…”的按钮,点击

可以进入头文件添加的窗口,我们在这里面可以添加需要用到的头文件

添加.c文件
找到最左侧的项目文件树,可以发现“Application/User/Core”

右键点击后,选择“Add Existing files…”,就可以添加已经写好的.c文件了

代码详解

我们首先增加状态灯的两个文件,分别是ws2812.h和ws2812.c

ws2812.h

#ifndef __WS2812_LED_H__
#define __WS2812_LED_H__

#include "tim.h"

#define ONE_PULSE 54
#define ZERO_PULSE 26

#define LED_NUM 60
#define LED_DATA_LEN 24
#define RESET_PULSE_LEN 80  
#define DATA_BUFFER_LEN RESET_PULSE_LEN+(LED_DATA_LEN*LED_NUM)

uint16_t static data_buffur[DATA_BUFFER_LEN] = { 0 };

void led_init(void);
void led_on(void);
void led_set(uint8_t led_id, uint8_t value_r, uint8_t value_g, uint8_t value_b);

#endif

ws2812.c

#include "ws2812.h"

void led_init(void)
{
    for(uint8_t i = 0; i < LED_NUM; i++)
    {
        led_set(i, 0x00, 0x00, 0x00);
    }
}

void led_set(uint8_t led_id, uint8_t value_r, uint8_t value_g, uint8_t value_b)
{
    uint16_t* p = (data_buffur + RESET_PULSE_LEN) + (LED_DATA_LEN * led_id);
    for (uint16_t i = 0; i < 8; i++)
    {
            p[i]      = (value_g << i) & (0x80)? ONE_PULSE: ZERO_PULSE;
            p[i + 8]  = (value_r << i) & (0x80)? ONE_PULSE: ZERO_PULSE;
            p[i + 16] = (value_b << i) & (0x80)? ONE_PULSE: ZERO_PULSE;
    }
}

void led_on(void)
{
     HAL_TIM_PWM_Start_DMA(&htim4, TIM_CHANNEL_1, (uint32_t *)data_buffur, DATA_BUFFER_LEN);
}

这两个文件的代码,将被主控用来控制状态灯的颜色。

总结

这篇文章暂时介绍到这儿,除了介绍算法的整体思路,还介绍了状态灯的代码文件。
接下来还有一篇文章,我们将全部的代码放到下一篇文章中,这样便于阅读

声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
MOmo
红包 点赞 收藏 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
MOmo
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区