一、前言
单总线也叫做一线总线(one-write),它只有1根信号线,既传输时钟又传输数据,而且数据传输是双向的,通过一问一答的形式实现两个设备之间的数据交互。具体的原理我就不细说了,感兴趣的同学可以自己去查阅相关的资料,今天我以DS18B20为例,讲一下树莓派的单总线的使用方法。
二、硬件连接
DS18B20引脚定义如下,根据引脚定义连接到树莓派上,我这里用的是一个扩展板,直接把传感器接上即可。
引脚 | 名称 | 说明 |
---|---|---|
1 | GND | 供电电源负极 |
2 | DQ | 数据输入输出引脚(和MCU任意一个IO口相连,注意:这里需要有上拉电阻) |
3 | VCC | 供电电源正极 |
注意:如果你的传感器是插件封装的,一定要分清楚正负,不然会烧坏的。判断方法(仅供参考):平的一面对着自己,左边的是GND,右边的是VCC,中间的是信号线。接上之后可以迅速上电然后断电,摸一下传感器,如果迅速发热并且非常烫说明接反了。
三、使能1-write接口
方法1:通过配置命令
sudo raspi-config // 打开配置
sudo reboot // 重启,如果之前没有使能,配置完之后要重启才能生效
方法2:在可视化界面的设置里面修改
注意:如果设备启动的时候是没有使能1-Write接口的,使能之后需要重启才能生效。
四、通讯测试
sudo modprobe w1-gpio
sudo modprobe w1-therm
cd /sys/bus/w1/devices
ls // 查询传感器的ID,如果什么都没有,可能是前面没有使能1-Write,或者使能了但是没有重启,也可能是硬件连接有问题
cd 28-xxxxxxx // 28-xxxxxxx:18b20的ID,每个传感器的id都是不同的,根据自己的输入,如果查询的ID里面不是28开头而是00开头的,那应该不是ds18b20
cat w1_slave
五、编写代码并运行
1、方式1
基于w1thermsensor库驱动DS18B20,w1thermsensor库集成了多款传感器的驱动(DS18S20、DS1822、DS18B20、DS28EA00、DS1825/MAX31850K)。
w1thermsensor Github 链接:https://github.com/timofurrer/w1thermsensor
示例代码:
from w1thermsensor import W1ThermSensor
sensor = W1ThermSensor(W1ThermSensor.THERM_SENSOR_DS18B20, "00000cb51493") #00000cb51493:是ds18b20的id,根据自己的id输入(注意不要把“28-”也复制进来)
temp = sensor.get_temperature()
print(temp)
注:该代码基于w1thermsensor库驱动,使用w1thermsensor库之前先要安装这个库,命令如下:
sudo apt-get install python3-pip // python3 pip安装管理器依赖包
sudo apt-get install python3-w1thermsensor // w1thermsensor库
查询要读取的ds18b20的id。
可以通过第四步的通讯测试查,也可以用下面的命令查。
cd /etc
ls /sys/bus/w1/devices
示例代码1运行结果:
2、方式2
这个方法其实就是基于第四点的通讯测试,把手动输入的命令写在脚本上运行。
示例代码:
#!/usr/bin/python
# -*- coding:utf-8 -*-
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_rom():
name_file=device_folder+'/name'
f = open(name_file,'r')
return f.readline()
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
print(' rom: '+ read_rom())
while True:
print(' C=%3.3f F=%3.3f'% read_temp())
time.sleep(1)
示例代码运行结果:
六、结束语
DS18B20是一款很简单的单总线传感器,我觉得以此为例去学习和了解单总线是一个非常好的选择。
关于树莓派和单片机的一些个人见解:
树莓派快速入门系列教程,刚刚进入基础编程的教学,为了避免大家进入思维的误区,在这里我想说说我对树莓派的一些看法。树莓派是一个微型的电脑,在运算能力方面是比单片机要强的,在编程上树莓派更偏向应用层的开发,也可以理解为电脑软件的开发。而单片机的话更多的是做底层外设驱动的开发,应用层主要也是以控制为主,不会说用单片机去做一个非常复杂的数据运算或者处理大量的数据。
所以,树莓派的编程其实是有一点点脱离硬件的,就是我们可以不管底层的硬件是怎么实现数据采集和传输的,直接调用库函数,把数据拿到就行了,当然,有时间和精力的话是可以去研究一下硬件的原理和底层的实现。而单片机的开发很多时候会遇到一些没用过的芯片,我们就需要根据芯片的数据手册去开发一个驱动程序,然后再做应用层的开发,当然了,单片机也是可以跑操作系统的,比如FreeRTos、RT-thread等,跑操作系统的话和树莓派的编程就有些类似了,但毕竟跑系统的单片机还是少数。
总结起来就是一句话:树莓派编程能用库的就用库,底层怎么实现的不用管,我们是做大事的,不要花太多的时间在一些小事情上面。纯粹是个人的看法,勿喷,如果你有不同的见解,欢迎在评论区留言,谢谢!!!
好了,这一讲的内容就这么多了,如果对你有帮助,可以给个收藏,如果想了解更多树莓派的知识可以关注我,后续我会继续更新更多的教程。
树莓派入门系列教程:树莓派从零开始快速入门系列汇总