本帖最后由 dcexpert 于 2017-2-8 22:51 编辑
此内容由EEWORLD论坛网友dcexpert原创,如需转载或用于商业用途需征得作者同意并注明出处
前几天终于将SensorTile传感器部分的MicroPython驱动移植成功,因此就想将传感器的基本使用方法和大家讨论一下,顺便也写写MicroPython的移植方法。去年就有网友希望介绍移植方面的教程,因为各种原因一直没有时间写,正好借这个机会补上了。因为时间较少,一些地方没有仔细检查,如果发现文中有错误的地方,欢迎大家提出。
SensotTile简介
SensorTile核心板非常紧凑小巧,看起来就是一个可穿戴的原型(智能手表),因此它配置的传感器也是和运动相关的。SensorTile核心板上有4个传感器,它们分别是:
- LPS22HB,气压+温度传感器
- LSM6DSM,三轴加速度+三轴角速度传感器
- LSM303AGR,三轴角速度+三轴磁场传感器
- MP34DT04,MEMS麦克风传感器
我们先从最简单的LPS22HB开始,逐步介绍传感器的使用和移植方法。而MP34DT04传感器这次没有使用到,它的接口也和其他传感器不同,所以暂时先不看。
LPS22HB气压传感器
硬件接口
LPS22HB的原理图如上,从上面我们可以看到,传感器使用了SPI连接方式,但是只用了CS、SCL/SPC、SDA/SDI/SDO这几个脚,SDO脚没有使用,说明它没有使用标准的SPI接口方式。此外,还可以看到INT信号也没有连接,所以也就不能使用INT模式了。通常在INT模式下,可以预先设置一个门限参数,当传感器的输出超过这个门限时,就会自动产生一个INT信号,用来唤醒MCU,然后读取并处理参数,这有助于简化编程,降低系统功耗。
从传感器的用户手册中可以看到,传感器支持SPI/I2C两种接口。这两种接口方式是通过CS脚进行切换的,当CS为低电平时是SPI方式,CS是高电平时是I2C方式。SensorTile在硬件设计时,使用了半双工的SPI接口(又叫3-wire模式),这个模式下主机只使用MOSI做数据线,而从机使用MISO。它的好处在于可以节约一个数据线,缺点就是牺牲了速度。
因为MicroPython目前不支持半双工的SPI接口方式(硬件SPI和软件SPI都不支持这个方式),因此要用SPI方式驱动传感器就只能自己通过软件模拟这种SPI方式,这不但增加了软件的复杂性,同时速度也会比较慢,所以我采用了I2C接口方式。因为SPI_SDA(PB15)和SPI_CLK(PB13)引脚并不是硬件I2C接口,所以需要用软件I2C方式。好在micropython底层已经支持软件I2C,使用方法和硬件I2C一样,速度也不慢。
这里先介绍一下软件I2C。为了使用软件I2C,我们需要使用到micropython的machine库,而不能使用pyb库。大家可能也注意到了,CC3200、ESP8266、STM32等分支在硬件底层函数接口上有很多不同,这给我们编程和程序移植带来很多不便。从v1.8版开始,micropython开始增强了machine库的功能,这样有助于统一底层接口。软件I2C的使用方法如下:
- import machine
- i2c = machine.I2C(-1, sda=machine.Pin('PB15'), scl=machine.Pin('PB13'))
复制代码
其中-1就代表使用了软件I2C,sda和scl就是使用的GPIO,可以使用任何GPIO,在SensorTile上就必须使用PB15和PB13。
直接这样定义后,大家会发现I2C还是不能工作,这是因为在SensorTile内部没有设置I2C的上拉电阻,这样I2C总线的状态无法确定,所以我们还需要使能GPIO内部的上拉电阻。注意这个步骤需要放在I2C初始化之后,因为在I2C初始化的时候,会重新设置GPIO状态和参数。直接在I2C定义中的sda=machine.Pin('PB15', pull=Pin.PULL_UP)加入上拉电阻定义也是不能工作的,因为在设置I2C时会忽略这个参数。在I2C定义后,再加入下面的定义,I2C就可以正常工作了,如果这时使用i2c.scan()函数,就可以搜索到4个设备。
- sda=machine.Pin('PB15', Pin.OPEN_DRAIN, pull=Pin.PULL_UP)
- scl=machine.Pin('PB13', Pin.OPEN_DRAIN, pull=Pin.PULL_UP)
复制代码
传感器寄存器
ST公司为SensorTile kit提供了多个例程,例程中包含了传感器的底层驱动函数。如果使用C++编程,可以使用这些驱动函数。而我们要使用micropython进行编程,所以无法直接使用ST的底层函数,需要自己对寄存器进行操作(其实ST的底层驱动函数也是对这些寄存器进行操作,只是它已经封装好了,不用再看寄存器说明了)。为了使用LPS22HB,需要对传感器的寄存器有初步的了解。
上图是LPS22HB的寄存器列表,它的寄存器不是太多,除去保留的寄存器(Reserved)外,一共大约有二十几个。每个寄存器都有一个地址,寄存器输出是8位的,大部分寄存器可以读写(RW),少量寄存器是只读的(R)。如果按照功能进行划分,传感器的寄存器大致可以分为下面几类:
功能设置寄存器可以设置传感器的工作模式、参数输出频率、参数范围、中断等参数,只有设置了正确的参数后,传感器才能工作。在上电/复位后,我们也需要先设置功能寄存器(初始化),否则传感器是没有输出的,因为默认情况下传感器是处于掉电模式(Power down)。
状态寄存器通常是只读的,可以通过它查询传感器当前的状态或者某种标志位。特别在中断工作模式下,需要通过状态寄存器查询发生的中断。
参数输出就是传感器的输出,如气压、温度等参数。很多参数使用了双字节甚至更多字节,需要读取后在组合起来。
因为寄存器较多,所以我们只介绍主要使用到的传感器,其他传感器大家可以慢慢研究(寄存器说明请见LPS22HB数据手册的第9节:Register description)。
主要寄存器可以用来识别芯片的型号。这个寄存器是只读的,输出是 0xB1,也就是十进制的177。
这是最重要的一个寄存器,主要参数都在这里设置
7
| 6
| 5
| 4
| 3
| 2
| 1
| 0
|
0
| ODR2
| ODR1
| ODR0
| EN_LPFP
| LPFP_CFG
| BDU
| SIM
|
ODR代表采样频率,当ODR=0时,传感器进入掉电模式,设置成其它参数时,传感器就按照指定频率开始采样。
EN_LPFP代表使用内部低通滤波器,默认是关闭的。
LPFP_CFG是低通滤波器带宽设置,它需要和EN_LPFP配合使用。
BDU是Block data update的缩小,它代表只有读取输出数据后才更新寄存器
SIM是选择3线/4线SPI方式。
气压参数由三个寄存器组成,分别是PRESS_OUT_XL (28h)、PRESS_OUT_L (29h)、PRESS_OUT_H (2Ah)
气压的计算方法是
气压 = PRESS_OUT_H·PRESS_OUT_L·PRESS_OUT_XL / 4096
就是将三个寄存器的值组合起来,然后除以4096。如果精度要求不高,也可以只取PRESS_OUT_H和PRESS_OUT_L,然后除以16。气压传感器的精度是±0.1hPa,所以保留一位小数就可以了。
如果希望通过气压计算高度,通常是用查表计算。不过因为气压容易受到温度、湿度、风力等多个条件影响,通过气压计算绝对高度的误差较大,所以通常是测量相对高度(高度变化)。
温度参数由两个寄存器组成:
温度的计算方法是:
温度 = TEMP_OUT_H·TEMP_OUT_L / 100
考虑到低于0°时是负数,所以需要将这个参数做为有符号数处理。温度传感器的精度是±1.5℃。
如果没有特殊要求,使用上述几个寄存器就可以实现基本的数据采集功能。如果希望进一步降低功耗、改变模式、使用中断、使用FIFO、使用参考值等功能,还需要进一步研究其它寄存器才行。
下一节将介绍使用MicroPython驱动LPS22HB的方法。