Correct procedure to initialize and configure LIS2DH12 for Stream mode

Hello Nordic,

I'm struggling to initialize and configure my LIS2DH12 accelerometer for Stream mode after an activity wake.

Platform: Running FreeRTOS with Nordic nRF52840 host MCU connected over I2C to LIS2DH12 device

I'm trying to use the Nordic SDK driver included in the SDK for this part (components\drivers_ext\lis2dh12\lis2dh12.c and .h) but having a hard time finding any examples of usage. The driver does not have API for individual register Write and handles registers via macros that modify multiple registers at a time ie:

LIS2DH12_DATA_CFG(...),  LIS2DH12_INT1_PIN_CFG(...)

LIS2DH12_INT1_CFG(...),   LIS2DH12_FIFO_CFG(...)

My ultimate goal is to

1) wake the MCU using the INT2 activity interrupt and

2) Stream FIFO data using the INT1 (OVRN_FIFO) interrupt when fifo is full and ready for reading

I can read individual samples but have not seen the OVRN_FIFO driven to the INT1 pin. I assume I'm not interacting with the registers correctly but not sure of the correct way.

Can you point me to a relevant example using this Nordic driver?

- Edwin

  • Hi Edwin,

    components\drivers_ext are external drivers that are not made in house of Nordic.

    The sensor that you are trying to use has been used a lot with nRF5SDK bate metal solution (no rtos). You need to take one of those solutions from devzone threads and port it to freertos. Porting a baremetal example to freertos is not that hard. You just need to convert some contexts in baremetal into freertos task after properly initializing freertos. If you have experience in freertos and driver development, this can be just one week time work.

  • Thanks Susheel,

    I did manage to configure the LIS2DH12 well enough to extract individual X.Y.Z magnitudes at a fast enough rate to keep up with the ODR interval. In fact reading from FIFO is not so workable at higher ODR speeds on my system so will not implement that yet. The activity wake on INT2 and DRDY data ready INT1 is working after getting scope out.

    I also opted to modify the original device driver to write individual registers rather than multiple ones in Macros as this is how all the examples I've seen configure the device - this part requires very specific register write order for it to work the way its documented to.

    In practical terms I did the following:

    1) Created single Register write function lis2dh12_direct_reg_write()

    // Exxperimental direct individual register Write
    //
     __STATIC_INLINE ret_code_t lis2dh12_direct_reg_write(lis2dh12_instance_t *     p_inst,
                                                         uint8_t reg_address,
                                                         uint8_t *                 p_data);
    

    2) used the above to first reset the device by initializing the control registers and clearing memory (LIS2DH12_BOOT_POS)

    3) followed STMicro driver examples to configure for DRDY based reads like below

        ResetAccelerometer();
        
        // Set polarity of INTx 0=HIGH
        NRF_TWI_SENSOR_REG_SET(acc.ctrl6, LIS2DH12_INT_POLARITY_MASK, LIS2DH12_INT_POLARITY_POS, 0);
        lis2dh12_direct_reg_write(pObj->pAcc, LIS2DH12_REG_CTRL_REG6, &acc.ctrl6);
        //FWK_TRACE1(FWK_TRACE_INFO_LEVEL, "acc.ctrl6 = 0x%X", acc.ctrl6); 
        
        // Set Activity Threshold
        NRF_TWI_SENSOR_REG_SET(acc.act_ths, LIS2DH12_ACT_THS_MASK, LIS2DH12_ACT_THS_POS, 4);
        lis2dh12_direct_reg_write(pObj->pAcc, LIS2DH12_REG_ACT_THS, &acc.act_ths);
        FWK_TRACE1(FWK_TRACE_INFO_LEVEL, "acc.act_ths = 0x%X", acc.act_ths);
    
        // Set Activity Duration
        // Sleep-to-wake, return-to-sleep duration.
        // 1 LSb = (8*1[LSb]+1)/ODR
        // eg: (8+1)/400Hz = 22.5ms
        // 2 second max / 22.5ms = 88.88
        NRF_TWI_SENSOR_REG_SET(acc.act_dur, LIS2DH12_ACT_THS_MASK, LIS2DH12_ACT_THS_POS, 89);
        lis2dh12_direct_reg_write(pObj->pAcc, LIS2DH12_REG_ACT_DUR, &acc.act_dur);
        FWK_TRACE1(FWK_TRACE_INFO_LEVEL, "acc.act_dur = 0x%X", acc.act_dur);
        
        // Set Activity interrupt
        NRF_TWI_SENSOR_REG_SET(acc.ctrl6, LIS2DH12_I2_ACT_MASK, LIS2DH12_I2_ACT_POS, 1);
        lis2dh12_direct_reg_write(pObj->pAcc, LIS2DH12_REG_CTRL_REG6, &acc.ctrl6);
          
        /* Enable Block Data Update. */
        NRF_TWI_SENSOR_REG_SET(acc.ctrl4, LIS2DH12_BDU_MASK, LIS2DH12_BDU_POS, 1);
        lis2dh12_direct_reg_write(pObj->pAcc, LIS2DH12_REG_CTRL_REG4, &acc.ctrl4);
        
        /* Set device for high resolution mode (12-bit) */
        //  ctrl_reg1.lpen = 0;
        //  ctrl_reg4.hr   = 1;
        NRF_TWI_SENSOR_REG_SET(acc.ctrl4, LIS2DH12_HR_MASK, LIS2DH12_HR_POS, 1);
        lis2dh12_direct_reg_write(pObj->pAcc, LIS2DH12_REG_CTRL_REG4, &acc.ctrl4);
        
        NRF_TWI_SENSOR_REG_SET(acc.ctrl1, LIS2DH12_LP_EN_MASK, LIS2DH12_LP_EN_POS, 0);
        lis2dh12_direct_reg_write(pObj->pAcc, LIS2DH12_REG_CTRL_REG1, &acc.ctrl1);
        
        vTaskDelay(MS_TO_TICKS(70));
        
        // Set ZYXDA interrupt
        NRF_TWI_SENSOR_REG_SET(acc.ctrl3, LIS2DH12_I1_ZYXDA_MASK, LIS2DH12_I1_ZYXDA_POS, 1);
        lis2dh12_direct_reg_write(pObj->pAcc, LIS2DH12_REG_CTRL_REG3, &acc.ctrl3);
        
        /* Set Output Data Rate to 100Hz. */
        NRF_TWI_SENSOR_REG_SET(acc.ctrl1, LIS2DH12_ODR_MASK, LIS2DH12_ODR_POS, LIS2DH12_ODR_400HZ);
        lis2dh12_direct_reg_write(pObj->pAcc, LIS2DH12_REG_CTRL_REG1, &acc.ctrl1);
        
        /* Set full scale to 2g. */
        NRF_TWI_SENSOR_REG_SET(acc.ctrl4, LIS2DH12_FS_MASK, LIS2DH12_FS_POS, LIS2DH12_SCALE_2G);
        lis2dh12_direct_reg_write(pObj->pAcc, LIS2DH12_REG_CTRL_REG4, &acc.ctrl4);
        
        // High Pass filter
        NRF_TWI_SENSOR_REG_SET(acc.ctrl2, LIS2DH12_HPM_MASK, LIS2DH12_HPM_POS, LIS2DH12_FILTER_MODE_NORMAL);
        lis2dh12_direct_reg_write(pObj->pAcc, LIS2DH12_REG_CTRL_REG2, &acc.ctrl2);
    
        // FDS
        NRF_TWI_SENSOR_REG_SET(acc.ctrl2, LIS2DH12_FDS_MASK, LIS2DH12_FDS_POS, 1);
        lis2dh12_direct_reg_write(pObj->pAcc, LIS2DH12_REG_CTRL_REG2, &acc.ctrl2);

    I've seen other developers adding 'magic delays' in certain places during configuration but do not have a clear idea why so will follow up directly with STMicro on this. I wanted first to reach out to Nordic since this driver is included in SDK.

    Hope this might help others.

Related