import network
import time
import machine
import math
from umqtt.simple import MQTTClient
# WiFi & MQTT
SSID = "Wokwi-GUEST"
PASSWORD = ""
MQTT_BROKER ="broker.hivemq.com"
CLIENT_ID = "esp32-client"
TOPIC_TEMP = b"esp32/temp"
TOPIC_CMD = b"esp32/relay_cmd"
TOPIC_MODE = b"esp32/mode"
TOPIC_THRESHOLD = b"esp32/set_threshold"
# ADC & Relay setup
adc = machine.ADC(machine.Pin(34))
adc.atten(machine.ADC.ATTN_11DB)
adc.width(machine.ADC.WIDTH_10BIT)
relay = machine.Pin(25, machine.Pin.OUT)
# System state
mode = "manual"
threshold = 30.0 # default °C
# Connect Wi-Fi
def connect_wifi():
print("Connecting to Wi-Fi...")
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(SSID, PASSWORD)
while not wlan.isconnected():
time.sleep(0.1)
print("Connected:", wlan.ifconfig())
# Read temperature using correct NTC equation
def read_temperature():
analog_value = adc.read()
if analog_value <= 0 or analog_value >= 1023:
return -273.15 # Error or out of range
try:
celsius = 1 / (math.log(1 / (1023. / analog_value - 1)) / 3950 + 1.0 / 298.15) - 273.15
return celsius
except:
return -273.15 # Catch any math error
# MQTT callback
def mqtt_callback(topic, msg):
global mode, threshold
print("Received:", topic, msg)
if topic == TOPIC_CMD:
if mode == "manual":
if msg == b'on':
relay.value(1)
elif msg == b'off':
relay.value(0)
elif topic == TOPIC_MODE:
if msg == b'auto':
mode = "auto"
elif msg == b'manual':
mode = "manual"
print("Mode changed to:", mode)
elif topic == TOPIC_THRESHOLD:
if mode == "auto":
try:
threshold = float(msg.decode())
print("Threshold set to:", threshold)
except:
print("⚠️ Invalid threshold")
# Main loop
def main():
connect_wifi()
client = MQTTClient(CLIENT_ID, MQTT_BROKER)
client.set_callback(mqtt_callback)
client.connect()
client.subscribe(TOPIC_CMD)
client.subscribe(TOPIC_MODE)
client.subscribe(TOPIC_THRESHOLD)
print("MQTT connected and subscribed.")
last_temp_publish = time.ticks_ms()
while True:
client.check_msg()
temp = read_temperature()
if mode == "auto":
if temp > threshold:
relay.value(1)
else:
relay.value(0)
if mode == "manual" or time.ticks_diff(time.ticks_ms(), last_temp_publish) >= 2000:
message = "Temperature is {:.2f}".format(temp)
client.publish(TOPIC_TEMP, message.encode())
last_temp_publish = time.ticks_ms()
time.sleep(0.1)
main()