"""
基于ESP32的智能温控保护装置
功能:温度检测 → LED分级指示 → OLED显示 → 超阈值报警 + 伺服马达断电
"""
from machine import Pin, I2C, PWM
import ssd1306
import dht
import time
# ==================== 引脚配置 ====================
# 可根据Wokwi中的实际连线修改引脚编号
DHT_PIN = 15 # DHT22传感器
LED_GREEN = 13 # 绿色LED
LED_YELLOW = 12 # 黄色LED
LED_RED = 14 # 红色LED
BUZZER_PIN = 27 # 蜂鸣器
SERVO_PIN = 23 # 伺服马达
OLED_SCL = 22 # OLED I2C时钟
OLED_SDA = 21 # OLED I2C数据
# ==================== 阈值设置 ====================
TEMP_WARN = 28 # 预警阈值(℃),超过则亮黄灯
TEMP_DANGER = 32 # 危险阈值(℃),超过则报警+断电
TEMP_RESET = 30 # 复位阈值(℃),低于此值解除危险状态(滞回控制)
SAMPLE_INTERVAL = 2 # 采样间隔(秒)
CONFIRM_COUNT = 3 # 连续超标次数才触发动作(防误判)
# ==================== 硬件初始化 ====================
# 1. 温度传感器
dht_sensor = dht.DHT22(Pin(DHT_PIN))
# 2. LED(三色)
led_green = Pin(LED_GREEN, Pin.OUT)
led_yellow = Pin(LED_YELLOW, Pin.OUT)
led_red = Pin(LED_RED, Pin.OUT)
# 3. 蜂鸣器(PWM)
buzzer = PWM(Pin(BUZZER_PIN), freq=1000, duty=0)
# 4. 伺服马达(PWM,50Hz标准频率)
servo = PWM(Pin(SERVO_PIN), freq=50)
# 伺服角度映射:0°对应duty≈26,180°对应duty≈130(Wokwi实测值)
SERVO_MIN = 26 # 0°
SERVO_MAX = 130 # 180°
servo.duty(SERVO_MIN) # 初始位置:0°(闭合状态)
# 5. OLED屏幕(I2C)
# 新的(兼容 Wokwi)
i2c = I2C(0, scl=Pin(OLED_SCL), sda=Pin(OLED_SDA), freq=400000)
oled = ssd1306.SSD1306_I2C(128, 64, i2c) # 新驱动专属的 I2C 子类
# ==================== 辅助函数 ====================
def set_led(state):
"""根据状态设置LED颜色:'safe'/'warn'/'danger'"""
led_green.value(0)
led_yellow.value(0)
led_red.value(0)
if state == 'safe':
led_green.value(1)
elif state == 'warn':
led_yellow.value(1)
elif state == 'danger':
led_red.value(1)
def servo_angle(angle):
"""将角度(0-180)转换为PWM duty值"""
angle = max(0, min(180, angle))
duty = int(SERVO_MIN + (SERVO_MAX - SERVO_MIN) * angle / 180)
servo.duty(duty)
def alarm_on():
"""开启蜂鸣器警报"""
buzzer.duty(512) # 50%占空比
def alarm_off():
"""关闭蜂鸣器"""
buzzer.duty(0)
def read_temperature():
"""读取温度,返回温度值或None(读取失败时)"""
try:
dht_sensor.measure()
return dht_sensor.temperature()
except:
return None
def update_display(temp, status, is_alarm):
"""更新OLED显示内容"""
oled.fill(0)
oled.text("Temp Monitor", 0, 0)
if temp is not None:
oled.text("Temp: {:.1f}C".format(temp), 0, 16)
else:
oled.text("Temp: -- C", 0, 16)
# 状态显示
status_text = {
'safe': 'Status: SAFE',
'warn': 'Status: WARN',
'danger': 'Status: DANGER'
}.get(status, 'Status: UNKNOWN')
oled.text(status_text, 0, 32)
# 警报状态
oled.text("Alarm: {}".format("ON " if is_alarm else "OFF"), 0, 48)
oled.show()
# ==================== 主程序 ====================
def main():
# 状态变量
danger_count = 0 # 连续危险计数
is_cutoff = False # 是否已切断电源
is_alarm = False # 是否正在报警
status = 'safe' # 当前状态
print("=== 智能温控保护装置启动 ===")
print("预警阈值: {}℃ | 危险阈值: {}℃ | 复位阈值: {}℃".format(
TEMP_WARN, TEMP_DANGER, TEMP_RESET))
while True:
# 1. 读取温度
temp = read_temperature()
if temp is None:
print("传感器读取失败,等待重试...")
time.sleep(SAMPLE_INTERVAL)
continue
# 2. 温度分级判断(含滞回逻辑)
if is_cutoff:
# 已切断状态下,需降至复位阈值以下才恢复
if temp < TEMP_RESET:
status = 'safe'
danger_count = 0
is_cutoff = False
is_alarm = False
alarm_off()
servo_angle(0) # 复位到0°(闭合)
print("温度已回落至{}℃,解除危险状态".format(temp))
else:
status = 'danger'
else:
# 正常监测状态
if temp >= TEMP_DANGER:
danger_count += 1
if danger_count >= CONFIRM_COUNT:
# 连续超标,触发危险
status = 'danger'
is_cutoff = True
is_alarm = True
alarm_on()
servo_angle(90) # 旋转90°模拟切断电源
print("!!! 危险!温度{}℃ 超过阈值,已切断电源 !!!".format(temp))
else:
status = 'warn'
elif temp >= TEMP_WARN:
danger_count = 0
status = 'warn'
else:
danger_count = 0
status = 'safe'
if is_alarm:
is_alarm = False
alarm_off()
# 3. 更新LED
set_led(status)
# 4. 更新OLED显示
update_display(temp, status, is_alarm)
# 5. 串口输出(便于调试和数据记录)
print("Temp: {:.1f}℃ | Status: {} | Cutoff: {} | Count: {}".format(
temp, status, is_cutoff, danger_count))
# 6. 等待下一个采样周期
time.sleep(SAMPLE_INTERVAL)
# ==================== 程序入口 ====================
if __name__ == "__main__":
main()