博主最近在調(diào)試 lsm6dso,一款集合加速度和陀螺儀的模塊,主要運(yùn)用在手持設(shè)備中。
1、前言
LSM6DSO 是 ST 公司的六軸傳感器,集成三軸加速度和三軸陀螺儀。
2、傳感器特性
- 具有數(shù)字 I2C、SPI 和 MIPI I3C 串口標(biāo)準(zhǔn)輸出,組合工作在高性能模式下功耗只要 0.55 mA。
- 滿量程加速度范圍:±2/±4/±8/±16 g,且角速率范圍為 ±125/±250/±500/±1000/±2000 dps。
- 經(jīng)過(guò)配置,LSM6DSO 可利用硬件識(shí)別出的自由落體事件、6D 方向、單擊和雙擊感應(yīng)、活動(dòng)或不活動(dòng)、喚醒事件,來(lái)生成中斷信號(hào)。
- SMD 封裝的超小尺寸和重量使其成為手持便攜式應(yīng)用的理想選擇,如智能手機(jī)、物聯(lián)網(wǎng)(IoT)連接設(shè)備,穿戴,以及需要減小封裝尺寸和重量的其他應(yīng)用,尺寸:2.5 mm x 3 mm x 0.83 mm
- 支持 1.71V to 3.6V 供電。
3、參考資料
ST 對(duì)于自己出的傳感器,都會(huì)提供驅(qū)動(dòng) demo,放在 github,如下:
https://github.com/STMicroelectronics
其中分為不同的平臺(tái),有的是僅僅基于 C 語(yǔ)言的平臺(tái)無(wú)關(guān)的驅(qū)動(dòng),有的是基于 STM32,有的是基于 Linux,有的是基于 Android,一開(kāi)始學(xué)習(xí)的時(shí)候,建議大家下載平臺(tái)無(wú)關(guān)的驅(qū)動(dòng):
若后續(xù)大家想移植到 Linux、Android ,也可以在這里可以找到工程:
https://github.com/STMicroelectronics/STMems_Standard_C_drivers
https://github.com/STMicroelectronics/st-mems-android-linux-drivers-input
https://github.com/STMicroelectronics/STMems_Linux_IIO_drivers
https://github.com/STMicroelectronics/STMems_Android_Sensor_HAL_IIO
lsm6dso-pid 參考代碼:
https://github.com/STMicroelectronics/STMems_Standard_C_drivers/tree/master/lsm6dso_STdC
https://github.com/arduino-libraries/Arduino_LSM6DSOX
https://github.com/micropython-Chinese-Community/mpy-lib/tree/master/sensor/LSM6DSO
數(shù)據(jù)手冊(cè)下載,其中包含有中文應(yīng)用手冊(cè):
https://www.st.com/zh/mems-and-sensors/lsm6dso.html
4、引腳說(shuō)明
一共 14 個(gè) PIN 腳,每個(gè)引腳的詳細(xì)說(shuō)明可以參考數(shù)據(jù)手冊(cè)。 總的來(lái)說(shuō)就是 I2C 和 SPI 無(wú)法同時(shí)使用,因?yàn)樗鼈冇泄灿?PIN 腳。
5、硬件模式
一般用模式 1,模式 2、模式 3、模式 4 比較復(fù)雜,可以外接傳感器,攝像頭等。
6、I2C 讀寫(xiě)地址
LSM6DSO 從機(jī)地址是 110101x ,最后一位 x 和一個(gè) PIN 的狀態(tài)有關(guān)系。 如果 SDO/SA0 是高,從機(jī)地址是 1101011。 如果 SDO/SA0 是低,從機(jī)地址是 1101010。
這個(gè)方案可以使得一路 I2C bus 掛兩個(gè) lsm6dso,同時(shí)使用。
加上讀寫(xiě)位,總結(jié)如下:
傳輸示意圖如下:
7、寄存器
該器件有 60+ 個(gè)寄存器,主要的幾個(gè)如下:
1、設(shè)備 ID
只讀,出廠已經(jīng)固化在硬件里面了,可以通過(guò)讀寫(xiě)這個(gè)寄存器,判斷設(shè)備是否存在,通訊是否正常,設(shè)備的 ID 是 0x6C。
2、加速度控制寄存器
這個(gè)寄存器可以設(shè)置加速度的量程、輸出速率等;
3、陀螺儀控制寄存器
這個(gè)寄存器可以設(shè)置陀螺儀的量程、輸出速率等;
4、狀態(tài)寄存器
通過(guò)讀取這個(gè)寄存器可以判斷,傳感器是否有新的數(shù)據(jù)。
5、溫度傳感器
2個(gè)寄存器,輸出的是有符號(hào)數(shù)據(jù)。
6、陀螺儀數(shù)據(jù)傳感器
總共 6 個(gè)寄存器,分 x、y、z 三軸的高位和低位,這里要注意,輸出的是有符號(hào)數(shù)據(jù)。
7、加速度數(shù)據(jù)傳感器
總共 6 個(gè)寄存器,分 x、y、z 三軸的高位和低位,這里要注意,輸出的是有符號(hào)數(shù)據(jù)。
8、代碼
博主用的是輪詢?nèi)プx數(shù)據(jù),大家也可以配置成中斷方式。 另外,博主是直接去各個(gè)數(shù)據(jù)寄存器去讀數(shù)據(jù),大家也可以配置成去器件 FIFO 中讀數(shù)據(jù)。 該器件有 3Kbyte 的 FIFO,若使用壓縮算法,可以達(dá)到 9Kbyte。
初始化部分:
i2c_init();
LSM6DSO_Check();
u8 LSM6DSO_Check(void)
{
u8 temp;
temp=LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_WHO_AM_I);
if(temp==0X6C)
return 0;
else
return 1;
}
LSM6DSO_WriteOneByte(LSM6DSO_ADDRESS,LSM6DSO_CTRL1_XL,ODR_XL_104Hz|FS_XL_2g);
LSM6DSO_WriteOneByte(LSM6DSO_ADDRESS,LSM6DSO_CTRL2_G,ODR_G_104Hz|FS_G_250);
讀數(shù)據(jù)
while(1)
{
status=LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_STATUS_REG);
if(status & TEM_DATA_AVAILABLE)
{
temp_raw=LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUT_TEMP_L)|(LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUT_TEMP_H)<<8);
temp_deg=temp_raw/TEMP_LSB_PER_DEG+TEMP_OFFSET_DEG;
sprintf((char*)temperature,"temperature:%02f",temp_deg);
LCD_ShowString(30,90,200,16,16,temperature);
}
if(status & GYR_DATA_AVAILABLE)
{
gyr_x_raw = LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTX_L_G)|(LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTX_H_G)<<8);
gyr_y_raw = LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTY_L_G)|(LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTY_H_G)<<8);
gyr_z_raw = LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTZ_L_G)|(LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTZ_H_G)<<8);
gyr_x = gyr_x_raw*GYR_LSB_250_PER;
gyr_y = gyr_y_raw*GYR_LSB_250_PER;
gyr_z = gyr_z_raw*GYR_LSB_250_PER;
printf("Gyro:X:%02f mdps,Y:%02f mdps,Z:%02f mdps \\r\\n",gyr_x,gyr_y,gyr_z);
}
if(status & ACC_DATA_AVAILABLE)
{
acc_x_raw=LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTX_L_A)|(LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTX_H_A)<<8);
acc_y_raw=LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTY_L_A)|(LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTY_H_A)<<8);
acc_z_raw=LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTZ_L_A)|(LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTZ_H_A)<<8);
acc_x=acc_x_raw*ACC_LSB_2G_PER;
acc_y=acc_y_raw*ACC_LSB_2G_PER;
acc_z=acc_z_raw*ACC_LSB_2G_PER;
printf("Acc:X:%02f mg,Y:%02f mg,Z:%02f mg \\r\\n",acc_x,acc_y,acc_z);
}
寄存器定義
#define LSM6DSO_ADDRESS 0xD4
#define LSM6DSO_ID 0x6C
#define LSM6DSO_SDO_CRTL 0x02
#define LSM6DSO_FIFO_CTRL1 0x07
#define LSM6DSO_FIFO_CTRL2 0x08
#define LSM6DSO_FIFO_CTRL3 0x09
#define LSM6DSO_FIFO_CTRL4 0x0A
#define LSM6DSO_COUNTER_BDR_REG1 0x0B
#define LSM6DSO_COUNTER_BDR_REG2 0x0C
#define LSM6DSO_INT1_CTRL 0x0D
#define LSM6DSO_INT2_CTRL 0x0E
#define LSM6DSO_WHO_AM_I 0x0F
#define LSM6DSO_CTRL1_XL 0x10
//bit[7:4]
typedef enum {
ODR_XL_OFF = (0<<4),
ODR_XL_1Hz6_LOW_POWER_ONLY = (11<<4),
ODR_XL_12Hz5 = (1<<4),
ODR_XL_26Hz = (2<<4),
ODR_XL_52Hz = (3<<4),
ODR_XL_104Hz = (4<<4),
ODR_XL_208Hz = (5<<4),
ODR_XL_416Hz = (6<<4),
ODR_XL_833Hz = (7<<4),
ODR_XL_1k66Hz = (8<<4),
ODR_XL_3k33Hz = (9<<4),
ODR_XL_6k66Hz = (10<<4),
} lsm6dso_odr_xl_t;
//bit[3:2]
typedef enum {
FS_XL_2g = (0<<2),
FS_XL_4g = (2<<2),
FS_XL_8g = (3<<2),
FS_XL_16g_SPIT_OIS_IU_FS = (1<<2), /* check XL_FS_MODE = ‘0’ in CTRL8_XL (17h) */
} lsm6dso_fs_xl_t;
#define ACC_LSB_2G_PER 0.061
#define ACC_LSB_4G_PER 0.122
#define ACC_LSB_8G_PER 0.244
#define ACC_LSB_16G_PER 0.488
#define LSM6DSO_CTRL2_G 0x11
//bit[7:4]
typedef enum {
ODR_G_OFF = (0<<4),
ODR_G_12Hz5 = (1<<4),
ODR_G_26Hz = (2<<4),
ODR_G_52Hz = (3<<4),
ODR_G_104Hz = (4<<4),
ODR_G_208Hz = (5<<4),
ODR_G_416Hz = (6<<4),
ODR_G_833Hz = (7<<4),
ODR_G_1k66Hz = (8<<4),
ODR_G_3k33Hz = (9<<4),
ODR_G_6k66Hz = (10<<4),
ODR_G_NOT_AVAILABLE = (11<<4),
} lsm6dso_odr_g_t;
//bit[3:2]
typedef enum {
FS_G_250 = (0<<2),
FS_G_500 = (1<<2),
FS_G_1000 = (2<<2),
FS_G_2000 = (3<<2),
} lsm6dso_fs_g_t;
#define GYR_LSB_250_PER 8.75
#define GYR_LSB_500_PER 17.50
#define GYR_LSB_1000_PER 35.0
#define GYR_LSB_2000_PER 70.0
#define LSM6DSO_CTRL3_C 0x12
#define LSM6DSO_CTRL4_C 0x13
#define LSM6DSO_CTRL5_C 0x14
#define LSM6DSO_CTRL6_C 0x15
#define LSM6DSO_CTRL7_G 0x16
#define LSM6DSO_CTRL8_XL 0x17
#define LSM6DSO_CTRL9_XL 0x18
#define LSM6DSO_CTRL10_C 0x19
#define LSM6DSO_ALL_INT_SRC 0x1A
#define LSM6DSO_WAKE_UP_SRC 0x1B
#define LSM6DSO_TAP_SRC 0x1C
#define LSM6DSO_D6D_SRC 0x1D
#define LSM6DSO_STATUS_REG 0x1E
#define TEM_DATA_AVAILABLE (1<<2)
#define GYR_DATA_AVAILABLE (1<<1)
#define ACC_DATA_AVAILABLE (1<<0)
#define LSM6DSO_OUT_TEMP_L 0x20
#define LSM6DSO_OUT_TEMP_H 0x21
#define TEMP_LSB_PER_DEG 256.0
#define TEMP_OFFSET_DEG 25
#define LSM6DSO_OUTX_L_G 0x22
#define LSM6DSO_OUTX_H_G 0x23
#define LSM6DSO_OUTY_L_G 0x24
#define LSM6DSO_OUTY_H_G 0x25
#define LSM6DSO_OUTZ_L_G 0x26
#define LSM6DSO_OUTZ_H_G 0x27
#define LSM6DSO_OUTX_L_A 0x28
#define LSM6DSO_OUTX_H_A 0x29
#define LSM6DSO_OUTY_L_A 0x2A
#define LSM6DSO_OUTY_H_A 0x2B
#define LSM6DSO_OUTZ_L_A 0x2C
#define LSM6DSO_OUTZ_H_A 0x2D
-
傳感器
+關(guān)注
關(guān)注
2550文章
51035瀏覽量
753071 -
陀螺儀
+關(guān)注
關(guān)注
44文章
783瀏覽量
98665 -
ST
+關(guān)注
關(guān)注
32文章
1133瀏覽量
128911 -
串口
+關(guān)注
關(guān)注
14文章
1551瀏覽量
76422 -
六軸傳感器
+關(guān)注
關(guān)注
1文章
18瀏覽量
16226
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論