2025-01-28 09:08 AM
Hi
I managed to read both accelerometer and gyroscope ISM330DLC in "polling" mode with INT1 pin with 3330 output data rate, but my goal is to reach peak data rate (6660 samples / s) so I need to use FIFO and this is where my problems start, I dont know how to set FIFO properly, results in FIFO are intertwined. Could you show me a problem in my configuration?
I have some success with enabling FIFO but I have no clue how to configure it to reach my goal which is reading acc ang gyro via primary SPI with max data rate (6660 Hz) and with lowest latency (low set fifo watermark)
My code
/* Header of application modules */
#include <sensors-board-app/logging.h>
#include <sensors-board-app/ism.h>
#include <sensors-board-app/ism330dlc.h>
/* Header from CubeMX autogenerated code */
#include <main.h>
#include <spi.h>
#include <gpio.h>
/* Constants */
/** @brief Timeout of ISM330 SPI interface */
#define ISM330_SPI_TIMEOUT_MS 100
/* Private data types */
/* Private functions declarations */
static int32_t s_ism330_cb_init(void);
static int32_t s_ism330_cb_deinit(void);
static int32_t s_ism330_cb_read(uint16_t address,
uint16_t reg,
uint8_t* data,
uint16_t len);
static int32_t s_ism330_cb_write(uint16_t address,
uint16_t reg,
uint8_t* data,
uint16_t len);
static int32_t s_ISM330DLC_Init_custom_version(ISM330DLC_Object_t *pObj);
/* Private data */
/** @brief ISM330 library handler */
static ISM330DLC_Object_t ism330_hdl = { 0 };
/** @brief Accelerometer sensitivity */
static float s_acc_sensitivity = 0.0f;
/** @brief Gyroscope sensitivity */
static float s_gyro_sensitivity = 0.0f;
int ism_init(void)
{
/* ISM330 library IO */
static ISM330DLC_IO_t ism330_io = {
.Init = s_ism330_cb_init,
.DeInit = s_ism330_cb_deinit,
.BusType = 2, /* 0 means I2C, 1 means SPI 4-Wires, 2 means SPI-3-Wires */
.Address = 69, /* dont know how to use this in this library */
.ReadReg = s_ism330_cb_read,
.WriteReg = s_ism330_cb_write,
.GetTick = NULL, /* callback not used int this library anyway */
};
/* Register ISM330 library callbacks */
ISM330DLC_RegisterBusIO(&ism330_hdl, &ism330_io);
/* Iniatialise ISM330 chip using fixed version of ISM330DLC_Init procedure */
s_ISM330DLC_Init_custom_version(&ism330_hdl);
/* Check ISM330 ID */
uint8_t ism330_id = 0;
ISM330DLC_ReadID(&ism330_hdl, &ism330_id);
if (ISM330DLC_ID == ism330_id) {
LOG_INFO("ISM330DLC chip id is valid");
} else {
LOG_ERROR("ISM330DLC chip id invalid");
}
/* Set ISM330 in high performance mode */
ism330dlc_xl_power_mode_set(&ism330_hdl.Ctx, ISM330DLC_XL_HIGH_PERFORMANCE);
ism330dlc_gy_power_mode_set(&ism330_hdl.Ctx, ISM330DLC_GY_HIGH_PERFORMANCE);
/* Set scale */
ISM330DLC_GYRO_SetFullScale(&ism330_hdl, 2000);
ISM330DLC_ACC_GetSensitivity(&ism330_hdl, &s_acc_sensitivity);
ISM330DLC_GYRO_GetSensitivity(&ism330_hdl, &s_gyro_sensitivity);
/* Enable toggling interrupt pin on reaching fifo watermark */
ISM330DLC_Set_Drdy_Mode(&ism330_hdl, ISM330DLC_DRDY_PULSED);
uint8_t int1_ctrl_reg_value = 0x8;
ISM330DLC_Write_Reg(&ism330_hdl, ISM330DLC_INT1_CTRL, int1_ctrl_reg_value);
/* Set output data rate (from 12.5, 208.0 to 1660.0 and even 6660.0) */
ISM330DLC_ACC_SetOutputDataRate(&ism330_hdl, 104);
ISM330DLC_GYRO_SetOutputDataRate(&ism330_hdl, 104);
ISM330DLC_ACC_Enable(&ism330_hdl);
ISM330DLC_GYRO_Enable(&ism330_hdl);
/* Set ODF of FIFO */
ISM330DLC_FIFO_Set_ODR_Value(&ism330_hdl, 104);
/* Set FIFO decimators */
ISM330DLC_FIFO_GYRO_Set_Decimation(&ism330_hdl, ISM330DLC_FIFO_GY_NO_DEC);
ISM330DLC_FIFO_ACC_Set_Decimation(&ism330_hdl, ISM330DLC_FIFO_XL_NO_DEC);
/* Turn on FIFO */
ISM330DLC_FIFO_Set_Mode(&ism330_hdl, ISM330DLC_FIFO_MODE);
/* Set FIFO watermark level */
ISM330DLC_FIFO_Set_Watermark_Level(&ism330_hdl, 120);
return 0;
}
ism_drdy_e ism_check_drdy(void)
{
ism_drdy_e retval = ISM_DRDY_ACC_AND_GYRO;
return retval;
}
int ism_read_acc_gyro(ism_acc_gyro_res_t* results)
{
/* Collect results */
ISM330DLC_AxesRaw_t gyro_raw = {0};
ISM330DLC_AxesRaw_t acc_raw = {0};
ISM330DLC_FIFO_Get_Data_Word(&ism330_hdl, &gyro_raw.x);
ISM330DLC_FIFO_Get_Data_Word(&ism330_hdl, &gyro_raw.y);
ISM330DLC_FIFO_Get_Data_Word(&ism330_hdl, &gyro_raw.z);
ISM330DLC_FIFO_Get_Data_Word(&ism330_hdl, &(acc_raw.x));
ISM330DLC_FIFO_Get_Data_Word(&ism330_hdl, &(acc_raw.y));
ISM330DLC_FIFO_Get_Data_Word(&ism330_hdl, &(acc_raw.z));
/* Calculate result */
results->acc_x = (int32_t)((float)((float)acc_raw.x * s_acc_sensitivity));
results->acc_y = (int32_t)((float)((float)acc_raw.y * s_acc_sensitivity));
results->acc_z = (int32_t)((float)((float)acc_raw.z * s_acc_sensitivity));
results->vel_x = (int32_t)((float)((float)gyro_raw.x * s_gyro_sensitivity));
results->vel_y = (int32_t)((float)((float)gyro_raw.y * s_gyro_sensitivity));
results->vel_z = (int32_t)((float)((float)gyro_raw.z * s_gyro_sensitivity));
return 0;
}
int ism_read_temp(float* temp)
{
int16_t t_raw = 0;
ism330dlc_temperature_raw_get(&ism330_hdl.Ctx, &t_raw);
*temp = (((float)t_raw) / 256.0f) + 25.0f;
return 0;
}
/* Private functions */
static int32_t s_ism330_cb_init(void)
{
/* Its only stub, all init is already done */
return 0;
}
static int32_t s_ism330_cb_deinit(void)
{
/* Its only stub */
return 0;
}
static int32_t s_ism330_cb_read(uint16_t address,
uint16_t reg,
uint8_t* data,
uint16_t len)
{
int32_t retval = 0;
/* Assert CS pin */
HAL_GPIO_WritePin(ISM_CS_GPIO_Port, ISM_CS_Pin, GPIO_PIN_RESET);
/* Read request is tagged with read request mask */
static const uint8_t spi_read_mask = 0x80U;
uint8_t reg_addr = reg | spi_read_mask;
/* Write address of register we want to read from */
const HAL_StatusTypeDef status_write_addr =
HAL_SPI_Transmit(&hspi3, ®_addr, 1U, ISM330_SPI_TIMEOUT_MS);
if (HAL_OK != status_write_addr) {
retval = -1;
goto exit;
}
/* Read data from selected address */
if (0 < len) {
const HAL_StatusTypeDef status_read_data =
HAL_SPI_Receive(&hspi3, data, len, ISM330_SPI_TIMEOUT_MS);
if (HAL_OK != status_read_data) {
retval = -1;
goto exit;
}
} else {
LOG_ERROR("Fail zero len read");
retval = -1;
goto exit;
}
exit:
/* Always deassert CS */
HAL_GPIO_WritePin(ISM_CS_GPIO_Port, ISM_CS_Pin, GPIO_PIN_SET);
return retval;
}
static int32_t s_ism330_cb_write(uint16_t address,
uint16_t reg,
uint8_t* data,
uint16_t len)
{
int32_t retval = 0;
/* Assert CS pin */
HAL_GPIO_WritePin(ISM_CS_GPIO_Port, ISM_CS_Pin, GPIO_PIN_RESET);
/* Write address of register we want to write to */
uint8_t reg_address = reg;
const HAL_StatusTypeDef status_write_addr =
HAL_SPI_Transmit(&hspi3, ®_address, 1, ISM330_SPI_TIMEOUT_MS);
if (HAL_OK != status_write_addr) {
retval = -1;
goto exit;
}
/* Write data */
if (0 < len) {
const HAL_StatusTypeDef status_write_data =
HAL_SPI_Transmit(&hspi3, data, len, ISM330_SPI_TIMEOUT_MS);
if (HAL_OK != status_write_data) {
retval = -1;
goto exit;
}
} else {
LOG_ERROR("Fail zero len write");
retval = -1;
goto exit;
}
exit:
/* Always deassert CS */
HAL_GPIO_WritePin(ISM_CS_GPIO_Port, ISM_CS_Pin, GPIO_PIN_SET);
return retval;
}
int32_t s_ISM330DLC_Init_custom_version(ISM330DLC_Object_t *pObj)
{
/* Reset all the configuration registers in order to set correctly */
if (ism330dlc_reset_set(&(pObj->Ctx),PROPERTY_ENABLE) != ISM330DLC_OK)
{
return ISM330DLC_ERROR;
}
/* Original library fn. lacks delay and reinitialisation of 3-wire SPI here */
HAL_Delay(10);
/* Enable SPI 3-Wires on the component */
uint8_t data = 0x0C;
if (ISM330DLC_Write_Reg(pObj, ISM330DLC_CTRL3_C, data) != ISM330DLC_OK)
{
return ISM330DLC_ERROR;
}
/* Enable register address automatically incremented during a multiple byte
access with a serial interface. */
if (ism330dlc_auto_increment_set(&(pObj->Ctx), PROPERTY_ENABLE) != ISM330DLC_OK)
{
return ISM330DLC_ERROR;
}
/* Enable BDU */
if (ism330dlc_block_data_update_set(&(pObj->Ctx), PROPERTY_ENABLE) != ISM330DLC_OK)
{
return ISM330DLC_ERROR;
}
/* FIFO mode selection */
if (ism330dlc_fifo_mode_set(&(pObj->Ctx), ISM330DLC_BYPASS_MODE) != ISM330DLC_OK)
{
return ISM330DLC_ERROR;
}
/* Select default output data rate. */
pObj->acc_odr = ISM330DLC_XL_ODR_104Hz;
/* Output data rate selection - power down. */
if (ism330dlc_xl_data_rate_set(&(pObj->Ctx), ISM330DLC_XL_ODR_OFF) != ISM330DLC_OK)
{
return ISM330DLC_ERROR;
}
/* Full scale selection. */
if (ism330dlc_xl_full_scale_set(&(pObj->Ctx), ISM330DLC_2g) != ISM330DLC_OK)
{
return ISM330DLC_ERROR;
}
/* Select default output data rate. */
pObj->gyro_odr = ISM330DLC_GY_ODR_104Hz;
/* Output data rate selection - power down. */
if (ism330dlc_gy_data_rate_set(&(pObj->Ctx), ISM330DLC_GY_ODR_OFF) != ISM330DLC_OK)
{
return ISM330DLC_ERROR;
}
/* Full scale selection. */
if (ism330dlc_gy_full_scale_set(&(pObj->Ctx), ISM330DLC_2000dps) != ISM330DLC_OK)
{
return ISM330DLC_ERROR;
}
pObj->is_initialized = 1;
return ISM330DLC_OK;
}
My results:
00:00:00.011: INFO: Sensors Board App booting up...
00:00:00.109: INFO: ISM330DLC chip id is valid
00:00:00.299: INFO: IMU X = -81 | Y = 221 | Z = 22 | X = 1610 | Y = 17710 | Z = 25270
00:00:00.318: INFO: IMU X = -5 | Y = 0 | Z = 23 | X = 5460 | Y = 36540 | Z = 26110
00:00:00.337: INFO: IMU X = -4 | Y = 0 | Z = 22 | X = -6930 | Y = 1470 | Z = 25900
00:00:00.356: INFO: IMU X = 0 | Y = 0 | Z = 22 | X = 770 | Y = -1330 | Z = 24780
00:00:00.375: INFO: IMU X = 0 | Y = 0 | Z = 23 | X = 910 | Y = -630 | Z = 26530
00:00:00.394: INFO: IMU X = 0 | Y = 0 | Z = 23 | X = 910 | Y = 140 | Z = 26740
00:00:00.413: INFO: IMU X = 0 | Y = 0 | Z = 22 | X = 910 | Y = -350 | Z = 26530
00:00:00.432: INFO: IMU X = 0 | Y = 0 | Z = 21 | X = 910 | Y = -560 | Z = 24570
00:00:00.451: INFO: IMU X = 0 | Y = 0 | Z = 19 | X = 910 | Y = -280 | Z = 23170
00:00:00.469: INFO: IMU X = 0 | Y = 0 | Z = 20 | X = 980 | Y = -350 | Z = 23800
00:00:00.488: INFO: IMU X = 0 | Y = 0 | Z = 22 | X = 980 | Y = -350 | Z = 25620
00:00:00.507: INFO: IMU X = 0 | Y = 0 | Z = 24 | X = 980 | Y = -350 | Z = 27160
00:00:00.526: INFO: IMU X = 0 | Y = 0 | Z = 24 | X = 980 | Y = -350 | Z = 28210
00:00:00.545: INFO: IMU X = 0 | Y = 0 | Z = 22 | X = 980 | Y = -420 | Z = 27160
00:00:00.564: INFO: IMU X = 0 | Y = 0 | Z = 23 | X = 910 | Y = -420 | Z = 27720
00:00:00.583: INFO: IMU X = 0 | Y = 0 | Z = 23 | X = 910 | Y = -420 | Z = 28490
00:00:00.602: INFO: IMU X = 0 | Y = 0 | Z = 22 | X = 910 | Y = -420 | Z = 26390
00:00:00.621: INFO: IMU X = 0 | Y = 0 | Z = 21 | X = 910 | Y = -420 | Z = 25130
00:00:00.640: INFO: IMU X = 0 | Y = 0 | Z = 20 | X = 910 | Y = -420 | Z = 24500
00:00:00.659: INFO: IMU X = 0 | Y = 0 | Z = 22 | X = 910 | Y = -350 | Z = 24360
00:00:00.677: INFO: IMU X = 0 | Y = 0 | Z = 22 | X = 910 | Y = -350 | Z = 24570
00:00:00.696: INFO: IMU X = 0 | Y = 0 | Z = 23 | X = 980 | Y = -420 | Z = 25690
00:00:00.715: INFO: IMU X = 0 | Y = 0 | Z = 23 | X = 980 | Y = -280 | Z = 27370
00:00:00.734: INFO: IMU X = 0 | Y = 0 | Z = 22 | X = 910 | Y = -280 | Z = 26110
00:00:00.753: INFO: IMU X = 0 | Y = 0 | Z = 21 | X = 980 | Y = -350 | Z = 24780
00:00:00.772: INFO: IMU X = 0 | Y = 0 | Z = 22 | X = 980 | Y = -280 | Z = 24850
00:00:00.791: INFO: IMU X = 0 | Y = 0 | Z = 23 | X = 910 | Y = -280 | Z = 26250
00:00:00.810: INFO: IMU X = 0 | Y = 0 | Z = 1043 | X = 910 | Y = -350 | Z = 27790
00:00:00.838: INFO: IMU X = -3 | Y = -19 | Z = 1044 | X = -3850 | Y = -21980 | Z = 1197280
00:00:00.857: INFO: IMU X = -3 | Y = -20 | Z = 1044 | X = -3850 | Y = -23380 | Z = 1198470
00:00:00.876: INFO: IMU X = -3 | Y = -20 | Z = 1044 | X = -3780 | Y = -23940 | Z = 1198540
00:00:00.895: INFO: IMU X = -3 | Y = -22 | Z = 1044 | X = -3780 | Y = -24640 | Z = 1197630
00:00:00.914: INFO: IMU X = -3 | Y = -22 | Z = 1043 | X = -3710 | Y = -24920 | Z = 1197280
00:00:00.933: INFO: IMU X = -3 | Y = -21 | Z = 1043 | X = -3710 | Y = -25480 | Z = 1197070
00:00:00.951: INFO: IMU X = -3 | Y = -19 | Z = 1043 | X = -3710 | Y = -23870 | Z = 1197560
00:00:00.970: INFO: IMU X = -3 | Y = -17 | Z = 1043 | X = -3780 | Y = -21350 | Z = 1198050
00:00:00.989: INFO: IMU X = -3 | Y = -16 | Z = 1043 | X = -3780 | Y = -20720 | Z = 1196930
00:00:01.008: INFO: IMU X = -3 | Y = -18 | Z = 1044 | X = -3710 | Y = -20090 | Z = 1197280
00:00:01.027: INFO: IMU X = -3 | Y = -19 | Z = 1042 | X = -3780 | Y = -21280 | Z = 1197490
00:00:01.046: INFO: IMU X = -3 | Y = -21 | Z = 1045 | X = -3640 | Y = -23590 | Z = 1197280
00:00:01.065: INFO: IMU X = -3 | Y = -23 | Z = 1043 | X = -3920 | Y = -24990 | Z = 1197420
00:00:01.084: INFO: IMU X = -3 | Y = -23 | Z = 1043 | X = -3780 | Y = -26950 | Z = 1197280
00:00:01.103: INFO: IMU X = -3 | Y = -22 | Z = 1043 | X = -3850 | Y = -26040 | Z = 1197980
00:00:01.122: INFO: IMU X = -3 | Y = -20 | Z = 1043 | X = -3780 | Y = -25480 | Z = 1196930
00:00:01.140: INFO: IMU X = -3 | Y = -20 | Z = 1044 | X = -3990 | Y = -23450 | Z = 1198470
00:00:01.159: INFO: IMU X = -3 | Y = -18 | Z = 1042 | X = -3780 | Y = -21420 | Z = 1196580
00:00:01.178: INFO: IMU X = -3 | Y = -18 | Z = 1043 | X = -3990 | Y = -21420 | Z = 1198960
00:00:01.197: INFO: IMU X = -3 | Y = -18 | Z = 1043 | X = -3850 | Y = -20580 | Z = 1196790
00:00:01.216: INFO: IMU X = -3 | Y = -20 | Z = 1042 | X = -3850 | Y = -23030 | Z = 1196580
00:00:01.235: INFO: IMU X = -3 | Y = -22 | Z = 1042 | X = -3710 | Y = -24430 | Z = 1196650
00:00:01.254: INFO: IMU X = -3 | Y = -23 | Z = 1042 | X = -3780 | Y = -25830 | Z = 1197280
00:00:01.273: INFO: IMU X = -3 | Y = -21 | Z = 1043 | X = -3710 | Y = -25410 | Z = 1196090
00:00:01.292: INFO: IMU X = -3 | Y = -20 | Z = 0 | X = -3710 | Y = -24780 | Z = 1197280
00:00:01.311: INFO: IMU X = 0 | Y = 23 | Z = 0 | X = -420 | Y = 27650 | Z = 980
00:00:01.329: INFO: IMU X = 0 | Y = 25 | Z = 0 | X = -350 | Y = 29820 | Z = 980
00:00:01.348: INFO: IMU X = 0 | Y = 25 | Z = 0 | X = -420 | Y = 28770 | Z = 980
00:00:01.367: INFO: IMU X = 0 | Y = 23 | Z = 0 | X = -350 | Y = 28140 | Z = 910
00:00:01.386: INFO: IMU X = 0 | Y = 22 | Z = 0 | X = -350 | Y = 26740 | Z = 910
00:00:01.405: INFO: IMU X = 0 | Y = 21 | Z = 0 | X = -350 | Y = 25970 | Z = 980
00:00:01.424: INFO: IMU X = 0 | Y = 21 | Z = 0 | X = -350 | Y = 24150 | Z = 910
00:00:01.443: INFO: IMU X = 0 | Y = 22 | Z = 0 | X = -350 | Y = 24640 | Z = 910
00:00:01.462: INFO: IMU X = 0 | Y = 23 | Z = 0 | X = -350 | Y = 26180 | Z = 910
00:00:01.481: INFO: IMU X = 0 | Y = 23 | Z = 0 | X = -350 | Y = 27510 | Z = 980
00:00:01.500: INFO: IMU X = 0 | Y = 22 | Z = 0 | X = -350 | Y = 26740 | Z = 980
00:00:01.518: INFO: IMU X = 0 | Y = 21 | Z = 0 | X = -350 | Y = 25830 | Z = 910
00:00:01.537: INFO: IMU X = 0 | Y = 21 | Z = 0 | X = -350 | Y = 23800 | Z = 980
00:00:01.556: INFO: IMU X = 0 | Y = 21 | Z = 0 | X = -350 | Y = 24360 | Z = 980
00:00:01.575: INFO: IMU X = 0 | Y = 22 | Z = 0 | X = -420 | Y = 25690 | Z = 980
00:00:01.594: INFO: IMU X = 0 | Y = 23 | Z = 0 | X = -350 | Y = 26320 | Z = 910
00:00:01.613: INFO: IMU X = 0 | Y = 24 | Z = 0 | X = -350 | Y = 27370 | Z = 980
00:00:01.632: INFO: IMU X = 0 | Y = 23 | Z = 0 | X = -420 | Y = 27510 | Z = 980
00:00:01.651: INFO: IMU X = 0 | Y = 22 | Z = 0 | X = -490 | Y = 27300 | Z = 980
00:00:01.670: INFO: IMU X = 0 | Y = 21 | Z = 0 | X = -420 | Y = 25130 | Z = 980
00:00:01.689: INFO: IMU X = 0 | Y = 20 | Z = 0 | X = -420 | Y = 24920 | Z = 980
00:00:01.708: INFO: IMU X = 0 | Y = 22 | Z = 0 | X = -350 | Y = 24710 | Z = 910
00:00:01.726: INFO: IMU X = 0 | Y = 22 | Z = 0 | X = -350 | Y = 25480 | Z = 910
00:00:01.745: INFO: IMU X = 0 | Y = 23 | Z = 0 | X = -350 | Y = 26670 | Z = 910
00:00:01.764: INFO: IMU X = 0 | Y = 24 | Z = 0 | X = -350 | Y = 28700 | Z = 910
00:00:01.783: INFO: IMU X = 0 | Y = 24 | Z = 0 | X = -350 | Y = 29120 | Z = 910
00:00:01.802: INFO: IMU X = 0 | Y = 23 | Z = 0 | X = -350 | Y = 27020 | Z = 910
00:00:01.821: INFO: IMU X = 0 | Y = 22 | Z = 0 | X = -280 | Y = 26180 | Z = 910
00:00:01.840: INFO: IMU X = 0 | Y = 20 | Z = 0 | X = -350 | Y = 23660 | Z = 910
00:00:01.859: INFO: IMU X = 0 | Y = 19 | Z = 0 | X = -350 | Y = 22400 | Z = 980
00:00:01.878: INFO: IMU X = 0 | Y = 20 | Z = 0 | X = -350 | Y = 22820 | Z = 980
00:00:01.897: INFO: IMU X = -22 | Y = 1044 | Z = -3 | X = -25200 | Y = 1196160 | Z = -3780
00:00:01.915: INFO: IMU X = -19 | Y = 1042 | Z = -3 | X = -23730 | Y = 1196370 | Z = -3780
00:00:01.934: INFO: IMU X = -18 | Y = 1043 | Z = -3 | X = -21840 | Y = 1197210 | Z = -3850
00:00:01.953: INFO: IMU X = -18 | Y = 1042 | Z = -3 | X = -21070 | Y = 1197070 | Z = -3850
00:00:01.972: INFO: IMU X = -18 | Y = 1042 | Z = -3 | X = -21000 | Y = 1196790 | Z = -3920
00:00:01.991: INFO: IMU X = -19 | Y = 1043 | Z = -3 | X = -22330 | Y = 1197000 | Z = -3850
00:00:02.010: INFO: IMU X = -21 | Y = 1042 | Z = -3 | X = -23170 | Y = 1196650 | Z = -3850
00:00:02.029: INFO: IMU X = -22 | Y = 1041 | Z = -3 | X = -25550 | Y = 1197840 | Z = -3780
00:00:02.048: INFO: IMU X = -21 | Y = 1042 | Z = -3 | X = -24290 | Y = 1195530 | Z = -3850
00:00:02.067: INFO: IMU X = -21 | Y = 1042 | Z = -3 | X = -24990 | Y = 1195880 | Z = -3780
00:00:02.086: INFO: IMU X = -19 | Y = 1042 | Z = -3 | X = -22260 | Y = 1196440 | Z = -3780
00:00:02.104: INFO: IMU X = -19 | Y = 1042 | Z = -3 | X = -22890 | Y = 1197420 | Z = -3710
00:00:02.123: INFO: IMU X = -19 | Y = 1042 | Z = -3 | X = -22400 | Y = 1196580 | Z = -3780
00:00:02.142: INFO: IMU X = -19 | Y = 1043 | Z = -3 | X = -21910 | Y = 1197000 | Z = -3710
00:00:02.161: INFO: IMU X = -20 | Y = 1043 | Z = -3 | X = -22120 | Y = 1196300 | Z = -3710
00:00:02.180: INFO: IMU X = -20 | Y = 1042 | Z = -3 | X = -24080 | Y = 1195600 | Z = -3780
00:00:02.199: INFO: IMU X = -20 | Y = 1043 | Z = -3 | X = -22680 | Y = 1197280 | Z = -3780
00:00:02.218: INFO: IMU X = -20 | Y = 1042 | Z = -3 | X = -22890 | Y = 1195880 | Z = -3780
00:00:02.237: INFO: IMU X = 23 | Y = 0 | Z = 0 | X = -24710 | Y = 1197560 | Z = -350
00:00:02.256: INFO: IMU X = 23 | Y = 0 | Z = 0 | X = 26530 | Y = 910 | Z = -350
00:00:02.275: INFO: IMU X = 22 | Y = 0 | Z = 0 | X = 26740 | Y = 980 | Z = -350
00:00:02.293: INFO: IMU X = 22 | Y = 0 | Z = 0 | X = 24360 | Y = 910 | Z = -280
00:00:02.312: INFO: IMU X = 21 | Y = 0 | Z = 0 | X = 25270 | Y = 910 | Z = -280
00:00:02.331: INFO: IMU X = 21 | Y = 0 | Z = 0 | X = 24850 | Y = 910 | Z = -350
00:00:02.350: INFO: IMU X = 22 | Y = 0 | Z = 0 | X = 25480 | Y = 910 | Z = -350
00:00:02.369: INFO: IMU X = 23 | Y = 0 | Z = 0 | X = 27370 | Y = 910 | Z = -350
00:00:02.388: INFO: IMU X = 24 | Y = 0 | Z = 0 | X = 27160 | Y = 980 | Z = -350
00:00:02.407: INFO: IMU X = 23 | Y = 0 | Z = 0 | X = 26740 | Y = 910 | Z = -350
00:00:02.426: INFO: IMU X = 22 | Y = 0 | Z = 0 | X = 26320 | Y = 980 | Z = -350
00:00:02.445: INFO: IMU X = 21 | Y = 0 | Z = 0 | X = 24080 | Y = 910 | Z = -420
00:00:02.464: INFO: IMU X = 21 | Y = 0 | Z = 0 | X = 23940 | Y = 910 | Z = -420
00:00:02.482: INFO: IMU X = 22 | Y = 0 | Z = 0 | X = 24990 | Y = 980 | Z = -420
00:00:02.501: INFO: IMU X = 22 | Y = 0 | Z = 0 | X = 25760 | Y = 980 | Z = -350
00:00:02.520: INFO: IMU X = 23 | Y = 0 | Z = 0 | X = 27300 | Y = 910 | Z = -350
00:00:02.539: INFO: IMU X = 24 | Y = 0 | Z = 0 | X = 28000 | Y = 910 | Z = -350
00:00:02.558: INFO: IMU X = 23 | Y = 0 | Z = 0 | X = 27160 | Y = 910 | Z = -350
00:00:02.577: INFO: IMU X = 24 | Y = 0 | Z = 0 | X = 27020 | Y = 910 | Z = -350
00:00:02.596: INFO: IMU X = 22 | Y = 0 | Z = 0 | X = 25970 | Y = 910 | Z = -350
00:00:02.615: INFO: IMU X = 20 | Y = 0 | Z = 0 | X = 26110 | Y = 910 | Z = -280
00:00:02.634: INFO: IMU X = 20 | Y = 0 | Z = 0 | X = 22890 | Y = 910 | Z = -280
00:00:02.653: INFO: IMU X = 20 | Y = 0 | Z = 0 | X = 22680 | Y = 910 | Z = -350
00:00:02.672: INFO: IMU X = 22 | Y = 0 | Z = 0 | X = 24850 | Y = 910 | Z = -280
00:00:02.690: INFO: IMU X = 23 | Y = 0 | Z = 0 | X = 26320 | Y = 980 | Z = -280
00:00:02.709: INFO: IMU X = 23 | Y = 0 | Z = 0 | X = 27230 | Y = 910 | Z = -350
00:00:02.728: INFO: IMU X = 23 | Y = 0 | Z = 0 | X = 27510 | Y = 910 | Z = -350
00:00:02.747: INFO: IMU X = 22 | Y = 0 | Z = 0 | X = 26740 | Y = 910 | Z = -350
00:00:02.766: INFO: IMU X = 22 | Y = 0 | Z = 0 | X = 25270 | Y = 980 | Z = -350
00:00:02.785: INFO: IMU X = 22 | Y = 0 | Z = 0 | X = 25060 | Y = 910 | Z = -350
00:00:02.804: INFO: IMU X = 21 | Y = 0 | Z = 0 | X = 24920 | Y = 910 | Z = -420
00:00:02.823: INFO: IMU X = 1043 | Y = -3 | Z = -20 | X = 25970 | Y = 910 | Z = -350
00:00:02.842: INFO: IMU X = 1042 | Y = -3 | Z = -21 | X = 1196440 | Y = -3710 | Z = -24080
00:00:02.861: INFO: IMU X = 1043 | Y = -3 | Z = -20 | X = 1195880 | Y = -3780 | Z = -24080
00:00:02.879: INFO: IMU X = 1043 | Y = -3 | Z = -19 | X = 1196790 | Y = -3780 | Z = -24150
00:00:02.898: INFO: IMU X = 1043 | Y = -3 | Z = -18 | X = 1197280 | Y = -3850 | Z = -22540
00:00:02.917: INFO: IMU X = 1041 | Y = -3 | Z = -20 | X = 1196510 | Y = -3710 | Z = -22820
00:00:02.936: INFO: IMU X = 1042 | Y = -3 | Z = -19 | X = 1197490 | Y = -3850 | Z = -21630
00:00:02.955: INFO: IMU X = 1041 | Y = -3 | Z = -20 | X = 1197140 | Y = -3780 | Z = -22120
00:00:02.974: INFO: IMU X = 1043 | Y = -3 | Z = -19 | X = 1196440 | Y = -3850 | Z = -22820
00:00:02.993: INFO: IMU X = 1041 | Y = -3 | Z = -19 | X = 1197490 | Y = -3920 | Z = -22610
00:00:03.012: INFO: IMU X = 1042 | Y = -3 | Z = -19 | X = 1196580 | Y = -3780 | Z = -23240
00:00:03.031: INFO: IMU X = 1042 | Y = -3 | Z = -21 | X = 1196230 | Y = -3780 | Z = -23380
00:00:03.050: INFO: IMU X = 1042 | Y = -3 | Z = -22 | X = 1197000 | Y = -3780 | Z = -25480
2025-01-28 10:44 PM
I forgot to add how I want to implement the flow in the program:
- INT1 pin changes state to 1 when FIFO reach watermark, which is set fairly low to keep samples latency as low as possible
- EXTI interrupt handler in STM32F7 MCU queues an event into events queue, then main program loop enqueues this event and performs readout of sample / samples from FIFO
In my code snippet in original post I have unused function "ism_check_drdy" and I call "ism_read_acc_gyro" from the context of event handler in my main program loop.
2025-01-28 11:28 PM
If I understand correctly results in FIFO could be mixed up in some manner and I should know the pattern from pattern register, lets try out then this FIFO readout function:
int ism_read_acc_gyro(ism_acc_gyro_res_t* results)
{
/* Collect results */
ISM330DLC_AxesRaw_t gyro_raw = {0};
ISM330DLC_AxesRaw_t acc_raw = {0};
uint16_t pattern[6] = {0};
ISM330DLC_FIFO_Get_Pattern(&ism330_hdl, &pattern[0]);
ISM330DLC_FIFO_Get_Data_Word(&ism330_hdl, &gyro_raw.x);
ISM330DLC_FIFO_Get_Pattern(&ism330_hdl, &pattern[1]);
ISM330DLC_FIFO_Get_Data_Word(&ism330_hdl, &gyro_raw.y);
ISM330DLC_FIFO_Get_Pattern(&ism330_hdl, &pattern[2]);
ISM330DLC_FIFO_Get_Data_Word(&ism330_hdl, &gyro_raw.z);
ISM330DLC_FIFO_Get_Pattern(&ism330_hdl, &pattern[3]);
ISM330DLC_FIFO_Get_Data_Word(&ism330_hdl, &(acc_raw.x));
ISM330DLC_FIFO_Get_Pattern(&ism330_hdl, &pattern[4]);
ISM330DLC_FIFO_Get_Data_Word(&ism330_hdl, &(acc_raw.y));
ISM330DLC_FIFO_Get_Pattern(&ism330_hdl, &pattern[5]);
ISM330DLC_FIFO_Get_Data_Word(&ism330_hdl, &(acc_raw.z));
/* Calculate result */
results->acc_x = (int32_t)((float)((float)acc_raw.x * s_acc_sensitivity));
results->acc_y = (int32_t)((float)((float)acc_raw.y * s_acc_sensitivity));
results->acc_z = (int32_t)((float)((float)acc_raw.z * s_acc_sensitivity));
results->vel_x = (int32_t)((float)((float)gyro_raw.x * s_gyro_sensitivity));
results->vel_y = (int32_t)((float)((float)gyro_raw.y * s_gyro_sensitivity));
results->vel_z = (int32_t)((float)((float)gyro_raw.z * s_gyro_sensitivity));
LOG_INFO("Pattern %u %u %u %u %u %u",
pattern[0], pattern[1], pattern[2],
pattern[3], pattern[4], pattern[5]);
return 0;
}
The results is:
00:00:11.498: INFO: Pattern 1 5 3 1 5 3
00:00:11.498: INFO: IMU X = -41 | Y = -3 | Z = 1043 | X = -46270 | Y = -3710 | Z = 1195110
It looks interesting, because I would expect 3th result to be Z axis of accelerometer, and it looks correct, but why I get pattern of 1, 5, 3, 1, 5, 3, instead of something like "0, 1, 2, 3, 4, 5" from page 92 of application note AN5125 when I set the same ODR settings as application note in this example (acc 104 Hz, gyro 104 Hz, FIFO 104 Hz, watermark = 120)
2025-01-29 01:53 AM
Ok I did try another settings: init:
int ism_init(void)
{
/* ISM330 library IO */
static ISM330DLC_IO_t ism330_io = {
.Init = s_ism330_cb_init,
.DeInit = s_ism330_cb_deinit,
.BusType = 2, /* 0 means I2C, 1 means SPI 4-Wires, 2 means SPI-3-Wires */
.Address = 69, /* dont know how to use this in this library */
.ReadReg = s_ism330_cb_read,
.WriteReg = s_ism330_cb_write,
.GetTick = NULL, /* callback not used int this library anyway */
};
/* Register ISM330 library callbacks */
ISM330DLC_RegisterBusIO(&ism330_hdl, &ism330_io);
/* Iniatialise ISM330 chip using fixed version of ISM330DLC_Init procedure */
s_ISM330DLC_Init_custom_version(&ism330_hdl);
/* Check ISM330 ID */
uint8_t ism330_id = 0;
ISM330DLC_ReadID(&ism330_hdl, &ism330_id);
if (ISM330DLC_ID == ism330_id) {
LOG_INFO("ISM330DLC chip id is valid");
} else {
LOG_ERROR("ISM330DLC chip id invalid");
}
/* Set ISM330 in high performance mode */
ism330dlc_xl_power_mode_set(&ism330_hdl.Ctx, ISM330DLC_XL_HIGH_PERFORMANCE);
/* Set scale */
ISM330DLC_ACC_GetSensitivity(&ism330_hdl, &s_acc_sensitivity);
/* Enable toggling interrupt pin on reaching fifo watermark */
ISM330DLC_Set_Drdy_Mode(&ism330_hdl, ISM330DLC_DRDY_PULSED);
uint8_t int1_ctrl_reg_value = 0x08;
ISM330DLC_Write_Reg(&ism330_hdl, ISM330DLC_INT1_CTRL, int1_ctrl_reg_value);
/* Set output data rate (from 12.5, 208.0 to 1660.0 and even 6660.0) */
ISM330DLC_ACC_SetOutputDataRate(&ism330_hdl, 52.0);
ISM330DLC_ACC_Enable(&ism330_hdl);
/* Set ODF of FIFO */
ISM330DLC_FIFO_Set_ODR_Value(&ism330_hdl, 52.0);
/* Set FIFO decimators */
ISM330DLC_FIFO_ACC_Set_Decimation(&ism330_hdl, ISM330DLC_FIFO_XL_NO_DEC);
/* Set FIFO watermark level */
ISM330DLC_FIFO_Set_Watermark_Level(&ism330_hdl, 6);
/* Dont stop on FTH */
ISM330DLC_FIFO_Set_Stop_On_Fth(&ism330_hdl, 0);
/* Turn on FIFO */
ISM330DLC_FIFO_Set_Mode(&ism330_hdl, ISM330DLC_STREAM_MODE);
return 0;
}
Readout function called after receiving fifo watermark reached event on INT1:
int ism_read_acc_gyro(ism_acc_gyro_res_t* results)
{
/* Collect results */
ISM330DLC_AxesRaw_t acc_raw = {0};
uint16_t pattern[3] = {0};
uint16_t samples_number = 0;
ISM330DLC_FIFO_Get_Num_Samples(&ism330_hdl, &samples_number);
ISM330DLC_FIFO_Get_Pattern(&ism330_hdl, &pattern[0]);
ISM330DLC_FIFO_Get_Data_Word(&ism330_hdl, &(acc_raw.x));
ISM330DLC_FIFO_Get_Pattern(&ism330_hdl, &pattern[1]);
ISM330DLC_FIFO_Get_Data_Word(&ism330_hdl, &(acc_raw.y));
ISM330DLC_FIFO_Get_Pattern(&ism330_hdl, &pattern[2]);
ISM330DLC_FIFO_Get_Data_Word(&ism330_hdl, &(acc_raw.z));
/* Calculate result */
results->acc_x = (int32_t)((float)((float)acc_raw.x * s_acc_sensitivity));
results->acc_y = (int32_t)((float)((float)acc_raw.y * s_acc_sensitivity));
results->acc_z = (int32_t)((float)((float)acc_raw.z * s_acc_sensitivity));
LOG_INFO("Samples %u Pattern %u %u %u",
samples_number,
pattern[0], pattern[1], pattern[2]);
return 0;
}
Result:
00:00:00.011: INFO: Sensors Board App booting up...
00:00:00.109: INFO: ISM330DLC chip id is valid
00:00:00.148: INFO: Samples 6 Pattern 0 1 2
00:00:00.148: INFO: IMU X = 1025 | Y = 1035 | Z = 1035 | X = 0 | Y = 0 | Z = 0
00:00:00.185: INFO: Samples 6 Pattern 0 1 2
00:00:00.185: INFO: IMU X = 1037 | Y = 1036 | Z = 1036 | X = 0 | Y = 0 | Z = 0
00:00:00.222: INFO: Samples 6 Pattern 0 1 2
00:00:00.222: INFO: IMU X = 1035 | Y = 1036 | Z = 1036 | X = 0 | Y = 0 | Z = 0
00:00:00.259: INFO: Samples 6 Pattern 0 1 2
00:00:00.259: INFO: IMU X = 1037 | Y = 1036 | Z = 1036 | X = 0 | Y = 0 | Z = 0
00:00:00.296: INFO: Samples 6 Pattern 0 1 2
00:00:00.297: INFO: IMU X = 1037 | Y = 1036 | Z = 1036 | X = 0 | Y = 0 | Z = 0
00:00:00.334: INFO: Samples 6 Pattern 0 1 2
00:00:00.334: INFO: IMU X = 1036 | Y = 1036 | Z = 1036 | X = 0 | Y = 0 | Z = 0
00:00:00.371: INFO: Samples 6 Pattern 0 1 2
00:00:00.371: INFO: IMU X = 1037 | Y = 1035 | Z = 1035 | X = 0 | Y = 0 | Z = 0
00:00:00.408: INFO: Samples 6 Pattern 0 1 2
00:00:00.408: INFO: IMU X = 1035 | Y = 1035 | Z = 1035 | X = 0 | Y = 0 | Z = 0
Pattern looks good, but result of Z axis is repeated over all axes.
2025-01-29 01:59 AM
Hi @amistar ,
Try this improved version of the code:
int ism_read_acc_gyro(ism_acc_gyro_res_t* results)
{
/* Collect results */
ISM330DLC_AxesRaw_t acc_raw = {0};
uint16_t pattern = 0;
uint16_t samples_number = 0;
if (ISM330DLC_FIFO_Get_Num_Samples(&ism330_hdl, &samples_number) != ISM330DLC_OK) {
LOG_ERROR("Failed to get number of samples from FIFO");
return -1;
}
if (samples_number < 3) {
LOG_ERROR("Insufficient samples in FIFO");
return -1;
}
for (int i = 0; i < 3; i++) {
if (ISM330DLC_FIFO_Get_Pattern(&ism330_hdl, &pattern) != ISM330DLC_OK) {
LOG_ERROR("Failed to get FIFO pattern");
return -1;
}
if (ISM330DLC_FIFO_Get_Data_Word(&ism330_hdl, ((uint16_t*)&acc_raw) + i) != ISM330DLC_OK) {
LOG_ERROR("Failed to get data word for axis %d", i);
return -1;
}
}
/* Calculate result */
results->acc_x = (int32_t)((float)((float)acc_raw.x * s_acc_sensitivity));
results->acc_y = (int32_t)((float)((float)acc_raw.y * s_acc_sensitivity));
results->acc_z = (int32_t)((float)((float)acc_raw.z * s_acc_sensitivity));
LOG_INFO("Samples %u Pattern %u %u %u",
samples_number,
pattern, pattern, pattern);
LOG_INFO("IMU X = %d | Y = %d | Z = %d",
results->acc_x, results->acc_y, results->acc_z);
return 0;
}
In this code, I used a loop to read the data for each axis (X, Y, Z) and checked that the data is read correctly. In addition, I added an error check for each read. Make sure the ISM330DLC_FIFO_Get_Data_Word function is correctly implemented and reads the data in the correct order.
If the problem persists, it might be useful to add additional debug logs to verify the values read from the FIFO before calculating them.
2025-01-29 02:25 AM
Thank you, but this did not helped, it looks like I have to stay with polling readout at 3380 rate which works perfectly.
I am using this library https://github.com/STMicroelectronics/STMems_Standard_C_drivers/tree/master/ism330dlc_STdC/examples
Could you please point which other device is the most similar or add ticket in your company work management tool for your teammates to create FIFO example for ISM330DLC ? Because there is no FIFO example for ISM330DLC and other devices often are different from it, for example they use tagging results instead of using pattern.
Best regards
2025-01-29 02:38 AM - edited 2025-01-29 02:38 AM
Hi @amistar ,
Ok, I will notice this to the team.
In the meantime, you can look at the LSM6DSM FIFO examples. Indeed, the FIFO of LSM6DSM and ISM330DLC are pretty similar.