2018-09-04 08:32 AM
Hello everyone,
I have an issue with the IIS2DH accelerometer when I try to pool data from it.
My setup is:
STM32L442 connected to the IIS2DH using SPI interface and sending data through USART to Tera Term (using a FTDI cable).
First I have a small initialization process which sets up the chip following my needs:
400Hz, X Y and Z axis enabled, +-2G scale, high resolution, SPI 4 wires, BDU.
Then I read all the 6 control registers and the "who I am" register to check if everything is ok and I display the results on Tera Term. All works nicely, as expected.
However, when I pool data from output registers (OUT_X_L, OUT_X_H, ...) it works only for X and Y axis...
Once data from the several registers are stored, there is a small sequence which constructs the 16-bit signed integers from the high and low regisiters of each axis, then it shifts the 16 bits to the right to keep only the first 12 bits (HR mode) and finally I send the data through USART (using atoi() function to convert the data into strings).
But as I said, it works perfectly for the X and Y axis, but not for the Z axis. Instead of having something corresponding to -1g (or -1024 on a 12 bit scale), I read almost -2g (-2039).
Sometimes when I hit the sensor, the Z axis moves a little bit but it does not correspond to normal operating.
Has anyone ever encountered this type of problem?
Thank you for your help!
Maxime
2018-09-05 12:05 AM
Can you share your code?
Do you see 1g in X and Y axis if your align the axis with gravity?
2018-09-10 08:18 AM
Hi,
Yes I was seeing 1g on both X and Y axis when I was aligning the axis
with gravity.
I did some debugging job and now it works.
For a moment I thought it was a problem with the turn-on time of the
chip and the clock of the MCU.
I got it working at 2MHz but when I was trying to increase the frequency
up to 4 or 8MHz the Z-axis was starting to stop working properly.
Even with a small delay between the starting of the chip (I use an
analog switch on my board to monitor the voltage supply) and the initialization
process, I did not have any improvement.
Today, after a simple "refresh" of the project inside
TrueSTUDIO, my app started to work properly...
FYI my debug code (simplified, only the principal is shown):
#include "main.h"
#include "stm32l4xx_hal.h"
#include "IIS2DH_driver.h"
#include <string.h>
#include <stdlib.h>
#define ACC_OFF HAL_GPIO_WritePin(SW_SENSOR_GPIO_Port, SW_SENSOR_Pin, GPIO_PIN_SET)
#define ACC_ON HAL_GPIO_WritePin(SW_SENSOR_GPIO_Port, SW_SENSOR_Pin, GPIO_PIN_RESET)
SPI_HandleTypeDef hspi1;
volatile uint8_t flag_bp = 0;
Type1_Axis16bit_t raw_data_acc;
ACC_HandleTypeDef hacc1;
ACC_Config_t cIIS2DH;
ACC_Status_t sIIS2DH;
float x, y, z;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
ACC_OFF;
while(flag_bp != 1); // Wait for the user to press the push button
flag_bp = 0;
ACC_ON; // Power up the accelerometer
HAL_Delay(1);
ACC_Init(&hspi1, &hacc1); // Accelerometer init
memset(raw_data_acc.u8bit, 0x00, 3*sizeof(int16_t));
while (1)
{
raw_data_acc.u8bit[0] = ACC_WriteRead(&hspi1, ACC_READ, ACC_OUT_X_L, 0x00);
raw_data_acc.u8bit[1] = ACC_WriteRead(&hspi1, ACC_READ, ACC_OUT_X_H, 0x00);
raw_data_acc.u8bit[2] = ACC_WriteRead(&hspi1, ACC_READ, ACC_OUT_Y_L, 0x00);
raw_data_acc.u8bit[3] = ACC_WriteRead(&hspi1, ACC_READ, ACC_OUT_Y_H, 0x00);
raw_data_acc.u8bit[4] = ACC_WriteRead(&hspi1, ACC_READ, ACC_OUT_Z_L, 0x00);
raw_data_acc.u8bit[5] = ACC_WriteRead(&hspi1, ACC_READ, ACC_OUT_Z_H, 0x00);
x = ACC_digit_to_g(&hacc1, raw_data_acc.i16bit[0]);
y = ACC_digit_to_g(&hacc1, raw_data_acc.i16bit[1]);
z = ACC_digit_to_g(&hacc1, raw_data_acc.i16bit[2]);
}
}
void EXTI9_5_IRQHandler(void)
{
if(__HAL_GPIO_EXTI_GET_FLAG(GPIO_PIN_5)){
flag_bp = 1;
}
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_5);
}
uint8_t ACC_WriteRead(void *handle_spi, uint8_t rw, uint8_t addr, uint8_t data_reg){
uint8_t buff_tx[2];
uint8_t buff_rx[2];
buff_tx[0] = rw | addr;
buff_tx[1] = data_reg;
HAL_GPIO_WritePin(SPI1_CS2_GPIO_Port, SPI1_CS2_Pin, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(handle_spi, buff_tx, buff_rx, 2, 100);
HAL_GPIO_WritePin(SPI1_CS2_GPIO_Port, SPI1_CS2_Pin, GPIO_PIN_SET);
return buff_rx[1];
}
void ACC_Init(void *handle_spi, ACC_HandleTypeDef *hacc){
uint8_t reg;
// Reboot the device //
reg = ACC_CTRL_REG5_BOOT;
ACC_WriteRead(handle_spi, ACC_WRITE, ACC_CTRL_REG5, reg);
// Set ODR to 400Hz and enable XYZ axis //
reg = (ACC_CTRL_REG1_ODR400 << ACC_CTRL_REG1_ODR_SHIFT)
| ACC_CTRL_REG1_Z_EN
| ACC_CTRL_REG1_Y_EN
| ACC_CTRL_REG1_X_EN;
ACC_WriteRead(handle_spi, ACC_WRITE, ACC_CTRL_REG1, reg);
HAL_Delay(2);
// Set +/-2G scale, high resolution, 4-wires SPI and enable BDU //
reg = (ACC_CTRL_REG4_FS_2G << ACC_CTRL_REG4_FS_SHIFT)
| ACC_CTRL_REG4_HR
| ACC_CTRL_REG4_SIM_4W
| ACC_CTRL_REG4_BDU;
ACC_WriteRead(handle_spi, ACC_WRITE, ACC_CTRL_REG4, reg);
HAL_Delay(1);
// Set the configuration of the sensor //
hacc->Configuration.resolution = RESOLUTION_12BIT;
hacc->Configuration.scale = SCALE_2G;
hacc->Configuration.sensitivity = 0.9765625;
}
float ACC_digit_to_g(ACC_HandleTypeDef *hacc, int16_t digit_value){
float conv_value;
conv_value = (digit_value >> (16-hacc->Configuration.resolution))*hacc->Configuration.sensitivity/1000.0;
return conv_value;
}
Maxime