cancel
Showing results for 
Search instead for 
Did you mean: 

LIS3DSH accelerometer returns weird values

cockatoo
Associate III

I work on a pedometer project, which uses built-in accelerometer and an LCD screen (ILI9341). The screen code works fine, but I struggle to get the pedometer part to work. I suspect there might something wrong with how I initialized the accelerometer, since it outputs weird values.

I use an stm32f407g-disc1 board with built-in accelerometer, which I communicate with via SPI. I find the values it returns very weird, since I don't move the device at the moment. Shouldn't they be close to zero since there is no acceleration? Moreover, they don't change when I shake the device slightly, although it may be because the acceleration is not big enough to be detected. Another problem is that mag value changes all the time, although x,y,z don't change.

Values

cockatoo_0-1769752995867.png

main function

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_DMA_Init();
  MX_I2S3_Init();
  MX_SPI1_Init();
  MX_USB_HOST_Init();
  MX_SPI2_Init();
  MX_TIM2_Init();
  MX_TIM3_Init();
  /* USER CODE BEGIN 2 */
  //timers
  HAL_TIM_Base_Start_IT(&htim2);
  HAL_TIM_Base_Start_IT(&htim3);
  //Reset the screen
  ILI9341_Init(&hspi2);
  //screen experiment, delete later (black rectangle)
  HAL_Delay(1000);

  //Write_Rectangle(0, 50, 0, 50, 0, &hspi2); //good
  //draw_digit(10, 10, 12, 8, 0, &hspi2); //good
  //draw_number(UINT32_MAX, 12, &hspi2); //good

  //Set everything for the accelometer
  //fill buffer with 0s
  for (int i = 0; i < ACC_BUF_SIZE; i++) {
	  acc_values_buf[i] = 0;
  }
  //receive and set accelerator sensitivity
  accelerometer_init(&hspi1);
  accelerometer_ready = 1;
  //initial dma call (deprecated)
  //HAL_SPI_TransmitReceive_DMA(&hspi1, xyz_addr, xyz_data, 6);
  //default value
  //clean_screen(0xFF, &hspi2);
  //draw_number(steps_count, 12, &hspi2);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  uint32_t steps_count_prev = -1;
  clean_screen(0xFFFF, &hspi2);
  draw_ready = 1;
  while (1)
  {

    /* USER CODE END WHILE */
    MX_USB_HOST_Process();

    /* USER CODE BEGIN 3 */
    //During each SPI clock cycle, full-duplex transmission of a single bit occurs.
    //1 clock cycle is 168/32MHz = 5.25MHz
    //meaning there are 5.25 * 10^6 bit, or 5.25 * 10^6/8 bytes = 656250 bytes
    //or, all coordinates are received 109375 times.
    if (update_lcd_flag == 1) {
    	Write_Rectangle(0, 30, 0, ILI9341_WIDTH - 1, 0xFFFF, &hspi2);
    	draw_number(steps_count, 12, &hspi2);
    	update_lcd_flag = 0;
    }
    steps_count_prev = steps_count;


  }
  /* USER CODE END 3 */
}

 Timer interrupt that causes accelerometer reads

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)
{
	 if (htim->Instance == TIM2) {
		 if ((draw_ready == 1) && (accelerometer_ready == 1)) {
			 accelerometer_read_all_axes_dma(xyz_data, &hspi1);
		 }
	 }
	 //else if (htim->Instance == TIM3) {
	 //	 if (draw_ready == 1) {
			 //steps_count += 1;
			 //update_lcd_flag = 1;
	 //	 }
	 //}
}

 Spi1 settings

static void MX_SPI1_Init(void)
{

  /* USER CODE BEGIN SPI1_Init 0 */

  /* USER CODE END SPI1_Init 0 */

  /* USER CODE BEGIN SPI1_Init 1 */

  /* USER CODE END SPI1_Init 1 */
  /* SPI1 parameter configuration*/
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI1_Init 2 */

  /* USER CODE END SPI1_Init 2 */

}

 Timer (100Hz)

static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 999;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 1679;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */

}

 Accelerometer read, write and initialization functions

#include "accelerometer.h"

void accelerometer_read_all_axes_dma(uint8_t src[6], SPI_HandleTypeDef *hspi1) {
	uint8_t tx[7] = {OUT_X_L | 0x80, 0, 0, 0, 0, 0, 0};
	uint8_t rx[7];
	HAL_GPIO_WritePin(ACC_GPIO_PORT, ACC_GPIO_PIN, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive_DMA(hspi1, tx, rx, 7);
	HAL_GPIO_WritePin(ACC_GPIO_PORT, ACC_GPIO_PIN, GPIO_PIN_SET);
	memcpy(src, &rx[1], 6);
}

uint8_t accelerometer_read(uint8_t reg, SPI_HandleTypeDef *hspi1) {
	//https://stackoverflow.com/questions/67922914/stm32-spi-communication-with-hal
	HAL_GPIO_WritePin(ACC_GPIO_PORT, ACC_GPIO_PIN, GPIO_PIN_RESET);
	uint8_t tx[2];
	uint8_t rx[2];
	tx[0] = reg | 0x80;  // READ bit
	tx[1] = 0x00; //the master transmits a dummy byte for the purpose of generating more clocks on which the slave can respond
	HAL_SPI_TransmitReceive(hspi1, tx, rx, 2, 100); //send and receive 1 byte
	HAL_GPIO_WritePin(ACC_GPIO_PORT, ACC_GPIO_PIN, GPIO_PIN_SET);
	return rx[1];
}

void accelerometer_write(uint8_t reg, uint8_t val, SPI_HandleTypeDef *hspi1) {
	HAL_GPIO_WritePin(ACC_GPIO_PORT, ACC_GPIO_PIN, GPIO_PIN_RESET);
	uint8_t tx[2];
	tx[0] = reg & 0x7F;
	tx[1] = val;
	HAL_SPI_Transmit(hspi1, tx, 2, 100);
	HAL_GPIO_WritePin(ACC_GPIO_PORT, ACC_GPIO_PIN, GPIO_PIN_SET);
}

void accelerometer_init(SPI_HandleTypeDef *hspi1) {
	//we don't need a queue
	accelerometer_write(FIFO_CTRL, 0x00, hspi1);

	//set sensitivity to 4
	uint8_t ctrl_val;
	ctrl_val = accelerometer_read(CTRL_REG5, hspi1);
	ctrl_val =  ctrl_val | 0x08; //set FSCALE0 so that sensitivity is +-4gg
	uint8_t tx_buf[2];
	tx_buf[0] = CTRL_REG5 & 0x7F; //register address
	tx_buf[1] = ctrl_val; //data to write into it
	accelerometer_write(CTRL_REG5, ctrl_val, hspi1);

	//enable the device
	uint8_t ctrl4_val = 0x7F;
	accelerometer_write(CTRL_REG4, ctrl4_val, hspi1);
}

 Acceleremoter RxTx interrupt

//spi callback function
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef * hspi)
{
	HAL_GPIO_WritePin(ACC_GPIO_PORT, ACC_GPIO_PIN, GPIO_PIN_SET);
	if(hspi == &hspi1) {
		//declare variables
		int16_t x, y, z;
		uint32_t mag;
		uint32_t prev_index, prev_prev_index, prev_sample, prev_prev_sample;
		prev_index = 0; prev_prev_index = 0; prev_sample = 0; prev_prev_sample = 0;
		//calculate magnitude
		x = (int16_t)((int16_t)xyz_data[0] | ((int16_t)xyz_data[1] << 8));
		y = (int16_t)((int16_t)xyz_data[2] | ((int16_t)xyz_data[3] << 8));
		z = (int16_t)((int16_t)xyz_data[4] | ((int16_t)xyz_data[5] << 8));
		mag = ((int32_t)x*x + (int32_t)y*y + (int32_t)z*z); //auto-convert float to int //was sqrt
			last_peak += 1; //when the last time there was a peak
			value_period = 0;
			prev_index = buf_index; //previous sample index
			prev_prev_index = (prev_index == 0) ? (ACC_BUF_SIZE - 1) : (prev_index - 1); //(prev_index - 1) % ACC_BUF_SIZE; //pre-previous sample index
			prev_sample = acc_values_buf[prev_index];
			prev_prev_sample = acc_values_buf[prev_prev_index];
			buf_index = (buf_index + 1) % ACC_BUF_SIZE; //update buf_index
			acc_values_buf[buf_index] = mag; //add the sample
			//make all checks
			if ((last_peak < MAX_PEAK_DIFF && last_peak > MIN_PEAK_DIFF)
				&& (prev_sample > prev_prev_sample
					&& prev_sample > mag)
				&& (prev_sample > PEAK_CUTOFF)) {
					steps_count += 1; //uncomment later
					update_lcd_flag = 1;
					last_peak = 0;
			}
			else {
				//update_lcd_flag = 0;
			}
		//call to SPI again //deprecated
		//HAL_SPI_TransmitReceive_DMA(&hspi1, xyz_addr, xyz_data, 6);
	}
}

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
cockatoo
Associate III

My pedometer still doesn't work, but I have solved this specific issue. The problem was in how I update xyz_data. This is the correct way to do this.

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)
{
	 if (htim->Instance == TIM2) {
		 if ((draw_ready == 1) && (accelerometer_ready == 1)) {
			 accelerometer_read_all_axes_dma(xyz_data, &hspi1);
		 }
	 }
	 //else if (htim->Instance == TIM3) {
	 //	 if (draw_ready == 1) {
			 //steps_count += 1;
			 //update_lcd_flag = 1;
	 //	 }
	 //}
}
void accelerometer_read_all_axes_dma(uint8_t src[7], SPI_HandleTypeDef *hspi1) {
	uint8_t tx[7] = {OUT_X_L | 0x80, 0, 0, 0, 0, 0, 0};
	uint8_t rx[7];
	HAL_GPIO_WritePin(ACC_GPIO_PORT, ACC_GPIO_PIN, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive_DMA(hspi1, tx, src, 7);
	HAL_GPIO_WritePin(ACC_GPIO_PORT, ACC_GPIO_PIN, GPIO_PIN_SET);
	//memcpy(src, &rx[1], 6);
}
volatile uint8_t xyz_data[7];

 

View solution in original post

1 REPLY 1
cockatoo
Associate III

My pedometer still doesn't work, but I have solved this specific issue. The problem was in how I update xyz_data. This is the correct way to do this.

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)
{
	 if (htim->Instance == TIM2) {
		 if ((draw_ready == 1) && (accelerometer_ready == 1)) {
			 accelerometer_read_all_axes_dma(xyz_data, &hspi1);
		 }
	 }
	 //else if (htim->Instance == TIM3) {
	 //	 if (draw_ready == 1) {
			 //steps_count += 1;
			 //update_lcd_flag = 1;
	 //	 }
	 //}
}
void accelerometer_read_all_axes_dma(uint8_t src[7], SPI_HandleTypeDef *hspi1) {
	uint8_t tx[7] = {OUT_X_L | 0x80, 0, 0, 0, 0, 0, 0};
	uint8_t rx[7];
	HAL_GPIO_WritePin(ACC_GPIO_PORT, ACC_GPIO_PIN, GPIO_PIN_RESET);
	HAL_SPI_TransmitReceive_DMA(hspi1, tx, src, 7);
	HAL_GPIO_WritePin(ACC_GPIO_PORT, ACC_GPIO_PIN, GPIO_PIN_SET);
	//memcpy(src, &rx[1], 6);
}
volatile uint8_t xyz_data[7];