Detecção de Queda Livre com acelerômetro LIS3DH e Franzininho C0

Este post faz parte da série Franzininho C0 com STM32CubeIDE

Introdução

A identificação de queda livre é uma aplicação frequente em sistemas com  acelerômetros, sendo muito utilizada em dispositivos como smartphones, wearables e sistemas de segurança. Essa técnica permite que dispositivos reconheçam quando estão em uma queda, o que pode disparar uma série de ações automáticas, como a ativação de alarmes de emergência ou sistemas de proteção.

Neste terceiro artigo com o acelerômetro LIS3DH, vamos implementar a detecção de queda livre que acionará um LED e exibirá a informação pela Serial. 

Circuito:

Configuração CubeMx

  1. Abra STM32Cube, crie um novo projeto e selecione o microcontrolador “STM32C011F6P6”. 
  1. Vá para a página de configurações de relógio e em HCLK digite 48 MHz para a frequência de saída desejada do sistema. Depois volte para a página de configuração dos pinos, selecione “Trace and Debug” e  habilite “Serial Wire.
  1. Para configurar a UART, selecione o pino PA10 como “USART1_RX” e PA9 como “USART1_TX”. Em “Connectivity” selecione a opção “USART1” e em Mode escolha o “Asynchronous”. As demais configurações deixe padrão. 
  1. Para a configuração do SPI, vá em “Connectivity’ > “SPI”, habilite o modo “FullDuplex Master” e  mude o “Clock Parameter” > “Prescaler (Baud Rate)” para 32. Os demais parâmetros de configuração não será necessário modificar. 
  1. O pino de CS é necessário configurar manualmente, então, selecione o PA4 como “GPIO_Output”.
  1. Configure também o pino PB6 como “GPIO_Output”, nele está conectado o LED.
  1. Por fim, gere o código em “Project” > “Generate Code”.

Implementação Código

  1. Crie em “Inc” “lis3dh.h” e em “Src” crie “lis3dh.c”. 
  1. Em  lis3dh.h, adicione algumas definições (#define) dos registradores do acelerômetro LIS3DH, assim como os protótipos das funções que serão implementadas em lis3dh.c:
#include <stdint.h>
#define LIS3DH_CTRL_REG1       0x20
#define LIS3DH_CTRL_REG3       0x22
#define LIS3DH_CTRL_REG4       0x23
#define LIS3DH_INT1_CFG        0x30
#define LIS3DH_INT1_SRC        0x31
#define LIS3DH_INT1_THS        0x32
#define LIS3DH_INT1_DURATION   0x33
/* Public APIs */
uint8_t LIS3DH_ReadReg(uint8_t address);
void LIS3DH_WriteReg(uint8_t address, uint8_t data);
void LIS3DH_FreeFallConfig();
void freeFallStatus();
  1. Em li3dh.c, adicione a inclusão das bibliotecas e seguintes variáveis: 
#include "lis3dh.h"
#include "stdio.h"
#include "string.h"
extern SPI_HandleTypeDef hspi1;
extern UART_HandleTypeDef huart1;
uint8_t msg[] = "Queda livre detectada! \r\n";
  1. Depois, adicione as funções de leitura e escrita por SPI:
// Leitura por SPI
uint8_t LIS3DH_ReadReg(uint8_t address) {
   uint8_t txData[2];
   uint8_t rxData[2];
   txData[0] = address | 0x80 ; // Set read bit (MSB = 1)
   txData[1] = 0x00; // Dummy byte
   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // CS low
   // delay to ensure CS is correctly registered
   HAL_Delay(1);
   if (HAL_SPI_TransmitReceive(&hspi1, txData, rxData, 2, HAL_MAX_DELAY) != HAL_OK) {
       char error_msg[] = "SPI Transmit/Receive Error\r\n";
       HAL_UART_Transmit(&huart1, (uint8_t *)error_msg, strlen(error_msg), 1000);
   }
   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // CS high
   return rxData[1]; // The second byte received is the actual data
}
// Escrita por SPI
void LIS3DH_WriteReg(uint8_t address, uint8_t data) {
   uint8_t txData[2];
   txData[0] = address;
   txData[1] = data;
   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // CS low
   // delay to ensure CS is correctly registered
   HAL_Delay(1);
   if (HAL_SPI_Transmit(&hspi1, txData, 2, HAL_MAX_DELAY) != HAL_OK) {
       char error_msg[] = "SPI Write Error\r\n";
       HAL_UART_Transmit(&huart1, (uint8_t *)error_msg, strlen(error_msg), 1000);
   }
   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);   // CS high
}
  1. Em seguida, crie as funções de configuração dos registradores no LIS3DH para trabalhar com identificação de queda livre:
// Função para configurar o LIS3DH para detecção de queda livre
void LIS3DH_FreeFallConfig(void) {
   LIS3DH_WriteReg(LIS3DH_CTRL_REG1, 0x97); // CTRL_REG1: Ativar XYZ, 50 Hz ODR
   LIS3DH_WriteReg(LIS3DH_CTRL_REG4, 0x88); // CTRL_REG4: High resolution, BDU enabled, ±2g
   LIS3DH_WriteReg(LIS3DH_CTRL_REG3, 0x40); // CTRL_REG3: AOI1 interrupt on INT1 pin
   LIS3DH_WriteReg(LIS3DH_INT1_CFG, 0x95); // INT1_CFG: 6 direction movement recognition
   LIS3DH_WriteReg(LIS3DH_INT1_THS, 0x16); // INT1_THS: Threshold = 350 mg
   LIS3DH_WriteReg(LIS3DH_INT1_DURATION, 0x03); // INT1_DURATION: Minimum event duration = 1/OD
}

  • CTRL_REG1: Ative o sensor e defina a taxa de dados (ODR). Por exemplo, para configurar uma taxa de 50Hz com todos os eixos ativos, envie: 0x97 (10010111).
  • CTRL_REG3: Configure as interrupções. Para roteá-las para o pino INT1, envie: 0x40 (01000000).
  • CTRL_REG4 (0x23): Configure a faixa de medição, se necessário. Para uma faixa de ±2g, por exemplo, envie: 0x88 (10001000).
  • INT1_CFG (0x30): Configure o tipo de evento para gerar a interrupção. Para detecção de queda livre, você deve monitorar quando todas as acelerações nos eixos caem abaixo de um determinado limiar. Configure: 0x95 (10010101) para habilitar a interrupção em todos os eixos com “6-direction movement recognition”.
  • INT1_THS: Defina o limiar de aceleração para detectar queda livre. Valores baixos, como 0x10 (0010000).
  • INT1_DURATION: Defina a duração mínima para considerar como queda livre. Um valor baixo, como 0x03 é  suficiente para detectar quedas rápidas.
  1. Ainda no arquivo li3dh.c, crie a função para identificar queda livre:
// Função para verificar o status da interrupção de queda livre
void freeFallStatus() {
   uint8_t int1Src;
   int1Src = LIS3DH_ReadReg(LIS3DH_INT1_SRC);
   // Verifica se o bit de queda livre foi ativado
   if (int1Src & 0x40) {
   	// Verifique se todos os bits XLow, YLow e ZLow estão setados
   	if ((int1Src & 0x01) && (int1Src & 0x04) && (int1Src & 0x10)) {
   		// Queda livre detectada: Todos os eixos estão abaixo do limiar configurado
   		HAL_UART_Transmit(&huart1, msg, (sizeof(msg)-1), 1000);	// Transmite mensagem serial pela UART
           HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_6); //muda estado led
   	}
   }
}

Essa função verifica se houve uma queda livre lendo o registrador de interrupção do acelerômetro. Primeiro, checa se o bit que indica uma interrupção de queda livre está ativado. Se estiver, a função então verifica se os eixos X, Y e Z estão todos abaixo do limite configurado. Se sim, a função aciona envia uma mensagem pela UART e alterna o estado de um LED.

  1. Veja na imagem abaixo o código do arquivo lis3dh.c
  1. Depois da finalização do código em  lis3dh.c, acesse main.c. Nele incluímos a biblioteca “lis3dh.h” adicionando ao ínicio do código:
#include "lis3dh.h"
  1. Depois modificamos o int main com:
int main(void)
{
 /* USER CODE BEGIN 1 */
 /* USER CODE END 1 */
 /* MCU Configuration--------------------------------------------------------*/
 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();
 /* USER CODE BEGIN Init */
 /* USER CODE END Init */
 /* Configure the system clock */
 SystemClock_Config();
 /* USER CODE BEGIN SysInit */
 /* USER CODE END SysInit */
 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_SPI1_Init();
 MX_USART1_UART_Init();
 /* USER CODE BEGIN 2 */
 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
 HAL_Delay(500);
 LIS3DH_FreeFallConfig();
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
  freeFallStatus();
 }
 /* USER CODE END 3 */
}

Nessa etapa, é chamado a configuração do acelerômetro com LIS3DH_FreeFallConfig e depois é lido continuamente o estado com freeFallStatus.

Gravação

Ao finalizar o código, partiremos para gravação. Nessa etapa você pode utilizar o ST-Link seguindo as conexões da imagem abaixo e clicando em “run” no STM32CubeIde.

Ou você pode optar por utilizar um cabo usb e gravar conforme explicado no seguinte tutorial: gravar-franzininho-c0-via-stm32cubeprogrammer

Funcionamento

Para testar o funcionamento simule um queda, como jogar a placa.

Desafio extra 

No exemplo deste artigo estamos verificando constantemente o status da queda livre dentro no loop infinito. No entanto, essa não é a melhor abordagem, como desafio, configure um pino na Franzininho C0 para interrupção externa e o conecte no “INT1” do acelerômetro, então chame a verificação do status da queda livre sempre que houver interrupção no pino. Em caso de dúvidas temos um artigo explicando como configurar interrupção externa, acesse:  https://embarcados.com.br/aprendendo-a-trabalhar-com-interrupcoes-externas-e-usart-na-franzininho-c0/

Conclusão

Neste artigo, demonstramos como configurar o acelerômetro LIS3DH para detectar quedas livres usando a Franzininho C0. Configuramos os registradores necessários e a implementamos o código para verificar o status de queda, acionando um LED e enviando uma mensagem pela Serial. Essa solução básica permite a identificação de quedas de forma simples e pode ser expandida com o uso de interrupções para otimizar o desempenho do sistema.

Franzininho C0 com STM32CubeIDE

Medição de ângulo com acelerômetro LIS3DH e Franzininho C0
Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.
Comentários:
Notificações
Notificar
0 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Home » Hardware » Detecção de Queda Livre com acelerômetro LIS3DH e Franzininho C0

EM DESTAQUE

WEBINARS

VEJA TAMBÉM

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Talvez você goste: