#ระบบควบคุมโรงเรือนเกษตรอัจฉริยะและระบายน้ำแบบอัตโนมัติผ่านเครือข่าย IoT (Smart Greenhouse & Water Management IoT System)
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
distance_cm = 0.0
led_blue = Pin(18, Pin.OUT)
led_red = Pin(19, Pin.OUT)
led_red.value(1)
led_blue.value(0)
relay1 = Pin(12, Pin.OUT)
relay2 = Pin(13, Pin.OUT)
relay1.value(0)
relay2.value(0)
i2c = I2C(0, sda=Pin(16), scl=Pin(17))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
sensor = dht.DHT22(Pin(20))
servo = PWM(Pin(14))
servo.freq(50)
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))
trig = Pin(28, Pin.OUT) # สายสีน้ำเงิน
echo = Pin(5, Pin.IN) # สายสีชมพู
trig.value(0)
def read_distance():
trig.value(0)
time.sleep_us(2)
trig.value(1)
time.sleep_us(10)
trig.value(0)
timeout_us = 30000 # 30ms
t0 = time.ticks_us()
while echo.value() == 0:
if time.ticks_diff(time.ticks_us(), t0) > timeout_us:
return -1.0
t1 = time.ticks_us()
while echo.value() == 1:
if time.ticks_diff(time.ticks_us(), t1) > timeout_us:
return -1.0
pulse_time = time.ticks_diff(time.ticks_us(), t1)
return (pulse_time * 0.0343) / 2
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))
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)
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)
while not wlan.isconnected():
print("\nกำลังเริ่มเชื่อมต่อ Wi-Fi...")
wlan.connect(ssid, password)
for attempt in range(1, 9):
if wlan.isconnected():
break
oled.fill(0)
oled.text("Connecting WiFi", 0, 10)
oled.text("Attempt: {}/8".format(attempt), 0, 30)
oled.show()
print(">> พยายามเชื่อมต่อครั้งที่ {}/8".format(attempt))
led_red.value(1)
time.sleep(0.5)
led_red.value(0)
time.sleep(0.5)
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)
ip_address = wlan.ifconfig()[0]
wifi_connected = True
print("เชื่อมต่อ Wi-Fi สำเร็จ! IP:", ip_address)
led_red.value(0)
led_blue.value(1)
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, "เริ่มต้นระบบ")
mqtt_interval = 5 * 60 * 1000
last_mqtt_pub = time.ticks_ms() - mqtt_interval
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()
if mqtt_connected:
try:
client.check_msg()
except:
pass
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)
if time.ticks_diff(current_time, last_dht_read) >= dht_read_interval:
dist = read_distance()
if dist != -1.0:
distance_cm = dist
if distance_cm < 50.0:
if relay2.value() == 0:
print(">> [อัตโนมัติ] ระดับน้ำสูง (ระยะ {:.1f} cm < 50): สั่งเปิดปั๊ม (Relay 2 ON)".format(distance_cm))
relay2.value(1)
elif distance_cm >= 150.0:
if relay2.value() == 1:
print(">> [อัตโนมัติ] ระดับน้ำต่ำ (ระยะ {:.1f} cm >= 150): สั่งปิดปั๊ม (Relay 2 OFF)".format(distance_cm))
relay2.value(0)
try:
sensor.measure()
temp = sensor.temperature()
hum = sensor.humidity()
if temp >= 35.0:
if relay1.value() == 0:
print(">> [อัตโนมัติ] Temp {:.1f} >= 35: สั่งเปิดพัดลม (Relay 1 ON)".format(temp))
relay1.value(1)
elif temp <= 26.0:
if relay1.value() == 1:
print(">> [อัตโนมัติ] Temp {:.1f} <= 26: สั่งปิดพัดลม (Relay 1 OFF)".format(temp))
relay1.value(0)
except OSError:
pass
last_dht_read = current_time
if time.ticks_diff(current_time, last_mqtt_pub) >= mqtt_interval:
if mqtt_connected:
try:
payload = "Temp:{:.1f}, Hum:{:.1f}, Dist:{:.1f}".format(temp, hum, distance_cm)
client.publish(TOPIC_PUB_DHT, payload.encode())
print("[MQTT] ส่งข้อมูลเซ็นเซอร์ขึ้น Cloud แล้ว ->", payload)
except:
pass
last_mqtt_pub = current_time
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
oled.fill(0)
oled.text("IP: {}".format(ip), 0, 0)
oled.text("T:{:.1f}C H:{:.1f}%".format(temp, hum), 0, 10)
oled.text("Dist: {:.1f} cm".format(distance_cm), 0, 20)
oled.text("Servo: {} deg".format(current_angle), 0, 30)
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, 40)
oled.text("MQTT: {}".format("OK" if mqtt_connected else "Wait"), 0, 50)
oled.show()
time.sleep(0.1)