Início da firmware no núcleo¶
Nesta página, você cria um projeto de firmware, coloca o ESP32 no estado Online no portal e verifica que a parte de rede funciona. Sensores e lógica de aquecimento serão adicionados nos próximos passos.
A abordagem é construída na fachada iDryer::Link. Você descreve o dispositivo com uma estrutura iDryer::Config, chama link.begin() e link.loop() — o núcleo cuida de toda a conexão de rede sozinho.
1. Prepare as ferramentas¶
Você vai precisar:
- VS Code com extensão PlatformIO;
- Cabo USB;
- Rede Wi-Fi
2.4 GHz(ESP32 não funciona com redes apenas5 GHz); - um smartphone com o app iDryer (App Store, Google Play), logado na sua conta do portal iDryer: é por ele que o dispositivo recebe a rede Wi-Fi e é vinculado à conta;
- a biblioteca de núcleo idryer-core;
- o projeto pronto deste capítulo — example/09-cabinet no repositório do tutorial: é de lá que vêm o driver do sensor e os outros arquivos que adiante se propõe copiar.
O que é firmware do controlador e como ele entra na placa — Firmware do controlador.
2. Crie um projeto¶
No PlatformIO, um projeto é uma pasta com estrutura fixa. Crie uma pasta de projeto (por exemplo my-cabinet) e abra-a em VS Code. Dentro devem haver esses arquivos:
my-cabinet/
├── platformio.ini # configurações de build (preencheremos na etapa 4)
├── lib/
│ └── idryer-core/ # biblioteca de núcleo (symlink ou cópia)
└── src/
└── main.cpp # código do dispositivo: Config + setup() + loop()
Todos os fragmentos de código abaixo vão para esses arquivos — cada etapa indica onde. Crie as pastas include/, lib/ e src/ manualmente, se não existirem.
Coloque a biblioteca idryer-core em lib/ — PlatformIO encontra bibliotecas lá automaticamente. A forma mais fácil é fazer um symlink para a biblioteca baixada:
git clone https://github.com/pavluchenkor/idryer-core.git ~/idryer-core
ln -s ~/idryer-core lib/idryer-core
Em vez do symlink, você pode simplesmente copiar a pasta da biblioteca para lib/idryer-core — funciona igual.
Isso também é necessário para a geração de menu (capítulo 6) — o hook procura o gerador dentro de lib/idryer-core/.
3. O Wi-Fi e a vinculação não ficam no código¶
O firmware não tem a senha da rede nem dados da conta. Na primeira inicialização o dispositivo não tem Wi-Fi e espera a configuração: o app iDryer a envia pelo ar (ESPTouch) e depois vincula o dispositivo à sua conta com um token de vinculação de uso único. O core faz tudo isso dentro de s_link.begin() e s_link.loop(); você só segue os passos no app — seção 9.
Como a rede chega ao dispositivo. Uma placa sem rede salva escuta o ar, como um receptor não sintonizado em nenhuma estação. Nesse momento o celular «bate» o nome da rede e a senha no ar — mais ou menos como em código Morse, só que em pacotes Wi-Fi. A placa capta essa transmissão, conecta-se à rede e daí em diante entra nela sozinha a cada ligação. Não são necessários pinos nem fios separados para isso: funciona pela antena padrão da placa, liga-se sozinho enquanto não há rede e dura até 90 segundos.
Se pelo ar não deu certo, existe o caminho com fio: o instalador web install.idryer.org entrega à placa a rede e o token de vinculação por USB — o mesmo que o app faz, só que por cabo. Uma reinicialização comum da placa também ajuda: depois dela ela volta a esperar a configuração.
4. Configure platformio.ini¶
Preencha platformio.ini na raiz do projeto:
[env:cabinet]
platform = espressif32
framework = arduino
board = esp32-c3-devkitm-1
; As bibliotecas do core (MQTT, ArduinoJson, WebSockets, Improv) vêm
; sozinhas de lib/idryer-core/library.json.
; ESPAsyncTCP é o transporte do ESP8266 que vem das dependências do espMqttClient:
; ele não compila no ESP32 e precisa ser excluído.
lib_ignore = ESPAsyncTCP
build_flags =
-DIDRYER_API_BASE='"https://portal.idryer.org/api"'
-DMQTT_BROKER='"mqtt.idryer.org"'
-DMQTT_PORT=8883
-DMQTT_USE_TLS=1
Substitua board pela sua placa (por exemplo, esp32-s3-devkitc-1). Você não precisa especificar idryer-core em lib_deps — ela está em lib/ (etapa 2).
O que estas linhas fazem
Você não lista as dependências do core: o PlatformIO pega de lib/idryer-core/library.json. lib_ignore = ESPAsyncTCP é obrigatório — sem ele o build falha em ESPAsyncTCP.cpp. As flags MQTT_BROKER e MQTT_PORT também são obrigatórias — sem elas o core não compila ('MQTT_BROKER' was not declared).
5. Descreva o dispositivo em Config¶
A seguir tudo acontece em um arquivo — src/main.cpp. Abra-o e escreva o código desta e das próximas etapas.
iDryer::Config é o passaporte do dispositivo. Os sinalizadores has* dizem ao portal o que o dispositivo tem e determinam quais campos de telemetria são publicados.
Para o gabinete aquecido no topo de src/main.cpp
#include <iDryer.h>
static const iDryer::Config CFG = {
.deviceType = iDryer::DeviceType::Unknown, // dispositivo próprio: o cartão é montado pelo manifesto
.unitsCount = 1,
.telemetryPeriodMs = 5000,
.statusPeriodMs = 10000,
.hardwareVersion = "1.0",
.firmwareVersion = "0.1.0",
.model = "DIY Storage Cabinet",
};
static iDryer::Link s_link(CFG);
Sinalizadores has* — é um contrato com o portal
Um campo de telemetria cujo sinalizador correspondente é false não é publicado. Por exemplo, sem hasAirHumidity = true, a umidade não vai para a nuvem, mesmo que você escreva no código. Inclua apenas o que fisicamente existe no dispositivo.
Lista de componentes e sinalizadores — Composição do sistema.
6. Função main mínima¶
No mesmo arquivo após o bloco Config, adicione as funções setup() e loop(). Para o primeiro lançamento é suficiente iniciar o link e rodá-lo em loop():
void setup() {
Serial.begin(115200);
s_link.begin();
// Dispositivo desvinculado no portal: apagar o segredo e aguardar nova vinculação.
s_link.onCommand("revoke", [](JsonObjectConst) { s_link.handleRevoke(); });
}
void loop() {
s_link.loop();
}
s_link.begin() sobe o Wi-Fi, a vinculação e a conexão com o portal. O comando revoke chega do portal quando o dispositivo é desvinculado da conta: handleRevoke() apaga o segredo do dispositivo, e ele fica esperando uma nova vinculação. Os sensores entram no passo Sensores.
Completo src/main.cpp após este capítulo¶
Pegue ambos os blocos acima em um arquivo — este é todo o src/main.cpp nesta etapa:
#include <iDryer.h>
static const iDryer::Config CFG = {
.deviceType = iDryer::DeviceType::Unknown, // dispositivo próprio: o cartão é montado pelo manifesto
.unitsCount = 1,
.telemetryPeriodMs = 5000,
.statusPeriodMs = 10000,
.hardwareVersion = "1.0",
.firmwareVersion = "0.1.0",
.model = "DIY Storage Cabinet",
};
static iDryer::Link s_link(CFG);
void setup() {
Serial.begin(115200);
s_link.begin();
// Dispositivo desvinculado no portal: apagar o segredo e aguardar nova vinculação.
s_link.onCommand("revoke", [](JsonObjectConst) { s_link.handleRevoke(); });
}
void loop() {
s_link.loop();
}
O capítulo anterior mostra o que adicionar e o src/main.cpp completo após as mudanças, para que você sempre veja o quadro geral, não fragmentos dispersos.
7. Flash¶
8. Abra o Serial Monitor¶
Enquanto o dispositivo não tem Wi-Fi, o log fica em silêncio: o core reserva a porta serial para o instalador web (Improv). Os logs ligam assim que o Wi-Fi sobe. Em um dispositivo ainda não vinculado, o log termina assim:
[BOOT] WiFi ok, logs enabled
[INFO ] CLOUD: WiFi connected, IP: 192.168.1.42, RSSI: -55 dBm, …
…
[INFO ] CLOUD: binding-v3: no secret — awaiting pairing token (SETUP)
A última linha é exatamente o que se espera nesta etapa: há rede, não há segredo de vinculação, o dispositivo espera o token do app. Deixe o monitor aberto e vá para o app.
9. Conecte o Wi-Fi e vincule o dispositivo no app¶
- Conecte o celular à rede Wi-Fi em que o dispositivo vai funcionar (
2.4 GHz) e entre no app iDryer com a sua conta do portal. - Na tela inicial, toque em Conectar novo dispositivo — abre o passo Wi-Fi.
- Confira o nome da rede (o app preenche sozinho se a localização estiver ligada), digite a senha e toque em Conectar dispositivo. O app envia a configuração por até 90 segundos; quando o dispositivo entra na rede, aparece Dispositivo conectado. Toque em Avançar.
- No passo Vinculação, toque em Vincular. O app encontra o dispositivo na rede, pega no portal um token de vinculação de uso único, entrega ao dispositivo e espera o portal confirmar que o dispositivo está online.
- Depois de Dispositivo vinculado, ele aparece na lista de dispositivos do portal e do app.
Se o dispositivo já estiver na rede, abra direto o passo Vinculação — toque no chip dele no topo da janela.
Passo Wi-Fi: o app envia a rede ao dispositivo pelo ar.
Passo Vinculação: o app encontrou o dispositivo na rede pelo número de série dele. Dispositivos de outras pessoas são marcados como ocupados.
Pronto: o dispositivo está vinculado à conta e já vai aparecer na lista.
O log mostra a vinculação:
[INFO ] CLOUD: binding-v3: pairing token received (… chars)
[INFO ] CLOUD: binding-v3: activating with pairing token (serial=DEVICE_… mcu=-)
[INFO ] CLOUD: binding-v3: activated, deviceId=… -> Ready
…
[INFO ] MQTT: Connected! …
Verificação de resultado¶
Nesta etapa o dispositivo deve estar Online no portal. Ainda não há dados de sensores — isso é esperado: o Config ainda não declarou nada sobre eles, e o cartão não tem o que mostrar.
Dispositivo no portal: nome, estado Idle, ícone de conexão. Não há leituras — elas aparecem no próximo capítulo.
O nome Device DEVICE_… é o de fábrica. Renomeie o dispositivo pelo lápis ao lado do nome: adiante nos exemplos ele se chama «Storage cabinet».
Se algo deu errado:
- o app não viu o dispositivo entrar na rede — confira a senha e se a rede é
2.4 GHz; com a senha errada o dispositivo volta a esperar a configuração, reinicie a placa e repita o passo Wi-Fi; - a rede não é transmitida pelo ar de jeito nenhum — faça o mesmo por USB através do instalador web install.idryer.org;
- no passo Vinculação o app não encontrou o dispositivo — o celular e o dispositivo precisam estar na mesma rede, e a rede não pode bloquear a descoberta de dispositivos (redes de convidados costumam bloquear);
- o dispositivo reinicia — confira a alimentação do ESP32 (quedas de tensão na partida são uma causa comum de reinícios);
- o build falha com erro — pergunte na comunidade: Telegram, Discord;
- veja Erros de alimentação e Erros do controlador.
O que vem a seguir¶
A parte de rede funciona. Vá para Sensores: vamos conectar SHT31 e termistor e ver seus dados no portal.