87浏览
查看: 87|回复: 0

[ESP8266/ESP32] [ESP8266/ESP32] FireBeetle 2 开发板_ESPNOW初体验

[复制链接]
本帖最后由 忙碌的死龙 于 2024-4-25 17:31 编辑

前言
ESPNOW协议是乐鑫信息科技(上海)有限公司(Espressif Systems)开发的一种基于IEEE 802.11标准的无线通信协议。乐鑫是一家专注于无线通信技术的企业,旗下产品如ESP8266和ESP32芯片广泛用于物联网(IoT)项目中,因其高性能和低成本获得了极大的流行。
ESPNOW协议允许设备在不需要建立WiFi连接的情况下进行直接通信,即可以在设备之间实现点对点或点对多点的数据传输。这种通信模式相对于传统的WiFi网络来说,在某些应用场景下可以提供更高效的数据交换方式,因为它省去了WiFi连接建立与断开的时间,从而减少了通信延迟。同时,ESPNOW协议还能够在低功耗模式下工作,这对于电池供电的物联网设备是非常重要的特性。
ESPNOW协议的主要特点包括:
  • 高效的通信协议:由于不需要传统的WiFi网络连接过程(如握手协议),ESPNOW可以更快地完成设备间的数据交换。
  • 灵活的设备对接模式:支持一对一、一对多和多对多的通信模式,这使得ESPNOW协议在物联网应用中非常灵活。
  • 低功耗:特别适合于电池供电的设备,有助于延长设备的使用寿命。
  • 使用简单:乐鑫为ESPNOW提供了一套相对简单的API和开发工具,使得开发人员可以相对容易地实现和部署基于此协议的应用。



1、ESPNOW的官方案例代码

我们直接使用官方的案例代码进行测试,这个案例需要使用两块ESP32开发板。
  1. /* Get Start Example
  2.    This example code is in the Public Domain (or CC0 licensed, at your option.)
  3.    Unless required by applicable law or agreed to in writing, this
  4.    software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  5.    CONDITIONS OF ANY KIND, either express or implied.
  6. */
  7. #include "freertos/FreeRTOS.h"
  8. #include "freertos/task.h"
  9. #include "esp_log.h"
  10. #include "esp_system.h"
  11. #include "esp_wifi.h"
  12. #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
  13. #include "esp_mac.h"
  14. #endif
  15. #include "espnow.h"
  16. #include "espnow_storage.h"
  17. #include "espnow_utils.h"
  18. #include "driver/uart.h"
  19. // You can modify these according to your boards.
  20. #define UART_BAUD_RATE 115200
  21. #define UART_PORT_NUM  0
  22. #define UART_TX_IO     UART_PIN_NO_CHANGE
  23. #define UART_RX_IO     UART_PIN_NO_CHANGE
  24. static const char *TAG = "app_main";
  25. static void app_uart_read_task(void *arg)
  26. {
  27.     esp_err_t ret  = ESP_OK;
  28.     uint32_t count = 0;
  29.     size_t size    = 0;
  30.     uint8_t *data  = ESP_CALLOC(1, ESPNOW_DATA_LEN);
  31.     ESP_LOGI(TAG, "Uart read handle task is running");
  32.     espnow_frame_head_t frame_head = {
  33.         .retransmit_count = CONFIG_RETRY_NUM,
  34.         .broadcast        = true,
  35.     };
  36.     for (;;) {
  37.         size = uart_read_bytes(UART_PORT_NUM, data, ESPNOW_DATA_LEN, pdMS_TO_TICKS(10));
  38.         ESP_ERROR_CONTINUE(size <= 0, "");
  39.         ret = espnow_send(ESPNOW_DATA_TYPE_DATA, ESPNOW_ADDR_BROADCAST, data, size, &frame_head, portMAX_DELAY);
  40.         ESP_ERROR_CONTINUE(ret != ESP_OK, "<%s> espnow_send", esp_err_to_name(ret));
  41.         ESP_LOGI(TAG, "espnow_send, count: %" PRIu32 ", size: %u, data: %s", count++, size, data);
  42.         memset(data, 0, ESPNOW_DATA_LEN);
  43.     }
  44.     ESP_LOGI(TAG, "Uart handle task is exit");
  45.     ESP_FREE(data);
  46.     vTaskDelete(NULL);
  47. }
  48. static void app_uart_initialize()
  49. {
  50.     uart_config_t uart_config = {
  51.         .baud_rate = UART_BAUD_RATE,
  52.         .data_bits = UART_DATA_8_BITS,
  53.         .parity    = UART_PARITY_DISABLE,
  54.         .stop_bits = UART_STOP_BITS_1,
  55.         .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
  56. #if SOC_UART_SUPPORT_REF_TICK
  57.         .source_clk = UART_SCLK_REF_TICK,
  58. #elif SOC_UART_SUPPORT_XTAL_CLK
  59.         .source_clk = UART_SCLK_XTAL,
  60. #endif
  61.     };
  62.     ESP_ERROR_CHECK(uart_param_config(UART_PORT_NUM, &uart_config));
  63.     ESP_ERROR_CHECK(uart_set_pin(UART_PORT_NUM, UART_TX_IO, UART_RX_IO, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
  64.     ESP_ERROR_CHECK(uart_driver_install(UART_PORT_NUM, 8 * ESPNOW_DATA_LEN, 8 * ESPNOW_DATA_LEN, 0, NULL, 0));
  65.     xTaskCreate(app_uart_read_task, "app_uart_read_task", 4 * 1024, NULL, tskIDLE_PRIORITY + 1, NULL);
  66. }
  67. static void app_wifi_init()
  68. {
  69.     esp_event_loop_create_default();
  70.     wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
  71.     ESP_ERROR_CHECK(esp_wifi_init(&cfg));
  72.     ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
  73.     ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
  74.     ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
  75.     ESP_ERROR_CHECK(esp_wifi_start());
  76. }
  77. static esp_err_t app_uart_write_handle(uint8_t *src_addr, void *data,
  78.                                        size_t size, wifi_pkt_rx_ctrl_t *rx_ctrl)
  79. {
  80.     ESP_PARAM_CHECK(src_addr);
  81.     ESP_PARAM_CHECK(data);
  82.     ESP_PARAM_CHECK(size);
  83.     ESP_PARAM_CHECK(rx_ctrl);
  84.     static uint32_t count = 0;
  85.     ESP_LOGI(TAG, "espnow_recv, <%" PRIu32 "> [" MACSTR "][%d][%d][%u]: %.*s",
  86.              count++, MAC2STR(src_addr), rx_ctrl->channel, rx_ctrl->rssi, size, size, (char *)data);
  87.     return ESP_OK;
  88. }
  89. void app_main()
  90. {
  91.     espnow_storage_init();
  92.     app_uart_initialize();
  93.     app_wifi_init();
  94.     espnow_config_t espnow_config = ESPNOW_INIT_CONFIG_DEFAULT();
  95.     espnow_init(&espnow_config);
  96.     espnow_set_config_for_data_type(ESPNOW_DATA_TYPE_DATA, true, app_uart_write_handle);
  97. }
复制代码
2、代码解析
这个代码其实并不负责,首先初始化nvs存储(espnow_storage_init()),然后初始化串口设备(app_uart_initialize()),接下来初始化wifi功能,并初始化espnow功能。最后绑定espnow的回调函数,绑定接收函数调用的回调函数,在接收到发送端的数据后,回显在串口设备上。
发送端的串口线程代码如下,这个线程不断地从串口读取数据,然后将数据通过广播的形式,发送到接收设备上。
  1. static void app_uart_read_task(void *arg)
  2. {
  3.     esp_err_t ret  = ESP_OK;
  4.     uint32_t count = 0;
  5.     size_t size    = 0;
  6.     uint8_t *data  = ESP_CALLOC(1, ESPNOW_DATA_LEN);
  7.     ESP_LOGI(TAG, "Uart read handle task is running");
  8.     espnow_frame_head_t frame_head = {
  9.         .retransmit_count = CONFIG_RETRY_NUM,
  10.         .broadcast        = true,
  11.     };
  12.     for (;;) {
  13.         size = uart_read_bytes(UART_PORT_NUM, data, ESPNOW_DATA_LEN, pdMS_TO_TICKS(10));
  14.         ESP_ERROR_CONTINUE(size <= 0, "");
  15.         ret = espnow_send(ESPNOW_DATA_TYPE_DATA, ESPNOW_ADDR_BROADCAST, data, size, &frame_head, portMAX_DELAY);
  16.         ESP_ERROR_CONTINUE(ret != ESP_OK, "<%s> espnow_send", esp_err_to_name(ret));
  17.         ESP_LOGI(TAG, "espnow_send, count: %" PRIu32 ", size: %u, data: %s", count++, size, data);
  18.         memset(data, 0, ESPNOW_DATA_LEN);
  19.     }
  20.     ESP_LOGI(TAG, "Uart handle task is exit");
  21.     ESP_FREE(data);
  22.     vTaskDelete(NULL);
  23. }
复制代码

接收端的回调函数如下:
接收端在接收到广播数据后,打印对应的内容。
  1. static esp_err_t app_uart_write_handle(uint8_t *src_addr, void *data,
  2.                                        size_t size, wifi_pkt_rx_ctrl_t *rx_ctrl)
  3. {
  4.     ESP_PARAM_CHECK(src_addr);
  5.     ESP_PARAM_CHECK(data);
  6.     ESP_PARAM_CHECK(size);
  7.     ESP_PARAM_CHECK(rx_ctrl);
  8.     static uint32_t count = 0;
  9.     ESP_LOGI(TAG, "espnow_recv, <%" PRIu32 "> [" MACSTR "][%d][%d][%u]: %.*s",
  10.              count++, MAC2STR(src_addr), rx_ctrl->channel, rx_ctrl->rssi, size, size, (char *)data);
  11.     return ESP_OK;
  12. }
复制代码


3、demo运行情况

[ESP8266/ESP32] FireBeetle 2 开发板_ESPNOW初体验图1



ESPNOW使用起来还是比较简单的,但是目前示范的代码也只是一些简单的单对单、单对多、广播等内容,想要组成比较复杂的通讯网络和自定义数据转发,还是需要花时间写代码的。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail