电控组队内教学第一讲——遥控器解码

队内主打的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体验一下,相信会对遥控器数据解码操作有更清晰的认识。

posted @ 2021-11-24 18:58  北京理工大学机器人队  阅读(759)  评论(0编辑  收藏  举报