Introdução
Na primeira parte deste projeto, realizamos a coleta dos dados e o treinamento do modelo de machine learning capaz de identificar diferentes tipos de movimento. Agora, na parte 2, vamos realizar a integração na Franzininho WiFi. Utilizando os novos dados lidos pelo acelerômetro LIS3DH, nosso objetivo é classificar movimentos como “caminhando”, “parado” e “pulando” em tempo real. Para tornar o feedback visual, três LEDs serão utilizados para indicar o movimento detectado.
Funcionamento Esperado
- O acelerômetro LIS3DH será configurado para operar em modo normal com uma taxa de amostragem de 50 Hz.
- Os dados dos eixos X, Y e Z serão lidos continuamente e armazenados em um buffer.
- O classificador de machine learning processará esses dados para identificar o tipo de movimento.
- Dependendo do resultado da inferência:
- O LED vermelho acenderá para indicar “caminhando”.
- O LED azul será ativado para “pulando”.
- O LED verde representará “parado”.
- Se a confiança da predição for baixa, todos os LEDs permanecerão apagados.
Hardware Necessário
Conexões:
- LIS3DH:
- MOSI: Pino 35
- MISO: Pino 37
- CLK: Pino 36
- CS: Pino 34
- LED RGB:
- Vermelho (caminhando): Pino 14
- Azul (pulando): Pino 12
- Verde (parado): Pino 13
Importando Modelo ML
Na etapa 1, após o treinamento do modelo, realizamos o deploy, que gerou um arquivo ZIP contendo o modelo treinado. Para integrá-lo ao seu projeto na Arduino IDE, importe esse arquivo como uma biblioteca. Para isso, vá em Sketch > Include Library > Add .ZIP Library e selecione o arquivo ZIP correspondente ao modelo.
Código
Carregue o seguinte código em sua placa. Para isso, coloque a Franzininho Wifi em modo bootloader (explicação aqui). Depois escolha para Board Selection Franzininho Wifi, PSRAM como Enabled e Upload Speed 115200.
#include <accel_inferencing.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_LIS3DH.h>
#include <Adafruit_Sensor.h>
static bool debug_nn = false; // Set this to true to see e.g. features generated from the raw signal
#define LIS3DH_CLK 36
#define LIS3DH_MISO 37
#define LIS3DH_MOSI 35
#define LIS3DH_CS 34
#define LED_VERMELHO 14 // LED vermelho para "caminhando"
#define LED_AZUL 12 // LED azul para "pulando"
#define LED_VERDE 13 // LED verde para "parado"
// software SPI
Adafruit_LIS3DH lis = Adafruit_LIS3DH(LIS3DH_CS, LIS3DH_MOSI, LIS3DH_MISO, LIS3DH_CLK);
void setup(void) {
Serial.begin(115200);
// Inicializa LEDs
pinMode(LED_VERMELHO, OUTPUT);
pinMode(LED_AZUL, OUTPUT);
pinMode(LED_VERDE, OUTPUT);
// Apaga todos os LEDs inicialmente
digitalWrite(LED_VERMELHO, LOW);
digitalWrite(LED_AZUL, LOW);
digitalWrite(LED_VERDE, LOW);
if (!lis.begin(0x18)) {
Serial.println("Couldn't start");
while (1) yield();
}
lis.setRange(LIS3DH_RANGE_2_G); // 2, 4, 8 or 16 G
lis.setPerformanceMode(LIS3DH_MODE_NORMAL); //LIS3DH_MODE_LOW_POWER, LIS3DH_MODE_NORMAL, LIS3DH_MODE_HIGH_RESOLUTION
lis.setDataRate(LIS3DH_DATARATE_50_HZ); //1Hz (1 leitura por segundo), 10Hz, 25Hz, 50Hz, 100Hz, 200Hz, 400Hz, POWERDOWN, LOWPOWER_5KHZ, LOWPOWER_1K6HZ
if (EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME != 3) {
ei_printf("ERR: EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME should be equal to 3 (the 3 sensor axes)\n");
return;
}
}
void loop() {
ei_printf("\nClassificacao inicia em 2 segundos...\n");
delay(2000);
ei_printf("Sampling...\n");
// buffer para leitura acelerometro
float buffer[EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE] = { 0 };
for (size_t ix = 0; ix < EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE; ix += 3) {
// proximo next tick
uint64_t next_tick = micros() + (EI_CLASSIFIER_INTERVAL_MS * 1000);
// captura accel X, Y e Z em m/s^2
sensors_event_t event;
lis.getEvent(&event);
Serial.println("----------- Aceleracoes lidas -----------");
Serial.print(event.acceleration.x);
Serial.print(",");
Serial.print(event.acceleration.y);
Serial.print(",");
Serial.println(event.acceleration.z);
// coloca leituras no buffer
buffer[ix + 0] = event.acceleration.x;
buffer[ix + 1] = event.acceleration.y;
buffer[ix + 2] = event.acceleration.z;
delayMicroseconds(next_tick - micros());
}
// Turn the raw buffer in a signal which we can the classify
signal_t signal;
int err = numpy::signal_from_buffer(buffer, EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, &signal);
if (err != 0) {
ei_printf("Failed to create signal from buffer (%d)\n", err);
return;
}
// roda classificador
ei_impulse_result_t result = { 0 };
err = run_classifier(&signal, &result, debug_nn);
if (err != EI_IMPULSE_OK) {
ei_printf("ERR: Failed to run classifier (%d)\n", err);
return;
}
// predicoes
ei_printf("Predictions ");
ei_printf("(DSP: %d ms., Classification: %d ms., Anomaly: %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);
}
// Controle dos LEDs com base nas predições
if (result.classification[0].value > 0.8) { // Label "caminhando"
digitalWrite(LED_VERDE, LOW);
digitalWrite(LED_VERMELHO, HIGH);
digitalWrite(LED_AZUL, LOW);
} else if (result.classification[1].value > 0.8) { // Label "parado"
digitalWrite(LED_VERDE, HIGH);
digitalWrite(LED_VERMELHO, LOW);
digitalWrite(LED_AZUL, LOW);
} else if (result.classification[2].value > 0.8) { // Label "pulando"
digitalWrite(LED_VERDE, LOW);
digitalWrite(LED_VERMELHO, LOW);
digitalWrite(LED_AZUL, HIGH);
} else {
// Se nenhuma predição for suficientemente alta, desliga todos os LEDs
digitalWrite(LED_VERDE, LOW);
digitalWrite(LED_VERMELHO, LOW);
digitalWrite(LED_AZUL, LOW);
}
}
Lembre-se de substituir o nome da biblioteca pelo nome do arquivo que você importou. Caso ocorra algum erro durante a compilação, será necessário editar o arquivo "ei_classifier_config.h", localizado no diretório \Arduino\libraries\nome-da-sua-biblioteca\src\edge-impulse-sdk\classifier. Dentro desse arquivo, altere a linha #define EI_CLASSIFIER_TFLITE_ENABLE_ESP_NN 1 para #define EI_CLASSIFIER_TFLITE_ENABLE_ESP_NN 0, a fim de corrigir o problema de compatibilidade.
Compreendendo o código
- Antes do setup()
- Inclusão de bibliotecas: O código importa bibliotecas essenciais, como Wire.h, SPI.h, Adafruit_LIS3DH.h e Adafruit_Sensor.h ei accel_inferencing.h.
- Definição de pinos e constantes: Define pinos específicos para controlar o acelerômetro (SPI) e LEDs para indicar os resultados da classificação.
- Inicialização do acelerômetro: Configura o acelerômetro LIS3DH usando SPI e especifica os pinos de comunicação.
- Dentro do setup()
- Inicialização da comunicação serial: Inicia a comunicação serial com Serial.begin(115200) para enviar informações ao monitor serial.
- Configuração dos LEDs: Define os pinos dos LEDs como saídas (pinMode), garantindo que o código possa controlá-los.
- Apagamento inicial dos LEDs: Todos os LEDs são desligados inicialmente para garantir que o sistema comece em um estado neutro.
- Inicialização do acelerômetro: Tenta inicializar o sensor LIS3DH e, caso falhe, imprime um erro e para a execução. O sensor é configurado para um alcance de 2G e taxa de amostragem de 50 Hz, com desempenho normal.
- Verificação quadro de dados: Verifica se a quantidade de amostras por quadro do classificador de machine learning está configurada corretamente para o número de eixos do acelerômetro.
- Dentro do loop()
- Mensagem de início: Exibe uma mensagem informando que a classificação começará após 2 segundos.
- Leitura do acelerômetro: Um buffer é preparado para armazenar os dados dos eixos X, Y e Z.
- Os dados de aceleração são lidos continuamente do sensor e armazenados no buffer, com um atraso para sincronizar a coleta de dados.
- As leituras de aceleração (X, Y, Z) são exibidas no monitor serial para depuração.
- Classificação dos dados: Os dados brutos lidos do acelerômetro são convertidos em um sinal para o classificador de machine learning. O classificador de machine learning é executado nos dados, e as predições são geradas para os possíveis movimentos (caminhando, parado, pulando). As predições, tempos de processamento e valores de anomalia são exibidos no monitor serial.
- Controle dos LEDs: Dependendo da predição com maior confiança, um dos três LEDs será aceso. Se nenhuma predição atingir o limite de confiança de 0,8, todos os LEDs permanecerão apagados.
Funcionamento
- Parado
- Caminhando
- Pulando
Conclusão
Neste segundo parte do projeto “Classificação de Movimento com Acelerômetro e LEDs”, conseguimos integrar o modelo de machine learning à Franzininho WiFi para realizar a classificação de movimentos em tempo real com base nos dados do acelerômetro LIS3DH. Os LEDs fornecem um retorno visual, tornando a identificação de ações como “caminhando”, “parado” e “pulando” acessível e interativa. Essa aplicação demonstra o potencial do machine learning embarcado, podendo ser base para diversas implementações.





