在SensorTile上使用MicroPython(二)

LPS22HB 的 Micropython 程序移植
前面介绍了传感器的接口、主要寄存器、参数计算等方面的内容,下面就介绍用MicroPython驱动LPS22HB的方法。

为了让程序具有通用性,以及系统模块化的要求,我们将为 LPS22HB 单独建立一个 Module,这样也方便其它程序使用。python语言中,一个module和C++的子程序差不多,里面可以包含多个对象(class),每个对象提供一系列函数或方法。但是python语言没有C++那么复杂,也不是面向对象的语言,使用起来简单得多。

一个典型的mudule的结构如下,它由若干class组成,每个class下又由多个函数组成。其中比较特殊的是__init__()函数,它类似C++的构造函数初始化,在定义class变量后就会自动调用__init__()函数,默认需要进行初始化的内容都放在这个函数中。此外,class下的每个函数在定义时的默认第一个参数都是self,但是调用时并不需要使用它,self参数由python系统内部使用。更多关于python语法部分的内容,请大家参考python教程或者参考书,这里就不重复了。

对于LPS22HB传感器,我们先定义一个基本的LPS22HB类:

  1. class LPS22HB(object):

  2. def __init__(self):

  3. xxxx

  4. def func1():

  5. xxxx

  6. def func2():

  7. xxxx

复制代码

然后再将初始化、其它功能函数逐步添加进去,最后就是一个完整的驱动了。

首先需要添加的就是初始化部分,在__init__()函数中,先添加GPIO部分,将CS的GPIO设置为输出,并设置为高电平,这样I2C才能正常工作:

  1. # set CS high

  2. CS_LPS22HB = Pin(LPS22HB_CS_PIN, Pin.OUT)

  3. CS_LPS22HB(1)

  4. CS_AG = Pin(LSM6DSM_CS_PIN, Pin.OUT)

  5. CS_AG(1)

  6. CS_A = Pin(LSM303AGR_CS_A_PIN, Pin.OUT)

  7. CS_A(1)

  8. CS_M = Pin(LSM303AGR_CS_M_PIN, Pin.OUT)

  9. CS_M(1)

复制代码

然后再添加I2C初始化部分的代码:

  1. # soft I2C

  2. self.i2c = machine.I2C(-1, sda=machine.Pin('PB15'), scl=machine.Pin('PB13'))

  3. # set open drain and pull up

  4. sda=machine.Pin('PB15', Pin.OPEN_DRAIN, pull=Pin.PULL_UP)

  5. scl=machine.Pin('PB13', Pin.OPEN_DRAIN, pull=Pin.PULL_UP)

复制代码

再设置LPS22HB的CTRL1_REG寄存器,让LPS22HB默认处于工作模式:

  1. # start LPS22HB

  2. self.setreg(0x18, LPS22HB_CTRL_REG1, LPS22HB_ADDRESS)

  3. self.temp0 = 0

  4. self.press = 0

  5. self.LPS22HB_ON = True

复制代码

self.temp0、self.press、self.LPS22HB_ON是内部变量,用于后面的参数计算和状态设置。它们不是必须的,这里定义它们主要是为了方便同一模块下其它函数调用。

初始化部分完成后,就是添加其它功能函数了。大家可以发现在上面的初始化部分我们使用了一个设置寄存器的函数,因为设置和读取寄存器是一个通用性的操作,所以我们将寄存器的操作也设置成函数,这样也方便将底层和应用层分离。为了方便读取参数,我们还设置了一个读取两个相邻寄存器的函数get2reg,这个函数没有使用传感器自动递增寄存器地址的功能,是因为在传感器的BUD模式下,地址自动递增的功能是无效的,为了让程序有更好的兼容性,所以稍微牺牲了一点性能。

  1. def setreg(self, dat, reg, addr):

  2. buf = bytearray(2)

  3. buf[0] = reg

  4. buf[1] = dat

  5. self.i2c.writeto(addr, buf)

  6. def getreg(self, reg, addr):

  7. buf = bytearray(1)

  8. buf[0] = reg

  9. self.i2c.writeto(addr, buf)

  10. t = self.i2c.readfrom(addr, 1)

  11. return t[0]

  12. def get2reg(self, reg, addr):

  13. l = self.getreg(reg, addr)

  14. h = self.getreg(reg+1, addr)

  15. return l+h*256

复制代码

为了增加程序的可读性和可维护下,我们将寄存器的名称定义为常量,并且将它放在class的前面,这类似于C语言中的#define。寄存器名称前面还加上LPS22HB前缀,这样可以在一个Module中存在多个芯片定义时防止和其它芯片的定义相冲突。

  1. # LPS22HB register

  2. LPS22HB_INTERRUPT_CFG= const(0x0B)

  3. LPS22HB_THS_P_L      = const(0x0C)

  4. LPS22HB_THS_P_H      = const(0x0D)

  5. LPS22HB_WHO_AM_I     = const(0x0F)

  6. LPS22HB_CTRL_REG1    = const(0x10)

  7. LPS22HB_CTRL_REG2    = const(0x11)

  8. LPS22HB_CTRL_REG3    = const(0x12)

  9. LPS22HB_FIFO_CTRL    = const(0x14)

  10. LPS22HB_REF_P_XL     = const(0x15)

  11. LPS22HB_REF_P_L      = const(0x16)

  12. LPS22HB_REF_P_H      = const(0x17)

  13. LPS22HB_RPDS_L       = const(0x18)

  14. LPS22HB_RPDS_H       = const(0x19)

  15. LPS22HB_RES_CONF     = const(0x1A)

  16. LPS22HB_INT_SOURCE   = const(0x25)

  17. LPS22HB_FIFO_STATUS  = const(0x26)

  18. LPS22HB_STATUS       = const(0x27)

  19. LPS22HB_PRESS_OUT_XL = const(0x28)

  20. LPS22HB_PRESS_OUT_L  = const(0x29)

  21. LPS22HB_PRESS_OUT_H  = const(0x2A)

  22. LPS22HB_TEMP_OUT_L   = const(0x2B)

  23. LPS22HB_TEMP_OUT_H   = const(0x2C)

  24. LPS22HB_LPFP_RES     = const(0x33)

复制代码

前面的寄存器操作、初始化等可以看成是准备工作,准备工作完成了,就是具体传感器的操作了。我们使用传感器最重要的目的就是需要获得传感器的参数,因此再定义两个函数,一个用于获取气压,一个获取温度。

  1. def LPS22HB_temp(self):

  2. self.temp0 = self.get2reg(LPS22HB_TEMP_OUT_L, LPS22HB_ADDRESS)

  3. if(self.temp0 > 0x7FFF):

  4. self.temp0 -= 65536

  5. return self.temp0/100

  6. def LPS22HB_press(self):

  7. self.press = self.getreg(LPS22HB_PRESS_OUT_XL, LPS22HB_ADDRESS)

  8. self.press += self.get2reg(LPS22HB_PRESS_OUT_L, LPS22HB_ADDRESS) * 256

  9. return self.press/4096

复制代码

气压函数是先读取三个寄存器的参数,然后将结果除以4096,这就是按照前面介绍的计算方法进行换算的。而温度函数稍微麻烦一点,因为存在负数的问题。在python语言中不像C语言那样可以自动进行类型转换,寄存器的参数不能直接转换为负数,所以需要自己判断和转换。因为这里是一个双字节的数据,最高位就是符号位,因此如果数据大于0x7FFF或者最高位是1,那么就认为它是负数。

另外在一些情况下,需要同时读取温度和气压两个数据,所以我们可以将两个参数放到一个函数中,通过一个列表返回。这里可以直接将前面两个函数放在return的列表中。

  1. def LPS22HB(self):

  2. return [self.LPS22HB_temp(), self.LPS22HB_press()]

复制代码

最后,为了降低功耗,还需要让传感器可以进入掉电模式,因此我们还需要增加两个功耗管理函数:

  1. def LPS22HB_poweron(self):

  2. t = self.getreg(LPS22HB_CTRL_REG1, LPS22HB_ADDRESS) & 0x0F

  3. self.setreg(t|0x10, LPS22HB_CTRL_REG1, LPS22HB_ADDRESS)

  4. self.LPS22HB_ON = True

  5. def LPS22HB_poweroff(self):

  6. t = self.getreg(LPS22HB_CTRL_REG1, LPS22HB_ADDRESS) & 0x0F

  7. self.setreg(t, LPS22HB_CTRL_REG1, LPS22HB_ADDRESS)

  8. self.LPS22HB_ON = False

复制代码

在掉电模式下(Power down),传感器的最低功耗是1uA。其实LPS22HB的功耗也不高,在ODR和LC_EN都是1时也只有3uA。
完成上面的工作后,我们就实现了一个最基本的LPS22HB驱动。我们可以把它保存到一个LPS22HB.py文件中,然后用下面的方法使用它:
>>> from LPS22HB import LPS22HB
>>> lp=LPS22HB()
>>> lp.LPS22HB_temp()
16.17
>>> lp.LPS22HB_press()
1025.827
>>> lp.LPS22HB()
[16.14, 1025.839]

如果用dir(LPS22HB),可以查看全部的函数
>>> dir(LPS22HB)
['__qualname__', 'LPS22HB_poweron', '__module__', 'LPS22HB_press', 'LPS22HB_temp', 'LPS22HB', 'getreg', 'setreg', 'get2reg', 'LPS22HB_poweroff', '__init__']
如果想进一步完善LPS22HB驱动,增加功能,使用中断等,大家可以在此基础上进行改进。

(0)

相关推荐

  • 一文快速入手:多实例学习

    翻译自Medium:https://medium.com/swlh/multiple-instance-learning-c49bd21f5620 导读 当涉及到在医学领域中应用计算机视觉时,大多数任 ...

  • Arduino在中断函数里面怎么延时

    Arduino在中断函数里面怎么延时 Arduino里面有两种中断,一种是内部中断,就象系统时钟那样,一直在那儿持续,轮询到中断信号,以最高的优先级去执行.另一种是外部中断,输入中断信号,以低于内部中 ...

  • 在SensorTile上使用MicroPython

    前几天终于将SensorTile传感器部分的MicroPython驱动移植成功,因此就想将传感器的基本使用方法和大家讨论一下,顺便也写写MicroPython的移植方法.去年就有网友希望介绍移植方面的 ...

  • 1982年《古钱大辞典》上、下二册

    1982年<古钱大辞典>上.下二册,丁福保编著,中华书局出版社出版,品相颇佳.

  • 1968年香港龙门书店印行《泉币》杂志第一至三十二期合订本上、下二册

    1968年香港龙门书店印行<泉币>杂志第一至三十二期合订本上.下二册,保存极好.

  • 【“天地同和”展上新之二!明代祝公望蕉叶...

    ["天地同和"展上新之二!明代祝公望蕉叶琴[鼓掌]]此琴为蕉叶式古琴创始人祝公望制.面桐底梓,造型精巧.鹿角灰胎,下裹青花夏布.黑漆,面呈小流水断兼蛇腹断,底现大蛇腹断.连弧形龙池 ...

  • 匹马陷阵摧敌锋,一骑可将万军冲——中华史上排名前二十的猛将 整合修正篇

    中华历史数千年,从不缺乏武艺超群,勇猛善战,攻城陷阵,斩将搴旗的猛将,在演义和小说中这些猛将甚至能凭借几场单挑,决定一场战争的胜败,但在历史上,个人勇武对战争胜负所起到的作用,并没有这么夸张. 首先要 ...

  • 在老街上行走(二)

          二 来到庐陵老街的第二天早上,我通过地下楼梯,进入设在停车场里的员工食堂.员工食党的门却是紧紧的关闭着.我那时还不知道员工食堂只提供中餐和晚餐,早餐是由员工自己解决的. 看着紧闭着的员工食 ...

  • 大辽河上之十二—从岗皮岭到曹蔡

    大辽河,是辽宁省独流入海河流浑河与其支流太子河合流后形成的下游河段的别称,系指浑河干流在盘锦市三岔河与太子河汇合后,由三岔河起始,向西南方向流至营口市永远角的大辽河口注入渤海辽东湾的下游94公里河段. ...

  • 大辽河上之三十二一从上口子到八家子

    大辽河,是辽宁省独流入海河流浑河与其支流太子河合流后形成的下游河段的别称,系指浑河干流在盘锦市三岔河与太子河汇合后,由三岔河起始,向西南方向流至营口市永远角的大辽河口注入渤海辽东湾的下游94公里河段. ...

  • 买食用油,不管啥牌子,只要瓶子上有这二字,无论贵贱,都是好油

    30年前,我还是个小屁孩时,在农村的外婆家生活.村东头有个老油坊,据说有80年的历史了, 传了3代人.每次家里的油吃光了,外婆就把油葫芦交给我,再塞给我一些钱,让我去老油坊打油. 老油坊都是手艺人,一 ...