MicroPython+ESP32驱动DS18B20进行温度读取
概述
在物联网和嵌入式系统开发中,温度监测是一项基础而重要的功能。DS18B20作为一款高精度、应用于环境监控、智能家居、支持单总线通信的数字温度传感器,因其布线简单、可多点组网、测温范围广等优点,被广泛农业大棚等多种场景。本文将结合硬件设计与软件实现,详细介绍如何在ESP32平台上使用MicroPython驱动单个DS18B20温度传感器,并通过轮询机制稳定读取温度数据。
一、DS18B20传感器特性简介
DS18B20是一款数字温度传感器,其核心优势在于采用单总线(1-Wire)协议,仅需一根数据线即可完成供电(可选寄生供电)和通信。主要技术参数如下:
- 测温范围:-55°C ~ +125°C
- 精度:±0.5°C(在-10°C ~ +85°C范围内)
- 分辨率可调:9~12位(默认12位)
- 转换时间:最长约750ms(12位精度)
- 支持多设备挂载:每个设备具有唯一64位ROM地址
本文聚焦于单个DS18B20的应用场景,因此无需复杂设备寻址逻辑,简化了系统设计。
二、硬件连接与电路原理图设计
在ESP32与DS18B20的连接中,需确保单总线协议的电气特性满足要求。以下是推荐的硬件连接方式:
1. 原理图
此连接方式适用于大多数开发板,如ESP32等。若使用面包板搭建,请确保接线牢固,避免接触不良导致通信异常。
2. 引脚连接说明
| DS18B20引脚 | 功能说明 | 连接至ESP32 |
|---|---|---|
| VDD | 电源正极 | 3.3V |
| GND | 电源地 | GND |
| DQ | 数据输入/输出 | GPIO22(或其他GPIO) |
3. 关于上拉电阻
由于单总线协议依赖于总线空闲时的高电平状态,必须在DQ与VDD之间接入一个4.7kΩ的上拉电阻。该电阻确保在无设备驱动总线时,信号线保持高电平,避免通信失败。
三、MicroPython代码实现
以下代码实现了对单个DS18B20的温度采集,重点在于非阻塞式轮询读取机制的设计,避免因频繁读取或等待转换造成系统卡顿。
from ds18x20 import DS18X20
from onewire import OneWire
from machine import Pin
import time
class TimeMs:
'''时间控制器'''
def __init__(self, val: int ,start=0):
'''
:param val: 时间间隔 毫秒
:param start: 开始时间的起始位置-start 毫秒
'''
self._interval = val # 时间间隔
self._start = time.ticks_ms() -start # 开始时间
def change(self, val: int):
'''改变时间间隔'''
self._interval = val
def reset(self):
'''重置计时'''
self._start = time.ticks_ms() # 开始时间
def update(self):
'''更新时间'''
t1 = time.ticks_ms()
if t1 - self._start >= self._interval:
self._start = t1
return True
return False
class DS18B20:
def __init__(self, pin=22):
self.ds = DS18X20(OneWire(Pin(pin)))
self._timeMs = TimeMs(800)
self.roms = self.ds.scan()[0]
def scan(self):
'''扫描设备'''
if self._timeMs.update():
self.ds.convert_temp()
return True
return False
def get(self):
"""获取温度(摄氏度)"""
if self.scan():
return self.ds.read_temp(self.roms)
return None
1.使用示例
# 使用示例
ds18b20 = DS18B20()
while True:
temp = ds18b20.get()
if not temp is None:
print(temp)
time.sleep_ms(1)
输出数据:

五、代码实现与核心逻辑解析
整个代码结构,采用了非阻塞式定时轮询机制,避免了传统 time.sleep() 带来的程序阻塞问题,提升了系统的响应性和可扩展性。
from ds18x20 import DS18X20
from onewire import OneWire
from machine import Pin
import time
OneWire:实现单总线协议的基础类,用于在指定 GPIO 引脚上模拟 1-Wire 通信时序。DS18X20:封装了对 DS18B20 芯片的操作指令,如启动温度转换和读取结果。Pin:用于配置和控制 ESP32 的 GPIO 引脚。time:提供时间相关函数,如ticks_ms()用于获取毫秒级时间戳。
2. 自定义时间控制器:TimeMs 类
为了实现精确且非阻塞的时间控制,代码中定义了一个 TimeMs 类,用于管理周期性任务的执行时机。
class TimeMs:
'''时间控制器'''
功能说明:
__init__(val, start):初始化一个时间控制器,val为触发间隔(毫秒),start可用于偏移初始时间,实现“延迟首次触发”。update():核心方法,判断距离上次触发是否已超过设定间隔。如果是,则更新起始时间并返回True,否则返回False。- 使用
time.ticks_ms()而非time.sleep(),实现了非阻塞延时,非常适合在主循环中与其他任务并行运行。
✅ 优势:避免使用
time.sleep(0.8)这类阻塞调用,允许系统在等待期间处理其他任务(如 Wi-Fi 通信、按键检测等)。
3. DS18B20 驱动类实现
class DS18B20:
def __init__(self, pin=22):
self.ds = DS18X20(OneWire(Pin(pin)))
self._timeMs = TimeMs(800)
self.roms = self.ds.scan()[0]
OneWire(Pin(pin)):在指定引脚(默认 GPIO22)上创建单总线通信接口。DS18X20(...):包装 OneWire 接口,提供高级操作。self.ds.scan():扫描总线上所有 DS18B20 设备,返回 ROM 地址列表。由于本文使用单个传感器,直接取第一个地址self.roms = ...[0]。
⚠️ 注意:若总线上无设备或连接异常,
scan()可能返回空列表。
def scan(self):
'''启动温度转换(轮询触发)'''
if self._timeMs.update():
self.ds.convert_temp()
return True
return False
scan()方法名虽为“扫描”,实则用于定时启动温度转换。- 每隔 800ms 触发一次
convert_temp(),符合 DS18B20 在 12 位精度下约 750ms 的转换时间要求。 - 启动转换后立即返回
True,表示“已更新”,为下一步读取做准备。
def get(self):
"""获取温度(摄氏度)"""
if self.scan():
return self.ds.read_temp(self.roms)
return None
get()是对外提供的温度读取接口。- 每次调用时,先通过
scan()判断是否该启动新一轮转换。 - 若是,则启动转换并立即读取上一次的转换结果(MicroPython 的
read_temp()会自动等待完成)。 - 若未到周期,则跳过本次读取,返回
None,避免重复或无效读取。
🔄 工作流程:
- 第 0ms:调用
get()→ 启动转换 A,返回None(尚无数据)- 第 800ms:调用
get()→ 启动转换 B,读取转换 A 的结果- 第 1600ms:启动转换 C,读取转换 B 的结果 ……
实现了“启动与读取”交错进行的高效机制。
五、设计亮点总结
| 特性 | 说明 |
|---|---|
| 非阻塞设计 | 使用 TimeMs 替代 sleep,系统可并行处理其他任务 |
| 精准定时 | 800ms 周期匹配 DS18B20 转换时间,确保数据有效性 |
| 简洁接口 | get() 一键获取温度,内部自动管理转换流程 |
| 可扩展性强 | 易于修改为多传感器支持或集成到 Web 服务中 |
六、结语
本文通过一个简洁而高效的代码实现,展示了如何在 ESP32 的 MicroPython 环境下驱动 DS18B20 温度传感器。借助自定义的 TimeMs 时间控制器,实现了稳定、非阻塞、周期性的温度采集机制,为后续构建环境监控系统、物联网终端等应用打下坚实基础。代码结构清晰,易于理解与复用,非常适合初学者入门和项目集成。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)