Parte 1 · Prática

Classificação de Gestos
com TinyML

Treine um modelo de redes neurais no PC, converta para TensorFlow Lite Micro e execute inferência em tempo real no Arduino Nano 33 BLE Sense.

🤖 TensorFlow Lite Micro 📡 IMU LSM9DS1 ⚡ Inferência int8 🐍 Python + Keras 🔵 Arduino Nano 33 BLE Sense
Começar tutorial ↓ Tutorial oficial Arduino ↗

O que vamos construir?

Um classificador de gestos que usa o acelerômetro e giroscópio do Arduino Nano 33 BLE Sense para reconhecer 3 movimentos (punch, flex e idle) diretamente no microcontrolador — sem conexão com a internet, sem servidor externo.

📊
Coleta IMU → CSV
🧠
Treinamento Keras · Python
🔧
Conversão TFLite int8
📋
Deploy .h → Arduino
Inferência Edge · Tempo real
1

Preparar ambiente

Instalar bibliotecas Arduino e configurar o Python virtual env.

2

Coletar dados IMU

Gravar amostras de gestos com coleta_dados.ino e salvar em CSV.

3

Treinar o modelo

Executar o notebook 01_treinamento_tensorflow.ipynb com Keras.

4

Converter para TFLite

Quantizar para int8 com o notebook 02_conversao_tflite.ipynb.

5

Gerar arquivos .h

Exportar model_data.h e norm_params.h para o Arduino.

6

Flash e inferência

Compilar inferencia_gestos.ino e testar gestos em tempo real.

Estrutura de arquivos

Organize os arquivos desta forma antes de começar:

tinyml/
  ├── arduino/
  │   ├── coleta_dados/
  │   │   └── coleta_dados.ino  ← sketch de coleta
  │   └── inferencia_gestos/
  │       ├── inferencia_gestos.ino  ← sketch principal
  │       ├── model_data.h  ← gerado pelo notebook 02
  │       └── norm_params.h  ← gerado pelo notebook 02
  ├── dados/
  │   ├── punch.csv
  │   ├── flex.csv
  │   └── idle.csv
  ├── notebooks/
  │   ├── 01_treinamento_tensorflow.ipynb
  │   └── 02_conversao_tflite.ipynb
  └── outputs/  ← modelos gerados

Bibliotecas necessárias

Arduino (Library Manager)

Arduino_LSM9DS1 v1.1.1+

Driver oficial para o IMU integrado (acelerômetro + giroscópio + magnetômetro).

Harvard_TinyMLx v1.2.2+

Biblioteca do curso de TinyML de Harvard/Google com TensorFlow Lite Micro já empacotado. Buscar por "TinyMLibrary" ou "Harvard" na Library Manager.

⚠️ Atenção — versão da biblioteca

Utilizar a Harvard_TinyMLx (não a "Arduino_TensorFlowLite" original). O construtor MicroInterpreter dessa versão exige 5 argumentos, incluindo um ErrorReporter*. O sketch inferencia_gestos.ino já está adaptado para essa API.

Python (venv)

# Ativar o ambiente virtual
source env/bin/activate

# Instalar dependências principais
pip install tensorflow numpy pandas scikit-learn matplotlib
Pacote Finalidade Versão testada
tensorflowTreinamento Keras + conversão TFLite2.x / 2.16
numpyManipulação de arrays e normalização1.26+
pandasLeitura e pré-processamento dos CSV2.x
scikit-learnTrain/test split e métricas1.4+
matplotlibVisualização dos resultados3.8+

Passo a passo completo

Siga as etapas abaixo na ordem indicada.

1

Instalar as bibliotecas no Arduino IDE

Abra o Arduino IDE, vá em Sketch → Include Library → Manage Libraries… e instale:

  • Arduino_LSM9DS1 — buscar por "LSM9DS1"
  • Harvard_TinyMLx — buscar por "TinyMLibrary" ou "Harvard"
💡 Dica

Após instalar, reinicie o Arduino IDE para que as bibliotecas sejam reconhecidas corretamente.

2

Coletar amostras de gestos

Carregue o sketch coleta_dados.ino no Arduino Nano 33 BLE Sense. Abra o Serial Monitor a 115200 baud e realize cada gesto conforme solicitado. Os dados IMU (aX, aY, aZ, gX, gY, gZ) serão impressos no monitor.

Use o script salvar_dados.py para capturar e salvar automaticamente em dados/punch.csv, dados/flex.csv e dados/idle.csv:

# Ativar venv
source env/bin/activate

# Salvar amostras (ajuste a porta serial conforme seu sistema)
python salvar_dados.py --porta /dev/ttyACM0 --gesto punch --amostras 50
python salvar_dados.py --porta /dev/ttyACM0 --gesto flex  --amostras 50
python salvar_dados.py --porta /dev/ttyACM0 --gesto idle  --amostras 50
ℹ️ Janela de 119 amostras

Cada janela de captura contém 119 leituras × 6 features (aX·aY·aZ·gX·gY·gZ), totalizando 714 valores por amostra. Esse valor está definido em norm_params.h como kNumSamples.

3

Treinar o modelo com Keras

Com o ambiente virtual ativado, abra o Jupyter e execute o notebook:

jupyter notebook notebooks/01_treinamento_tensorflow.ipynb

O notebook realiza:

  • Carregamento e pré-processamento dos CSV
  • Normalização Z-score por feature (salva norm_mean.npy / norm_std.npy)
  • Definição de uma rede densa (Dense → Dense → Softmax)
  • Treinamento com EarlyStopping e ModelCheckpoint
  • Avaliação e matriz de confusão

Ao final, o modelo é salvo em outputs/best_model.keras.

4

Converter para TensorFlow Lite int8

Execute o segundo notebook:

jupyter notebook notebooks/02_conversao_tflite.ipynb

O notebook automaticamente:

  • Carrega o modelo Keras salvo
  • Aplica quantização inteira (int8) com dataset representativo
  • Salva outputs/gesture_int8.tflite
  • Gera arduino/inferencia_gestos/model_data.h com o modelo como array C
  • Gera arduino/inferencia_gestos/norm_params.h com médias e desvios padrão
ℹ️ Por que int8?

A quantização reduz o modelo de float32 para 8 bits, diminuindo o tamanho em ~4× e acelerando a inferência no Cortex-M4 do Nano 33 BLE Sense, que não possui FPU de 64 bits.

5

Verificar os arquivos gerados

Confirme que os três arquivos coexistem na pasta arduino/inferencia_gestos/:

inferencia_gestos/
  ├── inferencia_gestos.ino
  ├── model_data.h  ← array do modelo int8
  └── norm_params.h  ← kNormMean, kNormStd, kNumSamples…

Abra norm_params.h e confirme que kNumSamples, kNumFeatures e kNumClasses batem com o que foi usado no treinamento.

6

Compilar e fazer upload para o Arduino

No Arduino IDE, abra arduino/inferencia_gestos/inferencia_gestos.ino. Selecione a placa correta:

  • Placa: Arduino Nano 33 BLE (Tools → Board → Arduino Mbed OS Nano Boards)
  • Porta: selecione a porta USB correspondente (/dev/ttyACM0 no Linux)
// Pressione Ctrl+U para compilar e fazer upload
⚠️ Erro de compilação — micro_interpreter.h

Se aparecer erro sobre número de argumentos no construtor MicroInterpreter, certifique-se de estar usando a biblioteca Harvard_TinyMLx (não Arduino_TensorFlowLite) e que o sketch declara um tflite::MicroErrorReporter passado como 5º argumento.

7

Testar a inferência em tempo real

Abra o Serial Monitor a 115200 baud. O Arduino aguardará um movimento brusco (threshold = 2,5 g) como gatilho, capturará 119 amostras, normalizará, e imprimirá o resultado:

====================================
  TinyML — Classificador de Gestos
  Arduino Nano 33 BLE Sense
====================================
  Modelo:      12748 bytes
  Arena:       32 KB
  Input dim:   714
  Classes:     punch, flex, idle
====================================
Realizando gestos — aguardando...

→ Gesto: punch  (94.3%)  |  tempo de inferência: 18.42 ms
   Scores: punch=94.3%  flex=3.1%  idle=2.6%

O LED RGB indica visualmente: vermelho = punch, verde = flex, azul = idle, amarelo = incerto.

Erros comuns

Erro Causa provável Solução
micro_log.h: No such file Header inexistente na Harvard_TinyMLx Remover a linha #include "tensorflow/lite/micro/micro_log.h"
MicroInterpreter expects 6 arguments API diferente entre versões da lib Passar error_reporter como 5º arg; usar MicroErrorReporter
TFLITE_SCHEMA_VERSION not declared Constante ausente na Harvard_TinyMLx Substituir verificação por if (model == nullptr)
Classificação sempre "idle" Normalização inconsistente Confirmar que norm_params.h foi gerado com os mesmos dados de treino
IMU não inicializa Biblioteca errada ou placa incorreta Verificar se a placa selecionada é "Arduino Nano 33 BLE" (não "Nano 33 IoT")
AllocateTensors() failed Arena de 32 KB insuficiente Aumentar kTensorArenaSize para 48 * 1024