import network
import time
from machine import Pin, I2C, PWM, ADC
import ssd1306
import dht
import ubinascii
import machine
from umqttsimple import MQTTClient
# ตัวแปรสำหรับเก็บสถานะระบบ
wifi_connected = False
mqtt_connected = False
current_angle = 0
last_pot_val = 0
# 1. ตั้งค่า Pin สำหรับอุปกรณ์ต่างๆ
led_blue = Pin(18, Pin.OUT)
led_red = Pin(19, Pin.OUT)
led_red.value(1)
led_blue.value(0)
# ตั้งค่า Relay 2 ตัว
relay1 = Pin(12, Pin.OUT)
relay2 = Pin(13, Pin.OUT)
relay1.value(0)
relay2.value(0)
# 2. ตั้งค่า I2C สำหรับจอ OLED (SDA=GP16, SCL=GP17)
i2c = I2C(0, sda=Pin(16), scl=Pin(17))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
# 3. ตั้งค่าเซ็นเซอร์ DHT22 (GP20)
sensor = dht.DHT22(Pin(20))
# 4. ตั้งค่า Servo Motor (GP14)
servo = PWM(Pin(14))
servo.freq(50)
def set_servo_angle(angle, source="ระบบ"):
global current_angle
current_angle = angle
min_duty = 1638
max_duty = 8192
duty = int(min_duty + (max_duty - min_duty) * (angle / 180))
servo.duty_u16(duty)
print(">> Servo หมุนไปที่: {} องศา (สั่งจาก: {})".format(angle, source))
# 5. ตั้งค่าปุ่มกด และ วอลลุ่ม
sw_yellow = Pin(27, Pin.IN, Pin.PULL_DOWN)
sw_red_btn = Pin(22, Pin.IN, Pin.PULL_DOWN)
sw_green = Pin(21, Pin.IN, Pin.PULL_DOWN)
pot = ADC(Pin(26))
# --- การตั้งค่า MQTT ---
MQTT_BROKER = "broker.emqx.io"
CLIENT_ID = ubinascii.hexlify(machine.unique_id())
TOPIC_PUB_DHT = b"wokwipico/dht"
TOPIC_SUB_SERVO = b"wokwipico/servo"
TOPIC_SUB_RELAY1 = b"wokwipico/relay1"
TOPIC_SUB_RELAY2 = b"wokwipico/relay2"
client = None
def mqtt_callback(topic, msg):
print("\n[MQTT] ได้รับคำสั่ง - Topic: {} | Msg: {}".format(topic.decode(), msg.decode()))
try:
if topic == TOPIC_SUB_SERVO:
angle = int(msg.decode())
if 0 <= angle <= 180:
set_servo_angle(angle, "MQTT")
global last_pot_val
last_pot_val = pot.read_u16()
elif topic == TOPIC_SUB_RELAY1:
cmd = msg.decode().lower()
if cmd in ["1", "on"]: relay1.value(1)
elif cmd in ["0", "off"]: relay1.value(0)
elif topic == TOPIC_SUB_RELAY2:
cmd = msg.decode().lower()
if cmd in ["1", "on"]: relay2.value(1)
elif cmd in ["0", "off"]: relay2.value(0)
except Exception as e:
print(">> ข้อผิดพลาดในการประมวลผลคำสั่ง MQTT:", e)
# ข้อมูล Wi-Fi
ssid = "Wokwi-GUEST"
password = ""
def connect_wifi_mqtt():
global wifi_connected, mqtt_connected, client, last_pot_val
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
# วนลูปใหญ่: ทำงานจนกว่าจะต่อ Wi-Fi สำเร็จ
while not wlan.isconnected():
print("\nกำลังเริ่มเชื่อมต่อ Wi-Fi...")
wlan.connect(ssid, password)
# วนลูปย่อย: เช็คสถานะ 8 ครั้ง
for attempt in range(1, 9):
if wlan.isconnected():
break # หลุดจากลูปเมื่อเชื่อมต่อสำเร็จ
# แสดงสถานะบนหน้าจอ OLED
oled.fill(0)
oled.text("Connecting WiFi", 0, 10)
oled.text("Attempt: {}/8".format(attempt), 0, 30)
oled.show()
print(">> พยายามเชื่อมต่อครั้งที่ {}/8".format(attempt))
# ทำให้ LED สีแดงกะพริบ
led_red.value(1)
time.sleep(0.5)
led_red.value(0)
time.sleep(0.5)
# ตรวจสอบหลังพยายามครบ 8 ครั้ง
if not wlan.isconnected():
print(">> ไม่สามารถเชื่อมต่อได้! กำลังรีเซ็ตการค้นหา...")
oled.fill(0)
oled.text("WiFi Failed!", 0, 10)
oled.text("Restarting...", 0, 30)
oled.show()
# สั่งยกเลิกการเชื่อมต่อเดิม เพื่อให้รอบถัดไปเริ่มค้นหาใหม่ได้สมบูรณ์
wlan.disconnect()
led_red.value(1) # เปิดไฟแดงค้างไว้เพื่อแสดงข้อผิดพลาด
time.sleep(2)
# --- เมื่อต่อ Wi-Fi สำเร็จแล้ว ---
ip_address = wlan.ifconfig()[0]
wifi_connected = True
print("เชื่อมต่อ Wi-Fi สำเร็จ! IP:", ip_address)
led_red.value(0)
led_blue.value(1)
# เริ่มต่อ MQTT ทันทีที่เน็ตมา
oled.fill(0)
oled.text("WiFi Connected!", 0, 10)
oled.text("Connecting MQTT..", 0, 30)
oled.show()
try:
client = MQTTClient(CLIENT_ID, MQTT_BROKER, keepalive=60)
client.set_callback(mqtt_callback)
client.connect()
client.subscribe(TOPIC_SUB_SERVO)
client.subscribe(TOPIC_SUB_RELAY1)
client.subscribe(TOPIC_SUB_RELAY2)
print("เชื่อมต่อ MQTT สำเร็จ!")
mqtt_connected = True
except Exception as e:
print("ไม่สามารถเชื่อมต่อ MQTT ได้:", e)
last_pot_val = pot.read_u16()
return ip_address
# เริ่มเชื่อมต่อ
ip = connect_wifi_mqtt()
set_servo_angle(0, "เริ่มต้นระบบ")
# --- ตัวแปรสำหรับจับเวลา (แยกกันทำงาน) ---
# 1. เวลาสำหรับการส่ง MQTT (ทุก 5 นาที)
mqtt_interval = 5 * 60 * 1000
last_mqtt_pub = time.ticks_ms() - mqtt_interval
# 2. เวลาสำหรับอ่าน DHT22 และคุม Relay (ทุก 2 วินาที)
dht_read_interval = 2000
last_dht_read = time.ticks_ms() - dht_read_interval
temp = 0.0
hum = 0.0
# ลูปการทำงานหลัก
while True:
current_time = time.ticks_ms()
# --- 1. ตรวจสอบข้อความจาก MQTT ---
if mqtt_connected:
try:
client.check_msg()
except:
pass
# --- 2. ตรวจสอบการกดปุ่ม ---
if wifi_connected:
if sw_yellow.value() == 1:
set_servo_angle(0, "ปุ่มเหลือง")
last_pot_val = pot.read_u16()
time.sleep(0.3)
elif sw_red_btn.value() == 1:
set_servo_angle(90, "ปุ่มแดง")
last_pot_val = pot.read_u16()
time.sleep(0.3)
elif sw_green.value() == 1:
set_servo_angle(176, "ปุ่มเขียว")
last_pot_val = pot.read_u16()
time.sleep(0.3)
# --- 3. อ่านค่า DHT22 และ ควบคุม Relay (ทำทุกๆ 2 วินาที) ---
if time.ticks_diff(current_time, last_dht_read) >= dht_read_interval:
try:
sensor.measure()
temp = sensor.temperature()
hum = sensor.humidity()
# ควบคุม Relay 1 แบบ Real-time
if temp >= 35.0:
if relay1.value() == 0:
print(">> [อัตโนมัติ] Temp {:.1f} >= 35: สั่งเปิด Relay 1".format(temp))
relay1.value(1)
elif temp <= 26.0:
if relay1.value() == 1:
print(">> [อัตโนมัติ] Temp {:.1f} <= 26: สั่งปิด Relay 1".format(temp))
relay1.value(0)
except OSError as e:
pass
last_dht_read = current_time
# --- 4. ส่งข้อมูลขึ้น MQTT (ทำทุกๆ 5 นาทีเท่านั้น) ---
if time.ticks_diff(current_time, last_mqtt_pub) >= mqtt_interval:
if mqtt_connected:
try:
payload = "Temp:{:.1f}, Hum:{:.1f}".format(temp, hum)
client.publish(TOPIC_PUB_DHT, payload.encode())
print("[MQTT] ส่งข้อมูลเซ็นเซอร์ขึ้น Cloud แล้ว ->", payload)
except:
pass
last_mqtt_pub = current_time
# --- 5. ตรวจสอบ Potentiometer ---
if wifi_connected:
current_pot = pot.read_u16()
if abs(current_pot - last_pot_val) > 800:
angle = int((current_pot / 65535) * 180)
set_servo_angle(angle, "วอลลุ่ม")
last_pot_val = current_pot
# --- 6. อัปเดตหน้าจอ OLED ---
oled.fill(0)
oled.text("IP: {}".format(ip), 0, 0)
oled.text("T:{:.1f}C H:{:.1f}%".format(temp, hum), 0, 12)
oled.text("Servo: {} deg".format(current_angle), 0, 24)
r1_stat = "ON" if relay1.value() else "OFF"
r2_stat = "ON" if relay2.value() else "OFF"
oled.text("R1:{} R2:{}".format(r1_stat, r2_stat), 0, 36)
oled.text("MQTT: {}".format("OK" if mqtt_connected else "Wait"), 0, 48)
oled.show()
time.sleep(0.1)