3635|4

1万

帖子

25

TA的资源

版主

楼主
 

LSM6DSO的MicroPython驱动移植 [复制链接]

 

每天一个X-NUCLEO-IKS01A3开发板的传感器MicroPython驱动移植,今天完成了LSM6DSO陀螺仪的驱动,也是最后一个驱动程序,下一步预备开始将这些驱动移植到MakeCode,这样以后大家也可以在MakeCode上用图形化方式使用它们了。

 

LSM6DSO可以看成是一颗芯片里面封装了两个传感器,控制的时候加速度和角速度也是分别控制的,所以LSM6DSO的体积也比其它几个传感器都要大一些(其它几个传感器都是2x2mm,LSM6DSO是2.5x3mm)。

 

从寄存器上看,LSM6DSO和LIS2DW12类似,分为控制寄存器、状态寄存器、输出寄存器、中断寄存器、事件寄存器、FIFO寄存器等。传感器的功能非常多,也很复杂,可以编写出适合不同应用的多种驱动。不过为了简化使用,并保持和其它驱动一致的风格,这次的驱动只包含了基本的参数设置、数据读取等功能,没有包含中断、事件、FIFO等,在需要时大家可以自行添加。

 

下面是LSM6DSO的部分寄存器列表,LSM6DSO的寄存器非常多,仅列表就占用了3页。不过对于基本功能,只需要用到其中一小部分寄存器。

 

LSM6DSO最基本的使用方法是先设置LSM6DSO_CTRL1_XL和LSM6DSO_CTRL2_G寄存器,将ODR从0修改为合适的数值,就可以开始读取数据了。和X-NUCLEO-IKS01A3开发板上其它传感器不同,LSM6DSO没有oneshot或者single模式,如果要降低功耗或进入休眠,需要将传感器的ODR设置为0。因为加速度和角速度是分别控制的,所以需要分别设置两个寄存器的ODR。

 

LSM6DSO的加速度传感器可以设置±2g、±4g、±8g、±16g四种量程,而角速度可以设置125、250、500、1000、2000dps五种量程,可以按需灵活选择。LSM6DSO的输出结果是16位的,传感器的灵敏度非常高,可以将它的输出和其它类似传感器比较就清楚了。

 

可能是为了做温度补偿,LSM6DSO内部同样带有一个温度传感器,使用方法和LIS2DW12是相同的。

 

另外值得注意的是,LSM6DSO也支持最新的I3C接口标准,这部分的驱动等以后有机会补上。


此内容由EEWORLD论坛网友dcexpert原创,如需转载或用于商业用途需征得作者同意并注明出处

点赞 关注(1)
 
 

回复
举报

1万

帖子

25

TA的资源

版主

沙发
 

 完整的驱动

# LSM6DSO 3D accelerometer and 3D gyroscope seneor micropython drive
# ver: 1.0
# License: MIT
# Author: shaoziyang (shaoziyang@micropython.org.cn)
# v1.0 2019.7

LSM6DSO_CTRL1_XL = const(0x10)
LSM6DSO_CTRL2_G = const(0x11)
LSM6DSO_CTRL3_C = const(0x12)
LSM6DSO_CTRL6_C = const(0x15)
LSM6DSO_CTRL8_XL = const(0x17)
LSM6DSO_STATUS = const(0x1E)
LSM6DSO_OUT_TEMP_L = const(0x20)
LSM6DSO_OUTX_L_G = const(0x22)
LSM6DSO_OUTY_L_G = const(0x24)
LSM6DSO_OUTZ_L_G = const(0x26)
LSM6DSO_OUTX_L_A = const(0x28)
LSM6DSO_OUTY_L_A = const(0x2A)
LSM6DSO_OUTZ_L_A = const(0x2C)

LSM6DSO_SCALEA = ('2g', '16g', '4g', '8g')
LSM6DSO_SCALEG = ('250', '125', '500', '', '1000', '', '2000')

class LSM6DSO():
    def __init__(self, i2c, addr = 0x6B):
        self.i2c = i2c
        self.addr = addr
        self.tb = bytearray(1)
        self.rb = bytearray(1)
        self.oneshot = False
        self.irq_v = [[0, 0, 0], [0, 0, 0]]
        self._power = True
        self._power_a = 0x10
        self._power_g = 0x10
        # ODR_XL=1 FS_XL=0
        self.setreg(LSM6DSO_CTRL1_XL, 0x10)
        # ODR_G=1 FS_125=1
        self.setreg(LSM6DSO_CTRL2_G, 0x12)        
        # BDU=1 IF_INC=1
        self.setreg(LSM6DSO_CTRL3_C, 0x44)
        self.setreg(LSM6DSO_CTRL8_XL, 0)
        # scale=2G
        self._scale_a = 0
        self._scale_g = 0
        self.scale_a('2g')
        self.scale_g('125')

    def int16(self, d):
        return d if d < 0x8000 else d - 0x10000

    def setreg(self, reg, dat):
        self.tb[0] = dat
        self.i2c.writeto_mem(self.addr, reg, self.tb)

    def getreg(self, reg):
        self.i2c.readfrom_mem_into(self.addr, reg, self.rb)
        return self.rb[0]

    def get2reg(self, reg):
        return self.getreg(reg) + self.getreg(reg+1) * 256

    def r_w_reg(self, reg, dat, mask):
        self.getreg(reg)
        self.rb[0] = (self.rb[0] & mask) | dat
        self.setreg(reg, self.rb[0])

    def ax(self):
        return self.int16(self.get2reg(LSM6DSO_OUTX_L_A))

    def ay(self):
        return self.int16(self.get2reg(LSM6DSO_OUTY_L_A))

    def az(self):
        return self.int16(self.get2reg(LSM6DSO_OUTZ_L_A))

    def gx(self):
        return self.int16(self.get2reg(LSM6DSO_OUTX_L_G))

    def gy(self):
        return self.int16(self.get2reg(LSM6DSO_OUTY_L_G))

    def gz(self):
        return self.int16(self.get2reg(LSM6DSO_OUTZ_L_G))

    def get_a(self):
        self.irq_v[0][0] = self.ax()
        self.irq_v[0][1] = self.ay()
        self.irq_v[0][2] = self.az()        
        return self.irq_v[0]

    def get_g(self):
        self.irq_v[1][0] = self.gx()
        self.irq_v[1][1] = self.gy()
        self.irq_v[1][2] = self.gz()        
        return self.irq_v[1]

    def get(self):
        self.get_a()
        self.get_g()
        return self.irq_v

    def temperature(self):
        try:
            return self.int16(self.get2reg(LSM6DSO_OUT_TEMP_L))/256 + 25
        except MemoryError:
            return self.temperature_irq()

    def temperature_irq(self):
        self.getreg(LSM6DSO_OUT_TEMP_L+1)
        if self.rb[0] & 0x80: self.rb[0] -= 256
        return self.rb[0] + 25

    def scale_a(self, dat=None):
        if dat is None:
            return LSM6DSO_SCALEA[self._scale_a]
        else:
            if type(dat) is str:
                if not dat in LSM6DSO_SCALEA: return
                self._scale_a = LSM6DSO_SCALEA.index(dat)
            else: return
            self.r_w_reg(LSM6DSO_CTRL1_XL, self._scale_a<<2, 0xF3)

    def scale_g(self, dat=None):
        if (dat is None) or (dat == ''):
            return LSM6DSO_SCALEG[self._scale_g]
        else:
            if type(dat) is str:
                if not dat in LSM6DSO_SCALEG: return
                self._scale_g = LSM6DSO_SCALEG.index(dat)
            else: return
            self.r_w_reg(LSM6DSO_CTRL2_G, self._scale_g<<1, 0xF1)

    def power(self, on=None):
        if on is None:
            return self._power
        else:
            self._power = on
            if on:
                self.r_w_reg(LSM6DSO_CTRL1_XL, self._power_a, 0x0F)
                self.r_w_reg(LSM6DSO_CTRL2_G, self._power_g, 0x0F)
            else:
                self._power_a = self.getreg(LSM6DSO_CTRL1_XL) & 0xF0
                self._power_g = self.getreg(LSM6DSO_CTRL2_G) & 0xF0
                self.r_w_reg(LSM6DSO_CTRL1_XL, 0, 0x0F)
                self.r_w_reg(LSM6DSO_CTRL2_G, 0, 0x0F)

 

 
 
 

回复

1万

帖子

25

TA的资源

版主

板凳
 

使用方法:

from machine import I2C
import LSM6DSO

i2c = I2C(1)
lsm = LSM6DSO.LSM6DSO(i2c)
lsm.ax()
lsm.get_a()
lsm.get()

 

回调函数:

from machine import I2C
from pyb import Timer
import LSM6DSO

i2c = I2C(1)
lsm = LSM6DSO.LSM6DSO(i2c)
lsm.ax()
lsm.get_a()
lsm.get()

def tim_irq(t):
    print(lsm.get(), lsm.temperature())

tim = Timer(1, freq = 1)
tim.callback(tim_irq)

 

 
 
 

回复

1万

帖子

25

TA的资源

版主

4
 

驱动在github上的网址,以后更新会同步到github上。

 

链接已隐藏,如需查看请登录或者注册

 

 
 
 

回复

1万

帖子

25

TA的资源

版主

5
 

驱动已经更新,保留原始数据输出同时,输出转换为实际的加速度和角速度值。

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表