2024 05 30 f2ceb61904e09 Saravati

TinyML no ESP32-S3 UNO: reconhecimento de gestos e sons

Neste tutorial, você vai aprender como implementar um sistema de reconhecimento de gestos (usando o sensor APDS‑9960) e de sons (microfone mini) diretamente em um ESP32, aproveitando o poder do TinyML com TensorFlow Lite for Microcontrollers.

 ESP32-S3 UNO

1. Visão geral do projeto

  1. Coleta de dados
    • Gestos: movimentos da mão (↑, ↓, ←, →) pelo APDS‑9960.
    • Sons: cliques e estalos captados pelo microfone MAX9814.
  2. Treinamento TinyML
    • Criação de dataset anotado.
    • Treinamento de rede leve em Python/Colab.
    • Conversão para TensorFlow Lite for Microcontrollers (TFLM).
  3. Firmware no ESP32
    • Integração das bibliotecas do TFLM.
    • Leitura do sensor e inferência em tempo real.

Ao final, você terá um dispositivo capaz de reconhecer gestos de mão e detectar cliques, podendo acionar LEDs, relés ou enviar dados via MQTT para dashboards web.

2. Materiais necessários

Item
Placa ESP32‑S3 UNO
Sensor de gestos APDS‑9960
Módulo microfone MAX9814
Cabo USB‑C para ESP32
Protoboard
Jumpers
Computador com Python e Google Colab

3. Coleta de dados

Preparando o ESP32 para captura

  1. Instale a ESP-IDF ou Arduino IDE com suporte ao ESP32‑S3.
  2. Conecte o sensor APDS‑9960 e o módulo MAX9814 à protoboard: ESP32‑S3 UNO APDS‑9960 MAX9814 ───────────── ───────────── ──────────── 3.3 V VCC VCC GND GND GND SDA (GPIO21) SDA SCL (GPIO22) SCL OUT (A0) — (não será usado aqui) GPIO34 — OUT
  3. Abra um sketch Arduino para coletar dados brutos: #include <Wire.h> #include "SparkFun_APDS9960.h" SparkFun_APDS9960 apds = SparkFun_APDS9960(); const int micPin = 34; void setup() { Serial.begin(115200); Wire.begin(); apds.init(); apds.enableGestureSensor(true); } void loop() { if (apds.isGestureAvailable()) { uint8_t gesture = apds.readGesture(); Serial.print("Gesto: "); Serial.println(gesture); } int micValue = analogRead(micPin); Serial.print("Microfone: "); Serial.println(micValue); delay(100); }
  4. No monitor serial, registre sequências de gestos (por exemplo 20 repetições de cada direção) e cliques (bater palmas ou pressionar um interruptor próximo ao microfone) em arquivos .csv. Nomeie colunas como label e feature_1, feature_2, ….

4. Treinamento TinyML

Ambiente de desenvolvimento

  1. Crie um notebook Google Colab com ambiente Python 3.x.
  2. Instale bibliotecas: !pip install numpy pandas tensorflow matplotlib

Preparando o dataset

  1. Faça o upload dos arquivos .csv coletados.
  2. Carregue os dados em um DataFrame Pandas: import pandas as pd df = pd.read_csv('gestos.csv') df_sounds = pd.read_csv('sons.csv')
  3. Combine e normalize features: from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler X = pd.concat([df.drop('label', axis=1), df_sounds.drop('label', axis=1)]) y = pd.concat([df['label'], df_sounds['label']]) scaler = StandardScaler() X_norm = scaler.fit_transform(X) X_train, X_test, y_train, y_test = train_test_split( X_norm, y, test_size=0.2, stratify=y)

Definindo e treinando o modelo

import tensorflow as tf

model = tf.keras.Sequential([
    tf.keras.layers.Input(shape=(X_train.shape[1],)),
    tf.keras.layers.Dense(32, activation='relu'),
    tf.keras.layers.Dense(16, activation='relu'),
    tf.keras.layers.Dense(len(y.unique()), activation='softmax')
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

history = model.fit(X_train, y_train, epochs=30,
                    validation_data=(X_test, y_test))
print("Acurácia final:", history.history['val_accuracy'][-1])

Conversão para TensorFlow Lite Micro

converter = tf.lite.TFLiteConverter.from_keras_model(model)
# Quantização inteira para microcontroladores
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_model = converter.convert()
with open('modelo_gestos_sons.tflite', 'wb') as f:
    f.write(tflite_model)

5. Integração no firmware do ESP32

Preparando bibliotecas

Sketch completo de inferência

#include "tensorflow/lite/micro/all_ops_resolver.h"
#include "tensorflow/lite/micro/micro_error_reporter.h"
#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/schema/schema_generated.h"
#include "modelo_gestos_sons_data.h"  // gerado pelo xxd

// Reservar memória para o interpreter
const int kTensorArenaSize = 8 * 1024;
uint8_t tensor_arena[kTensorArenaSize];

void setup() {
  Serial.begin(115200);
  // Inicializar sensores (APDS‑9960 e MAX9814)
  // ...
}

void loop() {
  float input_data[NUM_FEATURES];
  // Preencher input_data com leituras dos sensores
  // input_data[0..X] = ...
  
  // Configurar interpreter
  static tflite::MicroErrorReporter micro_error_reporter;
  static tflite::AllOpsResolver resolver;
  const tflite::Model* model = tflite::GetModel(modelo_gestos_sons_tflite);
  static tflite::MicroInterpreter interpreter(
      model, resolver, tensor_arena, kTensorArenaSize, &micro_error_reporter);
  interpreter.AllocateTensors();

  // Preencher tensor de entrada
  float* input = interpreter.input(0)->data.f;
  for (int i = 0; i < NUM_FEATURES; ++i) input[i] = input_data[i];

  // Executar inferência
  interpreter.Invoke();
  float* output = interpreter.output(0)->data.f;

  // Encontrar maior probabilidade
  int prediction = max_element(output, output + NUM_CLASSES) - output;
  Serial.print("Predição: ");
  Serial.println(prediction);
  
  delay(200);
}

Testando e ajustando

  1. Faça upload do sketch e abra o monitor serial.
  2. Execute gestos e clique perto do microfone; observe as predições.
  3. Se necessário, colete mais dados e refine o modelo.

Dicas de otimização

  • Reduza a complexidade: experimente camadas menores (8→8→N) para caber em menos memória.
  • Quantização agressiva: aplique quantização de peso e ativação para 8 bits.
  • Pré‑processamento on‑chip: mova filtragens ou médias móveis para o firmware, reduzindo variância de entrada.

Conclusão e próximos passos

Você criou um sistema TinyML completo: coleta de dados, treinamento, conversão e deploy em um ESP32‑S3 UNO, utilizando sensores adquiridos na Saravati. Com essa base, é possível expandir para:

  • Reconhecimento de mais gestos ou sons complexos.
  • Envio de eventos por Wi‑Fi/MQTT para dashboards ou apps móveis.
  • Integração com atuadores (motores, LEDs, relés).

Para continuar evoluindo seus projetos, acesse nosso catálogo completo em saravati.com.br e encontre todos os componentes necessários, de microcontroladores a sensores e módulos de comunicação. Qualquer dúvida ou sugestão, deixe um comentário no blog!