K210(SiPEED MaixBit)MicroPython使用参考(九、温湿度传感器HTS221驱动)
K210(SiPEED MaixBit)MicroPython使用参考(九、温湿度传感器HTS221驱动)
1.HTS221是ST出品的电容式温湿度数字传感器,工作电压1.7-3.6V,温度测量范围-40°C-120°C,湿度测量范围0-100%,16位数据输出,提供SPI和I²C数据接口。其器件地址(device address)如下,即读时为BF,写时BE,若只用7位则为5F(即下表的SAD):
1)寄存器地址如下:
2)寄存器30-3F被称做Calibration registers,意思是校准寄存器,这是因为在制造时都存在个体差异,出厂时将校准数据写入该寄存器,正常使用时加入校准数据,这也是很多传感器的常规做法。
不过需要注意的是,H0_rH_x2和H1_rH_x2所存储值是真实校准值的2倍,猜测有以下原因:提高精度,制造方便,计算简单且快速。T0_degC_x8和T1_degC_x8亦是如此。另外,H_OUT,T_OUT,H0_T0_OUT ,H1_T0_OUT,T0_OUT和T1_OUT的数据类型都是s16,官方资料说的是“signed 16-bit quantity using two's complement”,有符号的16位数,最高位为0时表示整数,最高位为1时表示负数,参考计算如下(以8位二进数为例):
但实际上,绝大多数参考代码均将之看作是无符号的16位数,并没有特意处理,即默认该寄存器最大值是32767,最小值是0。
2.官方资料提供的计算步骤
1)温度计算:
The steps for the temperature conversion from ADC_OUT (LSB) to °C are described as follows:
(1)Read the value of coefficients T0_degC_x8 and T1_degC_x8 from registers 0x32 & 0x33
(2)Divide by 8 the content of registers 0x32 (T0_degC_x8) and 0x33 (T1_degC_x8) in order to obtain the value of coefficients T0_degC and T1_degC
(3)Read the MSB bits of T1_degC (T1.9 and T1.8 bit) and T0_degC (T0.9 and T0.8 bit) from register 0x35 to compute T0_DegC and T1_DegC
(4)Read from registers 0x3C & 0x3D the value of T0_OUT
(5)Read the value of T1_OUT from registers 0x3E & 0x3F
(6)Read the value T_OUT (ADC_OUT) from 0x2A & 0x2B registers
(7)Compute the T [degC] value, by linear interpolation, applying the following formula:
2)湿度计算:
The steps for the humidity conversion from ADC_OUT (LSB) to RH % are described as follows:
(1)Read the value of coefficients H0_rH_x2 and H1_rH_x2 from registers 0x30 & 0x31
(2)Divide by two the content of registers 0x30 (H0_rH_x2) and 0x31 (H1_rH_x2) in order to obtain the value of coefficients H0_rH and H1_rH
(3)Read the value of H0_T0_OUT from registers 0x36 & 0x37
(4)Read the value of H1_T0_OUT from registers 0x3A & 0x3B
(5)Read the humidity value in raw counts H_T_OUT from registers 0x28 & 0x29
(6)Compute the RH [%] value, by linear interpolation, applying the formula below:
3.温湿度计算具体实现
1)官方资料的温湿度计算(C语言)
读出T0_degC_x8,T1_degC_x8
读T0_T1_DEGC_H2得到四位数tmp
T0_degC_x8,T1_degC_x8除以8后在最高位前,分别加tmp的末前两位得到T0_degC,T1_degC
读出T0_out
读出T1_out
读出T_out
计算出tmp32=(T_out-T0_out)*(T1_degC-T0_degC)*10
计算出温度值value=tmp32/(T1_out-T0_out)+T0_out*10
读H0_RH_X2,H1_RH_X2并除以2得到H0_rh,H1_rh
读H0_T0_OUT得到H0_T0_out
读H1_T0_OUT得到H1_T0_out
读H_T_OUT得到H_T_out
计算出tmp=(H_T_out-H0_T0_out)*(H1_rh-H0_rh)*10
计算出湿度值value=tmp/(H1_T0_out-H1_T0_out)+H1_T0_out*10
需要注意的是:返回的湿度值是1000制,源代码有判断语句,超过1000按照1000处理(可见该传感器测湿度很不准)
2)Arduino的温湿度计算方式(Nano 33 BLE Sense)
读T0_degC_x8_REG、T1_degC_x8_REG和T1_T0_MSB_REG得到t0degC、t1degC
读取得到t0Out、t1Out
计算出hts221TemperatureSlope = (t1degC - t0degC) / (8.0 * (t1Out - t0Out))
计算出_hts221TemperatureZero = (t0degC / 8.0) - _hts221TemperatureSlope * t0Out
读取HTS221_TEMP_OUT得到tout
计算出温度值tout * _hts221TemperatureSlope + _hts221TemperatureZero
读取得到h0rH、 h1rH
读取得到h0t0Out、h1t0Out
计算出_hts221HumiditySlope = (h1rH - h0rH) / (2.0 * (h1t0Out - h0t0Out))
计算出_hts221HumidityZero = (h0rH / 2.0) - _hts221HumiditySlope * h0t0Out
读取HTS221_HUMIDITY_OUT得到hout
计算出湿度值hout * _hts221HumiditySlope + _hts221HumidityZero
3)shaoziyang的MicroPython驱动
读出T0_OUT,T1_OUT
读T1/T0 msb寄存器(0x35)取低4位为t
读寄存器0x32,0x33,分别加上t的低高2位,计算出T0_degC,T1_degC
计算出K1=(T1_degC - T0_degC) / (T1_OUT -T0_OUT)
计算出(T0_degC + (get2reg(0x2A)-T0_OUT) *K1)/8
读出H0_OUT,H1_OUT
读寄存器0x30,0x31,乘5,计算出H0_rH,H1_rH
计算出K2=(H1_rH -H0_rH) / (H1_OUT -H0_OUT)
计算出(H0_rH + (get2reg(0x28) - H0_OUT) *K2)/10
该代码是少有的对有符号数据进行处理的,实测湿度结果略有差异,温度则相同。实际上,可能因为器件老化等原因,湿度测量数据很不准,数值很容易超过阈值,无法反映实际情况。另外,shaoziyang的驱动代码中还有使用中断获得数据的函数,计算方法类似,经过简化导致精度略低但速度更快。
4.ST有一款X-NUCLEO-IKS01A1扩展板,集成有HTS221传感器,具体如下:
5.shaoziyang驱动代码如下,需要将之命名为HTS221.py,注意是大写字母,并将之“发送文件到开发板”:
# HTS221 Humidity and temperature micropython drive
# ver: 2.0
# License: MIT
# Author: shaoziyang (shaoziyang@micropython)
# v1.0 2016.4
# v2.0 2019.7from machine import I2Cclass HTS221(object):def __init__(self, i2c):self.i2c = i2cself.addr = 0x5F# data bufferself.tb = bytearray(1)self.rb = bytearray(1)self.oneshot = Falseself.irq_v = [0, 0]# HTS221 Temp Calibration registersself.T0_OUT = self.int16(self.get2reg(0x3C))self.T1_OUT = self.int16(self.get2reg(0x3E))t = self.getreg(0x35) % 16self.T0_degC = self.getreg(0x32) + (t%4) * 256self.T1_degC = self.getreg(0x33) + (t//4) * 256# HTS221 Humi Calibration registersself.H0_OUT = self.int16(self.get2reg(0x36))self.H1_OUT = self.int16(self.get2reg(0x3A))self.H0_rH = self.getreg(0x30) * 5self.H1_rH = self.getreg(0x31) * 5self.K1 = (self.T1_degC - self.T0_degC) / (self.T1_OUT - self.T0_OUT)self.K2 = (self.H1_rH - self.H0_rH) / (self.H1_OUT - self.H0_OUT)# set av conf: T=4 H=8self.setreg(0x10, 0x26)# set CTRL_REG1: PD=1 BDU=1 ODR=1self.setreg(0x20, 0x85)self.oneshot_mode(0)def oneshot_mode(self, oneshot = None):if oneshot is None:return self.oneshotelse:self.getreg(0x20)self.oneshot = oneshotif oneshot: self.rb[0] &= 0xFCelse: self.rb[0] |= 0x01self.setreg(0x20, self.rb[0])def ONE_SHOT(self, b):if self.oneshot:self.setreg(0x21, self.getreg(0x21) | 0x01)self.getreg(0x2d - b*2)while 1:if self.getreg(0x27) & b:returndef int16(self, d):return d if d < 0x8000 else d - 0x10000def setreg(self, reg, dat):self.tb[0] = datself.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# calculate Temperaturedef temperature(self):try:self.ONE_SHOT(1)return round((self.T0_degC + (self.int16(self.get2reg(0x2A)) - self.T0_OUT) * self.K1)/8, 1)except MemoryError:return self.temperature_irq()# calculate Humiditydef humidity(self):try:self.ONE_SHOT(2)return round((self.H0_rH + (self.int16(self.get2reg(0x28)) - self.H0_OUT) * self.K2)/10, 1)except MemoryError:return self.humidity_irq()def get(self):try:return self.temperature(), self.humidity()except MemoryError:return self.get_irq()def temperature_irq(self):self.ONE_SHOT(1)return (self.T0_degC + (self.int16(self.get2reg(0x2A)) - self.T0_OUT) * (self.T1_degC - self.T0_degC) // (self.T1_OUT - self.T0_OUT)) >> 3def humidity_irq(self):self.ONE_SHOT(2)return (self.H0_rH + (self.int16(self.get2reg(0x28)) - self.H0_OUT) * (self.H1_rH - self.H0_rH) // (self.H1_OUT - self.H0_OUT))//10def get_irq(self):self.irq_v[0] = self.temperature_irq()self.irq_v[1] = self.humidity_irq()return tuple(self.irq_v)def power(self, on=None):self.getreg(0x20)if on is None: return self.rb[0] & 0x80 > 0elif on: self.rb[0] |= 0x80else: self.rb[0] &= 0x7F self.setreg(0x20, self.rb[0])
将HTS221接入电源,并将SCL、SDA分别连入K210的7脚和6脚,运行以下测试代码:
from machine import I2C,Timer
import time
import HTS221
i2c = I2C(I2C.I2C0, freq=100000, scl=7, sda=6)
devices = i2c.scan()
print(devices)
hts = HTS221.HTS221(i2c)
while True:time.sleep(1)print(hts.get())
i2c.scan返回I2C总线上所有的从机地址(故而可以用作I2C检测器),对于X-NUCLEO-IKS01A1来说,共有4个,分别是30(0x1E,LIS3MDL),93(0x5D,LPS25HB),95(0x5F,HTS221),107(0x6B,LSM6DSO)。hts.get返回值有两个,前者是温度,还算准确,后者是湿度,可能会相当不准,甚至于超过100。
6.HTS211的DatasheetHTS221温湿度传感器datasheet(英文)-OS文档类资源-CSDN文库
使用指南HTS221温湿度传感器的使用指南,官方所提供的资料-OS文档类资源-CSDN文库
- php开发API接口的代码案例
- springboot项目搭建0000
- Platform 设备驱动:platform
- 关于platform
- dump文件深度分析
- LRUCache的C++实现
- Shiro中principal和credential的区别
- vss命令行的使用
- TreeSet集合如何保证元素唯一
- ext3文件系统基础
- Mysql与Postgresql常用命令比较
- Shiro和SpringSecurity
- 集合类 CList的使用
- curl命令详解 (curl
- shiro反序列化漏洞学习(工具+原理+复现)
- Shiro系统权限管理、及原理剖析
- Qt QSqlQueryModel实现查询数据库内容