walker2048 发表于 2024-6-6 20:08

【FireBeetle 2 ESP32 C6开发板】8、使用触屏 + espnow控制led灯

<div class='showpostmsg'>### 前言
lvgl已经出到9.x版本了,github上的lv_port_esp32还是7.x版本,由于我自己有Linux和esp32两种设备的开发需求,esp32的RAM和Flash也不算小,
我打算直接使用9.1版本的lvgl,然后使用lvgl_esp32_drivers仓库,仓库地址是https://github.com/lvgl/lvgl_esp32_drivers.git

#### 远程点灯
前面我们已经实现了微雪板子的lvgl按钮和触屏案例,现在使用espnow来实现远程点灯,效果如视频
c2f030530b81986a7fd7659b7885125d<br/>

要实现这个功能,我们需要先定义一个自定义的数据结构。
```c
typedef enum {
ESPNOW_LED_STATUS_UPLOAD,
ESPNOW_LED_SET_STATUS,
} espnow_event_id_t;

typedef struct {
uint8_t mac_addr;
esp_now_send_status_t status;
espnow_event_id_t event;
} espnow_data_t;
```
这个数据结构包含了事件类型,led状态,mac地址这些数据。
然后照抄一下espnow的官方源码就可以了,把espnow工作条件弄好(就是初始化wifi,设定espnow相关信息,绑定回调函数等等)。我们需要把原来的main函数文件修改成以下内容。

```c
/*
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "sdkconfig.h"

#include "lvgl.h"
#include <inttypes.h>
#include <stdio.h>

#include "esp_err.h"
#include "esp_log.h"
#include "esp_timer.h"

#include "src/widgets/label/lv_label.h"

#include "driver/gpio.h"
#include "esp_mac.h"
#include "esp_netif.h"
#include "esp_now.h"
#include "esp_wifi.h"
#include "freertos/semphr.h"
#include "nvs_flash.h"

#define TAG "LVGL"

typedef enum {
ESPNOW_LED_STATUS_UPLOAD,
ESPNOW_LED_SET_STATUS,
} espnow_event_id_t;

typedef struct {
uint8_t mac_addr;
esp_now_send_status_t status;
espnow_event_id_t event;
} espnow_data_t;

lv_obj_t *btn = NULL;

static void btn_event_cb(lv_event_t *e) {
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t *btn = lv_event_get_target(e);

espnow_data_t data = {
      .mac_addr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
      .status = 1,
      .event = ESPNOW_LED_SET_STATUS,
};
if (code == LV_EVENT_CLICKED) {
    uint32_t current_time = esp_timer_get_time() / 1000;
    static bool status = true;
    static uint32_t last_check_time = 0;
    if (current_time - last_check_time >= 300) {
      static uint8_t cnt = 0;
      cnt++;
      last_check_time = current_time;
      /*Get the first child of the button which is the label and change its
       * text*/
      lv_obj_t *label = lv_obj_get_child(btn, 0);

      if (status) {
      lv_obj_set_style_bg_color(btn, lv_palette_main(LV_PALETTE_CYAN), 0);
      lv_label_set_text(label, "LED Off");
      } else {
      lv_obj_set_style_bg_color(btn, lv_palette_main(LV_PALETTE_AMBER), 0);
      lv_label_set_text(label, "LED On");
      }
      data.status = status;
      esp_now_send(data.mac_addr, &data, sizeof(data));
      status = !status;
    }
}
}

/**
* Create a button with a label and react on click event.
*/
void lv_example_get_started_2(void) {
btn =
      lv_button_create(lv_screen_active()); /*Add a button the current screen*/

lv_obj_set_style_bg_color(btn, lv_palette_main(LV_PALETTE_AMBER), 0);

lv_obj_set_pos(btn, 80, 140);/*Set its position*/
lv_obj_set_size(btn, 120, 50); /*Set its size*/
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_ALL,
                      NULL); /*Assign a callback to the button*/

lv_obj_t *label = lv_label_create(btn); /*Add a label to the button*/
lv_label_set_text(label, "Button");   /*Set the labels text*/
lv_obj_center(label);

lv_obj_t *btn1 =
      lv_button_create(lv_screen_active()); /*Add a button the current screen*/

lv_obj_set_style_bg_color(btn1, lv_palette_main(LV_PALETTE_DEEP_ORANGE), 0);

lv_obj_set_pos(btn1, 80, 60);   /*Set its position*/
lv_obj_set_size(btn1, 120, 50); /*Set its size*/
lv_obj_add_event_cb(btn1, NULL, LV_EVENT_ALL,
                      NULL); /*Assign a callback to the button*/

lv_obj_t *label1 = lv_label_create(btn1); /*Add a label to the button*/
lv_label_set_text(label1, "LED");         /*Set the labels text*/
lv_obj_center(label1);
}

static void example_increase_lvgl_tick(void *arg) {
/* Tell LVGL how many milliseconds has elapsed */
lv_tick_inc(2);
}

extern void lv_port_disp_init(void);
extern void lv_port_indev_init(void);

/* ESPNOW can work in both station and softap mode. It is configured in
* menuconfig. */
#if CONFIG_ESPNOW_WIFI_MODE_STATION
#define ESPNOW_WIFI_MODE WIFI_MODE_STA
#define ESPNOW_WIFI_IF ESP_IF_WIFI_STA
#else
#define ESPNOW_WIFI_MODE WIFI_MODE_AP
#define ESPNOW_WIFI_IF ESP_IF_WIFI_AP
#endif

#define BLINK_GPIO 15

#define ESPNOW_QUEUE_SIZE 6

#define IS_BROADCAST_ADDR(addr)                                                \
(memcmp(addr, s_example_broadcast_mac, ESP_NOW_ETH_ALEN) == 0)

#define ESPNOW_MAXDELAY 512
#define EXAMPLE_ESPNOW_DATA_MAX 10
#define CONFIG_ESPNOW_CHANNEL 1

static uint8_t broadcast_mac = {0xFF, 0xFF, 0xFF,
                                                0xFF, 0xFF, 0xFF};

/* WiFi should start before using ESPNOW */
static void example_wifi_init(void) {
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
ESP_ERROR_CHECK(esp_wifi_set_mode(ESPNOW_WIFI_MODE));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_ERROR_CHECK(
      esp_wifi_set_channel(CONFIG_ESPNOW_CHANNEL, WIFI_SECOND_CHAN_NONE));

#if CONFIG_ESPNOW_ENABLE_LONG_RANGE
ESP_ERROR_CHECK(esp_wifi_set_protocol(
      ESPNOW_WIFI_IF, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G |
                        WIFI_PROTOCOL_11N | WIFI_PROTOCOL_LR));
#endif
}

static void example_espnow_recv_cb(const esp_now_recv_info_t *recv_info,
                                 const uint8_t *data, int len) {
espnow_data_t *user_data = (espnow_data_t *)data;
if (user_data->event == ESPNOW_LED_SET_STATUS) {
    gpio_set_level(BLINK_GPIO, user_data->status);
    if (!user_data->status) {
      lv_obj_set_style_bg_color(btn, lv_palette_main(LV_PALETTE_AMBER), 0);
    } else {
      lv_obj_set_style_bg_color(btn, lv_palette_main(LV_PALETTE_CYAN), 0);
    }
}
}

static esp_err_t example_espnow_init(void) {
/* Initialize ESPNOW and register sending and receiving callback function. */
ESP_ERROR_CHECK(esp_now_init());
ESP_ERROR_CHECK(esp_now_register_recv_cb(example_espnow_recv_cb));

/* Add broadcast peer information to peer list. */
esp_now_peer_info_t *peer = malloc(sizeof(esp_now_peer_info_t));
if (peer == NULL) {
    ESP_LOGE(TAG, "Malloc peer information fail");
    esp_now_deinit();
    return ESP_FAIL;
}
memset(peer, 0, sizeof(esp_now_peer_info_t));
peer->channel = CONFIG_ESPNOW_CHANNEL;
peer->ifidx = ESPNOW_WIFI_IF;
peer->encrypt = false;
memcpy(peer->peer_addr, broadcast_mac, ESP_NOW_ETH_ALEN);
ESP_ERROR_CHECK(esp_now_add_peer(peer));
free(peer);

return ESP_OK;
}

void app_main(void) {
// Initialize NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
      ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
    ESP_ERROR_CHECK(nvs_flash_erase());
    ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);

example_wifi_init();
example_espnow_init();

#if CONFIG_IDF_TARGET_ESP32C6
gpio_reset_pin(BLINK_GPIO);
/* Set the GPIO as a push/pull output */
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
#endif

lv_init();
lv_port_disp_init();
lv_port_indev_init();

ESP_LOGI(TAG, "Install LVGL tick timer");
// Tick interface for LVGL (using esp_timer to generate 2ms periodic event)
const esp_timer_create_args_t lvgl_tick_timer_args = {
      .callback = &example_increase_lvgl_tick, .name = "lvgl_tick"};
esp_timer_handle_t lvgl_tick_timer = NULL;
ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, 2 * 1000));
lv_example_get_started_2();

/* handle the tasks of LVGL */
while (1) {
    lv_task_handler();
    vTaskDelay(pdMS_TO_TICKS(30));
}
}

```

两个设备都烧录同一个固件(没有触摸屏的设备注释掉初始化触屏的内容即可)。就可以啦,效果就和视频里的一样。</div><script>                                        var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;"   style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
                                       
                                        if(parseInt(discuz_uid)==0){
                                               
                                        }                </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>

Jacktang 发表于 2024-6-7 07:33

<p> &nbsp;</p>

<p>效果还是可以的</p>

Maker_kun 发表于 2024-6-7 12:25

<p>这个功能好,可以触摸控制</p><br/>
页: [1]
查看完整版本: 【FireBeetle 2 ESP32 C6开发板】8、使用触屏 + espnow控制led灯