电控组队内教学第一讲——遥控器解码
队内主打的RoboMaster系列比赛用的遥控器都是大疆生产的DT7,相对应的,有遥控器信号接受器DR16与板子连接,接收你操纵遥控器发送的信号,这样就能实现遥控器数据的接收。
而对于遥控器数据的传输我们一般采用DMA传输,简单来说就是跳过CPU,将数据直接由外设通过串口传输到存储器
DMA,全称Direct Memory Access,即直接存储器访问。
DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。
全面了解DMA是非常复杂的,这里不作具体阐述,只解释在程序中DMA的调用,如下所示,在这里DMA的运用其实还是依靠UART串口接收,我们只需调用DMA初始化函数以及调用串口中处理函数再编写Remote_RXCallback函数,作一个遥控接收中断的回调,剩下的配置都会在你CUBE里打开DMA后自动配置好。
void Remote_RXCallback(UART_HandleTypeDef* huart) { /* 清除DMA标识符 */ __HAL_DMA_DISABLE(huart->hdmarx); /* 对DMA传来的数据解码 */ int rxdatalen = Const_Remote_RX_BUFF_LEN - Uart_DMACurrentDataCounter(huart->hdmarx->Instance); Remote_DecodeRemoteData(&Remote_RemoteData, Remote_RxData, rxdatalen); /* 重启DMA传输 */ __HAL_DMA_SET_COUNTER(huart->hdmarx, Const_Remote_RX_BUFF_LEN); __HAL_DMA_ENABLE(huart->hdmarx); }
但是,由接收器DR16传送的数据是有他自己的一套编码规则的,如果想要使数据变得直观以方便我们后续处理(电机的解算),这就需要进行解码,如图所示遥控器能简化为如下操作端:
如图所示,分为0、1、2、3四个摇杆通道和两个拨杆S1、S2,接下来我们以0123四个摇杆通道的数据解码为例,其详细信息如表所示:
意思就是四个摇杆从左到右(或从下到上)的位置分别线性映射到364~1684,中间值为1024(这些都是解码后的数据而不是原始数据),不妨将所有解码后的数据都减去1024,就会得到 -660 ~ +660的数据,会方便很多(简单理解为正值电机正转,负值电机反转,也方便debug时肉眼观察),也就是说如果你将左摇杆拨到正左端,右摇杆拨到正上端,那么解码后的数据就一次应当是0,+660,-660,0;
接下来就是重头戏了,通过查阅DR16数据手册(上图)可知通道数据是11位的二进制,但是在Keil5里DR16的接收函数里存放数据的数组是8位二进制的,这就需要我们对数组buff作剪切拼接成11位二进制,如果想要获取通道0的数据就需要将buff[0]的8bit数据和buff[1]的后三bit数据拼接,如果想要获取通道1的数据就将buff[1]的前5bit和buff[2]的后6bit数据进行拼接,不断通过拼接就可以获得所有的通道数据,这个将8位数据转化为11位数据操作就称为解码,其运用的知识其实就是C语言中的位运算,在此建议先简单复习左移、右移、取或、取反等位运算操作,示意图如下所示:
不难理解在左移右移的剪切操作后将两段数据作或运算可实现拼接,最后和十六进制数0x07ff(二进制的0000 0111 1111 1111)作与运算,就能得到正确的十一位数据,这样依次操作就能得到完整的四个通道的数据。
具体代码如下(为锻炼自己能力不妨先在草稿纸上演算一下,再尝试自行写出解码代码):
void Remote_DecodeRemoteData(Remote_RemoteDataTypeDef* rc, uint8_t* buff, int rxdatalen) { rc->remote.ch[0]=( buff[0] | buff[1]<<8 ) & 0x07ff; //buff为需要解码的原始数据(8位二进制),rc->remote.ch[]为你解码后存放通道数据的数组(16位二进制) rc->remote.ch[1]=( buff[2]<<5 | buff[1]>>3) & 0x07ff; rc->remote.ch[2]=( buff[4]<<10 | buff[3]<<2 | buff[2]>>6) & 0x07ff; rc->remote.ch[3]=( buff[5]<<7 | buff[4]>>1) & 0x07ff; //位运算 for(int i=0;i<=3;i++){ rc->remote.ch[i]-=1024; //将遥控器摇杆数据直观转换为-660~+660 } }
在解码后我们得到的四个 -660~+660的 数据就可以非常简单直观地用于控制电机转动,例如通过查询3508电机数据手册可知其最大转速为480rpm,那么我们只需将-660+660简单做个乘法映射到-480+480,再通过CAN总线将数据输出给电机,即可推动摇杆,控制电机旋转。
本篇博客到此结束,解码知识相对较为简单,建议实操debug体验一下,相信会对遥控器数据解码操作有更清晰的认识。
本文作者:北京理工大学机器人队
本文链接:https://www.cnblogs.com/bit-dreamchaser/articles/15599596.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步