Com començar amb el desenvolupament del microprogramari ESP32
Table of Contents
Un ESP32 és un SoC petit i barat amb capacitats natives de WiFi i Bluetooth (amb LE). Tenen tots els sabors i mides, però normalment semblen una cosa així (a la meva mà per a referència de mida):

Aquesta versió específica que tinc és una imitació xinesa de this model que vaig trobar a aliexpress. Vaig comprar un paquet de 10 per uns 70 USD. Utilitza el xip ESP32-WROOM-32D i té un connector USB-C, així com un LED integrat fixat a GPIO-2 (etiquetat D2 a la placa). Això és molt útil per fer proves.
De totes maneres, quan escriu codi per a l'ESP32, hi ha 4 camins diferents que pots triar per baixar.
- Escriu codi C amb
esp-idf - Escriu codi micropython
- Escriu el codi C++ amb C externs i devolucions de trucada (també amb
esp-idf) - Escriu codi Arduino
L'objectiu d'aquest article és analitzar els punts forts i febles de cada mètode per decidir quin és el millor per a tu.
Estàndard C
Escriure en C és una gran opció per al desenvolupament de microprogramari en aquest xip. L'SDK, esp-idf, està ben documentat i robust. Escriure en C, però, significa gestió manual de la memòria, codi difícil de llegir i un paradigma de programació no objectiu. El que obteniu fer amb C és codi eficient i accés directe al maquinari. Aquí teniu un exemple senzill de parpelleig de tipus Hello-world utilitzant codi C:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "led_strip.h"
#include "sdkconfig.h"
static const char *TAG = "example";
#define BLINK_GPIO 2
static uint8_t s_led_state = 0;
static void blink_led(void) {
gpio_set_level(BLINK_GPIO, s_led_state);
}
static void configure_led(void) {
ESP_LOGI(TAG, "Example configured to blink GPIO LED!");
gpio_reset_pin(BLINK_GPIO);
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
}
void app_main(void) {
configure_led();
while (1) {
ESP_LOGI(TAG, "Turning the LED %s!", s_led_state == true ? "ON" : "OFF");
blink_led();
s_led_state = !s_led_state;
vTaskDelay(CONFIG_BLINK_PERIOD / portTICK_PERIOD_MS);
}
}
Micropython
Micropython és un port de CPython destinat a executar-se en SoC com ESP32. Penseu-hi com un subconjunt de Python 3 tradicional. Perquè això funcioni, haureu de flashejar un microprogramari Micropython proporcionat al xip, que us proporciona una REPL interactiva mitjançant una connexió UART. També és possible utilitzar una eina anomenada adafruit-ampy per copiar fitxers al sistema de fitxers perquè s'executin a l'arrencada del xip en lloc de generar simplement un REPL, però podeu fer la vostra pròpia investigació si ho voleu.
Tinc sentiments contradictoris a Micropython. D'una banda, és amb diferència (per a mi) la manera més senzilla de programar un ESP32 per fer tasques senzilles com fer peticions http. No obstant això, té un accés limitat al maquinari, depèn molt dels paquets preconstruïts i, a causa de la necessitat d'un intèrpret (el microprogramari Micropython), també és molt limitat en la mida dels programes i la memòria que té disponible.
Aquí teniu el mateix exemple de parpelleig, escrit en Micropython:
import machine
import time
led = machine.Pin(2, machine.Pin.OUT)
while True:
led.value(1)
time.sleep(1)
led.value(0)
time.sleep(1)
Com podeu veure, és increïblement senzill de llegir i entendre, cosa que el fa molt atractiu per als nous usuaris.
C++
Això és estrany. Com que C++ és un superconjunt de C per disseny, és possible escriure codi a C++ i fer-lo servir esp-idf de la mateixa manera que ho fa el C normal. Malauradament, hi ha algunes coses que cal tenir en compte.
- La gestió dinàmica de la memòria C++ pot ser un inconvenient a causa dels recursos limitats a bord
- Haureu d'utilitzar declaracions externes per integrar-vos amb
esp-idf - Les coses es tornen complicades quan es barregen les dues llengües
Aquí teniu el mateix exemple de parpelleig, escrit a C++:
#ifdef __cplusplus
extern "C" {
#endif
#include <esp_log.h>
#include <string>
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#ifdef __cplusplus
}
#endif
static char tag[] = "cpp_helloworld";
extern "C"
{
void app_main(void);
}
class Blink
{
public:
Blink(gpio_num_t blinkPin)
{
this->blinkPin = blinkPin;
gpio_pad_select_gpio(blinkPin);
gpio_set_direction(blinkPin, GPIO_MODE_OUTPUT);
}
void blinkTimes(int x)
{
ESP_LOGD(tag, "Blink Times %d", x);
int delayMs = 50;
int level = gpio_get_level(blinkPin);
gpio_set_level(blinkPin, 0);
vTaskDelay(1000 / delayMs);
for (int i = 0; i < x; i++)
{
gpio_set_level(blinkPin, 1);
vTaskDelay(1000 / delayMs);
gpio_set_level(blinkPin, 0);
vTaskDelay(1000 / delayMs);
}
gpio_set_level(blinkPin, level);
}
private:
gpio_num_t blinkPin = GPIO_NUM_2;
};
void app_main(void)
{
vTaskDelay(1);
Blink blink(GPIO_NUM_2);
blink.blinkTimes(5);
}
Arduino
Arduino és estrany i encara no ho entenc del tot. Arduino com a llenguatge és un embolcall i una capa d'abstracció posada sobre C. La gran part d'arduino són les seves extenses biblioteques i suport, a més de ser extremadament senzill. El nucli arduino proporciona gairebé totes les capacitats de esp-idf, amb la sintaxi agradable i fàcil de llegir d'arduino. Els inconvenients d'això són força abstractes i una mica polèmics. L'argument principal que he vist en contra de l'ús d'arduino per escriure codi ESP32 és que pot arribar a ser una càrrega quan s'escriu un codi extens, normalment girant al voltant d'un argument contra les funcions setup() i loop().
Aquí teniu el mateix exemple, però en arduino:
const int ledPin = 2;
void setup() {
pinMode (ledPin, OUTPUT);
}
void loop() {
digitalWrite (ledPin, HIGH);
delay(1000);
digitalWrite (ledPin, LOW);
delay(1000);
}
TL;DR
- Escriure en C és la manera viril i fresc de fer les coses", però és un mal de cul.
- Escriure en C++ és el mateix que C, però per a persones que són "massa cool per a C normal".
- Escriure en micropython és ideal per a projectes petit i senzill, com ara fer una sol·licitud HTTP ràpida.
- Escriure en Arduino és principalment el mateix que C, però sense els aspectes viril i fresc, i és immensament més fàcil d'utilitzar i té una comunitat més gran.