NODE MCU ESP 8266 + AP CONFIG แบบกดปุ่มตั้งค่า + Blynk SERVER
ก่อนอื่นต้องขอขอบคุณในความมีน้ำใจของเว็บไซต์ https://eleceasy.com ด้วยครับที่แบ่งปัน Server และ Energy ให้ผมได้มีโอกาสใช้งาน
ขอเริ่มเรื่องเลยนะครับ
1 ให้เราออกแบบการใช้อุปกรณ์ด้วย Software ตัวใดตัวหนึ่งก็ได้ที่เราถนัดแล้วทำการสั่งของมานะครับ
ที่ผมออกแบบมาก็จะมีวัสดุอุปกรณ์ตามนี้ (คือตอนนี้แบบจริงที่ทำไว้ผมไม่มีแล้วนะครับแต่จะเขียนเป็น 3D ให้ทุกคนได้เห็นภาพว่าเป็นอย่างไร)
2 ต่อตาม Wiring Diagram ตามภาพข้างล่าง ในที่นี้ใครจะลองใช้ บอร์ดทดลอง ก่อนก็ได้ครับ
จาก Wiring Diagram เราจะเห็นว่า NODE MCU ESP 8266 พอร์ตinput /output ที่เราใช้ไปก็เกือบจะหมดแล้ว ดังนั้นวัตถุประสงค์ของผมที่จะใช้ ESP 8266 ตัวนี้ จะใช้เพื่อการ กดปุ่ม Reset board ESP 8266 ให้เริ่มทำงานใหม่ ,การกดปุ่ม AP Config เพื่อตั้งค่า SSID และ Password ของ WiFi ผ่าน ESP 8266 SERVER, หลอด LED ที่แสดงความแรงของสัญญาณ WiFi 3 ระดับ และหลอด LED ที่แสดงการเชื่อมต่อ blynk server ส่วนพอร์ตที่เหลือก็อาจจะใช้ต่อกับ temperature โมดุลได้ ก็แล้วแต่ความต้องการของเรา เพราะหลอด LED ที่แสดงสถานะเหล่านี้จะทำให้เราสามารถวิเคราะห์หาสาเหตุการทำงานผิดพลาดของ ESP 8266 ได้เช่นความแรงของสัญญาณ WiFi ถ้าหลอดไม่แสดงสถานะเลยหรือดับ ก็แสดงว่าสัญญาณ WiFi ไม่มาหรือไม่มี ซึ่งส่งผลทำให้สถานะของหลอด LED ที่เช็คการเชื่อมต่อไปยัง blynk Server ก็จะกระพริบด้วยหรือถ้าหลอดแสดงสถานะสัญญาณ WiFi ติดแต่หลอดแสดงสถานะของ blynk Server มีการกระพริบก็มีประเด็นการวิเคราะห์ได้ 2 แบบคือสัญญาณอินเทอร์เน็ตมีปัญหาหรือ การเชื่อมต่อระหว่าง ESP 8266กับ blynk Server ไม่สามารถเชื่อมต่อการทำงานได้ครับ ส่วนการควบคุมอุปกรณ์ต่างๆ ผมจะใช้วิธีการเชื่อมต่อผ่าน Serial Port เช่นถ้าผมต้องการจะควบคุมปิดเปิดการทำงานของอุปกรณ์ 4 ตัวหรือ 8 ตัวผมก็อาจจะต้องใช้ arduino uno R3 หรือ arduino Mega ซึ่งมีการรับส่งข้อมูลผ่าน Serial port นั่นเอง
ต่อไปก็จะเป็น code สำหรับ code ชุดนี้จะใช้ได้ทั้ง blynk Server ปกติและ blynk Server ของ oasiskit.com ครับ ในส่วน comment ที่อยู่ใน Code ผิดบ้างถูกบ้างอย่าว่ากันนะครับ ผมต้องบอกก่อนนะครับว่า code ชุดนี้ผมไม่ได้เขียนเอง มันอยู่ใน Git Hub อยู่แล้ว เพียงแต่เราเอาโค้ดมาทำความเข้าใจและปรับปรุงแก้ไขให้ได้ตามความต้องการของเราเท่านั้นเองครับ ในส่วนอื่นๆ ทุกๆท่าน สามารถที่จะแก้ไขโค้ดชุดนี้ได้และเพิ่มเติมเข้าไปเพื่อให้ตรงตามวัตถุประสงค์ของตัวเอง
Download code กันครับ
//*********************************************************************************************
//NodeMCU V2 จะมี LED อยู่ 2 ตัวคือบนชิพ ESP8266 (D4) และบนบอร์ด (D0)
//NodeMCU V3 จะมี LED อยู่ 1 ตัวคือบนชิพ ESP8266 (D4) ซึ่งไม่มีบนบอร์ดเหมือน V2
//เลือกบอร์ดเป็น NodeMCU 1.0 ความเร็วอัพโหลดจะเป็น 115200 และ LED_BUILTIN จะเป็น D0
//*********************************************************************************************
#include <ESP8266WiFi.h> //โหลดไลบารี่ ..มาใช้งาน //https://github.com/esp8266/Arduino
#include <ESP8266WebServer.h> //โหลดไลบารี่ ..มาใช้งาน
#include <WiFiManager.h> //โหลดไลบารี่ ..มาใช้งาน //https://github.com/tzapu/WiFiManager
#include <FS.h> //โหลดไลบารี่ ..มาใช้งาน //this needs to be first, or it all crashes and burns...
#include <DNSServer.h> //โหลดไลบารี่ ..มาใช้งาน
#include <ArduinoJson.h> //โหลดไลบารี่ ..มาใช้งาน //https://github.com/bblanchon/ArduinoJson
#include <BlynkSimpleEsp8266.h> //โหลดไลบรารี่ของ BLYNK ..มาใช้งาน
//**********************************************************************************************************
#define BLYNK_DEBUG
#define BLYNK_PRINT Serial // Comment this out to disable prints and save space
#define D0 16 // ใช้ไฟ LED สีฟ้า ของบอร์ด MCU ESP8266 ให้มีสัญญาณไฟกระพริบ ตาม Code ที่เขียน
#define D6 12 // ใช้เป็นปุ่มกด เพื่อเข้า AP Config ได้ตามความต้องการของผู้ใช้
#define D1 5
long rssi;
int rssiled;
#define D4 2
#define D5 14
#define D7 13
//-------------------------------------------------------------------------------------------------------------------------------------------
int blynkIsDownCount = 0; //Integer Variable ตัวแปรชื่อ blynkIsDownCount ใช้เก็บเลขจำนวนเต็ม โดยเริ่มต้นให้มีค่า = 0
char blynk_token[34] = "OUoATnGCbV229TqtcE6PVW6xxxp8feTr"; //ใส่ Blynk token ของเราที่ Blynk ส่งมาทาง Email ตอนที่เรา Create Project ใหม่
//Character Variable ตัวแปรที่ใช้เก็บอักขระ
bool shouldSaveConfig = false;
//-------------------------------------------------------------------------------------------------------------------------------------------
BlynkTimer timer; //เรียกใช้การตั้งเวลาของ Blynk
//ฟังชั่นเปิดใช้งาน BlynkTimer ซึ่งทำหน้าที่คล้าย ๆ interrupt timer หมายถึงเมื่อครบเวลาตามที่กำหนดไว้โปรแกรมหลักจะกระโดด
//ไปทำงานในโปรแกรมตอบสนองที่กำหนดไว้
//กรณีนี้จะนำฟังชั่นที่เปิดใช้งาน BlynkTimer ไปใช้ในการ เชื่อมต่อซ้ำ (reconnecting)
//โดยรูปแบบคำสั่ง คือ timer.setInterval(30000L, reconnecting); อยู่ใน void setup
//-------------------------------------------------------------------------------------------------------------------------------------------
//callback notifying us of the need to save config
void saveConfigCallback () {
Serial.println("Should save config");
shouldSaveConfig = true;
}
//***********สำหรับ Blynk Server ของ https://eleceasy.com/ ที่แจกให้ เพิ่ม **** แค่ 2 บรรทัดนี้
char server[] = "oasiskit.com";
int port = 8080;
//***************************************************************
//*****************************************************************************************************
//******************************* void setup *********************************************
//*****************************************************************************************************
void setup() {
//****************************************************************************************************
pinMode(D6, INPUT);//กำหนดโหมดใช้งานให้กับขา D6 เป็นขา กดปุ่ม ค้าง เพื่อตั้งค่า AP config
pinMode(D0, OUTPUT);//กำหนดโหมดใช้งานให้กับขา D0 เป็นขา สัญญาณไฟ ในสภาวะต่างๆ
digitalWrite(D0, LOW);//ให้หลอด LED สีฟ้าดับก่อน
pinMode(D4, OUTPUT);
pinMode(D5, OUTPUT);
pinMode(D7, OUTPUT);
pinMode(D1, OUTPUT);
digitalWrite(D1, LOW);
digitalWrite(D4, LOW);
digitalWrite(D5, LOW);
digitalWrite(D7, LOW);
//***************************************************************************************************
Serial.begin(115200);
Serial.println();//แสดงข้อความใน Serial Monitor
//read configuration from FS json
Serial.println("mounting FS...");//แสดงข้อความใน Serial Monitor
if (SPIFFS.begin()) {
Serial.println("mounted file system");//แสดงข้อความใน Serial Monitor
if (SPIFFS.exists("/config.json")) {
//file exists, reading and loading
Serial.println("reading config file");//แสดงข้อความใน Serial Monitor
File configFile = SPIFFS.open("/config.json", "r");
if (configFile) {
Serial.println("opened config file");
size_t size = configFile.size();
// Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> buf(new char[size]);
configFile.readBytes(buf.get(), size);
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.parseObject(buf.get());
json.printTo(Serial);
if (json.success()) {
Serial.println("\nparsed json");//แสดงข้อความใน Serial Monitor
strcpy(blynk_token, json["blynk_token"]);
} else {
Serial.println("failed to load json config");//แสดงข้อความใน Serial Monitor
}
}
}
} else {
Serial.println("failed to mount FS");//แสดงข้อความใน Serial Monitor
}
//end read
//************************* จบการ อ่าน เขียนค่า WiFi + Password ]ลงใน Node MCU ESP8266 ***************
//************************** AP AUTO CONNECT **************************************************
WiFiManagerParameter custom_blynk_token("blynk", "blynk token", blynk_token, 34);
//WiFiManager
//Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wifiManager;
//set config save notify callback
wifiManager.setSaveConfigCallback(saveConfigCallback);
wifiManager.addParameter(&custom_blynk_token);
for (int i = 5; i > 0; i--) {
digitalWrite(D0, HIGH);
delay(500);
digitalWrite(D0, LOW);
delay(500);
Serial.print (String(i) + " ");//แสดงข้อความใน Serial Monitor
}
if (digitalRead(D6) == LOW) {
digitalWrite(D0, LOW);
Serial.println("Button Pressed");//แสดงข้อความใน Serial Monitor
wifiManager.resetSettings();//ให้ล้างค่า SSID และ Password ที่เคยบันทึกไว้
// wifiManager.autoConnect(); ใช้สร้างชื่อแอคเซสพอยต์อันโนมัติจาก ESP + ChipID
if (!wifiManager.autoConnect("ตั้งค่า WiFi")) {
Serial.println("failed to connect and hit timeout");//แสดงข้อความใน Serial Monitor
delay(3000);
//reset and try again, or maybe put it to deep sleep
ESP.reset();
delay(5000);
}
}
Serial.println("connected........:)");//แสดงข้อความใน Serial Monitor
strcpy(blynk_token, custom_blynk_token.getValue());
//save the custom parameters to FS
if (shouldSaveConfig) {
Serial.println("saving config");//แสดงข้อความใน Serial Monitor
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.createObject();
json["blynk_token"] = blynk_token;
File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
Serial.println("failed to open config file for writing");//แสดงข้อความใน Serial Monitor
}
json.printTo(Serial);
json.printTo(configFile);
configFile.close();
//end save
}
//************************** จบ AP AUTO CONNECT **************************************************
Serial.println("local ip"); //แสดงข้อความใน Serial Monitor
delay(100);
Serial.println(WiFi.localIP());//แสดงข้อความใน Serial Monitor
// Blynk.config(blynk_token);////เริ่มการเชื่อมต่อ Blynk Server *********สำหรับ Blynk Server ปกติ ใช้ตัวนี้ ไม่ต้องใส่ , server, port
Blynk.config(blynk_token, server, port);////เริ่มการเชื่อมต่อ Blynk Server *********สำหรับ Server local ที่แจกให้เราเพิ่ม , server, port เข้าไปแค่นี้จบ
timer.setInterval(30000L, reconnecting); //Function reconnect
//ตั้งเวลาส่งข้อมูลให้ Blynk Server ทุกๆ 30 วินาที
//มาจากฟังชั่นเปิดใช้งาน BlynkTimer ซึ่งทำหน้าที่คล้าย ๆ interrupt timer หมายถึงเมื่อครบเวลาตามที่กำหนดไว้โปรแกรมหลักจะกระโดดไปทำงานในโปรแกรมตอบสนองที่กำหนดไว้
// (1) ชื่อออฟเจคไว้อ้างอิง (ผู้ใช้งานตั้งชื่อเองในที่นี้ตั้งคำว่า "timer")
// (2) กำหนดค่าช่วงเวลาที่ให้บอร์ดกระโดดไปทำงานในโปรแกรมตอบสนอง ในที่นี้กำหนดเป็น 30000L หมายถึงให้บอร์ดมาทำงานในโปรแกรมตอบสนองทุก ๆ 30 วินาที
// (3) ชื่อโปรแกรมตอบสนอง (ฟังก์ชั่นย่อย) ในที่นี้ตั้งชื่อว่า reconnecting ซึ่งบอร์ดจะวนมาทำงานฟังก์ชั่นชื่อนี้ทุก ๆ เวลาที่กำหนด (ทุกๆ 30 วินาที)
}
//*****************************************************************************************************
//******************************* จบ void setup *********************************************
//*****************************************************************************************************
//*****************************************************************************************************
//******************************* void loop *************************************************
void loop() {
//--------------------------------------------------------------------------------------------------------
rssi = WiFi.RSSI();
rssiled = ((((rssi * 100) / -127) - 100) * -1);
//Blynk.virtualWrite(V5, ( ((rssi * 100) / -127) - 100) * -1); // ทำให้เป็น % ความแรงของ WiFi จะดูง่ายกว่า
//Serial.println(rssiled);
if (rssiled >= 60 ) {
digitalWrite(D7, HIGH);
} else {
digitalWrite(D7, LOW);
}
if (rssiled >= 50 ) {
digitalWrite(D5, HIGH);
} else {
digitalWrite(D5, LOW);
}
if (rssiled >= 30 ) {
digitalWrite(D4, HIGH);
} else {
digitalWrite(D4, LOW);
}
//delay(50);
yield();
//--------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------
if (Blynk.connected())
{
Blynk.run();// ถ้าเชื่อมต่ Blynk Server ได้-----ไฟ LED สีน้ำเงินบนบอร์ด จะติดค้าง
digitalWrite(D0, HIGH); //หลอด LED สีน้ำเงินที่ บอร์ด MCU esp8266 ติดค้างแสดงว่า WiFi ใช้งานได้
//-----// ถ้าเชื่อมต่ Blynk Server ไม่ได้-----ไฟ LED สีน้ำเงินบนบอร์ด จะกระพริบ---------------------------------
//----//หลอด LED สีแดงติดกระพริบแสดงว่ากำลังค้นหา WiFi ----------------------------------------------------
} else {
digitalWrite(D0, LOW);
delay(200);
digitalWrite(D0, HIGH);
delay(100);
}
//--------------------------------------------------------------------------------------------------------
timer.run();//ให้เวลาของ Blynk ทำงาน
delay(100);
}
//******************************* จบ void loop *************************************************
//*****************************************************************************************************
//--------------------------------------------------------------------------------------------------------
void reconnecting()
{
if (!Blynk.connected())
{
blynkIsDownCount++;
BLYNK_LOG("blynk server is down! %d times", blynkIsDownCount);
Blynk.connect(5000);
}
}
//--------------------------------------------------------------------------------------------------------
BLYNK_CONNECTED()
{
Blynk.syncAll();//ให้ซิงค์ข้อมูลทั้งหมดล่าสุดจาก Blynk Server
Serial.println(".");//per debug //แสดงข้อความใน Serial Monitor
}
และเมื่อเราอัพโหลด code เสร็จเรียบร้อยแล้วก็ทำการทดสอบได้เลย โดยใน code นี้ผมจะอธิบายเฉพาะจุดที่สำคัญนะครับ
1 char blynk_token[34] = “OUoATnGCbV229TqtcE6PVW6xxxp8feTr”; //ให้เรา Copy token มาใส่ใน Blynk token ของเราที่ Blynk หรือ ที่ทาง https://eleceasy.com/ ส่งมาทาง Email ตอนที่เรา Create Project ใหม่ใน App Blynk ใน Smart phone ของเรา
2 for (int i = 5; i > 0; i–) {
digitalWrite(D0, HIGH);
delay(500);
digitalWrite(D0, LOW);
delay(500);
Serial.print (String(i) + " ");//แสดงข้อความใน Serial Monitor
ค่า i ที่มีค่าเท่ากับ 5 ตรงนี้เมื่อมีไฟจ่ายเข้า ESP 8266 แล้วเมื่อมันทำงาน มันจะนับเวลาไป 5 วินาที ตัวเลขนี้ถ้าเราต้องการให้เร็วหรือช้าก็เปลี่ยนค่าได้เลย สำหรับเหตุผลที่มีตรงจุดนี้ก็เพื่อที่จะให้ผู้ใช้งานสามารถที่จะกดปุ่ม AP Config ค้างไว้ได้ภายในระยะเวลาที่เรากำหนดไว้เองแต่ถ้าเลยจากเวลาที่กำหนดไปแล้วมันจะเข้าไปเชื่อมต่อ SSID และ Password ของ WiFi ที่เราตั้งค่าเอาไว้ แต่ถ้าเรากดปุ่มนี้ไม่ทันก็ให้กดปุ่ม Reset 1 ครั้ง ESP 8266 จะทำงานใหม่โดยนับไปอีก 5 วินาทีช่วงนี้ให้เรากดปุ่ม AP Config ค้างไว้ได้เลย โดย LED ที่ต่อกับ D0 จะสว่างติดค้างเอาไว้ เพื่อทำให้เรารู้ว่าปุ่ม AP Config ที่เรากดค้างเอาไว้สามารถที่จะใช้งานได้แล้ว
จากนั้นถ้าคอมพิวเตอร์ของเราสามารถรับสัญญาณ WiFi ได้ก็ให้เปิดสัญญาณ WiFi ออกมาเราจะพบว่ามีชื่อของสัญญาณ WiFi ที่ออกมาจาก EP8226 เพื่อตั้งค่า SSID และ Password และ blynk_token ผ่าน IP Address 192.168.4.1 และในขั้นตอนนี้เราสามารถที่จะใช้สมาร์ทโฟนตั้งค่าได้เช่นกัน
3 if (!wifiManager.autoConnect(“ตั้งค่า WiFi”)) {
Serial.println(“failed to connect and hit timeout”);//แสดงข้อความใน Serial Monitor
delay(3000);
//reset and try again, or maybe put it to deep sleep
ESP.reset();
delay(5000);
เราสามารถที่จะเปลี่ยนชื่อ AP Config ที่โชว์ในรายชื่อของ WiFi ได้เดิมผมตั้งให้เป็น ตั้งค่า WiFi ชื่อนี้สามารถเปลี่ยนเป็นของเราได้ครับ
4 rssi = WiFi.RSSI();
rssiled = ((((rssi * 100) / -127) - 100) * -1);
//Blynk.virtualWrite(V5, ( ((rssi * 100) / -127) - 100) * -1); // ทำให้เป็น % ความแรงของ WiFi จะดูง่ายกว่า
ในส่วนเรื่องของ LED ที่แสดงสถานะของสัญญาณ WiFi 3 ระดับ ผมจะใช้คำสั่ง WiFi.RSSI ครับ จากนั้นก็ทำการแปลงค่าให้อยู่ในรูปแบบของเปอร์เซ็นต์เพื่อให้ดูง่ายขึ้นโดยระดับของสัญญาณนั้นถ้าหลอดที่ 1 ติดแสดงว่าระดับความแรงของสัญญาณ WiFi ที่ได้รับมาคือ 30% แต่ถ้าหลอดที่ 2 ติดหลอดที่ 1 ก็จะติดด้วยคือเราจะรู้ว่า ถ้าหลอด 2 หลอดติดแสดงว่าความแรงของสัญญาณ WiFi มา 50% และถ้าหลอดที่ 3 ติด หลอดที่ 1 และ 2 ก็จะติดด้วยสรุปก็คือติดทั้ง 3 หลอดหมายถึงความแรงของสัญญาณ WiFi อยู่ที่ 60% ครับ ส่วนตรงนี้ทุกท่านสามารถที่จะแก้ไขเปลี่ยนแปลงเพิ่มเติมได้นะครับ code ชุดนี้ สามารถใช้ในเชิงพาณิชย์ได้ครับ