[TH] ESP8266 Control Relay

บทความนี้เป็นตัวอย่างการเขียนโปรแกรมภาษาไพธอนเพื่อขับโมดูรีเลย์เพื่อเปิด/ปิดหลอดแอลอีดีให้สว่างหรือดับผ่านการสั่งงาน WiFi ในโหมด AP ของ ESP8266

ภาพที่ 1

โมดูลรีเลย์

รีเลย์เป็นอุปกรณ์ที่ทำหน้าที่เปลี่ยนพลังงานไฟฟ้าเป็นพลังงานแม่เหล็กผ่านขดลวดสำหรับดูดหน้าสัมผัสเพื่อให้เกิดการเปิด/ปิดเสมือนเป็นสวิตช์เปิด/ปิด

โมดูลรีเลย์เป็นโมดูลที่นิยมใช้สำหรับขับโหลดภายนอกซึ่งขึ้นอยู่กับคุณสมบัติของรีเลย์ที่เลือกใช้งาน จากในภาพที่ 2 จะพบว่ารีเลย์ที่เลือกใช้งานในการทดลองนี้เป็นรีเลย์ที่รองรับการขับโหลดในแบบ 220VAC/30VDC ที่ 10A หรือ 125VAC/28VDC ที่ 10A โดยใช้แรงดัน 5VDC และขาเชื่อมต่อของโมดูลรีเลย์สำหรับไมโครคอนโทรลเลอร์มี 3 ขา คือ S, + และ – สำหรับต่อเข้ากับขาควบคุม ขา Vcc และขา Gnd ส่วนขาอีกฝั่งเป็นขาสำหรับเชื่อมต่อกับโหลด ซึ่งการต่อโหลดเข้ากับรีเลย์นั้นมีหลักการมองดังนี้

  1. ขา COM เป็นขาเชื่อมต่อกับขานำเข้า
  2. ขา NC เป็นขาสำหรับใช้เมื่อโมดูลรีเลย์อยู่ในสภาวะปกติ
  3. ขา NO เป็นขาสำหรับใช้เมื่อโมดูลรีเลย์ได้รับการจ่ายกระแสไฟเข้า
ภาพที่ 2 โมดูลรีเลย์ที่ใช้ในการทดลองครั้งนี้

การเชื่อมต่อกับ ESP8266

การเชื่อมต่อโมดูลรีเลย์เข้ากับ ESP8266 ทำโดยการเชื่อมขา S เข้ากับ D1 (หรือขาอื่น) เพื่อใช้เป็นขาสำหรับการสั่งเปิดหรือปิดรีเลย์ เชื่อมต่อขา + เข้ากับ 5VDC หรือขา Vin ของ ESP8266 และต่อ – เข้ากับ GND ดังภาพที่ 3 และ 4

ภาพที่ 3 การต่อสายเข้ากับขั้วของโมดูลรีเลย์
ภาพที่ 4 การเชื่อมต่อกับ ESP8266

การเชื่อมต่อระหว่างโมดูลรีเลย์กับหลอดแอลอีดี

การเชื่อมต่อโหลดวงจรแอลอีดีเข้ากับโมดูลรีเลย์กระทำโดยต่อขา GND จากภาควงจรแอลอีดีเข้ากับขา NC หรือ NO ของรีเลย์ และจากขา COM ของรีเลย์ต่อกับ GND ของระบบ ส่วนขานำไฟเข้าวงจรแอลอีดีต่อเข้ากับ 3V3 ของ ESP8266

ภาพที่ 5 วงจรของฝั่งแอลอีดี (เลือกใช้ R ค่าสูงมากเพราะเหลือตัวเดียว)
ภาพที่ 6 แสดงการต่อสายจากภาคแอลอีดีเข้ากับรีเลย์

หลักการสั่งงานผ่านเว็บ

การสั่งงานจากเว็บสามารถกระทำได้หลายวิธี เช่น ให้ผู้ใช้ใส่ URL เพื่อเป็นอาร์กิวเมนต์ให้กับโปรแกรม หรือสร้างวัตถุสำหรับเชื่อมประสานกับผู้ใช้และทำการเชื่อมโยงไปยัง URL ที่เตรียมไว้ เป็นต้น

การอ่านค่าจากเว็บบราวเซอร์ของผู้ใช้ต้องอ่านจาก conn.recv(จำนวนบัฟเฟอร์) ดังรูปแบบการใช้งานดังนี้

conn,addr = s.accept()
ตัวแปรค่าจากการเชื่อมต่อ = str( conn.recv(1024) )

หลังจากได้ค่าจากการเชื่อมต่อและได้แปลงเป็นสายอักขระเพื่อนำมาเป็นส่วนนำเข้าของการค้นหาต่อไป

การค้นหาอาร์กิวเมนต์เพื่อใช้เป็นค่าสำหรับสร้างเงื่อนไขของการทำงานสามารถใช้คำสั่ง find เพื่อหาข้อมูลในสตริงที่แปลงมาจากค่าจากการเชื่อมต่อดังรูปแบบต่อไปนี้

ผลลัพธ์จากการหา = ตัวแปรสายอักขระ.find( ข้อความที่ต้องการค้นหา )

เมื่อพบค่าที่ต้องการค้นหาจะได้ค่าคืนกลับเป็น 6 ดังนั้น เมื่อนำมาประยุกต์เพื่อใช้ในการหาการสั่งเปิดหรือปิดโดยกำหนดค่า url เอาไว้เป็น relay=on เพื่อเรียกใช้ฟังก์ชัน ledOn() และ relay=off เพื่อเรียกใช้ฟังก์ชัน ledOff() สามารถเขียนโค้ดได้ดังนี้

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 80))
s.listen(5)
while True:
    conn, addr = s.accept()
    request = str(conn.recv(1024))
    relay_on = request.find('/?relay=on')
    relay_off = request.find('/?relay=off')
    if relay_on == 6:
        ledOn()
    if relay_off == 6:
        ledOff()

ตัวอย่างโปรแกรม

ตัวอย่างโปรแกรม code7-1 กำหนดค่า relayState เป็น False เพื่อใช้จำสถานะของ relay ด้วยเหตุนี้เมื่อรันโปรแกรมจะทำให้แสดงผลดังภาพที่ 8 เมื่อผู้ใช้กดที่ปุ่ม On จะทำให้เปลี่ยนสถานะเป็น True พร้อมทั้งสั่งเปิดหลอดแอลอีดีทำให้หลอดแอลอีดีเปล่งแสง และทำให้ผลลัพธ์ของการแสดงปุ่มเป็นดังภาพที่ 7

# code7-1 relay
# D1 --> Relay (S)
import socket
import network
import esp
import time
import gc
from machine import Pin
from machine import ADC
#---(1)
gc.collect()
relayPin = Pin(5,Pin.OUT) # D1
ap = network.WLAN(network.AP_IF)
#---(2)
ssid = 'JarutEx-AP'
password = '123456789'
relayState = False
ap.active(True)
ap.config(essid=ssid, password=password)
while ap.active() == False:
  pass
print('Connection successful')
#---(3)
def ledOn():
    global relayState
    relayPin.value(1)
    relayState = True
def ledOff():
    global relayState
    relayPin.value(0)
    relayState = False
def web_page():
    global relayState
    html = """
<!DOCTYPE html><html><head><meta name="viewport" content="width=device-width, initial-scale=1">
<style>.button {  border: none;  color: white;  padding: 20px;  text-align: center;  text-decoration: none;
  display: inline-block;  font-size: 16px;  margin: 4px 2px;  cursor: pointer;  border-radius: 52%;
}
.button1 {  background-color: #3ABC40; }
.button2 {  background-color: #BC4040; }
</style></head><body>
"""
    if relayState == False:
        html += "<a href='/?relay=on'><button  class='button button1'>On</button></a>"
    else:
        html += "<a href='/?relay=off'><button class='button button2'>Off</button></a>"
    html += "</body></html>"
    return html
#---(4)
print(ap.ifconfig())
#---(5)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 80))
s.listen(5)
#---(6)
while True:
    conn, addr = s.accept()
    print('conn {} from {}'.format(conn, addr))
    request = str(conn.recv(1024))
    print('request = {}'.format(request))
    relay_on = request.find('/?relay=on')
    relay_off = request.find('/?relay=off')
    if relay_on == 6:
        ledOn()
    if relay_off == 6:
        ledOff()
    response = web_page()
    conn.send('HTTP/1.1 200 OK\n')
    conn.send('Content-Type: text/html\n')
    conn.send('Connection: close\n\n')
    conn.send(response)
    conn.close()
ภาพที่ 7 หน้าจอเมื่อ relayState เป็น True
ภาพที่ 8 หน้าจอเมื่อ relayState เป็น False

สรุป

จากตัวอย่างการทดลองในครั้งนี้จะพบว่า เราสามารถขับโหลดไฟฟ้ากระแสตรงหรือกระแสสลับผ่านทางระบบเว็บได้ด้วยการใช้โมดูลรีเลย์ โดยการเชื่อมต่อวงจรดังตัวอย่างที่กล่าวถึงในบทความนี้ ซึ่งการสร้างหน้าจอแสดงผลที่ดูดีนั้นต้องอาศัยการเขียนโค้ดของฝั่ง HTML5/CSS นอกจากนี้ การเลือกใช้โมดูลรีเลย์เป็นตัวเลือกที่ต้องพิจารณาให้ดี เนื่องจาก ถ้าเลือกเป็นรีเลย์ขับโหลดได้เฉพาะไฟฟ้ากระแสตรงจะใช้งานกับกระแสสลับไม่ได้ และถ้าเลือกขับโหลดได้ 10A เมื่อเจอโหลดที่สูงกว่ารีเลย์จะเสียหาย หรือเลือกใช้รีเลย์แบบ 12VDC แต่ไม่มีภาคขับ 12VDC หรือมีกระแสไม่เพียงพอ ตัวรีเลย์จะไม่ทำงาน เป็นต้น

สุดท้ายนี้ขอให้สนุกกับการเขียนโปรแกรมครับ

(C) 2020, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรับปรุงเมื่อ 2020-10-14