马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
Robomaster中遥控机器人的手段是固定的,只能利用大疆提供的DR16&DT7套件举行操控数据的发送和接受。这个套件的手册可以在Robomaster的官网上下载到,里面有详细的阐明,以及官方给的解码demo。RoboMaster 遥控器套装
DT7遥控器:
遥控数据可以通过DT7遥控器直接发送,也可以将遥控器通过数据线毗连到电脑上,然后打开Robomaster客户端操作界面,遥控器会将客户端内的键鼠操作发送给吸收器。详细流程如下:
利用DT7&DR16套件前须要包管吸收机和遥控器之间已经乐成配对。
DR16上的LED指示灯一样平常有三种状态:红灯常亮,绿灯闪烁,绿灯常亮,对应的状态如下:
配对方法为打开须要配对的遥控器和吸收机,长按对频按键10s左右,然后松开。
套件参数如下,通信距离足足可以到达1km,实际利用中也确实很稳,DJI还是牛逼的。但是须要注意的是DT7遥控器很不耐摔,天线也轻易断,牢记要掩护好。
DBUS协议
吸收机与吸收机之间接纳DBUS协议举行通信,这个DBUS协媾和常用的SBUS协议应该是一样的东西,不知道为什么要改个名。
信号电平为TTL电平,但是和UART是反相的,须要过一个反相器再输入到单片机的串口上举行吸收。这个反相器可以本身搭,一个三极管加两个电阻就可以了。
吸收时对照着参数表举行串口的参数设置。
当然也可以直接毗连Robomaster的开发板上专门留给DR16吸收机的接口,一样平常是串口1,直接将吸收机上引出的线对应毗连即可,接口内置了反相器。DBUS与UART之间电平标准为反相关系,以是不能随意毗连到其他串口。
数据帧解析
下面开始是重头戏
遥控器发送给吸收机的数据帧。在实际利用时,我们须要将吸收到的数据流举行解码,将吸收到的数据流“翻译”成对应的遥控器/键盘/鼠标的数值。DBUS数据以18个字节为一帧.
可以将吸收机通过反相器,接给USB转TTL模块,然后接到PC上,开串口助手调成16进制显示看一下。
一个典范的数据帧长下面如许
00 04 20 00 01 78 00 00 00 00 00 00 00 00 00 00 00 00
将其对应到官方给的手册上,很轻易就可以理解数据帧的含义。
以通道0的数值为例,将上面的数据帧的前两个字节(00 04)写成二进制的情势,得到
0000 0000 0000 0100
按照规则,将第二个字节的后3位作为高八位,第一个字节团体作为低8位拼接起来,即可得到
100 0000 0000
这个二进制数转化成十进制后,得到的值恰好就是2的10次方,即1024。
通过同样的方式可以分离-拼接出全部的数据值,实际上我们的遥控器解码函数所作的也正是这个工作。
DMA吸收&&解码示例
这里以官方开源代码为例来解说遥控器吸收+解码的过程。
https://github.com/RoboMaster/RoboRTS-Firmware
在dbus.c下面,我们可以看到官方的解码函数,其完成的工作包罗——数据的分离和拼接;为了防止遥控器数据的零漂,设置了一个正负5的死区;数据溢出的处理
- static void get_dr16_data(rc_device_t rc_dev, uint8_t *buff)
- {
- memcpy(&(rc_dev->last_rc_info), &rc_dev->rc_info, sizeof(struct rc_info));
- rc_info_t rc = &rc_dev->rc_info;
-
- //satori:这里完成的是数据的分离和拼接,减去1024是为了让数据的中间值变为0
- rc->ch1 = (buff[0] | buff[1] << 8) & 0x07FF;
- rc->ch1 -= 1024;
- rc->ch2 = (buff[1] >> 3 | buff[2] << 5) & 0x07FF;
- rc->ch2 -= 1024;
- rc->ch3 = (buff[2] >> 6 | buff[3] << 2 | buff[4] << 10) & 0x07FF;
- rc->ch3 -= 1024;
- rc->ch4 = (buff[4] >> 1 | buff[5] << 7) & 0x07FF;
- rc->ch4 -= 1024;
-
- //satori:防止数据零漂,设置正负5的死区
- /* prevent remote control zero deviation */
- if(rc->ch1 <= 5 && rc->ch1 >= -5)
- rc->ch1 = 0;
- if(rc->ch2 <= 5 && rc->ch2 >= -5)
- rc->ch2 = 0;
- if(rc->ch3 <= 5 && rc->ch3 >= -5)
- rc->ch3 = 0;
- if(rc->ch4 <= 5 && rc->ch4 >= -5)
- rc->ch4 = 0;
-
- rc->sw1 = ((buff[5] >> 4) & 0x000C) >> 2;
- rc->sw2 = (buff[5] >> 4) & 0x0003;
-
- //satori:防止数据溢出
- if ((abs(rc->ch1) > 660) || \
- (abs(rc->ch2) > 660) || \
- (abs(rc->ch3) > 660) || \
- (abs(rc->ch4) > 660))
- {
- memset(rc, 0, sizeof(struct rc_info));
- return ;
- }
- rc->mouse.x = buff[6] | (buff[7] << 8); // x axis
- rc->mouse.y = buff[8] | (buff[9] << 8);
- rc->mouse.z = buff[10] | (buff[11] << 8);
- rc->mouse.l = buff[12];
- rc->mouse.r = buff[13];
- rc->kb.key_code = buff[14] | buff[15] << 8; // key borad code
- rc->wheel = (buff[16] | buff[17] << 8) - 1024;
- }
复制代码 找到对应的数据结构rc_info,其内容和手册上的内容完全逐一对应,可以看到官方代码为了方便后续代码的编写,在键盘的数据处利用了团结体。
- struct rc_info
- {
- /* rocker channel information */
- int16_t ch1;
- int16_t ch2;
- int16_t ch3;
- int16_t ch4;
- /* left and right lever information */
- uint8_t sw1;
- uint8_t sw2;
- /* mouse movement and button information */
- struct
- {
- int16_t x;
- int16_t y;
- int16_t z;
- uint8_t l;
- uint8_t r;
- } mouse;
- /* keyboard key information */
- union {
- uint16_t key_code;
- struct
- {
- uint16_t W : 1;
- uint16_t S : 1;
- uint16_t A : 1;
- uint16_t D : 1;
- uint16_t SHIFT : 1;
- uint16_t CTRL : 1;
- uint16_t Q : 1;
- uint16_t E : 1;
- uint16_t R : 1;
- uint16_t F : 1;
- uint16_t G : 1;
- uint16_t Z : 1;
- uint16_t X : 1;
- uint16_t C : 1;
- uint16_t V : 1;
- uint16_t B : 1;
- } bit;
- } kb;
- int16_t wheel;
- };
复制代码 关于遥控器数据的吸收,我们可以直接去寻找解码函数在何处被调用,按照
get_dr16_data -> rc_device_date_update -> dr16_rx_data_by_uart -> dr16_rx_callback -> dr16_uart_rx_data_handle -> USART1_IRQHandler
可以发现其是在串口1的吸收停止中被调用的,DMA初始化函数如下
- void dr16_uart_init(void)
- {
- UART_Receive_DMA_No_IT(&huart1, dr16_uart_rx_buff, DR16_RX_BUFFER_SIZE);
-
- __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
- }
复制代码 吸收处理函数如下
抛除一些HAL库为了驱动DMA举行的一些寄存器操作,实在我们可以看到整个DMA吸收逻辑实际上还是很简单的,即通过dr16_uart_rx_buff这个数组存储DMA获取的数据,每次完成吸收之后对吸收数据的长度举行判断,如果确认了是18个字节则判定为正当数据,传入dr16_rx_callback举行下一步的处理。
固然官方的代码为了各种目标举行了很多层的封装,但是实际上在dma吸收处理函数中举行数据正当性的判断之后,已经可以直接将数据送入解码函数了。
- uint32_t dr16_uart_rx_data_handle(UART_HandleTypeDef *huart)
- {
- if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
- {
- /* clear idle it flag avoid idle interrupt all the time */
- __HAL_UART_CLEAR_IDLEFLAG(huart);
- /* clear DMA transfer complete flag */
- __HAL_DMA_DISABLE(huart->hdmarx);
- /* handle dbus data dbus_buf from DMA */
- if ((DR16_RX_BUFFER_SIZE - huart->hdmarx->Instance->NDTR) == DR16_DATA_LEN)
- {
- if (dr16_rx_callback != NULL)
- {
- dr16_rx_callback(dr16_uart_rx_buff, DR16_DATA_LEN);
- }
- if (dr16_forword_callback != NULL)
- {
- dr16_forword_callback(dr16_uart_rx_buff, DR16_DATA_LEN);
- }
- }
- /* restart dma transmission */
- __HAL_DMA_SET_COUNTER(huart->hdmarx, DR16_RX_BUFFER_SIZE);
- __HAL_DMA_ENABLE(huart->hdmarx);
- }
- return 0;
- }
复制代码
结语
那么本讲就到此为之了,实际上DR16&DT7遥控器套件吸收是一个很轻易的工作,须要注意的是由于机器人对于任务执行的实时性需求,一样平常不会接纳耗时长,占用资源多的串口停止的方式举行吸收,而是利用DMA方式举行吸收。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |