概览
树莓派操作系统Occidentalis以及2012年12月之后的Raspbian系统已经能够支持DS18B20单总线(1-wire)温度传感器。这种传感器由半导体包裹的头和三个引脚组成,它是一种精确地数字设备。
这节课里,你将学习如何在树莓派上使用DS18B20来读取温度。
因为树莓派没有数模转换器(ADC, Analog to Digital Converter),因此它不能够直接读取像TMP36这样的模拟信号温度传感器,因此,DS18B20是比较合适的。
另外的代码库
如果你是一个Python爱好者,这有另外一种在树莓派上使用DS18B20的类库。
地址在这里:https://github.com/timofurrer/ds18b20(作者是Timo!)
你需要的
要完成这个项目,你需要下面的东西:
树莓派
DS18B20数字温度传感器 + 延长线,也可以是湿度或者高温型号的。另外你需要一个4.7k或者10k欧姆的电阻。
一小块面包板
一把跳线
扩展板
硬件部分
下图展示了基本的DS18B20接法。
DS18B20单总线(1-wire)传感器可以以非并行连接接入,这一点几乎与其他市售的传感器都不同!所有传感器共享相同的针脚,所以你只需要一个4.7k的电阻就够了。
电阻被用于拉高数据输出线(data-line),并且保持数据输出的稳定。
要注意DS18B20的方向,弧形的一边在图中的左侧。如果你接反了,有可能会烧坏传感器。
尽管DS18B20+和TMP36都是温度传感器,但是它们完全不同,因此TMP36不适用于这篇教程!
如果你是用的是防水版的DS18B20,那我们需要连接3个针脚,红,黑,黄,身下一个引脚不用连接。
如果你是用的是高温版本的DS18B20,把橙色引脚接入3.3V,白色接地,蓝色与数据针pin 4相连。
你同样需要一个4.7k~10k的电阻接在3.3v和数据针之间。
DS18B20
尽管DS18B20看上去就像一个普通的传感器,但它内部其实大有文章。
它的芯片包含了一个特别的单总线串行接口,逻辑控制部分以及一个温度传感器。
它的输出针输出数字消息以便Raspbian/Occidentalis能够在某一针上阅读。你可以在运行这个项目之前自己通过命令行或者SSH先试验一下。
在终端窗口里输入下面的命令。当你执行到”devices”目录下时,目录名称开头的”28-”可能与你的不一样,所以cd到你看到的目录下吧。
sudo modprobe w1-gpio sudo modprobe w1-therm cd /sys/bus/w1/devices ls cd 28-xxxx (change this to match what serial number pops up) cat w1_slave
这个接口有点不太稳定,但如果幸运的话系统会告诉我们有一个可供读取的温度。它类似于一个文件,所以我们要做的就是读这个文件。
在返回消息的第一行末尾都会有一个YES或NO,如果是yes,那第二行紧接着就是温度,以1/1000摄氏度为单位,所以在上面的例子中,实际读取到的温度是20.687和26.125摄氏度。
如果你接入了多个传感器,那么你将看到有多个28-xxx的文件,已经插入一个传感器,然后检查一下新生成的文件名,然后为这个传感器做上标记。这样才能区分出哪个传感器对应哪个文件。
软件部分
下面的Python程序处理失败消息并且每秒返回华氏和摄氏温度。
import os import glob import time os.system(‘modprobe w1-gpio’) os.system(‘modprobe w1-therm’) base_dir = ‘/sys/bus/w1/devices/’ device_folder = glob.glob(base_dir + ’28*’)[0] device_file = device_folder + ‘/w1_slave’ def read_temp_raw(): f = open(device_file, ‘r’) lines = f.readlines() f.close() return lines def read_temp(): lines = read_temp_raw() while lines[0].strip()[-3:] != ‘YES’: time.sleep(0.2) lines = read_temp_raw() equals_pos = lines[1].find(‘t=’) if equals_pos != -1: temp_string = lines[1][equals_pos+2:] temp_c = float(temp_string) / 1000.0 temp_f = temp_c * 9.0 / 5.0 + 32.0 return temp_c, temp_f while True: print(read_temp()) time.sleep(1)
在程序的开头运行了一下modprobe命令,来使接口运行。
紧接着的3行用于寻找哪些文件可以从中读取消息。
一个已知的问题是在Raspbian下读取温度时有时候会假死。如果你有同样的问题,使用下面的代码替换掉read_temp_raw方法。然后在程序开头加入一行”import subprocess”。
def read_temp_raw(): catdata = subprocess.Popen([‘cat’,device_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out,err = catdata.communicate() out_decode = out.decode(‘utf-8’) lines = out_decode.split(‘
‘) return lines
读取温度是通过两个方法进行的。read_temp_raw通过接口获取消息的前两行。read_temp把它包装了一层并且加入了失败消息检测并且重试直到第一行的末尾有一个YES。这个方法会返回两个值,第一个是摄氏温度,第二个是华氏温度。
你可以像下面这样把两个值分开
deg_c, deg_f = read_temp()
主方法只是一个循环,读取温度,打印出来,然后休息一秒。
要把这个程序传到树莓派上,你可以通过SSH在命令行里打开一个文本编辑器
nano thermometer.py
粘贴上面的代码,然后按一下Ctrl+X然后按一下Y保存。
测试与配置
运行这个程序需要超级用户权限,所以在命令行里运行下面的命令
sudo python thermometer.py
如果一切ok,那你将会看到像下面一样的一系列输出
试试把手指放在温度传感器上来给它升温。
加入更多的传感器
你可以以并行连接方式DS18B20把其他的DS18B20传感器接入到VCC,数据和地线针脚。只用一个4.7k电阻。你将会看到多个/sys/bus/w1/devices/28-nnnnn目录,每一个都有一个唯一的串口编号。目前的python程序只能读取一个传感器,所以你需要自己修改使它能够一次读取多个传感器。
新系统更新后gpio读不了w1了的解决办法:
http://bbs.nxez.com/thread-67-1-1.html