cancel
Showing results for 
Search instead for 
Did you mean: 

LSM6DSV FSM example with baro (LPS22XX) as external sensor?

KWine
Senior

I have examined the FSM example folder on github and, while there is an example for an external magnetometer, I haven't found any examples for an external barometer. Is there such an example? And if so, where can I find it?

I believe I can create my own, but it is always easier to follow a previous working example. Thanks!

1 ACCEPTED SOLUTION

Accepted Solutions

Just an FYI, I got this to work. First I configured the baro registers on Emb Adv Features page 2 with the hPa/LSB sensitivity and an average of the power-on pressure as a reference:

    // set baro sensitivity and offset for FSM operations
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_RW,    0x40);                             // Enable page write
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_SEL,   0x21);                             // Select page 2 (bit 0 must always be 1)
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_ADDR,  0x00);                             // Select EXT_FORMAT register
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x04);                             // select 3-byte format for barometer
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00);                             // set lower byte of baro sensitivity (1/4096 = 0x0C00 in HFP)
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x0C);                             // set higher byte for baro sensitivity
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, (refPressure & 0x000000FF));       // set XL byte for baro offset
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, (refPressure & 0x0000FF00) >> 8);  // set L byte for baro offset
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, (refPressure & 0x00FF0000) >> 16); // set H byte for baro offset
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_SEL,   0x01);                             // Select page 0 (bit 0 must always be 1)
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_RW,    0x00);                             // Disable page write

Then I adapted the ST motion detect FSM program to detect a 0.1 hPa pressue drop corresponding to a ~1 meter rise in altitude (so lift detect):

    // lift detect (threshold crossing) using barometer
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x51);                             // write to CONFIG_A (one threshold, one mask, one short timer)
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00);                             // write to CONFIG_B
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x10);                             // write to SIZE (18 byte program)
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00);                             // write to SETTINGS
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00);                             // write to RESET POINTER
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00);                             // write to PROGRAM POINTER
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x9A);                             // write to THRESH1 LSB
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x01);                             // write to THRESH1 MSB  (0x019A is 410 which means 0.1 mBar for barometer)
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x40);                             // write to MASKA  (-x axis) x-axis is pressure for barometer
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00);                             // write to TMASKA
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00);                             // write to TC
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x10);                             // write to TIMER3 (16 samples at 30 Hz = 0.53 seconds)
    
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x23);                             // write to SINMUX Set input multiplexer
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x02);                             // select external sensor
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x53);                             // write to GNTH1 | TI3
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x99);                             // write to OUTC
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x50);                             // write to GNTH1 | NOP
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00);                             // write to STOP

I get a "lift detect" interrupt whenever the pressure drops by ~0.1 hPa, i.e., whenever I lift the sensor over my head.

Pretty cool!

View solution in original post

4 REPLIES 4
Federica Bossi
ST Employee

Hi @KWine ,

Where have you found the example on github? Can you share the link?

Thanks

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.
KWine
Senior

https://github.com/STMicroelectronics/STMems_Finite_State_Machine

and specifically for the LSM6DSV,

https://github.com/STMicroelectronics/STMems_Finite_State_Machine/tree/master/application_examples/lsm6dsv

Very useful! But neither in the LSM6DSV nor any other (i.e., LSM6DSO) folder do I see an example for using external baro data. This would be a useful addition! Thanks.

KWine
Senior

A corollary question. I averaged ten baro samples at 1 Hz on start up to get:

15:17:43.812 -> reference Pressure = 973.6434 mBar
15:17:43.812 -> standard deviation = 0.0115 mBar
15:17:43.812 -> HF reference Pressure = 0x639B
15:17:43.812 -> FF reference Pressure = 973.5000 mBar

It looks like the half-precision result is only good to 0.5 mBar, but the difference in pressure I see when I raise the baro three feet off the table (a typical gesture motion) is about 0.1 mBar such that including baro data in the FIFO for FSM using Mode 2 seems rather hopeless.  

 

Nevermind, I see that only the sensitivity is to be entered in HFP format while the baro data is kept at full precision.

Just an FYI, I got this to work. First I configured the baro registers on Emb Adv Features page 2 with the hPa/LSB sensitivity and an average of the power-on pressure as a reference:

    // set baro sensitivity and offset for FSM operations
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_RW,    0x40);                             // Enable page write
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_SEL,   0x21);                             // Select page 2 (bit 0 must always be 1)
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_ADDR,  0x00);                             // Select EXT_FORMAT register
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x04);                             // select 3-byte format for barometer
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00);                             // set lower byte of baro sensitivity (1/4096 = 0x0C00 in HFP)
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x0C);                             // set higher byte for baro sensitivity
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, (refPressure & 0x000000FF));       // set XL byte for baro offset
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, (refPressure & 0x0000FF00) >> 8);  // set L byte for baro offset
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, (refPressure & 0x00FF0000) >> 16); // set H byte for baro offset
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_SEL,   0x01);                             // Select page 0 (bit 0 must always be 1)
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_RW,    0x00);                             // Disable page write

Then I adapted the ST motion detect FSM program to detect a 0.1 hPa pressue drop corresponding to a ~1 meter rise in altitude (so lift detect):

    // lift detect (threshold crossing) using barometer
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x51);                             // write to CONFIG_A (one threshold, one mask, one short timer)
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00);                             // write to CONFIG_B
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x10);                             // write to SIZE (18 byte program)
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00);                             // write to SETTINGS
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00);                             // write to RESET POINTER
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00);                             // write to PROGRAM POINTER
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x9A);                             // write to THRESH1 LSB
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x01);                             // write to THRESH1 MSB  (0x019A is 410 which means 0.1 mBar for barometer)
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x40);                             // write to MASKA  (-x axis) x-axis is pressure for barometer
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00);                             // write to TMASKA
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00);                             // write to TC
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x10);                             // write to TIMER3 (16 samples at 30 Hz = 0.53 seconds)
    
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x23);                             // write to SINMUX Set input multiplexer
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x02);                             // select external sensor
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x53);                             // write to GNTH1 | TI3
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x99);                             // write to OUTC
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x50);                             // write to GNTH1 | NOP
    _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00);                             // write to STOP

I get a "lift detect" interrupt whenever the pressure drops by ~0.1 hPa, i.e., whenever I lift the sensor over my head.

Pretty cool!