读取 Maxim 1-Wire 温度传感器
作者:Noah Crowley / 用例,产品,开发者
2019年9月5日
导航至
我最喜欢的传感器之一是 Maxim DS18*20 系列温度传感器,这是一系列价格低廉的温度传感器,它们通过名为 1-Wire 的“单接触串行接口”进行通信。我已经将它们集成到各种项目中多年,它们始终是可靠、准确且极容易使用的。这部分原因是它们使用单接触进行通信——当你在嵌入式计算机或微控制器上想要节省引脚时非常有价值——但也因为 Linux 内核中内置的 w1_therm
驱动程序,这意味着它们可以在任何具有适当物理接口的 Linux 机器上工作。
为了举例,我们将使用一个连接到 GPIO 引脚的 DS18B20 的 Raspberry Pi。您可以在本博客文章中找到电路图 http://www.circuitbasics.com/raspberry-pi-ds18b20-temperature-sensor-tutorial/。我们将加载 w1_therm
内核模块以及使用 GPIO API 提供的 w1_gpio
模块。
modprobe w1_gpio
modprobe w1_therm
启用内核模块后,传感器现在可以通过sysfs接口作为独立的目录进行访问。我们可以使用ls
命令和一些通配符来查找有关我们的传感器信息
$ ls -laH /sys/class/hwmon/hwmon*
total 0
drwxr-xr-x 3 root root 0 Apr 24 23:59 .
drwxr-xr-x 3 root root 0 Apr 24 23:59 ..
lrwxrwxrwx 1 root root 0 Apr 24 23:59 device -> ../../../28-000002e36be9
-r--r--r-- 1 root root 4096 Apr 24 23:59 name
drwxr-xr-x 2 root root 0 Apr 24 23:59 power
lrwxrwxrwx 1 root root 0 Apr 24 23:59 subsystem -> ../../../../../class/hwmon
-r--r--r-- 1 root root 4096 Apr 24 23:59 temp1_input
-rw-r--r-- 1 root root 4096 Apr 24 23:59 uevent
在这个目录中,你可以找到各种文件,包括指向设备自身的符号链接、传感器名称以及名为temp1_input
的文件,你可以读取它来获取传感器的温度,单位为摄氏度*1000
$ cat /sys/class/hwmon/hwmon0/temp1_input
27562
此外,你可以通过读取/sys/class/hwmon/hwmon0/device/w1_slave
文件来获取更多有关传感器的信息,它看起来像这样
$ cat /sys/class/hwmon/hwmon0/device/w1_slave
bb 01 4b 46 7f ff 05 10 c6 : crc=c6 YES
bb 01 4b 46 7f ff 05 10 c6 t=27678
这显示了设备左边的十六进制输出,以及右边CRC错误检查和温度读数的结果。
Telegraf的Temp插件
Telegraf的temp
输入插件在每次收集过程中从文件系统中读取温度传感器的数据。你可以使用官方InfluxData仓库在Raspberry Pi上安装Telegraf和InfluxDB(请点击此处查看安装指南)。安装完成后,我们可以通过在/etc/telegraf/telegraf.conf
中取消以下部分的注释来配置Telegraf
# # Read metrics about temperature
[[inputs.temp]]
# # no configuration
由于没有配置项,我们只需启用插件即可。重启Telegraf后,我们应该会在telegraf
数据库的temp
度量中看到数据开始出现(因为我们使用的是默认配置)。
使用多个传感器
不幸的是,当前temp插件的实现存在一个不足之处:它只支持单个传感器。这是因为DS18*20传感器和Telegraf的temp
插件使用的访问文件系统的库:gopsutil存在一个问题。
当使用gopsutil读取温度时,库会使用文件系统中的数据生成一个SensorKey,包括一个label
文件。下面是关于这些文件的内核文档的说明
temp[1-*]_label Suggested temperature channel label.
Text string
Should only be created if the driver has hints about what
this temperature channel is being used for, and user-space
doesn't. In all other cases, the label is provided by
user-space.
RO
由于DS18B20和其他类似传感器的应用可能不同,因此驱动程序是通用的,并且没有关于温度通道被用于什么的任何信息,所以这个文件不会创建。这意味着当Telegraf从多个传感器收集数据时,它们的标记值是相同的,因为它们都具有相同的SensorKey
。因此,尽管我们正在收集每个传感器的数据,但数据点具有相同的元数据和时间戳,因此会相互覆盖。我们可以通过运行Telegraf并使用--test
参数来验证这一点,该参数会将行协议打印到命令行。
使用Python处理多个传感器的问题
我们可以通过使用Python脚本读取数据(你可以在此处找到示例脚本),并使用Telegraf的exec
插件来执行该脚本,来解决这个问题。
下载脚本并将其复制到更永久的位置;现在,让我们将其放入/usr/local/bin
。因为我们使用官方InfluxData仓库安装了Telegraf,所以Telegraf以telegraf
用户运行,这意味着我们还需要更改脚本的权限,以便Telegraf可以执行它,如下所示
sudo chown telegraf:telegraf /usr/local/bin/read_multiple_ds18b20.py
$ sudo chmod 755 /usr/local/bin/read_multiple_ds18b20.py
然后我们可以配置Telegraf的exec
插件来执行脚本,通过启用插件并添加文件到commands
参数
# # Read metrics from one or more commands that can output to stdout
[[inputs.exec]]
# ## Commands array
commands = [
"/usr/local/bin/read_multiple_ds18b20.py"
]
完整的配置文件在这里,其中包含了描述默认值的注释。由于多个DS18B20可以共享一条数据线,因此连接额外的设备相当简单:它将共享第一个传感器使用的地线、电源和数据连接。重启Telegraf后,它应该会从每个设备开始收集数据。
未来改进
我有几个应用程序的想法,这些应用程序在每个设备上使用多个温度传感器,因此如果可能的话,迭代内置的temp
插件将很棒,而不是依赖于我们的Python脚本解决方案。
一个可能的方法是对gopsutil库进行小的修改,这将向SensorKey
结构体添加一个设备名称字段(对于每个DS18*20是唯一的)。然后Telegraf可以使用该字段向数据添加一个额外的标签,以防止数据点相互覆盖。我打算提交一个Pull Request,并从gopsutil维护者那里获取一些反馈。在此期间,如果您有任何问题,请随时使用我的Python脚本,或者在社区网站或直接在[email protected]或Twitter @noahcrowley上联系我!