树莓派&Python&SHT10
SHT10的性能.
eg: xx->xx->xx 表示 min值->typ值->max值.
- 湿度分辨率: 0.4->0.05->0.05(%RH) 或者用二进制位 8->12->12(bit)
- 湿度精度: ±4.5 %RH (typ 条件下.)
- 温度分辨率: 0.04->0.01->0.01(℃) 或者用二进制位 12->14->14(bit)
- 湿度精度: ±0.5 ℃ (typ 条件下.)
- 供电电压: 2.4->3.3->5.5(V)
传感器默认测量分辨率为温度14位, 湿度12位, 可以通过给状态寄存器发送命令将其降低为温度12位, 湿度8位.
以下分别为相对湿度和温度数据变化图.
SHT10接口.
接口图:
- 电源引脚: sensor供电电压范围为2.4-5.5v, 建议电压为3.3.在VDD与GND之间须加一个100nF的电容, 用以去耦滤波.
- 串行时钟输入(SCK): SCK用于处理器与sensor之间的通讯同步. 由于接口包含完全静态逻辑, 因而不存在最小SCK频率.
- 串行数据(DATA): 三态结构, 用于读取sensor数据.为保证通讯安全稳定, DATA应处于高电平, SCK处于低电平.
SHT10通讯.
通讯过程:
启动sensor即给其通电, 上电速率不能低于1V/ms. 通电后sensor需要11ms进入休眠状态, 在此之前不允许给sensor发送任何命令.
发送”启动传输”时序, 来完成数据传输的初始化.它包括: 当SCK为高电平时DATA翻转为低电平, 紧接着SCK变为低电平, 随后是在SCK时钟高电平是DATA翻转为高电平.(可看后2图).
发送”测量命令”, 来完成测量湿度/温度. 命名包括: 3个地址位 + 5个命令位.(eg: 000 00011 温度), sensor会以下面的方式来表示已经正确地接收到了命令: 在第8个SCK时钟的下降沿之后, 将DATA下拉为低电平即ACK位.在第9个SCK时钟的下降沿之后, 释放DATA即恢复高电平.(具体命令可看后3图.)
等待sensor测量, 发送一组测量命令后, 控制器需要等待sensor测量完成.这个过程大概为20/80/320ms, 分别对应8/12/14bit测量. sensor通过下拉DATA至低电平并进入空闲模式, 表示测量的结束. 控制器在再次触发SCK时钟前, 必须等待这个结束信号, 来读取数据.
控制器接收sensor传输来的2个字节的测量数据和1个字节的CRC奇偶校验(可以选择是否读取). 所有的数据从MSB开始, 右值有效.eg: 对于12位的数据, 从左到右第5为开始有效; 对于8位数据, 高8位为无意义数据.
数据接收后, sensor自动转入休眠模式.
通讯复位时序:
如果与sensor通讯中断, 可通过下列信号时序复位: 当DATA保持高电平时, 触发SCK时钟9次或者更多, 接着发送一个”启动传输”时序. 这里只是复位了串口, 状态寄存器中的内容仍然保留.
图二:
图三:
eg: 这里是测量湿度数据的通讯过程图. 拿去慢慢琢磨
SHT10数据转换.
相对湿度, 温度值, 湿度信号的温度补偿:
RH_true 为真正的湿度测量值.
T_C 为真正的温度测量值.
- RH_linear = c1 + c2 * SO_RH + c3 * SO_RH * SO_RH
- T_C = d1 + d2 * SO_T
- RH_true = (T_C - 25) * (t1 + t2 * SO_RH) + RH_linear
下列图为上面参数的数值, E为10, eg: -2.80000E-6 相当于 -2.8 * 10^(-6).
以上就是关于SHT10或者SHT1x系列传感器信息的个人理解, 如果有看不懂的地方可以直接百度相关文档查看跟细节的东西.
SHT10的理论介绍的也差不多,接下来走实际的.
在树莓派上使用python控制SHT10sensor读取温湿度数据.
树莓派基本操作我就不说了. 自行百度吧.
将sensor的VDD, GND, DATA, SCK脚分别连在树莓派的5.0v电源脚, 接地脚, 16脚(GPIO), 18脚(GPIO).这里的脚标号按照BOARD模式, 不懂的自己百度(树莓派BCM和BOARD), 这里就不解释了.
在用户目录中,创建python脚本(名字自己取).py code在后面给出.
运行脚本, 这就完了.
关于python code我想说的是:
没有接受CRC校验数据.
写了复位时序函数, 但是没用, 要用的自行修改.
delay_little()函数, 延时时间可以自行修改.
这个脚本非常的不pythoner, 不够优雅和完美.
脚本只完成了基本功能, 若想让脚本变得更强大, 请自行搞定, 因为作者实在太懒.
当然啦, 这是在windows上写的, 要在树莓派上跑, 请大家自行解决缩进的问题.(也就TAB和4个空格, 自己再写个py脚本来解决这个问题呗).
当然啦, 如果脚本出现错误, 请自己检查或者发信息给我等修改(没办法现写的code).
CODE:
# _*_ coding:utf-8 _*_
# !/usr/bin/python
import time
import RPi.GPIO as GPIO
# 测量温度/湿度/复位的命令.
MEASURE_TEMP = 0x03 # 000 0001 1
MEASURE_HUMI = 0x05 # 000 0010 1
RESET = 0x1e # 000 1111 0
noACK = 0 # 继续通信.
ACK = 1 # 不继续通信.
# 温湿度模式.
TEMP = 0
HUMI = 1
# DATA/SCK 对应树莓派GPIO脚号.
D = 16
S = 18
# 设置为BOARD模式.
GPIO.setmode(GPIO.BOARD)
# 将DATA, SCK 设置为输出脚, 并给默认电平值.
# 高电平: 1/GPIO.HIGH/True
GPIO.setup(D, GPIO.OUT, initial=1)
GPIO.setup(S, GPIO.OUT, initial=0)
# 测量函数.
def measure(mode):
start_up() # 发送启动时序.
error = 0 # 用于记录过程是否出错.
if mode == TEMP:
error += write_cmd(MEASURE_TEMP) # 传入温度测量命令.
elif mode == HUMI:
error += write_cmd(MEASURE_HUMI)
else:
error += 1
# print 'measure:', error
# try control sensor measure time.
# GPIO.setup(D, GPIO.OUT)
# time.sleep(0.080)
# GPIO.setup(D, GPIO.IN)
while GPIO.input(D): # 等待sensor测量完成, 等待sensor拉低DATA为低电平.
continue
delay_little()
h8 = read_data(noACK) # 接收高8位数据并继续读取接收.
l8 = read_data(ACK) # 接收低8位数据并停止继续接收CRC数据.
GPIO.setup(D, GPIO.OUT, initial=1)
return (h8 << 8) + l8 # 将h8左移8位再加上l8再返回给run()函数.
# 延时函数.
def delay_little():
time.sleep(0.0006)
# 通信中断时可调用的复位时序函数, 没有调用.
def communication_reset():
GPIO.output(D, 1)
GPIO.output(S, 0)
for i in range(0, 8):
GPIO.output(S, 1)
delay_little()
GPIO.output(S, 0)
delay_little()
start_up()
# 软复位函数, 没有调用.
def softreset():
communication_reset()
error = 0
error += write_cmd(RESET)
return error
# 发送"启动传输"时序 函数.
def start_up():
delay_little()
GPIO.output(S, 1)
delay_little()
GPIO.output(D, 0)
delay_little()
GPIO.output(S, 0)
delay_little()
GPIO.output(S, 1)
delay_little()
GPIO.output(D, 1)
delay_little()
GPIO.output(S, 0)
# 发送测量命令函数.
# 自己对应传输过程图来看吧, 没啥可解释的. error都是为了检测通讯是否正确.
def write_cmd(cmd):
GPIO.output(D, 0)
delay_little()
for i in range(0, 8):
GPIO.output(S, 0)
if (0x80 >> i) & cmd:
GPIO.output(D, 1)
else:
GPIO.output(D, 0)
delay_little()
GPIO.output(S, 1)
delay_little()
GPIO.output(S, 0)
GPIO.setup(D, GPIO.IN)
GPIO.output(S, 1)
while GPIO.input(D):
continue
error = 0
delay_little()
GPIO.output(S, 0)
delay_little()
return error
# 接收sensor测量数据的函数.
# 这里也一样没啥可解释的.
def read_data(ack):
data = 0
n = 0x80
for i in range(0, 8):
GPIO.output(S, 1)
if GPIO.input(D):
data = data | n
delay_little()
GPIO.output(S, 0)
delay_little()
n >>= 1
GPIO.setup(D, GPIO.OUT)
if ack:
GPIO.output(D, 1)
else:
GPIO.output(D, 0)
delay_little()
GPIO.output(S, 1)
delay_little()
GPIO.output(S, 0)
GPIO.setup(D, GPIO.IN)
return data
# 数据的转换计算函数.
def count_data(temp, humi):
c1 = -4.0
c2 = 0.0405
c3 = 0.0000028
t1 = 0.01
t2 = 0.00008
rh = humi
t = temp
tc = t * t1 - 40
rh_lin = c3 * rh * rh + c2 * rh + c1
rh_true = (tc - 25) * (t1 + t2 * rh) + rh_lin
if rh_true > 100.0:
rh_true = 100.0
if rh_true < 0.1:
rh_true = 0.1
return tc, rh_true
# 主函数.
def run():
while 1:
temp = measure(TEMP) # 测量一波温度数据.
humi = measure(HUMI) # 与上同理.
temp, humi = count_data(temp, humi)
print 'T: {}C\nH: {}%'.format(temp, humi)
time.sleep(2) # 延时2秒.
# 从这开始.
if __name__ == '__main__':
run()