Leitura dos Eixos X, Y e Z do acelerômetro LIS3DH com a Franzininho C0 via SPI

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

Introdução

Neste artigo, você aprenderá a configurar a Franzininho C0 para trabalhar com protocolo de comunicação SPI e realizar leituras do acelerômetro LIS3DH.

Materiais necessários: 

  • 1 Franzininho C0
  • 1 Módulo LIS3DH 

Esquema de montagem:

  • PA6 – SD0 (MISO)
  • PA1 – SCL (SCK)
  • PA2 – SDA (MOSI)
  • P4 – CS

Protocolo SPI

SPI é um protocolo de comunicação serial síncrono , full -duplex , baseado em mestre-escravo. Foi implementado pela primeira vez em 1970 pela Motorola. 

O protocolo de comunicação SPI (Serial Peripheral Interface) utiliza quatro fios principais: SCK (Clock Serial), MISO (Master-In Slave-Out), MOSI (Master-Out Slave-In) e CS (Chip Select). Diferente do protocolo I2C, que utiliza endereços para comunicação entre dispositivos, o SPI utiliza o pino CS para selecionar o escravo com o qual o mestre deseja se comunicar. Quando o mestre precisa iniciar uma comunicação com um escravo específico, ele ativa o pino CS desse escravo, levando-o para o nível lógico baixo (0). Isso estabelece o canal de comunicação exclusivo entre o mestre e o escravo selecionado.

Além disso, é preciso configurar corretamente os parâmetros CPOL (Clock Polarity) e CPHA (Clock Phase). O CPOL define o estado inativo do clock, enquanto o CPHA determina em qual borda do clock os dados serão amostrados, garantindo que a sincronização dos sinais entre mestre e escravo.

Para mais informações detalhadas deste protocolo recomendo a leitura de https://embarcados.com.br/spi-parte-1/  e https://embarcados.com.br/comunicacao-spi-parte-2/

LIS3DH 

O LIS3DH é um acelerômetro linear de três eixos, de alta performance e ultra baixa potência, com interface digital I²C/SPI. Oferece modos de ultra baixa potência, funções inteligentes e escalas selecionáveis de ±2g/±4g/±8g/±16g, medindo acelerações de 1 Hz a 5,3 kHz. Possui auto-teste, geradores de interrupção configuráveis, e um buffer FIFO de 32 níveis para otimizar a eficiência.

Características:

  • Tensão de alimentação: 1,71 V a 3,6 V
  • Consumo em ultra baixa potência: até 2 μA
  • Escala selecionável: ±2g/±4g/±8g/±16g
  • Interface comunicação I²C/SPI
  • Saída de dados de 16 bits
  • 2 geradores de interrupção programável (queda livre e movimento)
  • Detecção de orientação 6D/4D, queda livre e movimento
  • Sensor de temperatura e auto-teste embutidos
  • FIFO de 32 níveis, alta resistência a choques (até 10000 g)

Aplicações:

  • Funções por movimento, detecção de queda livre
  • Pedômetros, orientação de display
  • Dispositivos para jogos e realidade virtual
  • Economia de energia inteligente para portáteis
  • Reconhecimento e registro de impactos, monitoramento de vibrações

Acesse o datasheet em: https://www.st.com/resource/en/datasheet/lis3dh.pdf 

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 a configuração do SPI, neste exemplo, 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. Perceba que ao habilitar o SPI, o CubeMx ativa automaticamente os pinos de SCK, MOSI e MISO. O pino de CS é necessário configurar manualmente, para isso, selecione o PA4 como “GPIO_Output”.
  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. Por fim, gere o código em “Project” > “Generate Code”.

Implementação Código

  1. Inicialmente, criaremos dois arquivos novos. Em “Inc” crie “lis3dh.h” e em “Src” crie “lis3dh.c”. 
  1. Após criar esses novos arquivos, acesse o arquivo lis3dh.h. Neste arquivo, vamos adicionar algumas definições (#define) dos registradores do acelerômetro LIS3DH, assim como os protótipos das funções que implementaremos em lis3dh.c.
#include <stdint.h>


// Definições dos registradores do acelerômetro LIS3DH
#define LIS3DH_CTRL_REG1        0x20
#define LIS3DH_CTRL_REG4        0x23
#define LIS3DH_WHO_AM_I         0x0F
#define LIS3DH_OUT_X_L          0x28
#define LIS3DH_OUT_X_H          0x29
#define LIS3DH_OUT_Y_L          0x2A
#define LIS3DH_OUT_Y_H          0x2B
#define LIS3DH_OUT_Z_L          0x2C
#define LIS3DH_OUT_Z_H          0x2D


// Protótipos das funções para manipulação do acelerômetro
void LIS3DH_Init(void);
uint8_t LIS3DH_ReadReg(uint8_t address);
void LIS3DH_WriteReg(uint8_t address, uint8_t data);
void LIS3DH_ReadAccel(int16_t *acceleration);
  1. Acesse o arquivo lis3dh.c, inclua as bibliotecas necessárias e faça referência às interfaces SPI e UART que foram configuradas previamente.
#include "stm32c0xx.h"
#include "lis3dh.h"
#include "stdio.h"
#include "string.h"
extern SPI_HandleTypeDef hspi1;
extern UART_HandleTypeDef huart1;
  1. Ainda em lis3dh.c, criaremos as funções de leitura e escrita na SPI. Em ambas as funções, é necessário ativar e desativar o CS (Chip Select) entre as leituras ou escritas SPI, conforme explicado ao longo do artigo.
/** @brief Reads given amount of data from sensor
* @param reg: Register address to read from
* @retval data receive
*/
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
}
/** @brief Writes given amount of data to sensor
* @param reg: Register address to write to
* @param value: Number of bytes to be written
* @retval Zero on success, -1 otherwise
*/
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. Mantenha-se em lis3dh.c, adicione a função de inicialização do acelerômetro, nela vamos configurar os registradores LIS3DH_CTRL_REG1 e LIS3DH_CTRL_REG4. No LIS3DH_CTRL_REG1, ajustamos a taxa de dados e habilitamos os eixos. No LIS3DH_CTRL_REG4, configuramos o modo de comunicação (3 ou 4 fios), a escala e a resolução, conforme mostrado nas tabelas abaixo.
/** @brief Initializes LIS3DH device with following configuration:
* 100Hz sampling rate
* Enable all axis
* @retval None
*/
void LIS3DH_Init(void) {
	// delay to ensure LIS3DH is ready after power-up
	 HAL_Delay(10);
	 // Write to CTRL_REG1 to set data rate and enable all axes
	 LIS3DH_WriteReg(LIS3DH_CTRL_REG1, 0x57); // 100Hz, enable X, Y, Z
	 // Write to CTRL_REG4 to set scale default 2g and high-resolution mode
	 LIS3DH_WriteReg(LIS3DH_CTRL_REG4, 0xC8);
   uint8_t who_am_i = LIS3DH_ReadReg(LIS3DH_WHO_AM_I);
   char status[50];
   sprintf(status, "WHO_AM_I: 0x%02X\r\n", who_am_i);
   HAL_UART_Transmit(&huart1, (uint8_t *)status, strlen(status), 1000);
}

valor configurado no código: 0x57 = 01010111

valor configurado no código: 0xC8 = 11001000

  1. Por fim, no arquivo lis3dh.c, adicione a função de leitura de dados. Esta função lerá os valores de cada eixo do acelerômetro (vertical e horizontal) e os armazenará no array fornecido. A função faz a leitura dos registradores de saída de dados do acelerômetro e combina os bytes alto e baixo para formar os valores de 16 bits de cada eixo.
void LIS3DH_ReadAccel(int16_t *acceleration) {
   uint8_t x_l = LIS3DH_ReadReg(LIS3DH_OUT_X_L);
   uint8_t x_h = LIS3DH_ReadReg(LIS3DH_OUT_X_H);
   uint8_t y_l = LIS3DH_ReadReg(LIS3DH_OUT_Y_L);
   uint8_t y_h = LIS3DH_ReadReg(LIS3DH_OUT_Y_H);
   uint8_t z_l = LIS3DH_ReadReg(LIS3DH_OUT_Z_L);
   uint8_t z_h = LIS3DH_ReadReg(LIS3DH_OUT_Z_H);
   acceleration[0] = ((int16_t)x_h << 8) | x_l;  // X-axis
   acceleration[1] = ((int16_t)y_h << 8) | y_l;  // Y-axis
   acceleration[2] = ((int16_t)z_h << 8) | z_l;  // Z-axis
}
  1. Veja na imagem abaixo o código como todo do arquivo lis3dh.c
  1. Entre no arquivo main.c, faça a inclusão das seguintes bibliotecas e variáveis.
#include "lis3dh.h"
#include "stdio.h"
#include "string.h"
char uart_buf[50];
char acel_buf[50];
  1. Depois, modifique a função principal int main de main.c com o seguinte:
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 */
 /* Initialize LIS3DH device */
 // CS pin should default high
 // teste uart
 sprintf(uart_buf, "SPI Test\r\n");
 HAL_UART_Transmit(&huart1, (uint8_t *)uart_buf, strlen(uart_buf), 1000);
 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
 HAL_Delay(500);
 LIS3DH_Init();
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
   int16_t accel[3];
   LIS3DH_ReadAccel(accel);
  // Print values via UART
   sprintf(acel_buf, "Leitura Bruta - X: %i, Y: %i, Z: %i\r\n", accel[0], accel[1], accel[2]);
   HAL_UART_Transmit(&huart1, (uint8_t *)acel_buf, strlen(acel_buf), 1000);
   HAL_Delay(1000);
   // Conversão para mg (miligravidade)
   int32_t accel_x_mg = (int32_t)accel[0] * 1000 / 16384;
   int32_t accel_y_mg = (int32_t)accel[1] * 1000 / 16384;
   int32_t accel_z_mg = (int32_t)accel[2] * 1000 / 16384;
   sprintf(acel_buf, "Aceleracao (mg) - X: %ld, Y: %ld, Z: %ld\r\n", accel_x_mg, accel_y_mg, accel_z_mg);
   HAL_UART_Transmit(&huart1, (uint8_t *)acel_buf, strlen(acel_buf), 1000);
   HAL_Delay(1000);
 }
 /* USER CODE END 3 */
}

Neste código, estamos inicializando o acelerômetro LIS3DH. No loop principal, lemos os valores brutos do acelerômetro, os convertendo em valores em miligramas (mg) e, em seguida, imprimimos essas informações pela interface serial. Abaixo temos a tabela de conversão que explica o motivo pelo qual foi utilizado 16384 na conversão da aceleração sabendo que a sensibilidade foi configurada em 2g. 

  1. A imagem abaixo mostra o código main.c modificado.

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

Conclusão

Neste artigo, demonstramos como configurar e utilizar o acelerômetro LIS3DH com a Franzininho C0 via SPI. Detalhamos a configuração do SPI e a implementação do código para inicializar o acelerômetro, ler os valores dos eixos X, Y e Z, e converter esses valores para unidades de miligravidade (mg). 

Franzininho C0 com STM32CubeIDE

Controle de LED com Botão usando Azure RTOS na Franzininho C0 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 » Leitura dos Eixos X, Y e Z do acelerômetro LIS3DH com a Franzininho C0 via SPI

EM DESTAQUE

WEBINARS

VEJA TAMBÉM

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Talvez você goste: