如何用ESP32为物联网设备创建概念验证原型

您将学习如何为基于流行的 ESP32 微控制器系列的新物联网产品构建早期原型,这也是大规模生产的绝佳解决方案。

物联网 (IoT) 早已不是新浪潮,现在新硬件产品具有无线连接功能非常普遍,蓝牙和 WiFi 是两种最流行的协议。

凭借 FCC 许可和无线技术的各种电气复杂性,新公司或团队开始开发新的支持互联网的设备可能会令人生畏。

天线、无线电路和微控制器都可能带来各自独特的挑战。

单独开发或采购每一个,然后将它们组合成一个有凝聚力的工作设备是一个挑战。

幸运的是,有多种具有内置无线功能的微控制器可以作为 SoC(片上系统)或 SoM(系统级模块)使用。

这些通常带有一个开箱即用的集成许可天线,其外形尺寸对原型和成品等都很友好。

ESP32无线单片机介绍

一个这样的 SoC 是 ESP32,它是由中国公司 Espressif 开发的一种流行的芯片,支持 WiFi 和蓝牙。

ESP32 是一个非常实惠的解决方案,特别是考虑到它的高性能和广泛的功能。

它具有强大的单核或双核 CPU,具有 240MHz 的高时钟速度、448kB 的只读内存以及 520kB 的 SRAM。

除了支持 WiFi 和蓝牙外,它的套件还包括一系列具有嵌入式系统经验的外围设备。

这包括各种定时器,如 RTC、DAC/ADC,流行的串行接口,如 UART、I2C 和 SPI(支持用于外部闪存的四通道 SPI——想想照片或视频存储!),甚至支持以太网、PWM 和霍尔传感器。

制造商直接说明其潜在应用范围从视频流到可穿戴电子设备和机器人。

该 SoC 从头开始​​设计为多功能,其受欢迎程度意味着当您将该设备适应您的应用程序时,有大量的在线资源可供学习。

该 SoC 有几种不同的型号可供选择,最简洁的概述如下数据表摘录:

图 1:ESP32 微控制器的零件编号方案

您的应用程序所需的特定模型可能很重要,也可能不重要。

例如,具有高计算要求的用户(如复杂的多线程应用程序或视频流)将希望选择双核处理器。

或者,例如,具有数据记录要求的应用程序可能需要嵌入式闪存和/或 PSRAM。

从 POC 原型到量产

ESP32 微控制器非常适合原型设计的原因之一是制造商不仅制造裸芯片,而且还生产基于这些精确微控制器的即用型模块。

ESP32 平台可分为三个开发阶段,极大地简化了从 POC 到量产的过渡。这些阶段包括:

第 1 阶段– 使用包含 ESP32 模块的开发板开发早期 POC 原型(参见下图 2)。此阶段不需要 FCC 认证。

图 2:开发板上的 ESP32 模块

第 2 阶段——设计您自己的定制 PCB 并将 ESP32 模块(参见下图 3)直接焊接到您的定制板上。

此阶段需要有限的 FCC 认证。由于您设计的无线部分由预先认证的模块处理,因此 FCC 会将您的最终产品归类为“非故意辐射器”。

非故意散热器认证比完整的“故意散热器”认证更便宜且更容易获得。

图 3:ESP32-WROOM-32E 模组(金属屏蔽下是 ESP32 SoC)

第 3 阶段– 使用 ESP SoC 裸芯片设计您自己的定制射频电路。请注意,大多数产品不需要此阶段。

通常,这第三阶段仅适用于具有极端尺寸、物理限制或极高产量的设计,其中每一分钱的利润都至关重要。

此阶段需要昂贵的完整 FCC“故意散热器”认证,因此除非绝对必要,否则应避免使用。

从您的早期 POC 原型一直到大规模生产,通过始终使用相同的微控制器内核,您可以更轻松地在各个阶段之间转换您的固件代码。

实现 ESP32

第一步可能很熟悉——暂时忽略 WiFi 和蓝牙功能,ESP32 和其他任何微控制器一样。

您将首先确定控制外部组件的通信方法,并创建一个电路,最有可能在面包板或可焊接原型板上,用于概念验证。

例如,您可能有一个步进电机,因此您将确定 ESP32 开发板上的哪些引脚能够进行 PWM 输出来控制其速度,并分配一些 GPIO 引脚来控制其方向和睡眠模式。

SD 读卡器需要连接到开发板的 SPI 接口。

如果您过去曾使用任何类型的微控制器开发过产品,那么这部分过程将不会有什么不熟悉的地方。

将在 ESP32 的固件开发中引入新概念。

ESP32 固件编程

ESP32 固件开发主要有两种选择:Arduino 平台的 ESP32 支持,或者由乐鑫维护的官方 ESP-IDF 固件包。

这两种方法各有利弊,其中许多在其他文章中都有介绍,但这里简要总结了您在做出选择时的注意事项。

Arduino IDE

Arduino 的 IDE 主要优点是它的可移植性。如果您觉得您希望将您的应用程序完全迁移到另一个平台,Arduino 的跨板一致性将使该过程更加顺畅。

此外,它的平台为您可能希望在应用程序中使用的组件提供用户创建的库。

简而言之,如果可行,使用 Arduino IDE 可以加快软件开发周期。

有关使用 Arduino IDE 对 ESP32 进行编程的更多详细信息,请参阅本文。

ESP-IDF

ESP-IDF 具有由 Espressif 维护的直接且明显的好处,因此它最有可能最接近地匹配硬件的来龙去脉。

根据我个人的轶事经验,ESP32 是 Arduino 上漏洞较多的平台之一,因此对于许多应用程序来说,使用 ESP-IDF 可能是更好的选择。

虽然 ESP-IDF 是一种更高级的编程体验,但它也更强大。

这意味着您遇到的任何问题都更有可能是用户错误,而不是库中的一些错误或 Arduino 实现中遗漏的一些硬件不兼容。

此外,ESP-IDF 利用 FreeRTOS 提供多线程应用程序体验,这对于来自其他固件应用程序的开发人员来说可能很熟悉。

另请注意,这两个选项并不完全相互排斥。可以将 Arduino 库引入到 ESP-IDF 项目中,并且 Arduino 的实现尝试引入 ESP-IDF 的大部分功能。

与往常一样,这是一个很大程度上基于团队组成以及产品限制和要求的决定。

由于 Arduino 编程包含在各种其他资源中,本文的其余部分将重点介绍利用 ESP-IDF 开发 ESP32 应用程序。

乐鑫提供的在线文档非常棒,ESP-IDF 在安装时包含了各种示例以帮助用户入门。

固件案例研究

让我们看一个使用蓝牙的示例项目,特别是这个项目,其中演示了 ESP32 将自己报告为蓝牙鼠标、键盘等的能力。

在这个文件夹中,注意有几个sdkconfig文件。许多是使用 ESP-IDF 软件包附带的 Python 脚本自动生成的,并且基本上为某些开发板设置了项目的低级方面。

还有一个用于构建项目的CmakeLists.txt文件(ESP-IDF 支持使用Cmake 构建),最后是一个包含 C 应用程序代码的main/文件夹。

main/文件夹包含一个ble_hidd_demo_main.c文件,该文件具有应用程序的入口点。当我们打开它时,您会注意到该文件相当长。

它包含各种包含和几个对可能不熟悉的 API 的引用。乍一看可能会令人生畏,但可以将其分解以使其更易于消化。

函数app_main(void); 是应用程序的入口点,在更典型的 C 项目中代替main() 。

请注意,这实际上是从 FreeRTOS 任务调用的——ESP-IDF 在内部设置 FreeRTOS 内核以启动,用户自己实现app_main()

注意在app_main()的底部创建了一个新任务;这是在app_main()退出后保持进程继续运行的典型方法。

如果不一定需要多线程,用户可以将所有应用程序代码保留在app_main()中,但他们也可以通过调用xTaskCreate()来根据需要生成任务,就像示例中所做的那样。

请注意,该演示使用任务函数hid_demo_task()创建了一个任务,该任务在文件的其他位置定义。该任务包含一个无限的while循环,因此是程序的长时间运行控制循环。

回顾app_main()及其调用的函数,我们可以看到在生成新任务之前所做的很多事情只是外围初始化。

这与大多数 FreeRTOS 实现甚至在其他平台上所做的一致——初始化所需的硬件,然后启动主要任务。

对于那些来自 Arduino 的人来说,这里列出的代码流程与 Arduino 中的setup()loop()函数非常相似。

app_main ()函数扮演setup()的角色,关键区别在于它必须在返回之前显式定义/创建loop() “函数”(实际上是一个任务)。

总的来说,ESP-IDF 实现了原生 FreeRTOS。

与从头开始的实现相比,它的主要区别在于它不直接公开main(),而是使用裸外围初始化和内核初始化函数自动生成它。

因此,当到达用户应用程序代码时,系统时钟和 RTOS 等关键项目已经启动。

保持本文前面的主题的关键要点是,ESP32 平台在提供极大的灵活性方面做得非常出色,而且还提供了理智、简单的默认启动。

用户完全不必像使用 FreeRTOS 那样编写代码。

取而代之的是,简单地不要产生新任务并在app_main()的底部放置一个无限循环,并且您拥有基本微控制器程序的传统单线程超级循环结构。

由于提供了生成器脚本,您不必编写任何针对 SoC 定制的手动固件,但相同的脚本允许对项目设置进行大量精细调整,如图 4 所示。

图 4:随 ESP-IDF 软件包提供的 idf.py 菜单。用于设置 ESP32 项目。

处理完基本方面后,接下来要看的是 API——与 ESP32 硬件的实际接口是什么样的?

ESP-IDF 平台为所有可用的外设提供了一个硬件抽象层,完整的参考请点击此处

在通过ble_hidd_demo_main.c文件中的以下包含提供此功能之前的相同蓝牙示例中:

#include “esp_system.h”
#include “esp_wifi.h”
#include “esp_event.h”
#include “esp_log.h”
#include “nvs_flash.h”
#include “esp_bt.h”

#include “esp_hidd_prf_api.h”
#include “esp_bt_defs.h”
#include “esp_gap_ble_api.h”
#include “esp_gatts_api.h”
#include “esp_gatt_defs.h”
#include “esp_bt_main.h”
#include “esp_bt_device.h”
#包括“驱动程序/gpio.h”#包括
“hid_dev.h”

除了可以在与 C 文件相同的文件夹中找到的一些特定于示例的标头之外,这些包含表示此示例所需的 ESP-IDF API。

空白行进一步将头文件拆分为顶部的“核心”外围驱动程序文件和底部的应用程序特定文件。

例如,esp_bt.h包含 ESP32 上蓝牙堆栈的每个实现使用的引用,而esp_gatts_api.h包含用于运行蓝牙 GATT 服务器的 API 。

因此 ESP-IDF 不仅提供核心驱动功能,还提供用于高级实现外设的 API。

最后,ESP-IDF 示例参考实际上包含了数百个示例,这些示例来自十几个核心类别,包括以太网、安全、WiFi 和 Zigbee。

将其与 API 参考结合起来,最终形成大量文档,全部直接来自开发人员并定期更新。

在撰写本文时,蓝牙 HID 示例已在上个月更新。

结论

基于 ESP32 无线微控制器的设计可以根据您的产品在不同开发阶段的需求进行定制或方便。

这是一种成本极低的解决方案,受到制造商和产品开发商的欢迎。这种受欢迎程度有助于确保在线提供大量帮助和文档。

ESP32 不仅是构建早期 POC 原型的绝佳选择,而且还是大规模制造的绝佳选择,无论您是使用定制板上的模块还是基于裸 ESP32 芯片设计定制电路。