Introdução
Na primeira parte deste projeto, coletamos dados de temperatura e umidade utilizando a Franzininho WiFi e o sensor DHT11, treinamos um modelo na plataforma Edge Impulse e o convertemos em um arquivo .tflite pronto para ser implantado no microcontrolador. Neste tutorial, vamos focar em como carregar e utilizar esse modelo na Franzininho WiFi, permitindo que ela realize inferências em tempo real com base nos novos dados coletados.
Importando Biblioteca
Após converter o modelo para o formato .tflite, a plataforma Edge Impulse gera um arquivo .zip. Esse arquivo deve ser importado como uma biblioteca na Arduino IDE. Para isso, siga os passos: vá em “Sketch” > “Include Library” > “Add .ZIP Library” e selecione o arquivo .zip gerado. Após a importação, a biblioteca estará disponível no diretório onde as bibliotecas da Arduino IDE são salvas e poderá ser utilizada no seu projeto.
Lembre-se que ao trabalhar com as placas ESP32s é preciso também instalar na Arduino IDE o suporte ao ESP32. Caso não tenha configurado, vá em“Arduino”> “Preferences” e adicione o seguinte link para as URLs do gerenciador de placas adicionais:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.jsonEm seguida, instale as placas ESP32 no menu do gerenciador de placas.
Código
Compile o código abaixo na sua placa Franzininho. Não se esqueça de trocar “#include <graziele_rodrigues-project-1_inferencing.h>” pelo nome da sua biblioteca.
Este código lê temperatura e umidade com o sensor DHT11, executa inferências com o modelo de machine learning (ML) usando a função run_classifier, e exibe os resultados na Serial com ei_printf. Os dados do dht são lidos e armazenados no buffer (timestamp, temperatura e umidade), seguindo a ordem original para alimentar o modelo ML.
/* Includes ---------------------------------------------------------------- */
#include <DHT.h>
#include <graziele_rodrigues-project-1_inferencing.h>
#define DHTPIN 15 // Pino digital conectado ao sensor DHT
#define DHTTYPE DHT11 // Tipo de sensor DHT
DHT dht(DHTPIN, DHTTYPE);
#define FREQUENCY_HZ 50
#define INTERVAL_MS (1000 / (FREQUENCY_HZ + 1))
/* Private variables ------------------------------------------------------- */
static bool debug_nn = false; // Set this to true to see e.g. features generated from the raw signal
static unsigned long last_interval_ms = 0;
void setup()
{
// put your setup code here, to run once:
Serial.begin(115200);
// comment out the below line to cancel the wait for USB connection (needed for native USB)
while (!Serial);
Serial.println("Edge Impulse Inferencing Demo");
Serial.println(F("Inicializando DHT..."));
dht.begin();
if (EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME != 2) {
ei_printf("ERR: EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME deve ser ter temperatura e umidade)\n");
return;
}
}
void loop()
{
if (millis() > last_interval_ms + INTERVAL_MS) {
last_interval_ms = millis();
ei_printf("\nIniciando inferência...\n");
// Allocate a buffer here for the values we'll read from the DHT sensor
float buffer[EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE] = { 0 };
for (size_t ix = 0; ix < EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE; ix += 3) {
// Captura o timestamp
buffer[ix + 0] = (float)millis();
// Obter a próxima leitura de umidade e temperatura
float h = dht.readHumidity();
float t = dht.readTemperature();
// Verifica se a leitura falhou
if (isnan(h) || isnan(t)) {
ei_printf("Falha ao ler o sensor DHT!\n");
return;
}
// Preencher o buffer com os valores de temperatura e umidade
buffer[ix + 1] = t;
buffer[ix + 2] = h;
}
// Transformar o buffer bruto em um sinal para classificar
signal_t signal;
int err = numpy::signal_from_buffer(buffer, EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, &signal);
if (err != 0) {
ei_printf("Falha ao criar sinal do buffer (%d)\n", err);
return;
}
// Executar o classificador
ei_impulse_result_t result = { 0 };
err = run_classifier(&signal, &result, debug_nn);
if (err != EI_IMPULSE_OK) {
ei_printf("ERR: Falha ao executar classificador (%d)\n", err);
return;
}
// Imprimir as previsões com timestamp
ei_printf("Timestamp: %lu ms\n", millis());
ei_printf("Previsões ");
ei_printf("(DSP: %d ms., Classificação: %d ms., Anomalia: %d ms.)",
result.timing.dsp, result.timing.classification, result.timing.anomaly);
ei_printf(": \n");
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
ei_printf(" %s: %.5f\n", result.classification[ix].label, result.classification[ix].value);
}
}
}
Se ao compilar apresentar algum erro será necessário abrir o arquivo “ei_classifier_config.h” que está no diretório “\Arduino\libraries\nome-sua-biblioteca\src\edge-impulse-sdk\classifier e mudar “EI_CLASSIFIER_TFLITE_ENABLE_ESP_NN 1” por “EI_CLASSIFIER_TFLITE_ENABLE_ESP_NN 0”.
Após a compilação completa, sem a presença de erro podemos gravar na Franzininho Wifi. Coloque a sua placa em modo bootloader (explicação aqui), escolha para Board Selection Franzininho Wifi, PSRAM como Enabled e Upload Speed 115200.
Resultado
Para testar o funcionamento, usei um pano úmido sobre o DHT11. Ao colocá-lo, a probabilidade de anomalia aumenta significativamente, chegando a 0.99609. Quando retiro o pano, o ambiente volta a ser classificado como normal, indicando que o modelo está respondendo corretamente às mudanças de umidade.
Esse projeto pode ser encontrado no GitHub: https://github.com/Graziele-Rodrigues/TinyML_FranzininhoWifi/tree/main/qualidadeAr
Conclusão
Este tutorial mostrou como implementar inferências usando o nosso modelo criado na parte 1. Embora esse tenha sido um exemplo simples do uso da inferência, a mesma abordagem pode ser aplicada a diversas outras situações. Por exemplo, o modelo pode ser ajustado para detectar falhas em sistemas de ventilação, monitorar a qualidade do ar ou identificar condições ambientais específicas em processos industriais.







