ESP8266 SDDC 设备开发

更新时间:
2023-08-09
下载文档

ESP8266 SDDC 设备开发

本章将介绍如何在 ESP8266 上使用 FreeRTOS 和 libsddc 开发一个能接入到 EdgerOS 的 Wi-Fi 物联网设备。

硬件准备

ESP8266 开发板

ESP8266 是乐鑫科技推出的一款面向物联网应用的高性价比、高度集成的 Wi-Fi MCU。

ESP8266 内置超低功耗 Tensilica L106 32 位 RISC 处理器,CPU 时钟速度最高可达 160 MHz,支持实时操作系统(RTOS)和 Wi-Fi 协议栈,可将高达 80% 的处理能力留给应用编程和开发。

本实验使用的是一块 ESP8266 开发板,它带有两个按键,一个 RESET 复位按键和一个 FLASH 编程按键,如下图所示:

avatar

软件准备

开发 ESP8266 需要使用安信可科技 AI-Thinker 开发 IDE。

下载 IDE 软件包并安装

网盘链接:https://pan.baidu.com/s/1bk_mc-X9Aol9MgiU0gZA0A 提取码:shm3

下载 AiThinkerIDE_V1.5.2.exe 即可,双击 AiThinkerIDE_V1.5.2.exe,完成安装。

调整 IDE PATH

将 AiThinkerIDE 相关的 4 个环境变量上移到最前面:

avatar

下载 ESP8266 SDK

在一个路径不带空格的目录下,执行以下命令下载:

git clone --recursive https://github.com/ms-rtos/AiThinkerProjectForESP.git

如果 github 下载速度慢,可以试试 gitee:

git clone --recursive https://gitee.com/ms-rtos/AiThinkerProjectForESP.git

avatar

该 ESP8266 SDK 为翼辉信息工程师在安信可科技开源项目 AiThinkerProjectForESP 的基础上,二次开发而来,特此鸣谢安信可科技。

导入 ESP8266 SDK

双击桌面的 AiThinkerIDE_V1.5.2 图标,打开 AiThinkerIDE,点击 File > Import 菜单,将弹出 Import 向导:

avatar

选择 C/C++ 下的 Existing code as Makefile Project 类型,然后点击 Next 按钮:

avatar

点击 Browse 按钮选择刚刚下载的 ESP8266 SDK 的路径,Toolchain for indexer Settings 选择 Cross GCC,最后点击 Finish 按钮完成导入:

avatar

配置 SDK 工程

配置 IDF_PATH 变量

鼠标选中 AiThinkerProjectForESP 工程,点击右键,在右键菜单中选择 Properties,选择 C/C++ Build->Environment,点击 Add 按钮添加一个 IDF_PATH 变量,值为 ESP8266 SDK 的路径,注意需要将路径修改为 unix 风格,如 /D/AiThinkerWorkspace/AiThinkerProjectForESP,最后点击 OK 按钮:

avatar

avatar

配置构建路径

鼠标选中 AiThinkerProjectForESP 工程,点击右键,在右键菜单中选择 Properties,选择 C/C++ Build,修改 Build directory 为需要编译的例程路径,如${workspace_loc:/AiThinkerProjectForESP}/examples/protocols/sddc,最后点击 OK 按钮:

avatar

鼠标选中 AiThinkerProjectForESP 工程,点击右键,在右键菜单中选择 Make Targets > Create,在弹出的对话框中取消勾选 Same as the target name 与 User builder settings 这 2 个选项,将 Target name 修改为 menuconfig,并且在 Build command 中输入 mintty.exe -e make menuconfig,最后点击 OK 按钮:

avatar

鼠标选中 AiThinkerProjectForESP 工程,点击右键,在右键菜单中选择 Make Targets > Build,在弹出的对话框中选中 menuconfig 项,然后点击 Build 按钮:

avatar

avatar

修改连接 Wi-Fi AP 的配置,将 Wi-Fi SSID 和 Password 修改为智能边缘计算机 Spirit 1 的 Wi-Fi AP SSID 和密码,最后选中 Exit 回车后退出配置,等待配置完成。

avatar

连接 Wi-Fi 的方式还支持 SmartConfig,具体连接方式可见后文。

编译 SDK 和例程

鼠标选中 AiThinkerProjectForESP 工程,点击右键,在右键菜单中选择 Build project,等待编译完成。

avatar

烧写镜像

配置 FLASH 编程目标

将 ESP8266 开发板接入电脑,打开设备管理,查看操作系统为 ESP8266 开发板分配的 COM 号。

avatar

鼠标选中 AiThinkerProjectForESP 工程,点击右键,在右键菜单中选择 Make Targets > Create ,在弹出的对话框中取消勾选 Same as the target name 与 User builder settings 这 2 个选项,将 Target name 修改为 flash,并且在 Build command 中输入 make flash ESPPORT=COM11,最后点击 OK 按钮,注意 COM 号为 ESP8266 开发板插入电脑后分配出来的 COM 号:

avatar

烧写镜像

在右键菜单中选择 Make Targets > Build,在弹出的对话框中选中 flash 项,然后点击 Build 按钮:

avatar

avatar

验证功能

ESP8266 开发板连接 EdgerOS

使用 PuTTY 作为串口调试工具,新建一个 Serial 类型的 Session,按如下图所示配置串口,注意 Speed 为 74880,点击 Save 按钮保存 Session 方便以后直接打开,最后点击 Open 按钮:

avatar

按下 ESP8266 开发板的 RESET 按键,将看到 SDDC 程序运行起来:

avatar

如果在前面 make menuconfig 时配置了正确的 Spirit 1 的 Wi-Fi AP SSID 和密码,ESP8266 开发板将能成功连接 Spirit 1 的 Wi-Fi 网络,接下来请参考《SDDC introduction》章节的“添加设备流程”去添加 ESP8266 开发板。

注意 ESP8266 开发板的设备密码为 1234567890

ESP8266 开发板 SmartConfig

如果在前面 make menuconfig 时没有配置了正确的 Spirit 1 的 Wi-Fi AP SSID 和密码或在后续使用过程中修改了 Spirit 1 的 Wi-Fi AP SSID 或密码,则可以通过 SmartConfig 方式令 ESP8266 开发板重新加入 Spirit 1 的 Wi-Fi 网络,操作方式请参考《SDDC introduction》章节的“SmartConfig 流程”。

注意 长按 ESP8266 开发板的 FLASH 按键 3 秒进入 SmartConfig 模式。

ESP8266 SDDC 代码解析

SDDC demo 代码位于 examples/protocols/sddc/main/sddc_esp8266_example.c,在 void app_main() 函数中调用 xTaskCreate(sddc_example_task, "sddc_example_task", 4096, NULL, 5, NULL); 来创建 SDDC 的工作任务 ,具体 SDDC 协议细节可参考《SDDC introduction》章节。


// 应用入口函数
void app_main(void)
{
    // 初始化 FLASH
    ESP_ERROR_CHECK(nvs_flash_init());
    // 初始化 NETIF
    ESP_ERROR_CHECK(esp_netif_init());
    // 创建缺省的事件循环
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
     * Read "Establishing Wi-Fi or Ethernet Connection" section in
     * examples/protocols/README.md for more information about this function.
     */
    ESP_ERROR_CHECK(example_connect());
    // 创建 SDDC task
    xTaskCreate(esp_sddc_task, "sddc_task", ESP_SDDC_TASK_STACK_SIZE, NULL, ESP_SDDC_TASK_PRIO, NULL);
}

// SDDC 工作任务
static void esp_sddc_task(void *arg)
{
    sddc_t *sddc;
    char *data;
    uint8_t mac[6];
    char ip[sizeof("255.255.255.255")];
    tcpip_adapter_ip_info_t ip_info = { 0 };

    // 创建 SDDC 协议对象
    sddc = sddc_create(SDDC_CFG_PORT);

    // 设置事件响应函数
    sddc_set_on_message(sddc, esp8266_on_message);              // 设置接收消息请求时的回调函数
    sddc_set_on_message_ack(sddc, esp8266_on_message_ack);      // 设置接收消息确认时的回调函数
    sddc_set_on_message_lost(sddc, esp8266_on_message_lost);    // 设置丢失消息时的回调函数
    sddc_set_on_invite(sddc, esp8266_on_invite);                // 设置接受邀请请求时的回调函数
    sddc_set_on_invite_end(sddc, esp8266_on_invite_end);        // 设置发送邀请后的回调函数
    sddc_set_on_update(sddc, esp8266_on_update);                // 设置接收更新请求时的回调函数
    sddc_set_on_edgeros_lost(sddc, esp8266_on_edgeros_lost);    // 设置 EdgerOS 断连时的回调函数

    // 设置设备密码
#if SDDC_CFG_SECURITY_EN > 0
    sddc_set_token(sddc, "1234567890");
#endif

    // 创建并设置 Report 报文数据
    data = esp_report_data_create();
    sddc_set_report_data(sddc, data, strlen(data));

    // 创建并设置 Invite 报文数据
    data = esp_invite_data_create();
    sddc_set_invite_data(sddc, data, strlen(data));

    // 获取网卡 mac 地址
    esp_wifi_get_mac(ESP_IF_WIFI_STA, mac);

    // 使用网卡 mac 地址设置设备唯一标识 UID
    sddc_set_uid(sddc, mac);

    // 获取并打印 IP 地址
    tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info);

    inet_ntoa_r(ip_info.ip, ip, sizeof(ip));

    sddc_printf("IP addr: %s\n", ip);
    // 创建 Wi-Fi 事件组
    wifi_event_group = xEventGroupCreate();
    // 创建 FLASH 按键检测 task
    xTaskCreate(esp_flash_key_task, "flash_key_task",  ESP_KEY_TASK_STACK_SIZE, sddc, ESP_KEY_TASK_PRIO, NULL);

    // 运行 SDDC 协议循环
    while (1) {
        sddc_printf("SDDC running...\n");

        sddc_run(sddc);

        sddc_printf("SDDC quit!\n");
    }

    // 销毁 SDDC 协议对象
    sddc_destroy(sddc);
    // 删除 SmartConfig 任务
    vTaskDelete(NULL);
}

// FLASH 按键检测任务
static void esp_flash_key_task(void *arg)
{
    sddc_t *sddc = arg;
    gpio_config_t io_conf;
    int i = 0;
    
    (void)sddc;
    // 配置 GPIO 禁能中断
    io_conf.intr_type = GPIO_INTR_DISABLE;
    // 配置 GPIO 为输入模式
    io_conf.mode = GPIO_MODE_INPUT;
    // 配置 GPIO 引脚
    io_conf.pin_bit_mask = 1ULL << GPIO_INPUT_IO_SMARTCOFNIG;
    // 禁能下拉
    io_conf.pull_down_en = 0;
    // 使能上拉
    io_conf.pull_up_en = 1;
    // 配置 GPIO
    gpio_config(&io_conf);

    while (1) {
        vTaskDelay(1000 / portTICK_RATE_MS);
        // 检测 FLASH 按键按下
        if (!gpio_get_level(GPIO_INPUT_IO_SMARTCOFNIG)) {
            i++;
            // FLASH 按键按下超过三秒
            if (i > 3) {
                i = 0;

                sddc_printf("Start SmartConfig....\n");

                esp_wifi_disconnect();
                xEventGroupClearBits(wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT);
                // 注册 Wi-Fi 断开连接回调函数
                ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect, NULL));
                // 注册 Wi-Fi 获取 IP 回调函数
                ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip, NULL));
                // 设置 SmartConfig 类型
                ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS) );
                // 开始 SmartConfig
                ESP_ERROR_CHECK( esp_smartconfig_start(sc_callback) );

                while (1) {
                    // 等待连接上 Wi-Fi AP 和 ESPTOUCH 结束
                    EventBits_t uxBits = xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT,
                                                             true, false, portMAX_DELAY);
                    if (uxBits & CONNECTED_BIT) {
                        // 连接上 Wi-Fi AP
                        ESP_LOGI(TAG, "Wi-Fi Connected to AP");
                    }
                    if (uxBits & ESPTOUCH_DONE_BIT) {
                        // ESPTOUCH 结束
                        ESP_LOGI(TAG, "SmartConfig over");
                        // 停止 SmartConfig
                        esp_smartconfig_stop();
                        break;
                    }
                }
                // 取消注册 Wi-Fi 断开连接回调函数
                ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect));
                // 取消注册 Wi-Fi 获取 IP 回调函数
                ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip));
            }
        } else {
            i = 0;
        }
    }
}
文档内容是否对您有所帮助?
有帮助
没帮助