# 防火灾系统
from machine import Pin, I2C, ADC, PWM, RTC
from ssd1306 import SSD1306_I2C
import dht
import time
import ntptime
import network
# 硬件初始化
# OLED 显示屏(I2C)
i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)
oled = SSD1306_I2C(128, 64, i2c)
# 温湿度传感器(DHT22)
dht_sensor = dht.DHT22(Pin(4))
# 烟雾传感器
mq_sensor = ADC(Pin(36))
mq_sensor.atten(ADC.ATTN_11DB)
# 光敏电阻
flame_sensor = ADC(Pin(39))
flame_sensor.atten(ADC.ATTN_11DB)
# 输出设备
buzzer = PWM(Pin(5), freq=1000, duty=0) # 蜂鸣器
relay = Pin(17, Pin.OUT, value=0) # 继电器
# 系统参数
temp_threshold = 40.0 # 温度阈值(°C)
smoke_threshold = 4000 # 烟雾阈值
flame_threshold = 200 # 火焰阈值
# 显示时间控制
DISPLAY_ID_TIME = 3 # 姓名学号时长
DISPLAY_SENSOR_TIME = 2 # 传感器数据时长
# WiFi 连接与时间校准
def connect_wifi():
"""连接WiFi并校准时间"""
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print("正在连接WiFi...")
oled.fill(0)
oled.text("连接WiFi中...", 0, 0)
oled.show()
wlan.connect('Wokwi-GUEST', '')
# 等待连接
max_wait = 15
while max_wait > 0 and not wlan.isconnected():
time.sleep(1)
max_wait -= 1
oled.text(f"剩余: {max_wait}秒", 0, 16)
oled.show()
# 连接成功处理
if wlan.isconnected():
status = wlan.ifconfig()
print(f"WiFi连接成功")
oled.fill(0)
oled.text("WiFi连接成功", 0, 0)
oled.show()
# 校准RTC时间
try:
print("同步前本地时间:", time.localtime())
ntptime.settime()
print("同步后本地时间:", time.localtime())
oled.text("时间校准完成", 0, 16)
oled.show()
except Exception as e:
print(f"时间校准失败: {e}")
oled.text(f"校时失败: {e}", 0, 16)
oled.show()
else:
print("WiFi连接超时")
oled.fill(0)
oled.text("WiFi连接超时", 0, 0)
oled.text("请检查网络", 0, 16)
oled.show()
else:
print("已连接到WiFi")
oled.fill(0)
oled.text("已连接到WiFi", 0, 0)
oled.show()
def get_time_str():
"""获取格式化时间字符串(自定义格式:年-月-日 星期 时:分:秒)"""
try:
rtc = RTC()
# 获取RTC时间元组,格式:(年, 月, 日, 星期几(1-7,对应周一到周日), 时, 分, 秒, 亚秒)
year, month, day, wday, hour, minute, second, _ = rtc.datetime()
# 定义星期
week_days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
date_part = f"{year}-{month}-{day} {week_days[wday - 1]}"
time_part = f"{hour:02d}:{minute:02d}:{second:02d}"
return date_part, time_part
except Exception as e:
print(f"获取时间失败: {e}")
return "2023-01-01 Mon", "00:00:00" # 异常时返回默认时间
# 功能函数
def display_name_id_with_time():
"""显示姓名、学号和时间"""
oled.fill(0)
oled.text("hechunlong", 0, 0)
oled.text("2023103030020", 0, 16)
date_part, time_part = get_time_str()
oled.text(date_part, 0, 32)
oled.text(time_part, 0, 48)
oled.show()
def display_sensor_data():
"""显示传感器数据"""
# 读取温湿度
temp, hum = None, None
try:
dht_sensor.measure()
temp = dht_sensor.temperature()
hum = dht_sensor.humidity()
except Exception as e:
print(f"读取DHT22失败: {e}")
# 读取烟雾浓度
smoke_val = mq_sensor.read()
# 读取火焰传感器
flame_val = flame_sensor.read()
flame_detected = flame_val < flame_threshold
# 显示到 OLED
oled.fill(0)
oled.text(f"temperature: {temp:.1f}°C" if temp is not None else "temperature: error", 0, 16)
oled.text(f"Humidity: {hum:.1f}%" if hum is not None else "Humidity: error", 0, 28)
oled.text(f"Smoke: {smoke_val}", 0, 40)
oled.text(f"flame: {'detected' if flame_detected else 'Not detected.'}", 0, 52)
oled.show()
return temp, hum, smoke_val, flame_detected
def check_alarm(temp, smoke_val, flame_detected):
"""阈值检测与报警"""
alarm = False
alarm_reason = []
# 温度超限(检查)
if temp is not None and temp > temp_threshold:
alarm = True
alarm_reason.append(f"高温({temp:.1f}°C)")
# 烟雾超限
if smoke_val > smoke_threshold:
alarm = True
alarm_reason.append(f"烟雾({smoke_val})")
# 检测到火焰
if flame_detected:
alarm = True
alarm_reason.append("火焰")
# 报警动作
if alarm:
buzzer.duty(512) # 蜂鸣器响
relay.value(1) # 继电器吸合
# 显示报警原因
oled.fill(0)
oled.text("警告! 检测到:", 10, 10)
oled.text(" + ".join(alarm_reason), 10, 30)
oled.text("请立即处理!", 20, 50)
oled.show()
time.sleep(0.5) # 缩短显示时间
else:
buzzer.duty(0) # 关闭蜂鸣器
relay.value(0) # 继电器断开
# ------------------ 主程序 ------------------
def main():
try:
# 连接WiFi并校准时间
connect_wifi()
# 主循环状态
display_state = 0
last_state_change = time.time()
while True:
current_time = time.time()
# 状态切换逻辑
if display_state == 0 and current_time - last_state_change >= DISPLAY_ID_TIME:
display_state = 1
last_state_change = current_time
elif display_state == 1 and current_time - last_state_change >= DISPLAY_SENSOR_TIME:
display_state = 0
last_state_change = current_time
# 根据状态显示内容
if display_state == 0:
display_name_id_with_time()
else:
temp, hum, smoke_val, flame_detected = display_sensor_data()
check_alarm(temp, smoke_val, flame_detected)
time.sleep(0.1)
except Exception as e:
print(f"程序异常: {e}")
# 故障保护
buzzer.duty(0)
relay.value(0)
oled.fill(0)
oled.text(f"系统错误: {e}", 0, 0)
oled.show()
if __name__ == "__main__":
main()