import network
import time
from machine import Pin, ADC, PWM, reset, WDT
import dht
import ujson
from umqtt.simple import MQTTClient
import gc
import uasyncio as asyncio
# Configuration
WIFI_SSID = "Wokwi-GUEST"
WIFI_PASSWORD = ""
MQTT_CLIENT_ID = "micropython-weather-advanced"
MQTT_BROKER = "broker.mqttdashboard.com"
MQTT_TOPIC = "wokwi-weather"
MQTT_LWT_TOPIC = "wokwi-weather/status"
MQTT_LWT_MESSAGE = "Offline"
MQTT_USER = ""
MQTT_PASSWORD = ""
PUBLISH_INTERVAL = 5 # Seconds
TEMP_THRESHOLD = 0.5
HUMIDITY_THRESHOLD = 1.0
MAX_RETRIES = 3 # Max retries for Wi-Fi and sensor
TLS_ENABLED = False # Enable TLS if supported by the broker
# Initialize Components
sensor = dht.DHT22(Pin(15)) # DHT22 sensor on GPIO15
wdt = WDT(timeout=10000) # Watchdog timer with 10 seconds timeout
gc.collect() # Initial garbage collection
# PWM Setup (for LED)
led_pin = Pin(2, Pin.OUT) # LED connected to GPIO 2
led_pwm = PWM(led_pin) # PWM control for LED
led_pwm.freq(1000) # Set PWM frequency to 1kHz
# ADC Setup (for Potentiometer simulation)
adc_pin = ADC(Pin(34)) # ADC input from GPIO 34 (potentiometer)
adc_pin.atten(ADC.ATTN_0DB) # Set ADC attenuation (0-3.3V range)
# Wi-Fi Connection
async def connect_to_wifi():
sta_if = network.WLAN(network.STA_IF)
if not sta_if.isconnected():
print("Connecting to WiFi...")
sta_if.active(True)
sta_if.connect(WIFI_SSID, WIFI_PASSWORD)
retries = 0
while not sta_if.isconnected():
retries += 1
print(f"Attempt {retries}/{MAX_RETRIES}: Connecting to WiFi...")
await asyncio.sleep(1)
if retries > MAX_RETRIES:
print("\nFailed to connect to WiFi after multiple attempts.")
print("Please check WiFi credentials or network status.")
reset()
print("\nWiFi connected. IP Address:", sta_if.ifconfig()[0])
else:
print("WiFi already connected. IP Address:", sta_if.ifconfig()[0])
# MQTT Connection
async def connect_to_mqtt():
print("Connecting to MQTT broker...")
client = MQTTClient(
MQTT_CLIENT_ID, MQTT_BROKER,
user=MQTT_USER, password=MQTT_PASSWORD,
ssl=TLS_ENABLED, keepalive=60
)
client.set_last_will(MQTT_LWT_TOPIC, MQTT_LWT_MESSAGE, retain=True)
retries = 0
while True:
try:
client.connect()
print("MQTT connected.")
return client
except OSError as e:
print(f"MQTT connection failed: {e}")
retries += 1
if retries > MAX_RETRIES:
print("Max MQTT retries reached. Restarting...")
reset()
await asyncio.sleep(2)
# Sensor Measurement
async def measure_sensor_data():
for attempt in range(MAX_RETRIES):
try:
print("Measuring weather conditions...")
sensor.measure()
temperature = sensor.temperature()
humidity = sensor.humidity()
if -40 <= temperature <= 80 and 0 <= humidity <= 100:
return temperature, humidity
except OSError as e:
print(f"Sensor read failed: {e}")
await asyncio.sleep(1)
print("Max sensor retries reached. Returning None.")
return None, None
# ADC Reading (Potentiometer simulation)
async def read_adc_value():
adc_value = adc_pin.read() # Read ADC value (0 to 4095)
voltage = adc_value * (3.3 / 4095) # Convert ADC value to voltage (0V to 3.3V)
print(f"ADC Value: {adc_value}, Voltage: {voltage:.2f}V")
return voltage
# Main Loop
async def main():
await connect_to_wifi()
client = await connect_to_mqtt()
prev_temp, prev_humidity = None, None
last_publish_time = time.time()
while True:
wdt.feed() # Feed the watchdog to prevent a reset
temperature, humidity = await measure_sensor_data()
if temperature is None or humidity is None:
print("Skipping publish due to invalid sensor data.")
await asyncio.sleep(1)
continue
# Read analog sensor (potentiometer)
analog_value = await read_adc_value()
# Control PWM LED based on analog value
# Adjust PWM duty cycle based on potentiometer value
pwm_duty = int(analog_value / 3.3 * 1023) # Scale voltage to PWM duty (0-1023)
led_pwm.duty(pwm_duty) # Set PWM duty cycle for the LED
temp_diff = abs(temperature - (prev_temp or temperature))
humidity_diff = abs(humidity - (prev_humidity or humidity))
current_time = time.time()
if (
current_time - last_publish_time >= PUBLISH_INTERVAL
or temp_diff >= TEMP_THRESHOLD
or humidity_diff >= HUMIDITY_THRESHOLD
):
message = ujson.dumps({
"temperature": temperature,
"humidity": humidity,
"timestamp": current_time,
"analog_value": analog_value
})
try:
print(f"Publishing to {MQTT_TOPIC}: {message}")
client.publish(MQTT_TOPIC, message)
prev_temp, prev_humidity = temperature, humidity
last_publish_time = current_time
except OSError as e:
print(f"Publish failed: {e}. Reconnecting MQTT...")
client = await connect_to_mqtt()
gc.collect() # Run garbage collection periodically
await asyncio.sleep(1)
# Run the Program
try:
asyncio.run(main())
except KeyboardInterrupt:
print("Program stopped.")
except Exception as e:
print(f"Unhandled exception: {e}. Restarting...")
reset()