FritzenLab ESP32-C6 dev board

Esta é a página oficial do produto ESP32-C6 dev board do FritzenLab. Aqui você encontra toda informação sobre a utilização desta placa, pinagens, limites, bibliotecas, onde comprar, etc. Esta placa foi pensada para ser uma ferramenta de desenvolvimento de produtos com WiFi, baseada no novíssimo (2024) chip ESP32-C6 da Espressif.

Quer ver como foi o processo de desenvolvimento desta placa? aqui, aqui e aqui.

O chip ESP32-C6 Xiao pode oferecer conexões WiFi, Bluetooth 5 e Mesh, além de Zigbee. Ele conta com 512kB de memória RAM e 4MB de memória Flash (de programa). Conta com UART, i2c, SP, 11GPIO, 7 ADC e interface para cartão de memória (SDIO). A placa é single core RISC-V podendo rodar até 160MHz.

Diferenciais

A placa tem como diferencial poder ser conectada diretamente na proboard sem ocupar muito espaço (apenas um lado, veja imagem abaixo). Ela conta ainda com regulador de 3,3V integrado (LM1117-3.3), então você pode alimenta-la com 5V. ATENÇÃO: os pinos de IO NÃO SÃO tolerantes a 5V, apenas 3,3V.

Ela ainda pode ser alimentada diretamente por 3,3V ou por bateria (entrada VIN 4,2V). Conta com três periféricos para facilitar sua vida na hora de testar: um sensor de temperatura analógico LM35, um sensor de temperatura/umidade digital DHT11 e um LED endereçável WS2812 (Neopixel).

IMPORTANTE:

  • Se não quiser usar o WS2812 Neopixel, remova o jumper J4
  • Se não quiser usar o sensor DHT11, remova o jumper J3
  • Se não quiser usar o sensor LM35, remova o jumper J2
FritzenLab ESP32-C6 dev board 3D view
FritzenLab ESP32-C6 dev board 3D view
FritzenLab ESP32-C6 dev board em uma protoboard
FritzenLab ESP32-C6 dev board em uma protoboard

Pinagem

Onze (11) pinos de IO são disponibilizados no conector de protoboard da placa, são eles e suas funções:

  • D0:A0:GPIO 0 (digital, analógico A0)
  • D1:A1:GPIO 1 (digital, analógico A1)
  • D2:A2:GPIO 2 (digital, analógico A2)
  • D3:GPIO 21:SDIO_DATA1 (digital, cartão SD)
  • D4:SDA:GPIO 22:SDIO_DATA2 (digital, i2c, cartão SD)
  • D5:SCL:GPIO 23:SDIO_DATA3 (digital, i2c, cartão SD)
  • D6:TX:GPIO 16 (digital, Serial TX)
  • D7:RX:GPIO 17 (digital, Serial RX)
  • D8:SCK:GPIO 19:SDIO_CLK (digital, SPI, cartão SD)
  • D9:MISO:GPIO 20:SDIO_DATA0 (digital, SPI, cartão SD)
  • D10:MOSI:GPIO 18:SDIO_CMD (digital, SPI, cartão SD)
Pinagem da placa de desenvolvimento ESP32-C6
Pinagem da placa de desenvolvimento ESP32-C6

Os periféricos onboard ocupam os seguintes pinos:

  • LM35: A0
  • DHT11: D3
  • WS2812: D4

Lembrando sempre que para poder usar estes pinos para outras funções, remover os jumpers J2, J3 e J4 da placa.

Diagrama esquemático

Todos os arquivos para fabricação desta placa estão neste Github. O diagrama esquemático é visto abaixo.

Diagrama esquemático da placa dev de ESP32-C6 FritzenLab
Diagrama esquemático da placa dev de ESP32-C6 FritzenLab

Note o regulador de tensão 3,3V AMS1117-3.3 e seus capacitores de filtro na entrada e saída. Veja também o filtro RC no pino de sinal do sensor de temperatura LM35. Existe ainda um resistor de pull-up no pino de sinal do sensor DHT11.

Por fim note um resistor limitador de corrente no pino de sinal do LED RGB endereçável WS2812 neopixel, bem como um filtro RC no seu pino de VCC. Agor falando do ESP32, alguns pinos do seu footprint são provenientes do circuito de onde eu me referi, e não são usados aqui. É o caso de SWDIO e SWCLK, bem como +5V, GND e Reset que não estão conectados no diagrama acima.

O diagrama esquemático do módulo Xiao ESP32-C6 está aqui.

Alimentação

Segundo a especificação oficial da SeeedStudio, a placa Xiao ESP32-C6 pode ser alimentada via cabo USB C (não acompanha o produto), ou aplicando-se 5V no pino VIN (até 600mA) ou 5V no pino +5V (até 1A). Pode-se fornecer 3,3V diretamente ao pino 12 do conector para protoboard, com corrente de pelo menos 100mA.

Poderíamos ainda conectar uma bateria de lítio 3,7V (4,2V carregada) nos pinos “Bat” porém NÃO ESTÃO DISPONÍVEIS na minha versão da plca, os pinos ficam por baixo, inacessíveis.

DETALHE: para usar o WS2812 (LED RGB) é necessária alimentação 5V externa, vinda do pino 14 (+5V) do conector principal para protoboard.

O consumo de corrente da placa quando o ESP32-C6 está em “modem-sleep” (sem WiFi) é em torno de 30mA. Já em “deep-sleep” pode baixar de 0,3mA (que é basicamente o consumo do sensor DHT11). O consumo de corrente do LED RGB WS2812 quando ligado é em torno de 33mA, segundo esta fonte.

Configuração de hardware

Ao conectar a placa à uma protoboard para utilização, alguns cuidados precisam ser tomados:

  • Alimentar a placa OU com cabo USB OU +5V ou VIN (5V) ou 3,3V, nunca mais de uma fonte de energia.
  • Caso não for usar o LED RGB WS2812, o sensor LM35 ou o sensor DHT11, remover os respectivos jumpers.
  • Utilizar apenas sensores, atuadores ou módulos que sejam alimentados em 3,3V, a placa não tolera 5V nos pinos GPIO. Alguns módulos de Arduino tem pinos específicos para serem alimentados com 3,3V. Pode-se ainda usar conversores de nível lógico.
  • As entradas analógicas da placa também recebem sinal só até 3,3V.

Programando com Arduino IDE

A placa Xiao ESP32-C6 pode ser programada via IDE do Arduino. Os botões necessários para programação são vistos abaixo.

Botões do ESP32-C6 Xiao. Fonte: https://wiki.seeedstudio.com/xiao_esp32c6_getting_started/
Botões do ESP32-C6 Xiao. Fonte: https://wiki.seeedstudio.com/xiao_esp32c6_getting_started/

Você vai precisar de um cabo USB tipo C para conectar ao computador, bem como a IDE (software) do Arduino instalada. Em Junho de 2024 foi adicionado suporte ao ESP32-C6 na IDE do Arduino. Em “Arquivo > Preferências” coloque a seguinte linha:

https://espressif.github.io/arduino-esp32/package_esp32_dev_index.json

Depois vá em “Ferramentas > Placa > Gerenciador de placas” e digite “ESP32”. Se você tiver alguma placa ESP32 instalada na IDE, remova. Instale o pacote da Espressif com versão pelo menos “3.0.0-rc1” (versões anteriores não tem suporte á placa ESP32-C6).

Conecte o cabo USB C á placa e ao computador. Rode o exemplo “Blink” ou “BlinkWithoutDelay” deixando o pino do LED como “LED_BUILTIN” ou então pino 15, conforme visto abaixo.

Programando em Micropython

Aparentemente até o final de Junho de 2024 não havia suporte oficial para o ESP32-C6 no microPython, segundo esta thread do Github.

Programando em CircuitPython

Existe um port de CircuitPython da Adafruit para a placa ESP32-C6-DevKitC-N4, aqui neste link. O guia oficial da Adafruit sobre como gravar o bootloader na placa está aqui. Vou confirmar se funciona com o Xiao ESP32-C6.

Programando em Swift (Apple)

Segundo esta fonte o ESP32-C6 suporta ser programado em embedded Swift, um subset da linguagem de programação da Apple para seus produtos. Aqui tem um “getting started guide” que faz link para um repositório. No Github linkado tem um exemplo de controle de fita de LED RGB com o ESP32-C6.

Fonte: https://www.cnx-software.com/2024/06/13/embedded-swift-esp32-c6-raspberry-pi-rp2040-stm32f7-nrf52840-microcontrollers/

Selecionando Antena interna ou externa

Esta placa ESP32-C6 Xiao da SeeedStudio tem opção de usar a antena WiFi interna (montada na placa) ou conectar uma externa. Para fazer esta seleção é via software através do pino GPIO14, de acordo com o diagrama esquemático da placa. GPIO14 em 0 utiliza a antena interna (esse é o padrão) e GPIO14 em 1 permite antena externa. A antena é vendida separadamente pela SeeedStudio, aqui.

Use seu ESP32-C6 como modem WiFi para Raspberry Pi

Piscando o LED onboard do ESP32-C6 Xiao

A placa ESP32-C6 que estou utilizando é da linha Xiao da SeeedStudio. Ela tem um LED amarelo onboard (montado na placa), que vamos fazer piscar a partir de agora. Abra a IDE do Arduino mais atualizada (não pode ser as versões 1.8.x), cole o código abaixo.

// constants won't change. Used here to set a pin number:
const int ledPin =  15;// the number of the LED pin

// Variables will change:
int ledState = LOW;             // ledState used to set the LED

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated

// constants won't change:
const long interval = 1000;           // interval at which to blink (milliseconds)

void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the difference
  // between the current time and last time you blinked the LED is bigger than
  // the interval at which you want to blink the LED.
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
}

Observe que coloquei o pino “ledPin” como 15, onde está o LED na nossa placa. Não coloquei o “D” na frente porque este pino não está disponível no conector da protoboard, é um pino “interno”. Ainda poderia ter colocado “LED_BUILTIN”. Então salve o sketch, conecte o cabo USB-C ao ESP32-C6 e faça upload.

Utilizando o sensor analógico LM35 onboard

O sensor de temperatura analógico LM35 (montado na placa) é alimentado com 5V e está conectado ao pino A0 do ESP32-C6. Segundo o manual de referência do chip, os valores analógicos são convertidos para até 4096 (12 bit) inteiros.

O código abaixo lê o valor do LM35 a cada 500ms (meio segundo) e imprime no monitor serial, com velocidade de 115200bps. Minha referência par o código foi este link.

// LM35 is connected to GPIO0 (Analog A0) 
const int LM35Pin = A0;

// variable for storing the potentiometer value
int LM35Value = 0;

void setup() {
  Serial.begin(115200);
  delay(1000);
}

void loop() {
  // Reading potentiometer value
  LM35Value = analogRead(LM35Pin);
  Serial.println(LM35Value);
  delay(500);
}

Sensor de temperatura interno do ESP32-C6

O chip ESP32-C6 tem um sensor de temperatura interno, capaz de mostrar a temperatura do chip com grande precisão entre -10ºC e +80ºC. Seguindo esta referência copie o código abaixo para um arquivo de texto e nomeie-o temp_sensor.h .

/*
 * SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#pragma once

#include <stdint.h>
#include "esp_err.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief temperature sensor range option.
 */
typedef enum {
    TSENS_DAC_L0 = 0, /*!< offset = -2, measure range: 50℃ ~ 125℃, error < 3℃. */
    TSENS_DAC_L1,     /*!< offset = -1, measure range: 20℃ ~ 100℃, error < 2℃. */
    TSENS_DAC_L2,     /*!< offset =  0, measure range:-10℃ ~  80℃, error < 1℃. */
    TSENS_DAC_L3,     /*!< offset =  1, measure range:-30℃ ~  50℃, error < 2℃. */
    TSENS_DAC_L4,     /*!< offset =  2, measure range:-40℃ ~  20℃, error < 3℃. */
    TSENS_DAC_MAX,
    TSENS_DAC_DEFAULT = TSENS_DAC_L2,
} temp_sensor_dac_offset_t;

/**
 * @brief Configuration for temperature sensor reading
 */
typedef struct {
    temp_sensor_dac_offset_t dac_offset;    /*!< The temperature measurement range is configured with a built-in temperature offset DAC. */
    uint8_t clk_div;                        /*!< Default: 6 */
} temp_sensor_config_t;

/**
 * @brief temperature sensor default setting.
 */
#define TSENS_CONFIG_DEFAULT() {.dac_offset = TSENS_DAC_L2, \
                                .clk_div = 6}

/**
 * @brief Set parameter of temperature sensor.
 * @param tsens
 * @return
 *     - ESP_OK Success
 */
esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens);

/**
 * @brief Get parameter of temperature sensor.
 * @param tsens
 * @return
 *     - ESP_OK Success
 */
esp_err_t temp_sensor_get_config(temp_sensor_config_t *tsens);

/**
 * @brief Start temperature sensor measure.
 * @return
 *     - ESP_OK Success
 *     - ESP_ERR_INVALID_ARG
 */
esp_err_t temp_sensor_start(void);

/**
 * @brief Stop temperature sensor measure.
 * @return
 *     - ESP_OK Success
 */
esp_err_t temp_sensor_stop(void);

/**
 * @brief Read temperature sensor raw data.
 * @param tsens_out Pointer to raw data, Range: 0 ~ 255
 * @return
 *     - ESP_OK Success
 *     - ESP_ERR_INVALID_ARG `tsens_out` is NULL
 *     - ESP_ERR_INVALID_STATE temperature sensor dont start
 */
esp_err_t temp_sensor_read_raw(uint32_t *tsens_out);

/**
 * @brief Read temperature sensor data that is converted to degrees Celsius.
 * @note  Should not be called from interrupt.
 * @param celsius The measure output value.
 * @return
 *     - ESP_OK Success
 *     - ESP_ERR_INVALID_ARG ARG is NULL.
 *     - ESP_ERR_INVALID_STATE The ambient temperature is out of range.
 */
esp_err_t temp_sensor_read_celsius(float *celsius);

#ifdef __cplusplus
}
#endif

Coloque o arquivo acima na mesma pasta onde for salvar o arquivo abaixo. Agora faça o download do código abaixo para a placa ESP32-C6, alterando o caminho (URL) da primeira linha para onde no seu computador você salvou temp_sensor.h.

#include "C:\Users\Clovisf\Documents\Fritzenlab\ESP32-S2-Franzinho-WiFi\temp_sensor.h"

void initTempSensor(){
    temp_sensor_config_t temp_sensor = TSENS_CONFIG_DEFAULT();
    temp_sensor.dac_offset = TSENS_DAC_L2;  // TSENS_DAC_L2 is default; L4(-40°C ~ 20°C), L2(-10°C ~ 80°C), L1(20°C ~ 100°C), L0(50°C ~ 125°C)
    temp_sensor_set_config(temp_sensor);
    temp_sensor_start();
}

void setup() {
  Serial.begin(115200);
  initTempSensor();
}

void loop() {
  Serial.print("Temperature: ");
  float result = 0;
  temp_sensor_read_celsius(&result);
  Serial.print(result);
  Serial.println(" °C");
  delay(5000);
}

É esperado que seu monitor serial mostre a temperatura interna do chip da seguinte forma:

Temperatura interna do ESP32-C6 na IDE do Arduino
Temperatura interna do ESP32-C6 na IDE do Arduino

Utilizando sensor de temperatura digital DHT11 onboard

O sensor DHT11 é capaz de fornecer leituras de temperatura e umidade ambientes, de forma digital via apenas um pino. No caso da nossa placa ele está conectado ao pino D3, já contando com resistor de pull-up de 10k Ohm. Já escrevi aqui no blog sobre o DHT11 com o chip ESP32-S2, o código vai ser exatamente o mesmo. O que muda é que vamos definir o pino como 3.

#include "DHT.h"

#define DHTPIN D3     // Digital pin connected to the DHT sensor

// Uncomment whatever type you're using!
#define DHTTYPE DHT11   // DHT 11
//define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
// to 3.3V instead of 5V!
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 3 (on the right) of the sensor to GROUND (if your sensor has 3 pins)
// Connect pin 4 (on the right) of the sensor to GROUND and leave the pin 3 EMPTY (if your sensor has 4 pins)
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

// Initialize DHT sensor.
// Note that older versions of this library took an optional third parameter to
// tweak the timings for faster processors.  This parameter is no longer needed
// as the current DHT reading algorithm adjusts itself to work on faster procs.
DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(115200);
  Serial.println(F("DHTxx test!"));

  dht.begin();
}

void loop() {
  // Wait a few seconds between measurements.
  delay(2000);

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F("°C "));
  Serial.print(f);
  Serial.print(F("°F  Heat index: "));
  Serial.print(hic);
  Serial.print(F("°C "));
  Serial.print(hif);
  Serial.println(F("°F"));
}

Esperamos um resultado no monitor serial conforme imagem abaixo, mostrando umidade em percentual, temperatura em ºC e ºF e sensação térmica.

Saída serial do sensor DHT11 com ESP32-C6
Saída serial do sensor DHT11 com ESP32-C6

Utilizando LED RGB endereçável WS2812 oboard

Esta placa de desenvolvimento de ESP32-C6 conta com um LED RGB endereçável WS2812 montado, conectado ao pino D4. O LED é capaz de reproduzir 16 milhões de cores a pelo menos 400Hz e com 256 níveis de brilho.

LED RGB endereçável WS2812, 6 pinos
LED RGB endereçável WS2812, 6 pinos

O código para teste do LED é visto abaixo. Primeiro é necessária a instalação da biblioteca “Adafruit Neopixel” na IDE do Arduino, em “Sketch > Incluir biblioteca > Gerenciar bibliotecas…”. Minha referência para elaboração dete tutorial é este blog.

#include <Adafruit_NeoPixel.h>      //Adiciona a biblioteca Adafruit NeoPixel
#define D_in D4       //Nomeia o pino 6 do Arduino
#define qtdeLeds 1    //Informa a quantidade de LEDs que serão ligados em cascata
Adafruit_NeoPixel pixels(qtdeLeds, D_in);     //Instancia o objeto "pixels", informando a quantidade e o pino de sinal
void setup() {
  pinMode(D_in, OUTPUT);      //Configura o pino 6 como saída
  pixels.begin();             //Inicia o objeto "pixels"
}
void loop() {
  pixels.clear();      //desliga todos os LEDs
  for(int i=0; i<qtdeLeds; i++){        //para i = 0, se i menor que a quantidade de leds, incremente 1 em i
    pixels.setPixelColor(i, pixels.Color(255, 0, 0));     //liga o led correspondente ao número da variável i na cor vermelha
    pixels.show();      //executa os parâmetros do comando acima
    delay(500);         //Aguarda 500 milissegundos
    
    pixels.setPixelColor(i, pixels.Color(0, 255, 0));     //liga o led correspondente ao número da variável i na cor verde
    pixels.show();      //executa os parâmetros do comando acima
    delay(500);         //Aguarda 500 milissegundos
    
    pixels.setPixelColor(i, pixels.Color(0, 0, 255));     //liga o led correspondente ao número da variável i na cor azul
    pixels.show();      //executa os parâmetros do comando acima
    delay(500);         //Aguarda 500 milissegundos
  }
}

Observe que definimos o pino “D_in” como 4 (pino 4 do ESP32-C6) e “qtdeLeds” como 1, apenas uma unidade na placa. Estamos fazendo um simples código RGB, onde a cada 500ms uma cor (vermelho, verde, azul) é mostrada.

Conectando ao WiFi

Podemos utilizar o mesmo sketch para Arduino de qualquer outro ESP32, para testar o WiFi. O código abaixo escaneia as redes disponíveis, foi inspirado neste artigo.

#include "WiFi.h"

void setup() {
  Serial.begin(115200);

  // Set WiFi to station mode and disconnect from an AP if it was previously connected
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);

  Serial.println("Setup done");
}

void loop() {
  Serial.println("scan start");

  // WiFi.scanNetworks will return the number of networks found
  int n = WiFi.scanNetworks();
  Serial.println("scan done");
  if (n == 0) {
      Serial.println("no networks found");
  } else {
    Serial.print(n);
    Serial.println(" networks found");
    for (int i = 0; i < n; ++i) {
      // Print SSID and RSSI for each network found
      Serial.print(i + 1);
      Serial.print(": ");
      Serial.print(WiFi.SSID(i));
      Serial.print(" (");
      Serial.print(WiFi.RSSI(i));
      Serial.print(")");
      Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN)?" ":"*");
      delay(10);
    }
  }
  Serial.println("");

  // Wait a bit before scanning again
  delay(5000);
}

Como forma de testar a conexão da ESP32-C6 ao WiFi, vamos obter dados de clima no site Open Weather Map, conforme este tutorial.

Testando a comunicação Bluetooth do ESP32-C6

Vamos testar a função de comunicação Bluetooth do chip ESP32-C6 baseados no conteúdo deste blog. Para isso precisamos baixar um aplicativo de celular chamado “nRF Connect for Mobile”, disponível para Android e iPhone. O sketch do ESP32-C6 é visto abaixo e foi inspirado no link anteriormente disponibilizado:

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

void setup() {
  Serial.begin(115200);
  Serial.println("Starting BLE work!");

  BLEDevice::init("MyESP32");
  BLEServer *pServer = BLEDevice::createServer();
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE
                                       );

  pCharacteristic->setValue("Hello World says Neil");
  pService->start();
  // BLEAdvertising *pAdvertising = pServer->getAdvertising();  // this still is working for backward compatibility
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
  pAdvertising->setMinPreferred(0x12);
  BLEDevice::startAdvertising();
  Serial.println("Characteristic defined! Now you can read it in your phone!");
}

void loop() {
  // put your main code here, to run repeatedly:
  delay(2000);
}

Você deve entrar no site https://www.uuidgenerator.net/ para gerar os valores de SERVICE_UUID e CHARACTERISTIC_UUID.

Gerando números aleatórios verdadeiros

Exemplo neste link e com informações do manual de referência técnica. Ao portar a função de números aleatórios para a linguagem do Arduino, a função random() foi sobrescrita já com as características da esp_random(). Isto faz com que a forma de gerar número aleatórios do ESP32 seja idêntica à do Arduino.

void setup() 
{
  Serial.begin(115200);
}
 
void loop() 
{ 
  auto randomNumber0_10 = random(10); // random number between 0-10
  auto randomNumber10_20 = random(10, 20); // random number between 10-20
  Serial.println(randomNumber0_10);     
  Serial.println(randomNumber10_20);
 
  delay(1000);
}

No exemplo acima são gerados e printados no monitor serial dois números aleatórios: um entre 0 e 10 e outro entre 10 e 20. Isso tudo a cada um segundo.

Suporte ao ecossistema Matter

Matter é um protocolo baseado em IP, cujo objetivo é criar coisas conectadas. Tudo isso através do conceito de ioT. Apesar de estar disponível no ecossistema ESP-IDF, segundo este link ainda não é possível usa-lo com a IDE do Arduino. Com ESP-IDF este é um bom recurso para começar, tem firmware prontinho para usar no ESP32-C6.