วันอาทิตย์, ธันวาคม 15

MicroPython : เว็บเซิร์ฟเวอร์ ควบคุมเอาต์พุต ด้วย ESP32



เรียนรู้วิธีสร้างเว็บเซิร์ฟเวอร์เพื่อควบคุมเอาต์พุต ESP32 โดยใช้เฟรมเวิร์ก MicroPython ตัวอย่างเช่นเราจะสร้างเว็บเซิร์ฟเวอร์พร้อมปุ่มเปิดและปิดเพื่อควบคุม LED บนบอร์ดของ ESP32  เราจะใช้ Sockets และ Python socket API

ESP32 เปิดปิดไฟ เครือข่าย WiFi ด้วย เว็บเพจ

ควบคุมทุกสรรพสิ่งภายในบ้านของคุณด้วย ESP32 หรือ Home Automation ระบบนี้เป็นระบบที่ใช้ควบคุมอุปกรณ์ไฟฟ้าต่างๆผ่าน WiFi จากอุปกรณ์อื่น ๆ เช่น Mobile , PC/Laptop , Tablet ใช้เว็บบราวเซอร์ เปิดเว็บเพจแล้วป้อน IP ของ ESP32 โดยที่สามารถควบคุมได้ผ่านระบบอินทราเน็ต (ที่ใช้ WiFi  หรือ วง แลน หรือใช้ เราเตอร์ เดียวกัน เท่านั้น)





### อุปกรณ์ที่ใช้ ###


1. PICO KIT V4 ESP32 Development Board WiFi + Bluetooth

2. Micro USB Cable Wire 1m for NodeMCU

3. Breadboard 830 Point MB-102

4. หลอดไฟ LED 5 mm สีแดง

5. รีซิสเตอร์ 330 OHM 1/4W 1%

6. Jumper (M2M) 20cm Male to Male



โดยขั้นตอนการทำงานมีดังนี้


1. เริ่มต้นใช้งาน MicroPython กับ ESP32 ด้วย uPyCraft IDE



2. 
เว็บเซิร์ฟเวอร์ ควบคุมเอาต์พุต ด้วย ESP32 


2.1 เชื่อมต่อ  ESP32  กับ LED






ภาพรวมการต่อวงจร 





3. อัพโหลดโค้ด


3.1 อัพโหลดโค้ด 
ไฟล์ boot.py



สร้างไฟล์ boot.py โดยจะสร้างไว้ที่ workSpace ซึ่งส่วนนี้จะเก็บอยู่ที่ คอมพิวเตอร์ของเรา

(
ไฟล์ boot.py ถ้าอยู่ที่บอร์ด ESP32 จะทำงานโดยอัตโนมัติเมื่อมีการรีเซตบอร์ด และหลังจากนั้น ถ้ามีไฟล์ชื่อ main.py ก็จะทำงานเป็นลำดับถัดไป)


3.1.2 คลิกที่ New file





3.1.3 เขียนโค้ดดังนี้


try: import usocket as socket except: import socket from machine import Pin import network import esp esp.osdebug(None) import gc gc.collect() ssid = 'REPLACE_WITH_YOUR_SSID' password = 'REPLACE_WITH_YOUR_PASSWORD' station = network.WLAN(network.STA_IF) station.active(True) station.connect(ssid, password) while station.isconnected() == False: pass print('Connection successful') print(station.ifconfig()) led = Pin(27, Pin.OUT)


ก่อนการอัพโหลดต้องแก้ไขโค้ด ตรงตัวอักษรสีแดงให้ถูกต้อง ตามเครือข่าย WiFi ที่เลือกใช้งาน โดย

ssid = 'REPLACE_WITH_YOUR_SSID' # เครือข่าย Wi-Fi ที่ต้องการเชื่อมต่อ

password = 'REPLACE_WITH_YOUR_PASSWORD' # รหัสผ่านเครือข่าย



โค้ดทำงานอย่างไร


ดังที่ได้กล่าวไว้ก่อนหน้านี้เราสร้างเว็บเซิร์ฟเวอร์โดยใช้ sockets และ Python socket API
try:
  import usocket as socket
except:
  import socket

เราต้องนำเข้าคลาส Pin จากโมดูล machine เพื่อให้สามารถโต้ตอบกับ GPIO ได้

from machine import Pin

นำเข้าไลบรารี network เพื่อช่วยให้เราสามารถเชื่อมต่อ กับเครือข่าย Wi-Fi
import network

นำเข้าไลบรารี esp และปิดข้อความการดีบัก OS
import esp
esp.osdebug(None)

นำเข้าไลบรารี gc และ เรียกใช้ 
Garbage Collection คือชื่อของ process ที่ทำให้หน่วยความจำว่างสำหรับใช้งานอีกครั้ง
import gc
gc.collect()

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

ตัวแปรต่อไปนี้เก็บข้อมูลการเข้าใช้งานเครือข่ายของคุณ:
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'replace_with_your_password'
คุณควรแทนที่คำที่เน้นด้วยสีแดงด้วย ชื่อเครือข่าย Wi-Fi และรหัสผ่านเครือข่ายของคุณเพื่อให้ ESP32 สามารถเชื่อมต่อกับเราเตอร์ของคุณได้


จากนั้นตั้งค่าให้ ESP32 เป็น Wi-Fi station:
station = network.WLAN(network.STA_IF)

หลังจากนั้นเปิดใช้งาน station:
station.active(True)

ในที่สุด ESP32 เชื่อมต่อกับเราเตอร์ของคุณโดยใช้ ชื่อเครือข่าย และรหัสผ่านที่กำหนดไว้ก่อนหน้านี้:
station.connect(ssid, password)

จะไม่ดำเนินการต่อในขณะที่ ESP32 ไม่ได้เชื่อมต่อกับเครือข่ายของคุณ
while station.isconnected() == False:
  pass

หลังจากการเชื่อมต่อสำเร็จและให้แสดงพารามิเตอร์อินเทอร์เฟซเครือข่ายเช่นที่อยู่ IP ของ ESP32
print('Connection successful')
print(station.ifconfig())

สร้างตัวแปร led ที่อ้างถึง ESP32 พิน GPIO27 และกำหนดให้เป็นเอาท์พุท
led = Pin(27, Pin.OUT)



3.1.4 คลิกที่ Save file






3.1.5 ตั้งชื่อไฟล์ เป็น boot.py -> ok






3.1.6 อัพโหลดโค้ด ไปที่ ESP32






หากสามารถอัพโหลดโปรแกรมลงบอร์ดได้สำเร็จ จะแสดงคำว่า download ok ที่แถบด้านล่าง






3.2 อัพโหลดโค้ด ไฟล์ main.py


แก้ไขไฟล์ main.py ที่เคยสร้างไว้แล้ว (อยู่ที่คอมพิวเตอร์เรา workSpace) ตามโค้ดด้านล่าง





def web_page():
  if led.value() == 1:
    gpio_state="ON"
  else:
    gpio_state="OFF"
  
  html = """<html><head> <title>ESP Web Server</title> <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" href="data:,"> <style>html{font-family: Helvetica; display:inline-block; margin: 0px auto; text-align: center;}
  h1{color: #0F3376; padding: 2vh;}p{font-size: 1.5rem;}.button{display: inline-block; background-color: #e7bd3b; border: none; 
  border-radius: 4px; color: white; padding: 16px 40px; text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}
  .button2{background-color: #4286f4;}</style></head><body> <h1>ESP Web Server</h1> 
  <p>GPIO state: <strong>""" + gpio_state + """</strong></p><p><a href="/?led=on"><button class="button">ON</button></a></p>
  <p><a href="/?led=off"><button class="button button2">OFF</button></a></p></body></html>"""
  return html

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 80))
s.listen(5)

while True:
  conn, addr = s.accept()
  print('Got a connection from %s' % str(addr))
  request = conn.recv(1024)
  request = str(request)
  print('Content = %s' % request)
  led_on = request.find('/?led=on')
  led_off = request.find('/?led=off')
  if led_on == 6:
    print('LED ON')
    led.value(1)
  if led_off == 6:
    print('LED OFF')
    led.value(0)
  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.sendall(response)
  conn.close()


โค้ดทำงานอย่างไร

สคริปต์เริ่มต้นด้วยการสร้างฟังก์ชันที่เรียกว่า web_page () ฟังก์ชั่นนี้จะส่งคืนตัวแปรที่เรียกว่า html ที่มีข้อความ HTML เพื่อสร้างหน้าเว็บ

def web_page():

เว็บเพจแสดงสถานะ GPIO ปัจจุบัน ดังนั้นก่อนสร้างข้อความ HTML เราจำเป็นต้องตรวจสอบสถานะไฟ LED เราบันทึกสถานะไว้ในตัวแปร gpio_state:

if led.value() == 1:
  gpio_state="ON"
else:
  gpio_state="OFF"

หลังจากนั้นตัวแปร gpio_state จะรวมอยู่ในข้อความ HTML โดยใช้เครื่องหมาย“ +” เพื่อเชื่อมสตริงเข้าด้วยกัน
html = """<html><head> <title>ESP Web Server</title> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,"> <style>html{font-family: Helvetica; display:inline-block; margin: 0px auto; text-align: center;}
h1{color: #0F3376; padding: 2vh;}p{font-size: 1.5rem;}.button{display: inline-block; background-color: #e7bd3b; border: none; 
border-radius: 4px; color: white; padding: 16px 40px; text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}
.button2{background-color: #4286f4;}</style></head><body> <h1>ESP Web Server</h1> 
<p>GPIO state: <strong>""" + gpio_state + """</strong></p><p><a href="/?led=on"><button class="button">ON</button></a></p>
<p><a href="/?led=off"><button class="button button2">OFF</button></a></p></body></html>"""

การสร้าง socket server

หลังจากสร้าง HTML เพื่อสร้างหน้าเว็บเราต้องสร้างซ็อกเก็ตการฟังเพื่อฟังคำขอที่เข้ามาและส่งข้อความ HTML เพื่อตอบสนอง เพื่อความเข้าใจที่ดีขึ้นรูปต่อไปนี้แสดงไดอะแกรมเกี่ยวกับวิธีสร้าง socket สำหรับการโต้ตอบกับเซิร์ฟเวอร์ - ไคลเอ็นต์:





สร้างซ็อกเก็ตโดยใช้ socket.socket () และระบุประเภทซ็อกเก็ต เราสร้างวัตถุซ็อกเก็ตใหม่ที่เรียกว่า s กับตระกูลที่อยู่ที่กำหนดและประเภทซ็อกเก็ต นี่คือซ็อกเก็ต STREAM TCP:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

ถัดไปผูกซ็อกเก็ตไปยังที่อยู่ (เชื่อมต่อเครือข่ายและหมายเลขพอร์ต) โดยใช้วิธีการผูก () เมธอด bind () ยอมรับตัวแปร tupple ด้วยที่อยู่ ip และหมายเลขพอร์ต:
s.bind(('', 80))

ในตัวอย่างของเราเรากำลังส่งสตริงว่าง ‘‘ เป็นที่อยู่ IP และพอร์ต 80 ในกรณีนี้สตริงว่างหมายถึงที่อยู่ IP localhost (ซึ่งหมายถึงที่อยู่ IP ของ ESP32)

บรรทัดถัดไปทำให้เซิร์ฟเวอร์ยอมรับการเชื่อมต่อ มันทำให้ซ็อกเก็ต "ฟัง" อาร์กิวเมนต์ระบุจำนวนการเชื่อมต่อที่อยู่ในคิวสูงสุด สูงสุดคือ 5
s.listen(5)

ในขณะที่ห่วงเป็นที่ที่เราฟังคำขอและส่งคำตอบ เมื่อไคลเอ็นต์เชื่อมต่อเซิร์ฟเวอร์จะเรียกใช้เมธอด accept () เพื่อยอมรับการเชื่อมต่อ เมื่อไคลเอนต์เชื่อมต่อจะบันทึกวัตถุซ็อกเก็ตใหม่เพื่อยอมรับและส่งข้อมูลเกี่ยวกับตัวแปร conn และบันทึกที่อยู่ไคลเอนต์เพื่อเชื่อมต่อกับเซิร์ฟเวอร์ในตัวแปร addr

conn, addr = s.accept()

จากนั้นแสดงที่อยู่ของไคลเอนต์ที่บันทึกไว้ในตัวแปร addr

print('Got a connection from %s' % str(addr))


ข้อมูลจะถูกแลกเปลี่ยนระหว่างไคลเอนต์และเซิร์ฟเวอร์โดยใช้เมธอด send () และ recv ()

บรรทัดต่อไปนี้รับคำขอที่ได้รับบนซ็อกเก็ตที่สร้างขึ้นใหม่และบันทึกคำขอไว้ในตัวแปร
request = conn.recv(1024)

เมธอด recv () รับข้อมูลจากซ็อกเก็ตไคลเอนต์ (โปรดจำไว้ว่าเราได้สร้างวัตถุซ็อกเก็ตใหม่ในตัวแปร conn) อาร์กิวเมนต์ของเมธอด recv () ระบุข้อมูลสูงสุดที่สามารถรับได้ในครั้งเดียว

บรรทัดถัดไปเพียงแสดงเนื้อหาของคำขอ:
print('Content = %s' % str(request))

จากนั้นสร้างตัวแปรที่เรียกว่าการตอบกลับที่มีข้อความ HTML ที่ส่งคืนโดยฟังก์ชัน web_page ():
response = web_page()

ขั้นสุดท้ายให้ส่งการตอบกลับไปยังไคลเอ็นต์ซ็อกเก็ตโดยใช้เมธอด send () และ sendall ():
conn.send('HTTP/1.1 200 OK\n')
conn.send('Content-Type: text/html\n')
conn.send('Connection: close\n\n')
conn.sendall(response)

ในท้ายที่สุดปิดซ็อกเก็ตที่สร้างขึ้น

conn.close()


3.3 อัพโหลดโค้ด 
main.py ไปยัง บอร์ด ESP32





3.4 กดที่ปุ่ม EN 1 ครั้ง เพื่อเริ่มการทำงาน ของ ESP32





3.5 รอจนกระทั่งที่ Python shell แสดง IP ของ ESP32 ในตัวอย่างนี้คือ 192.168.1.39






4. ทดสอบการทำงาน



ใช้ คอมพิวเตอร์ หรือ สมาร์ทโฟน ที่เชื่อมต่อเครือข่าย WiFi เดียวกันกับ ESP32 แล้วเปิดเว็บบราวเซอร์ ที่ URL ป้อนไอพี  ที่ได้มาจากข้อ 4.4  ในตัวอย่างนี้คือ 192.168.1.39



คลิกที่ปุ่ม ON




LED จะติด





คลิกที่ปุ่ม OFF




LED จะดับ



credit : https://randomnerdtutorials.com/esp32-esp8266-micropython-web-server/

1 ความคิดเห็น:

  1. Casino at Charles Town Races - Mapyro
    › › Charles 군산 출장샵 Town 광주 출장안마 Races › › Charles Town Races › 동두천 출장마사지 3 hours ago — 광주 출장마사지 3 hours ago 1 answerSitting in our racecourse, you'll see a large and colourful park for more than 15 minutes a day in our 구미 출장안마 racecourse and on weekends. Place your

    ตอบลบ