背景介绍:
RT-Thread 的 nRF24L01 组件当前最近的更新发生在 2020-02-04。
Sugar 本篇从使用者的角度说一下最新组件的用法和测试结果。
使用方法
想了解一个 github 上的开源项目,首先就要去看项目的 ReadMe.md
nRF24L01 的开源地址是https://github.com/sogwms/nrf24l01.git,在开源项目上有提到:
点击 user_guide.md 看到这么一段代码:
如果读者是个玩儿代码的老手,并且对 RT-Thread 比较熟悉,那么看到这里就已经能会用了。当然,为了让新手也能顺利使用,下面 Sugar 还会继续啰嗦啰嗦。
使用方法看 demo。demo 的截图这里就不放了,直接说 Sugar 从 demo 上学到的用法(直接讲代码)。
Sugar 在 RT-Thread 社区上看到这么个问题:
对于引脚配置,Sugar 没有使用 env 直接改了代码(上面图中说了怎么改)。如果不知道引脚编号,在代码里直接用 rtt 的 GET_PIN() 就行了。
上面说了 CE 和 IRQ 的引脚,片选 CS 的引脚在代码里这样写的:
rtconfig.h 开启必要的宏
对于 demo,这样下来发送角色ROLE_PTX的全部配置就完成了。设计者其实已经做到了极简配置(只留了 5 个宏定义,都在上面的图片里)。
发送失败怎么回事
如果读者在跟着做,到这里会得到这样的结果:
上图来自 RT-Thread 社区,如果读者遇到了这个现象,那么恭喜读者,按照 Sugar 的实测,这样离成功就不远了。下面先来解释一下为什么发送失败,其实这个答案开源作者已经说了,但需要再深一步解释才能让初学者也看懂,如下:
加入自己的通信数据
关于 RT-Thread 使用 nRF24L01 组件加入自定义通信数据,Sugar 曾经写过两篇推文:
1、
2、
新的 nRF24L01 组件包(v2.0.0)与上一版(v1.0.0)不同的是:作者把收和发分别放在了两个不同的回调函数里。这与 Sugar 用过的 CubeMX 裸机版驱动的设计一致,关于 CubeMX 裸机驱动 Sugar 写过一篇推文:
nRF24L01 的新组件下把接收放在rx_ind()下,把发送放在tx_done()下就行了,以 ROLE_PTX 为例,Sugar 给出下面完整代码:
static uint32_t last_timestamp;static uint32_t timestamp; extern UART_HandleTypeDef huart1; ap_t mav_data;vel_target vel={.vel_x = 0.0f, .vel_y = 0.0f, .rad_z = 0.0f};uint8_t mode_mav; static void rx_ind(nrf24_t nrf24, uint8_t *data, uint8_t len, int pipe){ /*! Don't need to care the pipe if the role is ROLE_PTX */ if (len > 0) { // sent successfully and received data uint8_t i; mavlink_message_t msg_receive; mavlink_status_t mav_status; for(i=0; i<32; i++) { if(mavlink_parse_char(0, data[i], &msg_receive, &mav_status)) { last_timestamp = timestamp; switch (msg_receive.msgid) { case MAVLINK_MSG_ID_VELOCITY: { mavlink_velocity_t packet; mavlink_msg_velocity_decode(&msg_receive, &packet); vel.vel_x = packet.vel_x; vel.vel_y = packet.vel_y; vel.rad_z = packet.rad_z; break; } case MAVLINK_MSG_ID_CMD: { uint8_t myTxData[32]; uint8_t len = mavlink_msg_to_send_buffer( myTxData, &msg_receive ); HAL_UART_Transmit(&huart1,myTxData,len,10); break; } case MAVLINK_MSG_ID_MODE: { mavlink_mode_t packet; mavlink_msg_mode_decode(&msg_receive, &packet); uint8_t mode_msg[2]; mode_msg[0] = packet.mode; mode_msg[1] = packet.reason; rt_err_t uwRet = RT_EOK; uwRet = rt_mq_send(mode_mq, mode_msg, sizeof(mode_msg)); if(RT_EOK != uwRet) { rt_kprintf("data can not send to message queue, code: %lx\n", uwRet); } rt_sem_release(mode_sem); break; } } } } }} static void tx_done(nrf24_t nrf24, int pipe){ mavlink_message_t msg; char tbuf[32]; mav_data.mode = mode_mav; timestamp = HAL_GetTick(); if(abs(timestamp - last_timestamp) > 1000){ memset(&vel, 0, sizeof(vel_target)); mav_data.com = 1; } else { mav_data.com = 0; } mavlink_msg_simple_pack(0,0,&msg,mav_data.value); mavlink_msg_to_send_buffer((uint8_t *)tbuf, &msg); nrf24_send_data(nrf24, (uint8_t *)tbuf, sizeof(tbuf), pipe); rt_thread_mdelay(NRF24_DEMO_SEND_INTERVAL);} const static struct nrf24_callback _cb = { .rx_ind = rx_ind, .tx_done = tx_done,}; static void thread_entry(void *param){ nrf24_t nrf24; rt_kprintf("[nrf24/demo] Version:%s\n", PKG_NRF24L01_VERSION); nrf24 = nrf24_default_create(NRF24_DEMO_SPI_DEV_NAME, NRF24_DEMO_CE_PIN, NRF24_DEMO_IRQ_PIN, &_cb, NRF24_DEMO_ROLE); if (nrf24 == RT_NULL) { rt_kprintf("\n[nrf24/demo] Failed to create nrf24. stop!\n"); for(;;) rt_thread_mdelay(10000); } else { rt_kprintf("[nrf24/demo] running."); } nrf24_send_data(nrf24, "Hi\n", 3, NRF24_DEFAULT_PIPE); while (1) { nrf24_run(nrf24); if(!nrf24->flags.using_irq) rt_thread_mdelay(10); } } static int nrf24l01_sample_init(void){ rt_thread_t thread; thread = rt_thread_create("nrf_mav", thread_entry, RT_NULL, 1024, RT_THREAD_PRIORITY_MAX/2, 20); rt_thread_startup(thread); return RT_EOK;} INIT_APP_EXPORT(nrf24l01_sample_init);
与之相应的 PRX 的代码请看 Sugar 开源遥控器项目:
https://github.com/SuWeipeng/xm_rc
啊,爆露了!上图显示 Sugar 恢复了上一版代码,为什么会这样呢?
测试过程
Sugar 最近不论是车控还是遥控项目,都在做一件事:一个项目开始支持多种硬件平台。做这件事的时候用新版的 nRF24L01 组件代码,发现两个问题:
1、正点的遥控发了 ACK,但车控无论如何都收不到回复内容;
2、车控同型号的板子,同型号的直插式 nRF24L01 模块,有些组合无法工作。能工作的组合也要看运气,并不是每次上电都正常工作。
上面这些问题让 Sugar 决定用回上个版本。上个版本 Sugar 测过 F103C8、F407VE、L475VE与几种直插式 nRF24L01 组合都没有问题。
在公司里工作的技术人员会有一种体会:当出现问题的时候做软件的和做硬件的都有理由说自己这里没问题,然而产品工作就是不正常。解决这类问题第一靠“人品”,第二靠“耐心”。
第一靠“人品”:以前 Sugar 工作中遇到这类问题会把硬件、软件的人组织到一起找问题,一堆人在一起面对问题的时候人品立现。有些人会第一时间静下心来看已有的测试记录,有些人不看测试记录上来就先把锅甩出去。当团队里第一种人多的时候问题解决效率是明显高的,所以说第一靠“人品”。
第二靠“耐心”:能坐到一起解决技术问题是缘份,不论技术水平高低既然能坐上来就一定有自己的闪光点。找问题就是汇聚所有的闪光点,从各个角度照亮每一个细节的过程,这是需要极大耐心的。找问题最常用的办法是“交叉测试”。
新组件的交叉测试:
1、Sugar 先用上一版稳定代码确认出了 3 块车控(两个 F407VE、一个 F103C8) 4 个 nRF24L01 硬件完好可用;
2、好的硬件换上新版的代码,用 F103C8 车控和小马哥手柄测试 100% 好用;
3、换用 F407 车控和小马哥手柄,有时好用、有时不好用;
4、不论哪种车控,用正点原子的手柄都不行。
当车控与直插式 nRF24L01 出问题的时候,DEBUG 最常卡在下面这句:
当用正点原子手柄的时候,在手柄端 DEBUG 发现数据确实通过nrf24_send_data()接口发送了,但车控就是收不到。
因为 F407 车控与小马哥手柄有时好用, F103 车控和小马哥手柄 100% 好用,所以 Sugar 本文说的使用方法就是对的。已经通过上一版组件确认所有硬件是好的,所以定位在:新版 nRF24L01 组件还有改善空间。
本文源自微信公众号:MultiMCU EDU,不代表用户或本站观点,如有侵权,请联系nick.zong@aspencore.com 删除!