2025-03-26 6:38 PM
Hi,
I am really new to this sensor and I was able to get the polling mode working.
I am planning for full 6.6k odr rate and FIFO samples can be 256 when INT1 should be triggered or whenever possible so I can use FIFO .
I am really confused with the order / things to keep in mind to properly get this working. I am using steval Idp0051v which has ISM330DLC sensor connected via SPI1 .
This is my code that hass all the functions to use the sensor :
/*
* memsSensor.c
*
* Created on: Mar 26, 2025
* Author: amrith
*/
#include "memsSensor.h"
#include "ism330dlc.h"
#include "main.h"
extern SPI_HandleTypeDef hspi1;
ism330dlc_ctx_t ism330dlc_ctx = {
.write_reg = ism330dlc_spi_write,
.read_reg = ism330dlc_spi_read,
.handle = NULL // Not used in this case, but can point to &hspi1 if needed
};
// IO structure for ism330dlc.h
ISM330DLC_IO_t ism330dlc_io = {
.Init = ISM330DLC_SPI_Init,
.DeInit = ISM330DLC_SPI_DeInit,
.BusType = ISM330DLC_SPI_4WIRES_BUS, // Using SPI 4-wire mode
.Address = 0x00, // Not used for SPI
.WriteReg = ISM330DLC_SPI_WriteReg,
.ReadReg = ISM330DLC_SPI_ReadReg,
.GetTick = ISM330DLC_GetTick
};
// Object structure
ISM330DLC_Object_t ism330dlc_obj;
// Previous data for change detection
static ISM330DLC_Axes_t prev_accel_data = {0, 0, 0};
static ISM330DLC_Axes_t prev_gyro_data = {0, 0, 0};
// FIFO buffer and variables
#define FIFO_WATERMARK 100 // Number of samples to trigger interrupt (max 512)
#define FIFO_SAMPLE_SIZE 12 // 6 bytes accel + 6 bytes gyro per sample
static uint8_t fifo_buffer[FIFO_WATERMARK * FIFO_SAMPLE_SIZE]; // Buffer for FIFO data
static volatile uint8_t fifo_data_ready = 0; // Flag for ISR
// SPI read implementation
int32_t ism330dlc_spi_read(void *handle, uint8_t reg, uint8_t *data, uint16_t len) {
HAL_GPIO_WritePin(ISM330DLC_CS_PORT, ISM330DLC_CS_PIN, GPIO_PIN_RESET); // CS low
reg |= 0x80; // Set read bit (MSB = 1 for read)
if (HAL_SPI_Transmit(&hspi1, ®, 1, HAL_MAX_DELAY) != HAL_OK) {
HAL_GPIO_WritePin(ISM330DLC_CS_PORT, ISM330DLC_CS_PIN, GPIO_PIN_SET); // CS high
return -1; // Error
}
if (HAL_SPI_Receive(&hspi1, data, len, HAL_MAX_DELAY) != HAL_OK) {
HAL_GPIO_WritePin(ISM330DLC_CS_PORT, ISM330DLC_CS_PIN, GPIO_PIN_SET); // CS high
return -1; // Error
}
HAL_GPIO_WritePin(ISM330DLC_CS_PORT, ISM330DLC_CS_PIN, GPIO_PIN_SET); // CS high
return 0; // Success
}
// SPI write implementation
int32_t ism330dlc_spi_write(void *handle, uint8_t reg, uint8_t *data, uint16_t len) {
HAL_GPIO_WritePin(ISM330DLC_CS_PORT, ISM330DLC_CS_PIN, GPIO_PIN_RESET); // CS low
reg &= 0x7F; // Clear read bit (MSB = 0 for write)
if (HAL_SPI_Transmit(&hspi1, ®, 1, HAL_MAX_DELAY) != HAL_OK) {
HAL_GPIO_WritePin(ISM330DLC_CS_PORT, ISM330DLC_CS_PIN, GPIO_PIN_SET); // CS high
return -1; // Error
}
if (HAL_SPI_Transmit(&hspi1, data, len, HAL_MAX_DELAY) != HAL_OK) {
HAL_GPIO_WritePin(ISM330DLC_CS_PORT, ISM330DLC_CS_PIN, GPIO_PIN_SET); // CS high
return -1; // Error
}
HAL_GPIO_WritePin(ISM330DLC_CS_PORT, ISM330DLC_CS_PIN, GPIO_PIN_SET); // CS high
return 0; // Success
}
// Higher-level IO implementations
int32_t ISM330DLC_SPI_Init(void) {
return ISM330DLC_OK; // SPI1 already initialized by CubeMX
}
int32_t ISM330DLC_SPI_DeInit(void) {
return ISM330DLC_OK; // No de-init needed
}
int32_t ISM330DLC_SPI_WriteReg(uint16_t Addr, uint16_t Reg, uint8_t *pData, uint16_t Length) {
return ism330dlc_write_reg(&ism330dlc_ctx, (uint8_t)Reg, pData, Length);
}
int32_t ISM330DLC_SPI_ReadReg(uint16_t Addr, uint16_t Reg, uint8_t *pData, uint16_t Length) {
return ism330dlc_read_reg(&ism330dlc_ctx, (uint8_t)Reg, pData, Length);
}
int32_t ISM330DLC_GetTick(void) {
return HAL_GetTick();
}
void ISM330DLC_Setup(void) {
// Register the IO functions
if (ISM330DLC_RegisterBusIO(&ism330dlc_obj, &ism330dlc_io) != ISM330DLC_OK) {
// Handle error
while (1);
}
// Link the low-level context
ism330dlc_obj.Ctx = ism330dlc_ctx;
// Initialize the sensor
if (ISM330DLC_Init(&ism330dlc_obj) != ISM330DLC_OK) {
// Handle error
while (1);
}
// Verify device ID
uint8_t device_id;
if (ISM330DLC_ReadID(&ism330dlc_obj, &device_id) != ISM330DLC_OK || device_id != ISM330DLC_ID) {
// Handle error (ISM330DLC_ID = 0x6A)
while (1);
}
}
void ISM330DLC_ConfigureFIFO(void) {
if (ISM330DLC_FIFO_Set_Mode(&ism330dlc_obj, ISM330DLC_STREAM_MODE) != BSP_ERROR_NONE)
{
ret = -1;
}
if (ISM330DLC_FIFO_Set_INT2_FIFO_Full(&ism330dlc_obj, ENABLE) != BSP_ERROR_NONE)
{
ret = -1;
}
// Verify
uint8_t reg_val;
ism330dlc_read_reg(&ism330dlc_ctx, ISM330DLC_FIFO_CTRL5, ®_val, 1);
printf("FIFO_CTRL5: 0x%02X (Expected 0x66)\n", reg_val);
ism330dlc_read_reg(&ism330dlc_ctx, ISM330DLC_INT1_CTRL, ®_val, 1);
printf("INT1_CTRL: 0x%02X (Expected 0x08)\n", reg_val);
}
void ISM330DLC_Configure(void) {
// Enable accelerometer
ISM330DLC_ACC_Enable(&ism330dlc_obj);
ISM330DLC_ACC_SetOutputDataRate(&ism330dlc_obj, ISM330DLC_XL_ODR_6k66Hz); // 52 Hz
ISM330DLC_ACC_SetFullScale(&ism330dlc_obj, ISM330DLC_16g); // ±2g
// Enable gyroscope
ISM330DLC_GYRO_Enable(&ism330dlc_obj);
ISM330DLC_GYRO_SetOutputDataRate(&ism330dlc_obj, ISM330DLC_GY_ODR_6k66Hz); // 52 Hz
ISM330DLC_GYRO_SetFullScale(&ism330dlc_obj, ISM330DLC_2000dps); // ±500 dps
// Enable Block Data Update
ism330dlc_block_data_update_set(&ism330dlc_ctx, PROPERTY_ENABLE);
// Configure FIFO
ISM330DLC_ConfigureFIFO();
// Verify
uint8_t reg_val;
ism330dlc_read_reg(&ism330dlc_ctx, ISM330DLC_CTRL1_XL, ®_val, 1);
printf("CTRL1_XL: 0x%02X (Expected 0x90)\n", reg_val);
ism330dlc_read_reg(&ism330dlc_ctx, ISM330DLC_CTRL2_G, ®_val, 1);
printf("CTRL2_G: 0x%02X (Expected 0x94)\n", reg_val);
}
//void ISM330DLC_ReadData(void) {
// ISM330DLC_Axes_t accel_data;
// ISM330DLC_Axes_t gyro_data;
//
// if (ISM330DLC_ACC_GetAxes(&ism330dlc_obj, &accel_data) == ISM330DLC_OK) {
// // printf("Accel: X=%ld, Y=%ld, Z=%ld mg\n", accel_data.x, accel_data.y, accel_data.z);
// printf("$%d %d %d;",accel_data.x, accel_data.y, accel_data.z);
// }
//
//// if (ISM330DLC_GYRO_GetAxes(&ism330dlc_obj, &gyro_data) == ISM330DLC_OK) {
//// printf("Gyro: X=%ld, Y=%ld, Z=%ld mdps\n", gyro_data.x, gyro_data.y, gyro_data.z);
//// }
//}
void ISM330DLC_ReadData(void) {
uint16_t fifo_level;
if (ism330dlc_fifo_data_level_get(&ism330dlc_ctx, &fifo_level) != 0) {
return; // Error
}
if (fifo_level > 0) {
// Each sample is 12 bytes (6 for accel, 6 for gyro)
uint8_t buffer[12 * 100]; // Buffer for up to 100 samples
uint16_t bytes_to_read = fifo_level * 12;
if (ism330dlc_fifo_raw_data_get(&ism330dlc_ctx, buffer, bytes_to_read) == 0) {
for (uint16_t i = 0; i < fifo_level; i++) {
// Extract accel and gyro from buffer (16-bit per axis)
int16_t accel_x = (int16_t)(buffer[i * 12 + 0] | (buffer[i * 12 + 1] << 8));
int16_t accel_y = (int16_t)(buffer[i * 12 + 2] | (buffer[i * 12 + 3] << 8));
int16_t accel_z = (int16_t)(buffer[i * 12 + 4] | (buffer[i * 12 + 5] << 8));
int16_t gyro_x = (int16_t)(buffer[i * 12 + 6] | (buffer[i * 12 + 7] << 8));
int16_t gyro_y = (int16_t)(buffer[i * 12 + 8] | (buffer[i * 12 + 9] << 8));
int16_t gyro_z = (int16_t)(buffer[i * 12 + 10] | (buffer[i * 12 + 11] << 8));
// Convert raw to physical units (example for ±2g and ±500 dps)
float accel_x_mg = ISM330DLC_FROM_FS_2g_TO_mg(accel_x);
float accel_y_mg = ISM330DLC_FROM_FS_2g_TO_mg(accel_y);
float accel_z_mg = ISM330DLC_FROM_FS_2g_TO_mg(accel_z);
float gyro_x_mdps = ISM330DLC_FROM_FS_500dps_TO_mdps(gyro_x);
float gyro_y_mdps = ISM330DLC_FROM_FS_500dps_TO_mdps(gyro_y);
float gyro_z_mdps = ISM330DLC_FROM_FS_500dps_TO_mdps(gyro_z);
// Check for changes (optional threshold)
#define CHANGE_THRESHOLD 10
if (abs(accel_x_mg - prev_accel_data.x) > CHANGE_THRESHOLD ||
abs(accel_y_mg - prev_accel_data.y) > CHANGE_THRESHOLD ||
abs(accel_z_mg - prev_accel_data.z) > CHANGE_THRESHOLD) {
printf("Accel: X=%.2f, Y=%.2f, Z=%.2f mg\n", accel_x_mg, accel_y_mg, accel_z_mg);
prev_accel_data.x = accel_x_mg;
prev_accel_data.y = accel_y_mg;
prev_accel_data.z = accel_z_mg;
}
if (abs(gyro_x_mdps - prev_gyro_data.x) > CHANGE_THRESHOLD ||
abs(gyro_y_mdps - prev_gyro_data.y) > CHANGE_THRESHOLD ||
abs(gyro_z_mdps - prev_gyro_data.z) > CHANGE_THRESHOLD) {
printf("Gyro: X=%.2f, Y=%.2f, Z=%.2f mdps\n", gyro_x_mdps, gyro_y_mdps, gyro_z_mdps);
prev_gyro_data.x = gyro_x_mdps;
prev_gyro_data.y = gyro_y_mdps;
prev_gyro_data.z = gyro_z_mdps;
}
}
}
}
}