"""
MicroPython IoT Weather Station Example for Wokwi.com
To view the data:
1. Go to http://www.hivemq.com/demos/websocket-client/
2. Click "Connect"
3. Under Subscriptions, click "Add New Topic Subscription"
4. In the Topic field, type "wokwi-weather" then click "Subscribe"
Now click on the DHT22 sensor in the simulation,
change the temperature/humidity, and you should see
the message appear on the MQTT Broker, in the "Messages" pane.
Copyright (C) 2022, Uri Shaked
https://wokwi.com/arduino/projects/322577683855704658
"""
import network
import time
from machine import Pin, I2C
import dht
import ujson
from umqtt.simple import MQTTClient
import ssd1306
# 配置参数
CONFIG = {
'mqtt': {
'client_id': "micropython-weather-demo",
'broker': "broker.mqttdashboard.com",
'user': "",
'password': "",
'topic': "wokwi-weather"
},
'sensor_pin': 15,
'i2c_pins': {'scl': 22, 'sda': 21},
'oled_size': {'width': 128, 'height': 64},
'wifi_ssid': 'Wokwi-GUEST',
'wifi_password': '',
'button_pin': 14, # 假设设置按钮连接到GPIO14
'buzzer_pin': 2, # 假设蜂鸣器连接到GPIO2
'threshold_mode_time': 3000, # 设定阈值模式持续时间,单位毫秒
}
# 初始化硬件
sensor = dht.DHT22(Pin(CONFIG['sensor_pin']))
i2c = I2C(0, scl=Pin(CONFIG['i2c_pins']['scl']), sda=Pin(CONFIG['i2c_pins']['sda']))
oled = ssd1306.SSD1306_I2C(CONFIG['oled_size']['width'], CONFIG['oled_size']['height'], i2c)
button = Pin(CONFIG['button_pin'], Pin.IN, Pin.PULL_UP)
buzzer = Pin(CONFIG['buzzer_pin'], Pin.OUT)
# 初始化阈值
temp_threshold = 25.0
humidity_threshold = 50.0
is_setting_threshold = False
start_time = 0
# 连接WiFi
def connect_wifi():
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
sta_if.connect(CONFIG['wifi_ssid'], CONFIG['wifi_password'])
while not sta_if.isconnected():
print(".", end="")
time.sleep(0.1)
print(" Connected!")
return sta_if
# 连接MQTT服务器
def connect_mqtt():
client = MQTTClient(CONFIG['mqtt']['client_id'], CONFIG['mqtt']['broker'], user=CONFIG['mqtt']['user'], password=CONFIG['mqtt']['password'])
client.connect()
print("Connected to MQTT!")
return client
# 发布消息到MQTT
def publish_to_mqtt(client, temp, humidity):
message = ujson.dumps({"temp": temp, "humidity": humidity})
client.publish(CONFIG['mqtt']['topic'], message)
return message
# 更新并显示OLED信息
def update_oled(oled, temp, humidity, temp_alert=False, hum_alert=False):
oled.fill(0)
oled.text("Temp: {:.1f}C".format(temp), 0, 0)
oled.text("Humidity: {}%".format(humidity), 0, 12)
if temp_alert:
oled.text("Temp Alert!", 0, 24)
if hum_alert:
oled.text("Humidity Alert!", 0, 36)
oled.show()
# 蜂鸣器报警
def beep_alarm(duration=1000):
buzzer.on()
time.sleep_ms(duration)
buzzer.off()
# 主循环
sta_if = connect_wifi()
client = connect_mqtt()
prev_weather = ""
while True:
button_state = button.value()
current_time = time.ticks_ms()
# 按键处理逻辑
if button_state == 0 and not is_setting_threshold: # 按钮被按下
is_setting_threshold = True
start_time = current_time
print("Enter threshold setting mode.")
elif is_setting_threshold and (current_time - start_time) > CONFIG['threshold_mode_time']: # 结束阈值设定模式
is_setting_threshold = False
print("Exit threshold setting mode.")
elif is_setting_threshold:
# 在阈值设定模式下,用户可以通过再次按下按钮切换设置温度或湿度
print("Press button to set threshold.")
if not is_setting_threshold:
print("Measuring weather conditions... ", end="")
sensor.measure()
temp = sensor.temperature()
humidity = sensor.humidity()
# 判断是否需要报警
temp_alert = temp > temp_threshold
hum_alert = humidity > humidity_threshold
if temp_alert or hum_alert:
beep_alarm(1000) # 报警持续1秒
# 更新并显示OLED信息
update_oled(oled, temp, humidity, temp_alert, hum_alert)
# 发送MQTT消息
publish_to_mqtt(client, temp, humidity)
print("Updated!")
else:
update_oled(oled, temp_threshold if temp_threshold < humidity_threshold else humidity_threshold, "", False, False) # 显示正在设置的阈值
time.sleep(2) # 延迟以控制测量频率,避免频繁触发蜂鸣器