บทความนี้เป็นการเรียบเรียงข้อมูลที่เกี่ยวของกับคลาส ESP8266WiFi ซึ่งทำหน้าที่ด้านระบบ WiFi ของไมโครคอนโทรลเลอร์ ESP8266 โดยคลาสดังกล่าวนี้สามารถเข้าถึงผ่านทางวัตถุชื่อ WiFi ที่เป็นวัตถุที่ถถูกสร้างขึ้นสำหรับเข้าถึงโมดูลไร้สายของชิพ และต้องนำเข้าไฟล์ส่วนหัวชื่อ ESP8266WiFi.h
ไมโครคอนโทรลเลอร์ ESP8266 รองรับการทำงานของระบบสื่อสารไร้สาย IEEE802.11 b/g/n และมีรายการใช้กระแสดังนี้
- 0.9mA เมื่ออยู่ในโหมด Standby
- 135-215mA เมื่อส่งข้อมูล
- 60mA เมื่อรับข้อมูล
- 1mA เมื่ออยู่ในโหมดประหยัดพลังงาน
- 0.5uA เมื่อปิดการใช้งาน WiFi
โครงสร้างของคลาส WiFi
คลาสย่อยที่อยู่ภายใต้คลาส ESP8266WiFi มีรายการดังนี้
- BufferDataSource
- BufferedStreamDataSource
- ClientContext
- DataSource
- ESP8266WiFiAPClass
- ESP8266WiFiClass
- ESP8266WiFiGenericClass
- ESP8266WiFiMulti
- ESP8266WiFiScanClass
- ESP8266WiFiSTAClass
- ProgmemStream
- SList
- SSLContext
- UdpContext
- WiFiAPlist_t
- WiFiClient
- WiFiClientSecure
- WiFiEventHandlerOpaque
- WiFiEventModeChange
- WiFiEventSoftAPModeProbeRequestReceived
- WiFiEventSoftAPStationConnected
- WiFiEventSoftAPStationDisconnected
- WiFiEventStationModeAuthModeChanged
- WiFiEventStationModeConnected
- WiFiEventStationModeDisconnected
- WiFiEventStationModeGetIP
- WiFiServer
- WiFiUDP
เริ่มต้นใช้งาน
การอ่านรหัสแม็คแอดเดรส (MAC address) ซึ่งเป็นค่าที่อุปกรณ์แต่ละชิ้นแตกต่างกัน (ยกเว้นทำการปลอมรหัส) เพื่อใช้เป็นตัวเลขอ้างอิงแทนชื่อของอุปกรณ์ โดยมีโครงสร้างเป็นเลขฐานสิบหกจำนวน 6 ชุด ดังรูปแบบต่อไปนี้
xx:xx:xx:xx:xx:xx
การเขียนโปรแกรมเพื่ออ่านค่าแม็คแอดเดรสของชิพ esp8266 ใช้คำสั่ง macAddress() ตามรูปแบบการใช้งานดังนี้
ค่าแม็คแอดเดรส = WiFi.macAddress()
ตัวอย่างโปรแกรมสำหรับแสดงค่าแม็คแอดเดรสเป็นดังนี้
#include <ESP8266WiFi.h>
void setup() {
Serial.begin(115200);
Serial.print("\n\nMAC Address: ");
Serial.println(WiFi.macAddress());
}
void loop() {
}
กรณีต้องการอ่านค่า MAC Address เป็นแถวลำดับของตัวอักษรให้สร้างตัวแปร uint8_t จำนวน 6 ตัวและเรียกใช้งานคำสั่งตามรูปแบบต่อไปนี้
uint8_t ตัวแปร[6];
WiFi.macAddress( ตัวแปร );
ถ้าต้องการตั้งค่าของ MAC Address ให้กับอุปกรณ์สามารถทำได้โดย
เมื่อต้องนำไมโครคอนโทรลเลอร์ esp8266 เชื่อมต่อเข้าระบบเครือข่ายไร้สายจะต้องอาศัยอุปกรณ์เชื่อมต่อที่เกี่ยวข้อง ได้แก่ AP (Access Point) และเครื่องลูกในเครือข่ายเดียวกันหรือจากในเครือข่ายอินเทอร์เน็ตดังภาพที่ 1 ซึ่งตัวชิพเองนั้นรองรับการทำงานทั้งในรูปแบบให้ตัวเองเป็นลูกข่ายภายในเครือข่ายไร้สาย และทำตัวเองเหมือนเป็น AP เพื่อให้บริการแก่ลูกข่ายอื่น ๆ
การทำงานในโหมด Station
คลาส Station
จากภาพที่ 1 การเริ่มต้นทำงานโหมด Station หรือ STA เป็นเชื่อมต่อกับเครือข่ายไร้สายที่มี AP ซึ่งถูกระบุด้วยชื่อของ AP ที่เรียกว่า SSID (Service Set IDentifier) และรหัสการเข้าใช้งาน โดยใช้คำสั่ง begin( ) ตามรูปแบบต่อไปนี้ โดย AP_NAME คือ ชื่อของ AP ที่ต้องการเชื่อมต่อ และ AP_PASSWD คือ รหัสผ่านสำหรับเข้าใช้ AP
WiFi.begin( AP_NAME, AP_PASSWD )
นอกจากนี้ ในบางกรณีผู้เขียนโปรแกรมต้องการเชื่อมต่อโดยระบุช่องสื่อสาร (Channel) BBSID (ค่า MAC Address ของ SSID) และการสั่งให้เชื่อมต่อในทันทีหรือไม่ทำโดยใช้คำสั่ง begin เช่นเดียวกันแต่อาร์กิวเมนต์เหล่านี้ถูกตั้งค่าเบื้องต้นไว้ ดังนั้น คำสั่ง begin จึงมีรูปแบบการสั่งงานดังนี้
WiFi.begin( AP_NAME, AP_PASSWD, channel, bbsid, conect )
การกำหนดโหมดทำงานให้เป็น STA ใช้คำสั่ง mode() พร้อมทั้งส่งอาร์กิวเมนต์เป็น WIFI_STA ดังนี้
WiFi.mode( WIFI_STA )
ประเภทของโหมดการทำงานของ WiFi มีทั้งหมดดังนี้
- WIFI_AP สำหรับกำหนดให้เป็น Access Point
- WIFI_STA สำหรับกำหนดทำงานเป็นเครื่องลูกในเครือข่ายที่มี Access Point อยู่แล้ว
- WIFI_AP_STA สำหรับทำงานทั้งโหมด AP และ STA
- WIFI_OFF สำหรับปิดการทำงานระบบ WiFi ของไมโครคอนโทรลเลอร์
การตรวจสอบสถานะของการร้องขอเพื่อเข้าใช้เครื่องข่ายไร้สายของ AP ต้องใช้คำสั่ง status() ซึ่งคำสั่งนี้จะคืนค่าเป็น WL_CONNECTED เมื่อการเชื่อมต่อสำเร็จ โดยคำสั่งมีรูปแบบการใช้งานดังนี้
ผลลัพธ์ของการเชื่อมต่อ = WiFi.status()
ผลลัพธ์ของสถานะได้แก่
- 0 หรือ WL_IDLE_STATUS ถ้ามีเหตุการเปลี่ยนการทำงานของ WiFi ขณะมีการอ่านสถานะ
- 1 หรือ WL_NO_SSID_AVAIL ถ้าไม่พบชื่อของ AP ที่กำหนด
- 3 หรือ WL_CONNECTED ถ้าเชื่อมต่อสำเร็จ
- 4 หรือ WL_CONNECT_FAILED ถ้าไม่สามารถเชื่อมต่อได้สำหรับ
- 6 หรือ WL_CONNECT_WRONG_PASSWORD ถ้ากำหนดรหัสผ่านผิด
- 7 หรือ WL_DISCONNECTED ถ้าโมดูลไม่ได้ตั้งค่าโหมดทำงานอยู่ในโหมด STA
การบริหารจัดการการเชื่อมต่อ
คำสั่งสำหรับบริหารจัดการการเชื่อมต่อได้แก่คำสั่งการยกเลิกการเชื่อมต่อ คำสั่งให้เชื่อมต่ออีกครั้ง คำสั่งตรวจสอบสถานะการเชื่อมต่อ คำสั่งตั้งค่าให้เชื่อมต่ออัตโนมัติ คำสั่งอ่านสถานะของการเชื่อมต่ออัตโนมัติ คำสั่งตั้งค่าการเชื่อมต่ออีกครั้งแบบอัตโนมัติ และคำสั่งรอผลการเชื่อมต่อ ดังรายละเอียดของแต่ละคำสั่งใช้งานต่อไปนี้
การออกจากการเชื่อมต่อกระทำได้ด้วยการใช้คำสั่งต่อไปนี้ ซึ่งทำหน้าที่ตั้งค่าให้กับค่า AP_NAME และ AP_PASSWD มีค่าเป็น null
WiFi.disconnect()
การสั่งให้ทำการเชื่อมต่ออีกครั้งเพื่อซึ่งเป็นการเชื่อมต่อโดยใช้การตั้งค่าเดิมจากที่เคยได้รับมาจากการ begin() ก่อนหน้านี้ มีรูปแบบคำสั่งการใช้งานดังนี้ และหลังจากสั่ง reconect() ให้วนรอบรอการเชื่อมต่อด้วย status() เหมือนกับการใช้คำสั่ง begin()
WiFi.reconect()
วิธีการตรวจสอบสถานะของการเชื่อมต่อใช้คำสั่ง isConnected() ซึ่งจะคืนค่ากลับเป็น true ถ้าไมโครคอนโทรลเลอร์ยังเชื่อมต่อกับระบบเครือข่าย และคืนค่า false ถ้าไม่ได้เชื่อมต่อกับเครือข่าย ดังรูปแบบการใช้งานต่อไปนี้
สถานะของการเชื่อมต่อ = WiFi.isConnected()
กรณีที่ต้องการให้อุปกรณ์ทำการเชื่อมต่ออัตโนมัติเข้ากับ AP ตัวหลังสุดที่เข้าใช้งานต้องใช้คำสั่ง setAutoConnect พร้อมด้วยอาร์กิวเมนต์การตั้งค่าให้เป็น true หรือ false เพื่อเปิดหรือปิดการทำงานเชื่อมต่ออัติโนมัติดังนี้
WiFi.setAutoConnect( ค่ากำหนดการทำงานของการเชื่อมต่ออัตโนมัติ )
การตรวจสอบว่าได้กำหนดตั้งค่าให้อุปกรณ์ทำการเชื่อมต่ออัตโนมัติเอาไว้หรือไม่สามารถใช้คำสั่ง getAutoConnect() เป็นคำสั่งสำหรับอ่านค่าสถานะนั้นกลับมาดังนี้ ซึ่งถ้าเป็น true หมายถึง ได้เปิดให้การเชื่อมต่ออัตโนมัติทำงาน และ false หมายถึงปิดการเชื่อมตออัตโนมัติไว้
สถานะ = WiFi.getAutoConnect()
กรณีที่ได้ยกเลิกการเชื่อมต่อด้วย disconnect() และต้องการเชื่อมต่อใหม่อีกครั้งให้ใช้คำสั่ง reconnect() อีกครั้ง แต่ถ้าผู้เขียนโปรแกรมต้องการให้ไมโครคอนโทรลเลอร์ esp8266 ทำการเชื่อมต่ออีกครั้งโดยอัติโนมัติจะต้องเรียกใช้การตั้งค่าการทำงานนี้ผ่านทาง setAutoReconnect() ด้วยอาร์กิวเมนต์ true และยกเลิกการทำงานอัตโนมัติด้วยการส่งอาร์กิวเมนต์ false ตามรูปแบบของคำสั่งดังนี้
WiFi.setAutoReconnect( การเปิดหรือปิดการทำงานอัตโนมัติ )
คำสั่งสำหรับให้รอจนกว่า esp8266 จะถูกเชื่อมต่อกับ AP และคืนค่าสถานะดังนี้ คือคำสั่ง waitForConnectResult()
- 0 หรือ WL_IDLE_STATUS กำลังจะดำเนินการเชื่อมต่อ
- 1 หรือ WL_NO_SSID_AVAIL ถ้าไม่พบชื่อของ AP ที่กำหนด
- 3 หรือ WL_CONNECTED ถ้าเชื่อมต่อสำเร็จ
- 4 หรือ WL_CONNECT_FAILED ถ้าไม่สามารถเชื่อมต่อได้สำหรับ
- 6 หรือ WL_CONNECT_WRONG_PASSWORD ถ้ากำหนดรหัสผ่านผิด
- 7 หรือ WL_DISCONNECTED ถ้าโมดูลไม่ได้ตั้งค่าโหมดทำงานอยู่ในโหมด STA
- -1 เกิดการ Timeout
รูปแบบของคำสั่งคือ
สถานะ = WiFi.waitForConnectResult()
ข้อมูลของการเชื่อมต่อเครือข่าย
กรณีที่เข้าใช้เครือข่ายไร้สายได้สำเร็จ ตัวเครื่องให้บริการจะให้หมายเลขไอพี (IP Address) แก่อุปกรณ์เพื่อใช้แทนค่าที่อยู่ของอุปกรณ์บนระบบเครือข่ายไร้สาย ซึ่งคำสั่งสำหรับอ่านค่าหมายเลขไอพีคือ
ค่าหมายเลขไอพี = WiFi.localIP()
นอกจากการใช้ IP Address เป็นตัวอ้างอิงในเครือข่ายแล้ว ผู้เขียนโปรแกรมสามารถตั้งชื่อของอุปกรณ์หรือเรียกว่า hostname (ปกติสามารถเข้าถึงด้วยชื่อแทน IP Address ได้ด้วยการตั้งค่าชื่อไว้ใน DNS) ด้วยคำสั่ง hostname() โดยรูปแบบของการใช้งานมี 2 ลักษณะคือ อ่านชื่อที่ตั้งไว้ และกำหนดชื่อให้กับอุปกรณ์ดังรูปแบบต่อไปนี้ ซึ่งปกติชื่อของ hostname จะถูกกำหนดเป็น “ESP-” ตามด้วย 3 ตัวหลังของ MAC Address เช่น “ESP-123121” นั่นหมายความว่า 12:31:21 เป็นเลข 3 ชุดสุดท้ายของ MAC Address
ชื่อที่ตั้งไว้ = WiFi.hostname()
WiFi.hostname( ชื่อของอุปกรณ์ )
ส่วนค่า sub netmask และ gateway สามารถอ่านค่าได้ด้วยคำสั่งต่อไปนี้
ค่าสับเน็ตแมสค์ = WiFi.subnetMask()
ค่าเกตเวย์ = WiFi.gatewayIP();
การแสดงรายการข้อมูลจาก WiFi เพื่อแสดงค่า เหล่านี้ทางพอร์ตสื่อสารอนุกรม
- Mode
- PHY mode
- Channel
- AP id
- Status
- Auto connect
- SSID
- Passphase
- BSSID set
มีรูปแบบการใช้งานดังนี้
WiFi.printDiag( Serial )
ดังนั้น ตัวอย่างโปรแกรมสำหรับขอเข้าใช้บริการเครือข่ายไร้สาย และแสดงรหัสหมายเลขไอพีที่ได้แจกจ่ายกลับมาจึงเขียนได้ดังนี้
#include <ESP8266WiFi.h>
#define AP_NAME "ชื่อ AP"
#define AP_PASSWD "รหัสผ่าน"
void setup() {
Serial.begin(115200);
Serial.println("\n\n");
WiFi.begin( AP_NAME, AP_PASSWD );
int countLimit = 200;
while (WiFi.status() != WL_CONNECTED) {
delay(250);
if (countLimit == 0) {
break;
}
countLimit--;
}
if (countLimit > 0) {
Serial.println(WiFi.localIP());
WiFi.printDiag(Serial);
}
WiFi.disconnect();
}
void loop() {
}
คำสั่งสำหรับอ่านค่า DNS1 และ 2 โดยระบุหมายเลขของ DNS เป็น 0 หรือ 1 มีรูปแบบของคำสั่งดังนี้
ค่าคืนกลับ = WiFi.dnsIP( หมายเลขของDNS )
การอ่านชื่อ SSID และรหัสผ่าน (PSK: Pre-shared Key) สามารถเข้าถึงด้วยคำสั่งต่อไปนี้
ชื่อAP = WiFi.SSID()
รหัสผ่านAP = WiFi.psk()
ถ้าต้องการอ่านค่า MAC Address ของ SSID หรือที่เรียกว่า BSSID (Basic Service Set Identifier) จะได้ค่า Pointer ที่ชี้ไปยังตำแหน่ง แต่ ESP8266 มีคำสั่งแปลงเป็นสสตริงให้ใช้งานด้วยเช่นกัน ดังนี้
ค่าตำแหน่งของBSSID = WiFi.BSSID()
ค่าMACAddress = WiFi.BSSIDstr()
การอ่านค่า RSSI (Received Signal Strength Indication) ซึ่งเป็นค่าความเข้มของสัญญาณไร้สายมีหน่วยเป็น dBm สามารถใช้งานดังนี้
ค่าความเข้มของสัญญาณ = WiFi.RSSI()
ในบางเครือข่ายไร้สายได้กำหนดให้ข้อมูลมีการเข้ารหัส การเขียนอ่านประเภทของการเข้ารหัสกระทำได้ด้วยคำสั่งต่อไปนี้ ซึ่งโดยปกติจะคืนค่าเป็น ENC_TYPE_NONE
วิธีการเข้ารหัส = WiFi.encryptionType()
ค่าประเภทของการเข้ารหัสมีดังนี้
- 2 หรือ ENC_TYPE_TKIP หรือ WPA/SPK
- 4 หรือ ENC_TYPE_CCMP หรือ WPA2/PSK
- 5 หรือ ENC_TYPE_WEP หรือ WEP
- 7 หรือ ENC_TYPE_NONE หรือ Open
- 8 หรือ ENC_TYPE_AUTO หรือ WPA/WPA2/PSK
การคอนฟิก
ในบางกรณีที่ AP ปิดการให้บริการ DHCP ที่ทำหน้ที่แจกจ่ายค่า IPAddress, DNS1, DNS2, subnetmask และ gateway IP Adress ผู้เขียนโปรแกรมสามารถสั่งตั้งค่าเหล่านี้เองด้วยคำสั่ง config ตามรูปแบบการใช้งานดังนี้
WiFi.config( IPAddress, gatewayIP, subnetmask, DNS1, DNS2 )
โดยให้เรียกใช้ config() ก่อนทำการ begin()
WPS
WPS หรือ WiFi Protected Setup เดิมเรียกว่า WiFi Simple Config ซึ่งเป็นโพรโทคอลที่ออกแบบเพื่อใช้กับเครือข่ายไร้สายภายในบ้านทำให้อุปกรณ์ทำงานโดยไม่ต้องป้อนรหัสผ่านที่ใช้กับ AP โดยในปัจจุบัน ESP8266 รองรับเฉพาะโหมด push-button (WPS_TYPE_PBC) โดยรูปแบบของคำสั่งการตั้งค่าเป็นดังนี้
ผลของการตั้งค่า = WiFi.beginWPSConfig()
ตัวอย่างของการใช้งานเป็นดังนี้
#include <ESP8266WiFi.h>
void setup() {
Serial.begin(115200);
Serial.println("\n\r---------------------\n\r");
WiFi.mode(WIFI_STA);
bool wpsStatus = WiFi.beginWPSConfig();
if (wpsStatus) {
Serial.println("WPS success.");
while (WiFi.status() != WL_CONNECTED) {
delay(330);
}
Serial.print("IP Address : ");
Serial.println(WiFi.localIP());
} else {
Serial.println("WPS failed!!!");
}
}
void loop() {
}
จากตัวอย่างจะพบว่าเราใช้ beginWPSConfig() แทนการใช้ begin() เพื่อเชื่อมต่อกับ AP ที่รองรับ WPS และจะพบว่าสามารถเข้าถึงได้โดยไม่ต้องใส่รหัสผ่าน
การสแกน AP
การสแกน AP ต้องเริ่มด้วยการเปิดโหมดทำงาน WIFI_STA หลังจากนั้นสั่ง disconnect() เพื่อเริ่มต้นทำงาน ดังนี้
WiFi.mode( WIFI_STA );
WiFi.disconnect();
การนับจำนวน AP ที่สามารถสแกนได้ทำโดยเรียกใช้คำสั่ง scanNetworks() และได้ค่าคืนกลับเป็นจำนวน AP ดังนี้ ซึ่งมีการใช้งาน 2 รูปแบบ คือ เรียกใช้แบบการทำงานปกติ และเรียกโดยกำหนดค่า async และ hidden เป็น true หรือ false โดย async เป็นการกำหนดให้ทำการสแกนเป็นฉากหลังและตรวจสอบผลการทำงานด้วย scanComplete() และ hidden เป็นการกำหนดให้สแกนรายการ AP ที่ซ่อน
จำนวนAPที่พบ = WiFi.scanNetworks()
จำนวนAPที่พบ = WiFi.scanNetworks( async, hidden )
กรณีที่สแกนด้วย async เป็น true จะทำให้หน่วยประมวลผลไม่ต้องรอการสแกนจนเสร็จและทำคำสั่งถัดไป ด้วยเหตุนี้ผู้เขียนโปรแกรมจะต้องตรวจสอบสถานะการสแกนผ่านฟังก์ชัน scanComplete() ดังรูปแบบต่อไปนี้
ผลลัพธ์ = WiFi.scanComplete()
ผลลัพธ์ของการเรียกใช้คำสั่งมี 2 ลักษณะ คือ ถ้าคำตอบที่ได้มากหรือเท่ากับ 0 หมายถึงจำนวน AP ที่พบ และถ้าต่ำกว่า 0 หมายถึงเกิดความผิดพลาด โดย -1 หมายถึง กำลังสแกน และ -2 หมายถึง การสแกนไม่ถูกกระตุ้นให้ทำงาน (Scanning has not been triggered)
ข้อมูลของการสแกน AP จะถูกเก็บไว้ในหน่วยความจำ (เป็นเหตุให้หน่วยความจำกึ่งหนึ่งของ esp8266 หายไป เพราะกันไว้สำหรับการทำงานของ WiFi) ซึ่งสามารถลบออกด้วยคำสั่งต่อไปนี้
WiFi.scanDelete()
การสั่งให้ทำการสแกนแบบ Asynchronous โดยระบุฟังก์ชันตอบสนองเพื่อจะได้ไม่ต้องคอยตรวจสอบจาก scanComplete() สามารถทำเองได้ด้วย 2 ขั้นตอน คือ
- สร้างฟังก์ชันตอบสนอง ตามรูปแบบนี้
void ชื่อฟังก์ชัน( int networksFound ) {
// สิ่งที่ทำ
} - เรียกใช้คำสั่ง scanNetworksAsync() ตามรูปแบบต่อไปนี้ โดย hidden เป็น true หรือ false เพื่อกำหนดให้สแกน AP ที่ซ่อนไว้ด้วยหรือไม่
WiFi.scanNetworksAsync( ชื่อฟังก์ชัน, hidden )
การตรวจสอบว่า AP นั้นซ่อนไว้หรือไม่สามารถตรวจสอบได้จาก isHidden() ตามรูปแบบการใช้งานต่อไปนี้
สถานะการซ่อน = WiFi.isHidden( ลำดับที่พบ )
การอ่านค่า SSID, BSSID, channel, RRSI, encryptionType ของ AP สามารถใช้คำสั่ง SSID(), channel(), RSSI(), BSSID()/BSSIDstr() และ encryptionType() โดยใส่ลำดับ AP เป็นอาร์กิวเมนต์หรือใช้คำสั่งต่อไปนี้มาเก็บในบัฟเฟอร์
WiFi.getNetworkInfo( ลำดับAP, &ssid, &encryptionType, &RSSI, *&BSSID, &channel, &isHidden)
การสแกนรายชื่อ AP ที่สามารถเข้าถึงได้เขียนเป็นตัวอย่างโปรแกรมได้ดังนี้
#include <ESP8266WiFi.h>
void showAPs( int networksFound ) {
Serial.printf("Found %d AP(s)\n", networksFound);
for (int i = 0; i < networksFound; i++) {
Serial.print("AP No.");
Serial.print(i + 1);
Serial.print(" : ");
Serial.print(WiFi.SSID(i));
if (WiFi.isHidden( i )) {
Serial.print("*");
}
Serial.print(" Ch:");
Serial.print(WiFi.channel(i));
Serial.print(" S:");
Serial.print(WiFi.RSSI(i));
Serial.print("dBm ENC:");
switch (WiFi.encryptionType(i)) {
case ENC_TYPE_TKIP:
Serial.print("WPA/PSK");
break;
case ENC_TYPE_CCMP:
Serial.print("WPA2/PSK");
break;
case ENC_TYPE_WEP:
Serial.print("WEP");
break;
case ENC_TYPE_NONE:
Serial.print("Open");
break;
case ENC_TYPE_AUTO:
Serial.print("WPA/WPA2/PSK");
break;
default:
Serial.print("Unknown");
}
Serial.print(" BSSID:");
Serial.println(WiFi.BSSIDstr(i));
}
}
void setup() {
Serial.begin(115200);
Serial.println("\n\r\n\r");
WiFi.mode( WIFI_STA );
WiFi.disconnect();
delay(100);
WiFi.scanNetworksAsync( showAPs, true );
}
void loop() {
}
ESP8266WiFiMulti
ในกรณีที่ผู้พัฒนาโปรแกรมต้องการกำหนดให้ระบบมีการเชื่อมต่อกับ AP ตัวอื่นเมื่อ AP ตัวปัจจุบันที่กำหนดไว้ไม่สามารถเข้าถึงได้ ตัวคลาส ESP8266WiFiMulti จะรองรับประเด็นนี้ได้ โดยให้ผู้เขียนโปรแกรมเพิ่ม AP เข้าไปเป็นรายการ AP ที่ให้เข้าถึงเมื่อตัวอื่นเข้าถึงไม่ได้ โดยการใช้จะต้องนำเข้าไฟล์ส่วนหัวเพิ่มเติมดังนี้
#include <ESP8266WiFiMulti.h>
การสร้างวัตถุประเภท ESP8266WiFiMulti สั่งสร้างได้ดังนี้
ESP8266WiFiMulti ชื่อวัตถุ;
การเพิ่มรายการ AP เข้าไปในวัตถุจะต้องระบุ SSID และ PSK ของแต่ละรายการเป็นอาร์กิวเมนต์ของ addAP() ดังนี้
ชื่อวัตถุ.addAP( SSID, PSK )
การเชื่อมต่อจะต้องเปลี่ยนวิธีการจากที่ใช้ begin() ต้องเปลี่ยนเป็น run() ดังนี้
ผลการเชื่อมต่อ=ชื่อวัตถุ.run()
ตัวอย่างโปรแกรมเป็นดังนี้
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
ESP8266WiFiMulti wifiMulti;
void doConnect() {
if (wifiMulti.run() != WL_CONNECTED) {
delay(500);
}
else {
Serial.printf("SSID : %s\n", WiFi.SSID());
Serial.print("Hostname :");
Serial.println(WiFi.hostname());
Serial.print("\nMAC Address: ");
Serial.println(WiFi.macAddress());
Serial.print("IP Address :");
Serial.println(WiFi.localIP());
Serial.print("subnetmask :");
Serial.println(WiFi.subnetMask());
Serial.print("Gateway :");
Serial.println(WiFi.gatewayIP());
Serial.print("DNS:");
Serial.print(WiFi.dnsIP(0));
Serial.print(", ");
Serial.println(WiFi.dnsIP(1));
Serial.print("SSID :");
Serial.print(WiFi.SSID());
Serial.print(" PSK:");
Serial.println(WiFi.psk());
Serial.printf("BBSD: %s\n",WiFi.BSSIDstr().c_str());
Serial.printf("RSSI: %s dBm\n", WiFi.RSSI());
Serial.println();
WiFi.printDiag(Serial);
}
}
void setup() {
Serial.begin(115200);
Serial.println("\n\n");
wifiMulti.addAP( "SSID1", "PASSWD1" );
wifiMulti.addAP( "SSID2", "PASSWD2" );
wifiMulti.addAP( "SSID3", "PASSWD3" );
wifiMulti.addAP( "SSID4", "PASSWD4" );
wifiMulti.addAP( "SSID5", "PASSWD5" );
}
void loop() {
doConnect();
delay(5000);
}
การทำงานในโหมด SoftAP
โหมดการทำงานแบบ SoftAP ดังภาพที่ 2 จะพบว่าตัว ESP8266 ทำตัวเองเป็น AP เพื่อให้บริการกับ Station อื่น ซึ่งการทำแบบนี้ไม่ได้เน้นการเข้าอินเทอร์เน็ตแต่เป็นการสร้างเครือข่ายภายในที่ทำงานผ่านโพรโทคอลอินเทอร์เน็ต หรือสร้างข่ายงานแบบเสช (Mesh networks) สำหรับสร้างข่ายของเซ็นเซอร์ (network sensors) และรองรับจำนวนลูกข่ายที่เชื่อมต่อได้ไม่เกิน 8 โหนด ซึ่งปกติตั้งค่าเริ่มต้นไว้ 4 โหนด
การบริหารจัดการ softAP
การกำหนดชื่อ SSID ให้แก่ esp8266 ทำโดยใช้คำสั่ง softAP() ดังนี้ โดยคืนค่าการทำงานเป็น true หรือ false
ผลการทำงาน = WiFi.softAP( ชื่อ )
หรือสร้างโดยกำหนดรายละเอียดการทำงานเกี่ยวกับ SSID, PSK, channel, hidden และ max_connection เพื่อตั้งชื่อ (ไม่เกิน 32 ตัวอักษร) รหัสผ่าน (ไม่เกิน 64 ตัวอักษร และไม่ต่ำกว่า 8 ตัวอักษร) ช่องสัญญาณที่ใช้ (กำหนดได้เป็นตัวเลข 1 ถึง 13 โดยปกติใช้ค่าเป็น 1) สถานะการซ่อน (ถ้ากำหนดเป็น true จะซ่อนAP) และจำนวนโหนดที่เชื่อมต่อได้สูงสุด (เป็นค่าตัวเลข 0 ถึง 8) ด้วยคำสั่ง softAP() ที่กำหนดอาร์กิวเมนต์ดังนี้
ผลการทำงาน = WiFi.softAP( SSID, PSK, channel, hidden, max_connection )
เมื่อเริ่มทำงานเป็น AP สำเร็จ ตัว ESP8266 จะกำหนดหมายเลขไอพีให้กับตัวเองเป็นค่า 192.168.4.1 ซึ่งสามารถเปลี่ยนแปลงได้ด้วยคำสั่ง softAPConfig()
เมื่อทำงานเสร็จและต้องการยกเลิกตัวเองจากโหมด softAP ให้เรียกใช้คำสั่ง softAPdisconnect() ดังนี้
WiFi.softAPdisconnect()
การตรวจสอบจำนวนลูกข่ายหรือโหนดที่เชื่อมต่อกับไมโครคอนโทรลเลอร์ที่ตั้งเป็น softAP ใช้คำสั่งดังนี้
จำนวนลูกข่าย = WiFi.softAPgetStationNum()
สำหรับการอ่านค่า MAC Address ให้เรียกใช้ softAPmacAddress() และให้สร้างตัวแปรแถวลำดับแบบ uint8_t จำนวน 6 สมาชิกสำหรับเก็บค่าของแต่ละหลัก หรือเรียกใช้ฟังก์ชันเพื่อนำค่าคืนกลับไปใช้ ดังนี้
uint8_t myMACaddr[6];
WiFi.softAPmacAddress( myMACaddr );ค่าแม็คแอดเดรส = WiFi.softAPmacAddress();
คลาส IPAddress
คลาส IPAddress เป็นคลาสสำหรับจัดการกับโครงสร้างข้อมูลสำหรับ IP Address ด้วยเหตุนี้ ถ้ามีการสร้างวัตถุหรือตัวแปรสำหรับค่าตำแหน่งไอพี หรือ IP Address ให้ใช้คลาสนี้เป็นตัวจัดการ
คำสั่งสำหรับกำหนดค่าตำแหน่งไอพีให้แก่ไมโครคอนโทรลเลอร์ในโหมด SoftAP กระทำด้วยคำสั่ง softAPConfig() ตามรูปแบบการใช้งานดังนี้ และคืนค่าผลการทำงานเป็น true และ false
IPAddress ค่าตำแหน่งไอพี(xx, xx, xx, xx );
IPAddress ค่าตำแหน่งไอพีของเกตเวย์( xx, xx, xx, xx );
IPAddress ค่าสับเน็ตมาสค์( xx, xx, xx, xx );
ผลการทำงาน = WiFi.softAPConfig( ค่าตำแหน่งไอพี, ค่าตำแหน่งไอพีของเกตเวย์, ต่าสับเน็ตมาสก์ );
การอ่านค่าตำแหน่งไอพีของ softAP ต้องใช้คำสั่ง softAPIP() ดังนี้
ค่าตำแหน่งไอพี = WiFi.softAPIP()
ตัวอย่างโปรแกรมการสร้าง softAP ที่กำหนดค่า IP Address เป็น 192.168.4.54 กำหนดเกตเวย์เป็น 192.168.4.11 และทำงานในคลาส C พร้อมทั้งตั้งชื่อ AP เป็น “JarutEx” รหัสผ่าน ‘123456789″ ใช้ช่องสัญญาณลำดับที่ 8 ให้ซ่อนตัวเอง และยินยอมให้โหนดลูกเข้าใช้ได้ 3 โหนด เป็นดังนี้
#include <ESP8266WiFi.h>
IPAddress myIP(192, 168, 4, 54);
IPAddress gwIP(192, 168, 4, 11);
IPAddress subnet(255, 255, 255, 0);
uint8_t myMACaddr[6] = {99, 99, 99, 99, 99, 99};
void setup() {
Serial.begin(115200);
Serial.println("\n\r\n\r");
WiFi.softAPmacAddress( myMACaddr );
Serial.print("MAC Address : ");
Serial.println(WiFi.softAPmacAddress());
Serial.printf("%d:%d:%d:%d\n\n",
myMACaddr[0],
myMACaddr[1],
myMACaddr[2],
myMACaddr[3],
myMACaddr[4],
myMACaddr[5]);
if (WiFi.softAPConfig( myIP, gwIP, subnet )) {
if (WiFi.softAP("JarutEx", "123456789", 8, true, 3)) {
Serial.print("IP Address : ");
Serial.println(WiFi.softAPIP());
Serial.print(WiFi.softAPgetStationNum());
Serial.println(" connected.");
WiFi.softAPdisconnect();
} else {
Serial.println("softAP() failed!!");
}
} else {
Serial.println("softAPConfig() failed!");
}
}
void loop() {
}
สรุป
จากบทความนี้ผู้เขียนหวังว่าคงได้ประโยชน์ในการทำความเข้าใจในการใช้งานความสามารถด้าน WiFi ของไมโครคอนโทรลเลอร์ ESP8266 กันมากขึ้น ซึ่งจะพบว่าตัวชิพนี้ทำงานได้ทั้ง 2 แบบ คือ เป็นลูกข่ายของเครือข่ายที่มีอยู่แล้ว หรือตั้งตัวเป็น AP เพื่อสร้างเครือข่ายสำหรับใช้งานเอง ซึ่งการนำไปประยุกต์ใช้จะเขียนถึงในบทความต่อไป
สุดท้ายขอให้สนุกกับการเขียนโปรแกรมครับ
แหล่งอ้างอิง
- ESP8266 Arduino Core: ESP8266WiFi Library
- ESP8266 Arduino Core: Station class
- WiKiperia: Wi-Fi Protected Setup
(C) 2021, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรับปรุงเมื่อ 2021-07-30, 2021-07-31, 2021-08-01