背景介紹:
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、《為了解決 RT-Thread nRF24L01 軟體包在 STM32F103C8 上死活調不通的問題,我都幹了啥?》
2、《RT-Thread mavlink 甜蜜相擁教程》
新的 nRF24L01 組件包(v2.0.0)與上一版(v1.0.0)不同的是:作者把收和發分別放在了兩個不同的回調函數裡。這與 Sugar 用過的 CubeMX 裸機版驅動的設計一致,關於 CubeMX 裸機驅動 Sugar 寫過一篇推文:
《一起來做遙控車(讓車聽遙控的話)》
nRF24L01 的新組件下把接收放在 rx_ind() 下,把發送放在 tx_done() 下就行了,以 ROLE_PTX 為例,Sugar 給出下面完整代碼:
#include <nrf24l01.h>#include <rtconfig.h>#include <entry.h>#include <rtt_interface.h>#include <mavlink.h>#include <stm32f4xx_hal.h>
#define NRF24_DEMO_ROLE ROLE_PTX#define NRF24_DEMO_SEND_INTERVAL 10#define NRF24_DEMO_SPI_DEV_NAME "spi10"#define NRF24_DEMO_CE_PIN GET_PIN(B, 6)#define NRF24_DEMO_IRQ_PIN GET_PIN(B, 8)
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){ if (len > 0) { 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。
提示:在公眾號「關於我」頁面可加作者微信好友。喜歡本文求點讚,有打賞我會更有動力。