Linux下DS18B20多传感器1-Wire温度采集与排障实践

发布时间:2026/10/27 16:00:31
Linux下DS18B20多传感器1-Wire温度采集与排障实践 1. 项目背景与整体思路拆解一条1-Wire总线上挂多颗DS18B20在Linux下用DS9490R这类USB转1-Wire适配器把温度读上来难点从来不是把线拧在一起而是总线物理层、驱动绑定、ROM ID识别和采集节奏这几件事同时要稳。单颗传感器在面包板上跑通很容易多颗传感器上到几米线、加上定时采集和长时间运行之后CRC错误、偶发85℃、设备掉线这些问题才会慢慢冒出来。这个项目适合已经能在Linux下看懂基本命令、又想把多路温度采集做成可长期运行方案的读者也适合刚接触1-Wire总线、想少走弯路的初学者。DS9490R在这里扮演的是USB主机侧适配器角色它把Linux的USB接口转换成1-Wire总线时序DS18B20则是挂在总线上的从设备每颗都有自己唯一的64位ROM ID所以多颗并联并不需要手动设地址。Linux侧有两条常见路线一条是内核自带的w1子系统设备枚举后直接读/sys/bus/w1/devices/28-*/w1_slave另一条是owfs/owserver用户态方案通过USB访问适配器并把1-Wire设备映射成文件。两条路线各有取舍下面我会把选型逻辑、接线细节、驱动配置、采集脚本和故障排查一次讲透。1.1 为什么“插上USB就能读”往往只是错觉很多人第一次接触DS9490R会默认它像U盘一样插上就出现一个温度文件。实际并不是。USB适配器只负责电气转换和总线时序内核还需要对应的主控制器驱动把USB设备注册成1-Wire总线主机再由从设备驱动把DS18B20识别成温度传感器。也就是说至少要有主控驱动、1-Wire核心层和DS18B20从设备驱动三层配合/sys/bus/w1/devices下面才会出现28-开头的设备目录。少一层现象就是lsusb能看到适配器但sysfs里空空的。我在现场遇到最多的情况不是硬件坏而是发行版内核把相关模块拆到了额外包里或者owfs先一步占用了USB设备。前者表现为modprobe ds2490找不到模块后者表现为内核驱动和owfs只能二选一。先把这条链路想清楚后面排查就不会一上来就怀疑传感器。1.2 DS9490R、DS18B20与1-Wire总线的角色分工DS9490R负责把USB命令转成1-Wire的复位、 presence、读写时隙DS18B20负责响应ROM命令、启动温度转换、把暂存器里的温度值交出来。总线上的多颗DS18B20是并联关系VDD接VDDGND接GNDDQ全部接到同一根数据线再由一个上拉电阻把DQ拉到空闲高电平。每颗DS18B20出厂时已经写好64位ROM前8位是家族码0x28中间48位是唯一序列号最后8位是CRC。Linux枚举出来后目录名通常就是28-xxxxxxxxxxxx这种形式。这里有个容易误解的点多颗传感器并不需要“分配地址”也不存在地址冲突。总线主机通过ROM搜索命令逐个发现设备读温度时可以用Match ROM点名某一颗也可以用Skip ROM广播让所有传感器同时开始转换。真正需要你操心的是总线能不能带得动、上拉够不够、线材分布合不合理而不是给每颗传感器写编号。1.3 选型内核w1子系统还是owfs我一般优先用内核w1子系统原因是它轻量、开机自动枚举、直接读sysfs文件就能拿到温度适合做长期采集。只要内核配置里有CONFIG_W1、CONFIG_W1_MASTER_DS2490和CONFIG_W1_THERM插上适配器后基本就是modprobe加读文件的事。它的缺点是不同内核版本的sysfs细节略有差异批量转换接口也不一定齐全遇到问题要看内核日志。owfs更适合内核驱动缺失、需要跨平台或者需要更丰富1-Wire设备支持的情况。它通过用户态访问USB适配器把设备树挂载到某个目录读温度就是读文件。缺点是它和内核驱动可能争抢同一个USB设备部署时要么让内核绑定要么让owfs独占不能两边同时上手。选型时不要追求“都能用”先把一条路线跑稳再考虑备用方案。方案优点限制适合场景内核w1 sysfs轻量、开机自动枚举、脚本简单依赖内核模块批量转换接口随版本变化固定Linux设备、长期采集owfs/owserver用户态部署、设备支持面广与内核驱动可能冲突需要额外服务内核驱动缺失、多类型1-Wire设备自己写libusb程序控制力最强开发量大时序和错误处理都要自己做特殊时序、批量转换要求高2. 硬件接线与总线物理层多颗DS18B20能不能稳定读七成看接线。1-Wire虽然叫“一根线”但它并不是随便找根杜邦线拉几米就能稳的。数据线DQ需要上拉电阻长线有分布电容分支会产生反射电源供不上时传感器会在转换期间掉压。先把物理层做扎实后面Linux侧的很多“玄学CRC错误”会自然消失。2.1 三线供电与寄生供电怎么选DS18B20支持外部供电和寄生供电两种方式。外部三线供电是VDD、GND、DQ各自接线稳定性最好寄生供电是VDD和GND都接地靠DQ线在空闲时给内部电容充电转换期间需要强上拉。实验室里短距离、少量传感器用寄生供电可能看不出问题但多颗传感器同时转换时电流叠加强上拉不到位就容易出现CRC失败或者读到85℃。我自己的原则是只要布线允许优先三线供电别为了省一根线牺牲稳定性。三线供电时上拉电阻接在DQ和VDD之间常见取值4.7kΩ。这个值不是拍脑袋来的5V总线、4.7kΩ时DQ被拉低时上拉电流大约1mA既能保证上升沿又不会给总线主机太大灌电流。线很长、节点很多时可以适当降到2.2kΩ左右但别低到让适配器吃不消。上拉电压要和适配器的1-Wire电平匹配DS9490R这类适配器常见是5V总线具体以手头设备说明为准不要想当然把5V灌进3.3V系统。供电方式接线优点风险三线外部供电VDD、GND、DQ稳定转换期间不掉压多一根线布线稍麻烦寄生供电VDD与GND接地DQ取电省线转换期间需要强上拉多传感器易不稳2.2 上拉电阻、线材与拓扑的实际取舍上拉电阻只是总线稳定的一部分线材和拓扑同样重要。DQ和GND最好用双绞线VDD单独走一路减少数据线对电源的干扰。总线尽量走菊花链或者一条主线加很短的分支避免星形拓扑星形拓扑会让信号在分支末端反射短线时看不出来线一长CRC错误就上来了。分支长度能短则短几厘米的引出可以接受几十厘米的悬空分支就是隐患。如果现场必须用星形接线我的做法是先把传感器数量减到最少确认单颗稳定后再逐颗加观察CRC错误率。不要一次把十几颗全焊上去然后对着一个不稳定的总线猜问题。上拉电阻也可以准备4.7kΩ、3.3kΩ、2.2kΩ几个规格现场替换测试找到能稳定工作的最小值。电阻越小上升沿越陡但静态电流和主机灌电流也越大所以不是越小越好。2.3 多传感器并联时的接线检查清单多颗DS18B20并联最容易犯的错是把VDD和GND接反、把DQ接到VDD、或者某颗传感器的引脚虚焊。上电前用万用表打一遍VDD对GND不能短路DQ对GND不能短路DQ对VDD之间应该有上拉电阻的阻值。上电后再量总线空闲电压DQ应该被上拉到接近VDD如果只有零点几伏说明总线被拉死或者上拉没接好。还有一个细节TO-92封装的DS18B20引脚定义容易看反平面对着自己、引脚朝下时常见是1脚GND、2脚DQ、3脚VDD但不同封装和不同厂家批次要以器件资料为准。我见过把整条总线接反的现场适配器一插上就保护传感器发热。上电前花两分钟检查比事后换一堆传感器划算。注意首次上电建议用带限流的USB口或者USB Hub确认总线空闲电压正常后再接大量传感器。发现适配器发热、系统反复识别断开立刻断电检查接线。2.4 线长、节点数和转换时间的经验关系1-Wire总线的线长和节点数没有绝对上限它取决于线材电容、上拉电阻、主机驱动能力和供电方式。短距离、几颗传感器4.7kΩ上拉加普通双绞线通常没问题几十米、十几颗传感器就要考虑降低上拉、加中继、缩短分支甚至改用分区总线。不要迷信“理论支持几百米”现场干扰和电源压降会把理论值打回原形。转换时间也要提前算。DS18B20在12位分辨率下最大转换时间750ms10颗传感器如果逐颗触发转换再逐颗读一轮下来可能七八秒。采集周期设得太短脚本会重叠运行sysfs读数还没完成就被下一次读取打断表现为偶发CRC错误。后面的采集脚本里我会用锁和合理的周期来避免这个问题。3. Linux驱动与设备枚举硬件接好之后Linux侧第一件事是确认USB适配器被识别第二件事是确认1-Wire主控驱动和DS18B20从设备驱动都加载了。不要急着写脚本先把/sys/bus/w1/devices下面的设备目录跑出来后面所有采集都建立在这个基础上。3.1 内核w1子系统需要哪些模块先看系统识别情况uname -r lsusb dmesg | tail -n 30DS9490R这类适配器在lsusb里常见会显示为04fa:2490一类的ID具体以你的输出为准。然后加载主控和温度从设备驱动sudo modprobe ds2490 sudo modprobe w1_therm lsmod | grep -E ds2490|w1如果modprobe报“Module not found”先别怀疑硬件查内核模块目录find /lib/modules/$(uname -r) -iname *ds2490* -o -iname *w1_therm*有些发行版把相关模块放在linux-modules-extra包里需要补装对应内核版本的额外模块包。内核配置层面需要CONFIG_W1、CONFIG_W1_MASTER_DS2490、CONFIG_W1_THERM如果是自己编译内核漏掉任何一个都会导致设备不出现。模块加载后看内核日志正常会看到1-Wire总线主机注册以及从设备挂接的信息。3.2 识别多个ROM ID与w1_slave文件设备枚举成功后sysfs里会出现类似下面的目录ls -l /sys/bus/w1/devices/典型输出会有28-00000xxxxxxx这样的目录28是DS18B20家族码后面是序列号。每个目录下的w1_slave就是温度入口。直接读一颗cat /sys/bus/w1/devices/28-00000xxxxxxx/w1_slave输出通常长这样72 01 4b 46 7f ff 0c 10 57 : crc57 YES 72 01 4b 46 7f ff 0c 10 57 t23125第一行末尾的crc57 YES表示这次总线读数CRC校验通过第二行的t23125表示23.125℃。如果第一行是NO说明数据在总线上被干扰了温度值不可信。如果t85000要特别小心85℃是DS18B20上电默认值常见于转换还没完成、寄生供电掉压或者总线时序异常不一定代表真实温度。3.3 owfs路线的部署与冲突处理如果内核驱动实在没有或者你需要owfs的其他能力可以走用户态路线。先确认系统包管理器里有owfs相关包安装后用USB选项启动。不同版本的参数名可能有差异下面是一种常见写法实际以owfs --help和owserver --help为准sudo modprobe -r ds2490 w1_therm sudo mkdir -p /mnt/1wire sudo owfs --usb /mnt/1wire挂载成功后设备目录下会出现28.xxxxxxxxxxxx这样的节点温度文件通常是temperaturels /mnt/1wire cat /mnt/1wire/28.xxxxxxxxxxxx/temperature这里的关键是“不要两边同时抢设备”。如果内核ds2490已经绑定适配器owfs通过用户态访问时可能打不开USB设备反过来owfs占用期间sysfs也不会正常枚举。我的做法是固定一条路线能用内核就用内核不能用内核就卸载内核驱动再上owfs不在同一台机器上混着跑。现象可能原因处理lsusb有设备sysfs无28-目录主控或从设备模块未加载加载ds2490、w1_therm查dmesgmodprobe ds2490失败内核模块缺失或版本不匹配安装对应内核额外模块包owfs打不开USB设备内核驱动已绑定卸载ds2490后重试sysfs有目录但读文件报错权限或总线异常用sudo测试查接线和CRC4. 多传感器采集脚本与落盘设备能枚举只是第一步真正要用起来还得有稳定的采集脚本。多颗DS18B20逐颗读w1_slave时每次读文件都可能触发一次温度转换脚本要接受“一轮采集需要几秒”这个事实。下面先给一个能快速验证的bash脚本再给一个带CRC校验和重试的Python版本。4.1 先用一条命令确认每颗传感器都在线临时排查时用循环把所有28-*设备读一遍最直接for f in /sys/bus/w1/devices/28-*/w1_slave; do id$(basename $(dirname $f)) raw$(cat $f) crc$(printf %s\n $raw | awk /crc/{print $NF}) t$(printf %s\n $raw | awk -Ft /t/{print $2}) if [ $crc YES ] [ -n $t ]; then printf %s %.3f C\n $id $(awk -v x$t BEGIN{printf %.3f, x/1000}) else printf %s CRC_FAIL\n $id fi done这段脚本的价值在于快速区分三种状态正常、CRC失败、没有温度字段。如果输出里某颗传感器反复CRC_FAIL先查它的接线和上拉不要急着换传感器。如果所有传感器都正常但某颗偶尔冒85℃重点查供电和转换时间。4.2 Python采集脚本带CRC校验、重试和CSV输出下面这个脚本可以直接放到/usr/local/bin/read_w1.py按需改传感器匹配路径和重试次数。它做四件事枚举28-*设备、读取w1_slave、校验CRC、失败重试最后输出一行CSV。#!/usr/bin/env python3 import csv import glob import os import re import sys import time from datetime import datetime SENSOR_GLOB /sys/bus/w1/devices/28-*/w1_slave RETRY 3 RETRY_WAIT 0.2 def read_one(path): sid os.path.basename(os.path.dirname(path)) last_err unknown for _ in range(RETRY): try: with open(path, r, encodingascii) as f: text f.read() except OSError as e: last_err fopen_error:{e} time.sleep(RETRY_WAIT) continue if crc not in text or YES not in text.splitlines()[0]: last_err crc_fail time.sleep(RETRY_WAIT) continue m re.search(rt(-?\d), text) if not m: last_err no_t_field time.sleep(RETRY_WAIT) continue temp_c int(m.group(1)) / 1000.0 if temp_c 85.0: last_err suspicious_85c time.sleep(RETRY_WAIT) continue return sid, temp_c, return sid, None, last_err def main(): now datetime.now().isoformat(timespecseconds) writer csv.writer(sys.stdout) writer.writerow([timestamp, rom_id, temp_c, status]) for path in sorted(glob.glob(SENSOR_GLOB)): sid, temp, err read_one(path) if temp is None: writer.writerow([now, sid, , err]) else: writer.writerow([now, sid, f{temp:.3f}, ok]) if __name__ __main__: main()实际部署时可以把CSV追加到日志文件再用采集服务定时执行。注意脚本里把85℃当成可疑值而不是直接采信。真正需要85℃的场景当然有但工业现场更多是转换未完成或者供电不足。如果你确定环境温度可能接近85℃可以把这条判断改成告警而不是丢弃避免误杀正常数据。4.3 定时采集与防止任务重叠用cron定时跑最简单*/1 * * * * flock -n /tmp/w1.lock /usr/local/bin/read_w1.py /var/log/w1/temp.csv 21这里的flock -n很关键。多颗12位传感器一轮采集可能超过一秒如果定时周期太短上一次还没跑完下一次又启动sysfs读取会互相干扰日志里就会出现莫名其妙的CRC失败。用文件锁保证同一时间只有一个采集进程周期根据传感器数量调整5颗以内一分钟一次很轻松十几颗又要求12位精度建议先测一轮实际耗时再定周期。如果系统用systemd可以把脚本包成service再用timer触发日志交给journald管理。无论哪种方式都要保证日志目录存在、磁盘有空间、脚本有读sysfs的权限。长期运行的项目最怕日志把分区写满建议按天切割或者只记录异常和分钟级汇总。4.4 给每颗探头建立ROM ID与位置的映射多传感器项目里ROM ID是一串没有语义的字符不建立映射过两天就不知道哪颗对应哪个位置。我一般会维护一张简单的表把ROM ID、安装位置、备注写清楚ROM ID安装位置备注28-00000aaaaaaa冷藏区上层避开冷凝水直滴28-00000bbbbbbb冷藏区下层靠近回风口28-00000ccccccc环境区远离发热源这张表可以放在采集脚本的配置里也可以在数据落盘后做关联。不要依赖“接线顺序”来识别传感器因为总线枚举顺序不一定等于物理顺序。最稳的办法是接一颗、读一颗、贴一张标签最后再用脚本全量核对一遍。5. 常见故障排查与避坑多传感器1-Wire项目的故障大多有规律要么完全枚举不到要么少几颗要么读到了但CRC不稳要么温度值明显不对。下面按症状整理一张速查表再讲几个现场最容易踩的坑。5.1 症状速查表症状优先怀疑排查动作lsusb有适配器sysfs无设备主控/从设备模块未加载modprobe ds2490、modprobe w1_therm看dmesg只有部分传感器出现接线虚焊、供电不足、分支过长逐颗断开测试量DQ空闲电压全部传感器CRC失败上拉缺失、总线短路、电平不匹配断电量DQ对GND、DQ对VDD偶发85℃转换未完成、寄生供电掉压改三线供电延长采集间隔读文件权限不足普通用户无sysfs读权限用sudo验证配置udev或服务用户owfs和sysfs只能二选一驱动争抢USB设备固定一条路线卸载另一边驱动5.2 CRC失败与85℃假值的处理顺序看到CRC失败先不要改脚本重试次数先查物理层。第一步量总线空闲电压DQ应该接近上拉电压第二步看总线是否有短路断电测DQ对GND第三步减少传感器数量只留一颗测试第四步换短线和换个上拉电阻。很多CRC失败不是传感器坏而是某段线太长、分支太多或者上拉太弱。把物理层理顺之后脚本的重试才有意义。85℃更典型。DS18B20上电后暂存器温度寄存器默认就是85℃如果转换命令没完成、总线在转换期间掉压、或者读取时序被打断读到的就是默认值。处理办法是确认供电方式、延长转换等待、避免高频重复读同一个文件。内核w1_therm逐文件读取时本身会处理转换等待但多颗传感器轮询时总时间会累加采集周期设得太短仍然会出问题。注意不要把85℃直接当成传感器故障换掉。先看它是不是固定出现、是否集中在某几颗、是否在增加传感器后变多这些信息比换件更有价值。5.3 传感器数量增加后不稳定的排查顺序数量增加后不稳定我通常按“供电、线材、上拉、时序、主机”五步走。先确认电源能提供足够电流多颗传感器同时转换时电压不能明显跌落再检查线材是否太长、分支是否太多然后调整上拉电阻接着放慢采集周期观察CRC错误率是否下降最后才怀疑适配器主机能力。不要一上来就换DS9490R大多数问题在总线上不在USB口。如果条件允许做一个对照实验同样代码、同样电源只把传感器从10颗减到5颗看CRC错误是否消失再把线长减半看是否改善。通过变量控制找到临界点比盲目换件快得多。现场记录也很重要把每次改动后的错误率记下来后面长期运维会感谢现在的自己。5.4 驱动、权限与owfs冲突的细节权限问题经常被忽略。/sys/bus/w1/devices下面的文件默认可能只有root可读普通用户跑脚本会报Permission denied。临时可以用sudo验证长期方案是让采集服务以有权限的用户运行或者写udev规则调整设备节点权限。不要把整个脚本长期挂在root下跑能降权就降权。owfs冲突则更隐蔽有时sysfs里能看到设备但owfs启动后设备消失或者反过来。原因是USB设备只能被一个驱动绑定。确定用内核方案后就不要同时启动owfs服务确定用owfs后先modprobe -r ds2490 w1_therm再启动owfs。把这条规则写进部署文档避免下次重启后两边服务同时拉起。6. 工程化参数与长期运行经验把温度读出来只是开始长期运行还要考虑分辨率、采集周期、数据校验和异常恢复。下面这些参数和经验是我在实际项目里反复调过的直接拿去用能少踩不少坑。6.1 分辨率与转换时间怎么配DS18B20支持9到12位分辨率分辨率越高转换时间越长。12位分辨率下温度步进是0.0625℃最大转换时间750ms11位是375ms10位是187.5ms9位是93.75ms。多传感器轮询时转换时间会直接决定一轮采集的耗时。如果只是做环境监测9位或10位往往够用要做精密温差或者快速变化检测再上12位。分辨率温度步进最大转换时间适用场景9位0.5℃93.75ms粗略环境监测10位0.25℃187.5ms一般温度记录11位0.125℃375ms需要较细变化12位0.0625℃750ms精密测量、慢速采集部分内核的w1_therm提供resolution属性可以写入9到12改变分辨率echo 10 | sudo tee /sys/bus/w1/devices/28-00000xxxxxxx/resolution这个设置不一定在重启后保留长期项目要在启动脚本里重新写入或者用udev规则处理。写入前先确认你的内核版本支持这个属性不支持就按默认12位跑通过采集周期来适配。6.2 批量转换与逐颗读取的差别多颗DS18B20挂在同一条总线上理论上可以用Skip ROM广播“开始转换”让所有传感器同时转换然后再逐个Match ROM读温度这样总转换时间只算一次750ms而不是每颗都等750ms。但内核sysfs的逐文件读取不一定自动帮你做批量转换具体行为跟内核版本和驱动实现有关。表现就是10颗传感器逐颗cat一轮下来可能要七八秒。如果对采集频率要求高可以先查当前内核有没有批量转换节点比如总线目录下与therm_bulk_read相关的属性有就按文档使用没有就接受逐颗读取的耗时把采集周期放宽。不要为了追求高频率去疯狂读sysfs总线时序和驱动等待不会因为你读得快就变快反而容易把CRC错误率拉高。6.3 数据落盘、告警与异常恢复数据落盘建议至少记录时间戳、ROM ID、温度值、状态四个字段。状态字段不要只记ok要把crc_fail、suspicious_85c、open_error区分开后面排查才知道是总线问题还是权限问题。CSV简单够用数据量大再考虑SQLite或者时序数据库。温度采集的数据量通常不大别一上来就上重型方案。告警不要只看瞬时值。传感器偶发一次CRC失败很常见连续多次失败才值得告警温度超过阈值也要加持续时间条件避免开门、除霜等短时波动触发误报。采集脚本自身要有异常恢复能力USB适配器被拔掉再插上后内核会重新枚举脚本下一次循环应该能自动发现新设备而不是启动时就固定了设备列表。用glob每次重新扫描比缓存路径更稳。6.4 长时间运行后的现场体会我在现场最愿意先做的一件事不是写多复杂的程序而是把总线接上示波器或者万用表看一眼DQ空闲电压和转换期间的电压跌落。很多“软件问题”在电压波形上一眼就能看出来。多颗传感器项目里电源和上拉是最值得投入时间的地方脚本反而可以很简单。另一个体会是不要把采集周期设到理论极限留出两三倍余量系统长期运行会稳得多。如果后面还要扩展可以考虑把总线分区比如一条总线带5到8颗传感器多路适配器或者多路1-Wire中继分别接入这样单条总线的负载和线长都可控。分区之后某个区域出问题不会拖垮全部数据维护时也更容易定位。这个思路在冷库、温室、机柜温度监测这类场景里特别实用。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询