Skip to content

Commit 86064ce

Browse files
committed
Add LSM6DSV16B
1 parent d92979a commit 86064ce

File tree

8 files changed

+248
-13
lines changed

8 files changed

+248
-13
lines changed

src/cfg/cfg.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ SOFTWARE.
205205
MF_PARAM( gps_baud, 0, int32_t, 'i') \
206206
\
207207
/*IMU - Inertial Measurement Unit (acc/gyro)*/ \
208-
MF_PARAM( imu_gizmo, 0, int32_t, 'e', mf_NONE,mf_BMI270,mf_MPU6000,mf_MPU6050,mf_MPU6500,mf_MPU9150,mf_MPU9250,mf_ICM45686,mf_ICM42688,mf_ICM42688P,mf_AUTO,mf_LSM6DSV,mf_LSM6DSO) \
208+
MF_PARAM( imu_gizmo, 0, int32_t, 'e', mf_NONE,mf_BMI270,mf_MPU6000,mf_MPU6050,mf_MPU6500,mf_MPU9150,mf_MPU9250,mf_ICM45686,mf_ICM42688,mf_ICM42688P,mf_AUTO,mf_LSM6DSV,mf_LSM6DSO,mf_LSM6DSV16B) \
209209
MF_PARAM( imu_spi_bus, -1, int32_t, 'i') \
210210
MF_PARAM( imu_i2c_bus, -1, int32_t, 'i') \
211211
MF_PARAM( imu_i2c_adr, 0, int32_t, 'i') \

src/imu/ImuGizmoAuto.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ SOFTWARE.
2929
#include "ImuGizmoICM45686.h"
3030
#include "ImuGizmoICM426XX.h"
3131
#include "ImuGizmoLSM6DSV.h"
32+
#include "ImuGizmoLSM6DSV16B.h"
3233
#include "ImuGizmoLSM6DSO.h"
3334
#include "ImuGizmoBMI270.h"
3435
#include "ImuGizmoMPUXXXX.h"
@@ -49,6 +50,7 @@ class ImuGizmoAuto : public ImuGizmo {
4950
if(!gizmo) gizmo = ImuGizmoICM45686::create(config, state);
5051
if(!gizmo) gizmo = ImuGizmoICM426XX::create(config, state);
5152
if(!gizmo) gizmo = ImuGizmoLSM6DSV::create(config, state);
53+
if(!gizmo) gizmo = ImuGizmoLSM6DSV16B::create(config, state);
5254
if(!gizmo) gizmo = ImuGizmoLSM6DSO::create(config, state);
5355
if(!gizmo) gizmo = ImuGizmoBMI270::create(config, state);
5456
if(!gizmo) gizmo = ImuGizmoMPUXXXX::create(config, state);

src/imu/ImuGizmoLSM6DSV16B.h

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*==========================================================================================
2+
MIT License
3+
4+
Copyright (c) 2026 https://madflight.com
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
SOFTWARE.
23+
===========================================================================================*/
24+
25+
#pragma once
26+
27+
#include "imu.h"
28+
#include "LSM6DSV16B/LSM6DSV16B.h"
29+
30+
class ImuGizmoLSM6DSV16B : public ImuGizmo {
31+
private:
32+
ImuGizmoLSM6DSV16B() {} //private constructor
33+
ImuState *state = nullptr;
34+
35+
public:
36+
const char* name() override {return "LSM6DSV16B";}
37+
LSM6DSV16B *sensor = nullptr;
38+
SensorDevice *dev = nullptr;
39+
40+
~ImuGizmoLSM6DSV16B() {
41+
delete sensor;
42+
delete dev;
43+
}
44+
45+
static ImuGizmo* create(ImuConfig *config, ImuState *state) {
46+
if(!config || !state) return nullptr;
47+
48+
// Create SensorDevice
49+
SensorDevice *dev = SensorDevice::createImuDevice(config);
50+
if(!dev) return nullptr;
51+
52+
// Detect sensor, exit without printing anything
53+
if (!LSM6DSV16B::detect(dev)) {
54+
delete dev;
55+
return nullptr;
56+
}
57+
58+
// Create sensor
59+
auto *sensor = new LSM6DSV16B();
60+
int rv = sensor->begin(dev);
61+
if(rv < 0) {
62+
delete sensor;
63+
delete dev;
64+
Serial.printf("IMU: LSM6DSV16B init failed, rv=%d\n", rv);
65+
return nullptr;
66+
}
67+
68+
// Create gizmo
69+
auto gizmo = new ImuGizmoLSM6DSV16B();
70+
gizmo->state = state;
71+
gizmo->sensor = sensor;
72+
gizmo->dev = dev;
73+
//return config
74+
config->sample_rate = sensor->actual_sample_rate_hz;
75+
Serial.printf("IMU: LSM6DSV16B started, sample_rate:%d\n", sensor->actual_sample_rate_hz);
76+
return gizmo;
77+
}
78+
79+
/* Get sensor data in NED frame
80+
x=North (forward), y=East (right), z=Down
81+
acc: gravitation force is positive in axis direction:
82+
[ax,ay,az] nose-down:[1,0,0], right-down:[0,1,0], level:[0,0,1]
83+
gyr: direction of positive rotation by right hand rule:
84+
[gx,gy,gz] roll-right:[positive,0,0], pitch-up:[0,positive,0], yaw-right:[0,0,positive]
85+
86+
LSM6DSV has NWU orientation
87+
88+
* +--+ Y
89+
| | --> X ^ Z-up
90+
+--+ |
91+
92+
*/
93+
94+
void getMotion6NED(float *ax, float *ay, float *az, float *gx, float *gy, float *gz) override {
95+
int16_t raw[6];
96+
sensor->readraw(raw);
97+
*gx = raw[0] * sensor->gyr_scale; // N = N
98+
*gy = -raw[1] * sensor->gyr_scale; // E = -W
99+
*gz = -raw[2] * sensor->gyr_scale; // D = -U
100+
*ax = -raw[5] * sensor->acc_scale; //-N = -N
101+
*ay = raw[4] * sensor->acc_scale; //-E = W
102+
*az = raw[3] * sensor->acc_scale; //-D = U
103+
}
104+
};

src/imu/LSM6DSV/LSM6DSV.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,43 +45,46 @@ int LSM6DSV::begin(SensorDevice* dev) {
4545
// Autoincrement register address when doing block SPI reads and update continuously
4646
dev->writeReg(LSM6DSV_CTRL3, LSM6DSV_CTRL3_IF_INC | LSM6DSV_CTRL3_BDU); /*BDU bit need to be set*/
4747

48-
// Select high-accuracy ODR mode 1
48+
// Select high-accuracy ODR mode 1 - 0x62 = 0x01
49+
// Note: HAODR mode has to be enabled / disabled when the device is in power-down mode.
4950
dev->writeReg(LSM6DSV_HAODR_CFG,
5051
LSM6DSV_ENCODE_BITS(LSM6DSV_HAODR_MODE1,
5152
LSM6DSV_HAODR_CFG_HAODR_SEL_MASK,
5253
LSM6DSV_HAODR_CFG_HAODR_SEL_SHIFT));
5354

54-
// Enable the accelerometer in high accuracy
55+
// Enable the accelerometer in high accuracy - 0x10 = 0x10
56+
// Note: HAODR mode has to be enabled / disabled when the device is in power-down mode.
5557
dev->writeReg(LSM6DSV_CTRL1,
5658
LSM6DSV_ENCODE_BITS(LSM6DSV_CTRL1_OP_MODE_XL_HIGH_ACCURACY,
5759
LSM6DSV_CTRL1_OP_MODE_XL_MASK,
5860
LSM6DSV_CTRL1_OP_MODE_XL_SHIFT));
5961

60-
// Enable the gyro in high accuracy
62+
// Enable the gyro in high accuracy - 0x11 = 0x10
63+
// Note: HAODR mode has to be enabled / disabled when the device is in power-down mode.
6164
dev->writeReg(LSM6DSV_CTRL2,
6265
LSM6DSV_ENCODE_BITS(LSM6DSV_CTRL2_OP_MODE_G_HIGH_ACCURACY,
6366
LSM6DSV_CTRL2_OP_MODE_G_MASK,
6467
LSM6DSV_CTRL2_OP_MODE_G_SHIFT));
6568

66-
// Enable 16G sensitivity
69+
// Enable 16G sensitivity - 0x17 = 0x03
6770
dev->writeReg(LSM6DSV_CTRL8,
6871
LSM6DSV_ENCODE_BITS(LSM6DSV_CTRL8_FS_XL_16G,
6972
LSM6DSV_CTRL8_FS_XL_MASK,
7073
LSM6DSV_CTRL8_FS_XL_SHIFT));
7174

72-
// Enable the accelerometer odr at 1kHz
75+
// Enable the accelerometer odr at 1kHz - 0x10 = 0x09
7376
dev->writeReg(LSM6DSV_CTRL1,
7477
LSM6DSV_ENCODE_BITS(LSM6DSV_CTRL1_ODR_XL_1000HZ,
7578
LSM6DSV_CTRL1_ODR_XL_MASK,
7679
LSM6DSV_CTRL1_ODR_XL_SHIFT));
7780

78-
// Enable the gyro odr at 1kHz
81+
// Enable the gyro odr at 1kHz - 0x11 = 0x09
7982
dev->writeReg(LSM6DSV_CTRL2,
8083
LSM6DSV_ENCODE_BITS(LSM6DSV_CTRL2_ODR_G_1000HZ,
8184
LSM6DSV_CTRL2_ODR_G_MASK,
8285
LSM6DSV_CTRL2_ODR_G_SHIFT));
8386

84-
// Set the LPF1 filter bandwidth - Enable 2000 deg/s sensitivity and selected LPF1 filter setting
87+
// Set the LPF1 filter bandwidth - Enable 2000 deg/s sensitivity and selected LPF1 filter setting - 0x15 = 0x04
8588
/* filter options
8689
[LPF_NORMAL] = LSM6DSV_CTRL6_FS_G_BW_288HZ,
8790
[LPF_OPTION_1] = LSM6DSV_CTRL6_FS_G_BW_157HZ,
@@ -96,13 +99,13 @@ int LSM6DSV::begin(SensorDevice* dev) {
9699
LSM6DSV_CTRL6_FS_G_MASK,
97100
LSM6DSV_CTRL6_FS_G_SHIFT));
98101

99-
// Enable the gyro digital LPF1 filter
102+
// Enable the gyro digital LPF1 filter - 0x16 = 0x01
100103
dev->writeReg(LSM6DSV_CTRL7, LSM6DSV_CTRL7_LPF1_G_EN);
101104

102-
// Generate pulse on interrupt line, not requiring a read to clear
105+
// Generate pulse on interrupt line, not requiring a read to clear - 0x13 = 0x02
103106
dev->writeReg(LSM6DSV_CTRL4, LSM6DSV_CTRL4_DRDY_PULSED);
104107

105-
// Enable the INT1 output to interrupt when new gyro data is ready
108+
// Enable the INT1 output to interrupt when new gyro data is ready - 0x0D = 0x02
106109
dev->writeReg(LSM6DSV_INT1_CTRL, LSM6DSV_INT1_CTRL_INT1_DRDY_G);
107110

108111
// Set full speed
@@ -112,5 +115,5 @@ int LSM6DSV::begin(SensorDevice* dev) {
112115
}
113116

114117
void LSM6DSV::readraw(int16_t *raw) {
115-
dev->readRegs(LSM6DSV_OUTX_L_G, (uint8_t*)raw, 12); //ax,ay,az,gx,gy,gz little endian, no byte juggling needed for RP2,ESP32,STM32
118+
dev->readRegs(LSM6DSV_OUTX_L_G, (uint8_t*)raw, 12); //reg 0x22 - gx,gy,gz,ax,ay,az little endian, no byte juggling needed for RP2,ESP32,STM32
116119
}

src/imu/LSM6DSV/LSM6DSV.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class LSM6DSV {
3939
return (dev->readReg(0x0F) == 0x70);
4040
}
4141
int begin(SensorDevice* dev); //returns negative error code, positive warning code, or 0 on success
42-
void readraw(int16_t *raw); //read gyr[3],acc[3]
42+
void readraw(int16_t *raw); //read gx,gy,gz,ax,ay,az
4343

4444
SensorDevice* dev = nullptr;
4545
};

src/imu/LSM6DSV16B/LSM6DSV16B.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*==========================================================================================
2+
MIT License
3+
4+
Copyright (c) 2026 https://madflight.com
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
SOFTWARE.
23+
===========================================================================================*/
24+
25+
//Driver for LSM6DSV16B, LSM6DSV16BX gyroscope/accelometer
26+
27+
#include "LSM6DSV16B.h"
28+
29+
//returns negative error code, positive warning code, or 0 on success
30+
int LSM6DSV16B::begin(SensorDevice* dev) {
31+
this->dev = dev;
32+
dev->setLowSpeed(); // Use low speed for setup
33+
34+
// Check who-am-i
35+
if (!detect(dev)) return -1;
36+
37+
// Perform a software reset
38+
dev->writeReg(0x12, 0x01); //CTRL3, SW_RESET
39+
40+
// Wait for the device to be ready
41+
while (dev->readReg(0x12) & 0x01) {} //CTRL3, SW_RESET
42+
43+
// Autoincrement register address when doing block SPI reads and update continuously
44+
dev->writeReg(0x12, 0x44); //BDU bit need to be set - CTRL3, IF_INC | BDU
45+
46+
// Acc 16G sensitivity, LPF1 ODR/2, LPF2 ODR/4 (in high-performance mode)
47+
dev->writeReg(0x17, 0x03); //CTRL8, FS_XL, HP_LPF2_XL_BW
48+
49+
// Enable acc LPF2 filter
50+
dev->writeReg(0x16, 0x08); //CTRL9, LPF2_XL_EN
51+
52+
// Gyro 2000 deg/s sensitivity, LPF1 240Hz (@960kHz ODR)
53+
dev->writeReg(0x15, 0x04); //CTRL6, FS_G, LPF1_G_BW
54+
55+
// Enable gyro LPF1 filter
56+
dev->writeReg(0x16, 0x01); //CTRL7, LPF1_G_EN
57+
58+
// Acc ODR 960Hz in high-performance mode
59+
dev->writeReg(0x10, 0x09); //CTRL1, OP_MODE_XL, ODR_XL
60+
61+
// Gyro ODR 960Hz in high-performance mode
62+
dev->writeReg(0x11, 0x09); //CTRL2, OP_MODE_G, ODR_G
63+
64+
// Generate pulse on interrupt line, not requiring a read to clear
65+
dev->writeReg(0x13, 0x02); //CTRL4, DRDY_PULSED
66+
67+
// Enable the INT1 output to interrupt when new gyro data is ready
68+
dev->writeReg(0x0D, 0x02); //INT1_CTRL, INT1_DRDY_G
69+
70+
// Set full speed
71+
dev->setFreq(10000000); //10MHz
72+
73+
return 0;
74+
}
75+
76+
void LSM6DSV16B::readraw(int16_t *raw) {
77+
dev->readRegs(0x22, (uint8_t*)raw, 12); //LSM6DSV_OUTX_L_G - gx,gy,gz,az,ay,ax little endian, no byte juggling needed for RP2,ESP32,STM32
78+
}

src/imu/LSM6DSV16B/LSM6DSV16B.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*==========================================================================================
2+
MIT License
3+
4+
Copyright (c) 2026 https://madflight.com
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
SOFTWARE.
23+
===========================================================================================*/
24+
25+
//Driver for LSM6DSV16B, LSM6DSV16BX gyroscope/accelometer
26+
27+
#pragma once
28+
29+
#include <SPI.h>
30+
#include "../common/SensorDevice.h"
31+
32+
class LSM6DSV16B {
33+
public:
34+
const int actual_sample_rate_hz = 1000; //MF_TODO: allow variable sample rate
35+
const float acc_scale = 1.0 / 2048.0; //Accel scale +/-16g, 16bit, 2048 LSB/g
36+
const float gyr_scale = 0.070; // From datasheet: 70mdps/LSB for FS = ±2000 dps (so, actual FS = ±2294)
37+
38+
static bool detect(SensorDevice* dev) {
39+
return (dev->readReg(0x0F) == 0x71);
40+
}
41+
int begin(SensorDevice* dev); //returns negative error code, positive warning code, or 0 on success
42+
void readraw(int16_t *raw); //read gx,gy,gz,az,ay,ax - note swapped az,ax
43+
SensorDevice* dev = nullptr;
44+
};

src/imu/imu.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ int Imu::setup() {
107107
gizmo = ImuGizmoLSM6DSO::create(&config, (ImuState*)this);
108108
break;
109109
}
110+
case Cfg::imu_gizmo_enum::mf_LSM6DSV16B : {
111+
gizmo = ImuGizmoLSM6DSV16B::create(&config, (ImuState*)this);
112+
break;
113+
}
110114
}
111115

112116
//check gizmo

0 commit comments

Comments
 (0)