简介
最近想DIY一个四轴飞行器(简易的十字形遥控飞行器) , 也从晚上找了很多的视频和做了相关的简易研究(如果搞出来了会分享,没有经验). 除去电机根据MPU6050的姿态计算PID进行输出不谈. 还有一点比较重要的就是通讯功能. 飞行器接收或者向遥控器发送指令然后执行对应的数据处理或者动作. 因此考虑到多种的数据传输方式. 如下是一个简要的对比.
通信技术通信速率(最大)通信距离(典型)通信频段特点说明
由于之前并没有接触过飞行器相关的. 因此我让GPT对常见的无人机通讯方案进行了一下分析. 下述表格为GPT生成的不同通讯协议对应的无人机应用的方向.
场景通信技术选型
所以最后选用的是NRF24L01, 根据某宝店家介绍,其在空旷场地下通讯的距离可以达到1000米左右(已经是一个非常大的距离了, 再远人眼可能就不可视了)
上图为经典的NRF24L01
当然国内也有很多其他系列的2.4G模块, 比如说安信可的NF-02-PA或者NF-02-PE (使用的SI24R1芯片)
但是考虑到本次使用的是ESP32, 结合对应的库文件的丰富程度. 因此我准备了两个不同的NRF24L01 和 ESP32来进行这次通讯实验.
驱动步骤
主要介绍如何在IDF框架下结合组件管理器来快速实现通过组件nopnop2002/mirf 来快速驱动2.4G模块.
1- 首先新建一个IDF的项目, 基于HelloWorld的项目
2- 新建idf_component.yml,然后输入下面的内容
dependencies: protocol_examples_common: path: ${IDF_PATH}/examples/common_components/protocol_examples_common nopnop2002/mirf: path: components/mirf/ git: https://github.com/nopnop2002/esp-idf-mirf.git
3- 编译一次当前的项目, 然后组件管理器会自动下载组件.
4- 访问https://github.com/nopnop2002/esp-idf-mirf.git 来查找对应的example
可以使用Clone到本地, 或者是直接拷贝文件内容.
5- 使用Menuconfig 配置2.4G模块PIN的连接情况.
6- 配置项目目录的KConfig, 在menuconfig中进行搜索Application Configuration
menu "Application Configuration" endmenu DIRECTION prompt "Communication polarity" default SENDER help Select Communication polarity. config SENDER bool "As the sender" help As the sender. config RECEIVER bool "As the receiver" help As the receiver. endchoice endmenu
将两个ESP32分别以Sender 和 receiver 的方式进行烧录.
这样的话, sender task便会根据地址FGHIJ进行数据发送,
void sender(void *pvParameters) { ESP_LOGI(pcTaskGetName(NULL), "Start"); NRF24_t dev; Nrf24_init(&dev); uint8_t payload = 32; uint8_t channel = CONFIG_RADIO_CHANNEL; Nrf24_config(&dev, channel, payload); // Set destination address using 5 characters esp_err_t ret = Nrf24_setTADDR(&dev, (uint8_t *)"FGHIJ"); if (ret != ESP_OK) { ESP_LOGE(pcTaskGetName(NULL), "nrf24l01 not installed"); while (1) { vTaskDelay(1); } } #if CONFIG_ADVANCED AdvancedSettings(&dev); #endif // CONFIG_ADVANCED // Print settings Nrf24_printDetails(&dev); uint8_t buf[32]; while (1) { TickType_t nowTick = xTaskGetTickCount(); sprintf((char *)buf, "Hello World %" PRIu32, nowTick); Nrf24_send(&dev, buf); // vTaskDelay(1); ESP_LOGI(pcTaskGetName(NULL), "Wait for sending....."); if (Nrf24_isSend(&dev, 1000)) { ESP_LOGI(pcTaskGetName(NULL), "Send success:%s", buf); } else { ESP_LOGW(pcTaskGetName(NULL), "Send fail:"); } vTaskDelay(1000 / portTICK_PERIOD_MS); } }
另一个receiver的 task便会进行接收.
void receiver(void *pvParameters) { ESP_LOGI(pcTaskGetName(NULL), "Start"); NRF24_t dev; Nrf24_init(&dev); uint8_t payload = 32; uint8_t channel = CONFIG_RADIO_CHANNEL; Nrf24_config(&dev, channel, payload); // Set my own address using 5 characters esp_err_t ret = Nrf24_setRADDR(&dev, (uint8_t *)"FGHIJ"); if (ret != ESP_OK) { ESP_LOGE(pcTaskGetName(NULL), "nrf24l01 not installed"); while (1) { vTaskDelay(1); } } #if CONFIG_ADVANCED AdvancedSettings(&dev); #endif // CONFIG_ADVANCED // Print settings Nrf24_printDetails(&dev); ESP_LOGI(pcTaskGetName(NULL), "Listening..."); uint8_t buf[32]; // Clear RX FiFo while (1) { if (Nrf24_dataReady(&dev) == false) break; Nrf24_getData(&dev, buf); } while (1) { // Wait for received data if (Nrf24_dataReady(&dev)) { Nrf24_getData(&dev, buf); ESP_LOGI(pcTaskGetName(NULL), "Got data:%s", buf); // ESP_LOG_BUFFER_HEXDUMP(pcTaskGetName(NULL), buf, payload, ESP_LOG_INFO); } vTaskDelay(1); // Avoid WatchDog alerts } }
实验现象
总结
在上文中, 我们主要是用nopnop2002/mirf库快速实现和调试了2.G模块的通讯和调试, 目前来看效果还是非常不错的, 符合预期. 但是对于通讯的距离和稳定性还需要进一步进行拉锯测试.
附件