#include #include #include #include #include #include #define BLYNK_MAX_SENDBYTES 1200 #include #include //------------------------------ การกำหนดค่าในส่วนของ Blynk ------------------------------------------------// #define BLYNK_DEBUG #define BLYNK_PRINT Serial int blynkIsDownCount = 0; char blynk_token[34] = "8dwBaSBOE8htLFrK37JPAYB1hm8TaQkU";//ใส่ Blynk_token ของเราที่ Blynk ส่งมาทาง Email ตอน Create Project ใหม่ BlynkTimer timer; //---------------------------------- กำหนดหมายเลขของขาของ Node MCU ESP 8266 --------------------------------------------// #define D0 16 // ใช้ไฟ LED สีฟ้า ของบอร์ด MCU ESP8266 ให้มีสัญญาณไฟกระพริบ ตาม Code ที่เขียน #define D3 0 // ใช้เป็นปุ่มกด เพื่อเข้า AP Config ได้ตามความต้องการของผู้ใช้ //------------------------------------------------------------------------------------------------------------------------// #include // ------------------------โหลดไลบารี่ของจอ LCD มาใช้งาน โดยแบบนี้จะสามารถ Create Characterได้ ---------------------------------// #include // บรรทัดที่ 1 และ 2 สามารถสลับบรรทัดกันได้ #include // บรรทัดที่ 1 และ 2 สามารถสลับบรรทัดกันได้ #include //บรรทัดนี้ต้องอยู่ในบรรทัดที่ 3 เท่านั้น ถ้าไปอยู่บรรทัดที่ 1 และ 2 จะคอมไพล์ไม่ผ่าน LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); //// ตั้งค่า Address ของอุปกรณ์จอ LCD ที่มีการเชื่อมต่อแบบ I2C //------------------------------------------------------------------------------------------------------------------------// bool shouldSaveConfig = false; //callback notifying us of the need to save config void saveConfigCallback () { Serial.println("Should save config"); shouldSaveConfig = true; } //------------------------------------------------------------------------------------------------------------------------// //-------------สำหรับ Server local ที่แจกให้ เพิ่ม **** แค่ 2 บรรทัดนี้-------------- (ถ้าเป็น Blynk Server ปกติไม่ต้องใส่) ----------// char server[] = "oasiskit.com"; int port = 8080; //------------------------------------------------------------------------------------------------------------------------// #include PZEM004Tv30 pzem(12, 13); // 12(D6)=RX , 13(D7) = TX : TX->D6(GPIO012),RX->D7(GPIO013) //ตัวแปรรับค่า Ft จาก Blynk มาเก็บใน EEPROM float Ft; String Ft_1; float Ft_2; //ตัวแปรรับค่า วันที่ จาก Blynk มาเก็บใน EEPROM float Rst_D; String Rst_D1; float Rst_D2; //ตัวแปรรับค่า ชั่วโมง จาก Blynk มาเก็บใน EEPROM float Rst_H; String Rst_H1; float Rst_H2; //ตัวแปรรับค่า นาที จาก Blynk มาเก็บใน EEPROM float Rst_M; String Rst_M1; float Rst_M2; //ตัวแปรรับค่า ค่าไฟประเดือน float Electric_bill; float kWh_1; float kWh_2; float kWh_3; float kWh_T; float kWh_T1; //กดปุ่ม Reset kWh จาก Blynk int Blynkreset_kWh; WidgetLED led_rst_kWh(V12);//จะ ON เมื่อกดปุ่มค้างไว้ 5 วินาที //RTC Library #include "Arduino.h" #include "Wire.h" #include "uRTCLib.h" // uRTCLib rtc; uRTCLib rtc(0x68); //ชุดกำหนดการส่ง Email แค่ครั้งเดียว int Email_status = 0; int Email_status1 = 0; BLYNK_WRITE(V10) { Ft_1 = param.asString();//รับค่าข้อความจาก Blynk เข้ามา เก็บในรูปแบบ String Ft_2 = Ft_1.toFloat();//แปลงค่าจาก String เป็น Float //เราป้อนค่า จาก Blynk เป็น String = -0.116 ให้ Ft_1 รับค่ามา //Ft จะรับค่าการแปลง จาก Ft_1 เป็น Float = -0.12 //จะเห็นว่า ค่า Folat จะปัดค่าเป็นจุดทศนิยม ไปเป็น 2 ตำแหน่งจะไม่มากกว่านี้เนื่องด้วยความสามารถตัวของอุปกรณ์เอง //ทำให้ค่าเพี้ยนไป ประมาณ 3.44% ทำให้ค่าไฟ/เดือน น้อยกว่าค่าจริงไป 3.44% ประมาณ 0.64(150หน่วย) - 2.14(500หน่วย) บาท //โปรเจคนี้จะไม่เปลี่ยนค่า ใดๆ เพราะค่าต่างกันเล็กน้อย (1 เดือน ใช้ไฟไม่ถึง 500 หน่วยแน่นอน) //ชุดนี้ทำขึ้นในกรณีที่ ไม่ได้เชื่อมต่อกับ App Blynk ก็ยังสามารถดูค่าทั้งหมดได่อย่างถูกต้อง แต่ทุกครั้งที่มีการเปลี่ยนค่า Ft วันที่ ชั่วโมง นาที จะต้องถูกกำนดค่าผ่าน App Blynk มาทุกครั้ง EEPROM.put(0, Ft_2); //เขียนค่า Ft_2 ที่เป็น Float ลงใน Address 0 EEPROM.commit(); //จบการเขียน Ft = EEPROM.get(0, Ft_2);//อ่าน ค่า Ft_2 ที่เป็น Float จาก Address 0 Serial.println(Ft);//แสดงค่า Ft ใน Serial Monitor lcd.clear(); lcd.setCursor(0, 1); lcd.print("...... Sync Ft ....."); lcd.setCursor(6, 3); lcd.print(Ft, 3); delay(2000); lcd.clear(); } BLYNK_WRITE(V20)//Reset kWh Automatic ตามวันที่ ที่ตั้งจาก Blynk เข้าเครื่อง { Rst_D1 = param.asString();//รับค่าข้อความจาก Blynk เข้ามา เก็บในรูปแบบ String Rst_D2 = Rst_D1.toFloat();//แปลงค่าจาก String เป็น Float //ชุดนี้ทำขึ้นในกรณีที่ ไม่ได้เชื่อมต่อกับ App Blynk ก็ยังสามารถ Rst ค่า kWh ได้ แต่ทุกครั้งที่มีการเปลี่ยนค่า วัน เวลา จะต้องถูกกำนดค่าผ่าน App Blynk มาทุกครั้ง EEPROM.put(20, Rst_D2); //เขียนค่า Rst_D2 ที่เป็น Float ลงใน Address 20 EEPROM.commit(); //จบการเขียน Rst_D = EEPROM.get(20, Rst_D2);//อ่าน ค่า Rst_2 ที่เป็น Float จาก Address 20 Serial.println(Rst_D);//แสดงค่า Rst ใน Serial Monitor lcd.clear(); lcd.setCursor(0, 1); lcd.print("Sync Auto Rst By Day"); lcd.setCursor(0, 2); lcd.print(" Day: "); lcd.setCursor(10, 2); lcd.print(Rst_D, 0); delay(2000); lcd.clear(); } BLYNK_WRITE(V21)//Reset kWh Automatic ตามชั่วโมง ที่ตั้งจาก Blynk เข้าเครื่อง { Rst_H1 = param.asString();//รับค่าข้อความจาก Blynk เข้ามา เก็บในรูปแบบ String Rst_H2 = Rst_H1.toFloat();//แปลงค่าจาก String เป็น Float //ชุดนี้ทำขึ้นในกรณีที่ ไม่ได้เชื่อมต่อกับ App Blynk ก็ยังสามารถ Rst ค่า kWh ได้ แต่ทุกครั้งที่มีการเปลี่ยนค่า วัน เวลา จะต้องถูกกำนดค่าผ่าน App Blynk มาทุกครั้ง EEPROM.put(30, Rst_H2); //เขียนค่า Rst_H2 ที่เป็น Float ลงใน Address 30 EEPROM.commit(); //จบการเขียน Rst_H = EEPROM.get(30, Rst_H2);//อ่าน ค่า Rst_H2 ที่เป็น Float จาก Address 30 Serial.println(Rst_H);//แสดงค่า Rst ใน Serial Monitor lcd.clear(); lcd.setCursor(0, 1); lcd.print("Sync AutoRst By Hour"); lcd.setCursor(0, 2); lcd.print(" Hour: "); lcd.setCursor(10, 2); lcd.print(Rst_H, 0); delay(2000); lcd.clear(); } BLYNK_WRITE(V22)//Reset kWh Automatic ตามนาที ที่ตั้งจาก Blynk เข้าเครื่อง { Rst_M1 = param.asString();//รับค่าข้อความจาก Blynk เข้ามา เก็บในรูปแบบ String Rst_M2 = Rst_M1.toFloat();//แปลงค่าจาก String เป็น Float //ชุดนี้ทำขึ้นในกรณีที่ ไม่ได้เชื่อมต่อกับ App Blynk ก็ยังสามารถ Rst ค่า kWh ได้ แต่ทุกครั้งที่มีการเปลี่ยนค่า วัน เวลา จะต้องถูกกำนดค่าผ่าน App Blynk มาทุกครั้ง EEPROM.put(40, Rst_M2); //เขียนค่า Rst_H2 ที่เป็น Float ลงใน Address 0 EEPROM.commit(); //จบการเขียน Rst_M = EEPROM.get(40, Rst_M2);//อ่าน ค่า Rst_M2 ที่เป็น Float จาก Address 40 Serial.println(Rst_M);//แสดงค่า Rst ใน Serial Monitor lcd.clear(); lcd.setCursor(0, 0); lcd.print(" Sync Auto Rst "); lcd.setCursor(0, 1); lcd.print(" By Minute "); lcd.setCursor(0, 3); lcd.print(" Minute: "); lcd.setCursor(10, 3); lcd.print(Rst_M, 0); delay(2000); lcd.clear(); } BLYNK_WRITE(V11)//Reset kWh ภายใน 5 วินาที จาก Blynk { int pinValue = param.asInt(); if (pinValue == 1) { Blynkreset_kWh = 1; } if (pinValue == 0) { Blynkreset_kWh = 0; } } //การเชื่อมต่อ Blynk Server class Task_1 : public Task { protected: void setup() { } void loop() { //-----------------------------------------------------------------------------------------------------------// if (Blynk.connected()) { Blynk.run(); digitalWrite(D0, LOW); } else { digitalWrite(D0, LOW); delay(200); digitalWrite(D0, HIGH); delay(100); } //-----------------------------------------------------------------------------------------------------------// timer.run();//ให้เวลาของ Blynk ทำงาน delay(500); } } Task_1_task; //แสดงค่า ต่างๆ ของ PZEM ออกมา class Task_2 : public Task { protected: void setup() { } void loop() { float voltage = pzem.voltage(); if (voltage != NAN) { //Serial.print("Voltage: "); Serial.print(voltage); Serial.println("V"); lcd.setCursor(1, 0); lcd.print(voltage, 0); lcd.setCursor(4, 0); lcd.print("Vac"); Blynk.virtualWrite(V1, voltage); } else { } float current = pzem.current(); if (current != NAN) { //Serial.print("Current: "); Serial.print(current); Serial.println("A"); lcd.setCursor(13, 0); lcd.print(current, 2); lcd.print(" A"); Blynk.virtualWrite(V2, current); } else { } float power = pzem.power(); if (current != NAN) { lcd.setCursor(0, 1); lcd.print(power, 2); lcd.setCursor(8, 1); lcd.print("W"); Blynk.virtualWrite(V3, power); } else { } float energy = pzem.energy(); if (current != NAN) { lcd.setCursor(10, 1); lcd.print(energy, 2); lcd.print(" kWh"); Blynk.virtualWrite(V4, energy); } else { } float frequency = pzem.frequency(); if (current != NAN) { lcd.setCursor(8, 0); lcd.print(frequency, 0); lcd.setCursor(10, 0); lcd.print("Hz"); Blynk.virtualWrite(V5, frequency); } else { } float pf = pzem.pf(); if (current != NAN) { Blynk.virtualWrite(V6, pf); } else { } delay(4000); }//loop } Task_2_task; //คิดค่าไฟฟ้า ตามการใช้งานที่บ้าน ของเรามากกว่า 150 หน่วย/เดือน ใครน้อยกว่านี้ก็คิดสูตรเอง class Task_3 : public Task { protected: void setup() { } void loop() { float energy = pzem.energy(); // กดปุ่มที่หน้าเครื่อง 5 วินาที เพื่อ Reset kWh if (digitalRead(D3) == LOW) { delay(3000); pzem.resetEnergy(); } // กดปุ่มจาก Blynk 5 วินาที เพื่อ Reset kWh กดค้างจนกว่า LED จะดับ if (Blynkreset_kWh == 1) { led_rst_kWh.on(); delay(3000); pzem.resetEnergy(); led_rst_kWh.off(); pzem.resetEnergy(); } if (Blynkreset_kWh == 0) { led_rst_kWh.off(); } // Reset kWh แบบ Auto โดยการตั้งค่ามาจาก Blynk โดยเก็บไว้ใน EEPROM ของเครื่อง // ส่ง Email 1 ครั้งเท่านั้น if (Rst_D == rtc.day() && Rst_H == rtc.hour() && Rst_M == rtc.minute() && Email_status == 0) { pzem.resetEnergy(); //Serial.println("reset kWh");มันจะ Reset ซ้ำ กันใน 1 นาทีนี้ และยกเลิกจนกว่าจะขึ้นนาทีใหม่ String body = String("ค่าไฟฟ้าประจำเดือนที่ ") + (rtc.month() - 1) + String(" เป็นจำนวนเงิน ") + Electric_bill + String(" บาท ระบบทำการ Reset kWh = 0 แล้ว ***ให้ตรวจสอบค่า Ft ประจำเดือนด้วย*** By PUYIOT"); Blynk.email("xxxxxxxxxx@gmail.com", "แจ้งค่าไฟฟ้าประจำเดือน ", body); delay(500); Email_status = 1; Email_status1 = 0; } else if (Rst_D == rtc.day() && Rst_H == rtc.hour() && Rst_M == rtc.minute() && Email_status == 1) { delay(10); Email_status1 = 1; } if (Rst_M != rtc.minute() && Email_status1 == 1 ) { delay(10); Email_status = 0; } //1.2 อัตราปกติปริมาณการใช้พลังงานไฟฟ้าเกินกว่า 150 หน่วยต่อเดือน //ที่บ้านเราใช้ค่านี้ ประเภท 1125 คือ ใช้ไฟฟ้าเกิน 150 หน่วย/เดือน อัตราค่าบริการ 38.22 บาท/เดือน //1 - 150 หน่วยละ 3.2484 บาท if (energy >= 1 && energy <= 150) { kWh_1 = energy * 3.2484; } if (energy > 150) { kWh_1 = 150 * 3.2484; } //หน่วยที่ 151 - 400 หน่วยละ 4.2218 บาท if (energy >= 151 && energy <= 400) { kWh_2 = (energy-150) * 4.2218; } if (energy > 400) { kWh_2 = 250 * 4.2218; //401 -- > หน่วยละ 4.4217 บาท kWh_3 = (energy - 400) * 4.4217; } //รวมค่าใช้จ่ายทั้งหมด kWh_T = kWh_1 + kWh_2 + kWh_3; kWh_T1 = kWh_T + 38.22 + (energy * Ft); Electric_bill = kWh_T1 + (kWh_T1 * 0.07); lcd.setCursor(0, 3); lcd.print("B/M: "); lcd.setCursor(5, 3); lcd.print(Electric_bill , 2); lcd.setCursor(12, 3); //lcd.print("Bath"); Blynk.virtualWrite(V7, Electric_bill); lcd.setCursor(13, 3); lcd.print(Rst_D, 0); //lcd.print("D"); lcd.setCursor(15, 3); lcd.print(Rst_H, 0); lcd.setCursor(17, 3); lcd.print(":"); //lcd.print("H"); lcd.setCursor(18, 3); lcd.print(Rst_M, 0); delay(2000); }//loop } Task_3_task; //แสดง dd:mm:yy hh:mm class Task_4 : public Task { protected: void setup() { } void loop() { rtc.refresh(); int year_ = rtc.year() + 43; //+43 เพื่อให้ได้ปี พ.ศ. 63 lcd.setCursor(0, 2); //เติม 0 กรณีเป็นเลข วัน เดือน ชม. นาที วินาที ตัวเดียว if (rtc.day() < 10) { lcd.print("0"); lcd.print(rtc.day()); } else lcd.print(rtc.day()); lcd.print('-'); if (rtc.month() < 10) { lcd.print("0"); lcd.print(rtc.month()); } else lcd.print(rtc.month()); lcd.print('-'); lcd.print(year_); lcd.setCursor(12, 2); if (rtc.hour() < 10) { lcd.print("0"); lcd.print(rtc.hour()); } else lcd.print(rtc.hour()); lcd.print(':'); if (rtc.minute() < 10) { lcd.print("0"); lcd.print(rtc.minute()); } else lcd.print(rtc.minute()); lcd.print(':'); if (rtc.second() < 10) { lcd.print("0"); lcd.print(rtc.second()); } else lcd.print(rtc.second()); delay(1000); } } Task_4_task; //------------------------------------------------------------------------------------------------------------------------// //********************************************* void setup **************************************************// //------------------------------------------------------------------------------------------------------------------------// void setup() { //-------IO NODE MCU Esp8266-------// pinMode(D0, OUTPUT); //กำหนดโหมดใช้งานให้กับขา D0 เป็นขา สัญญาณไฟ ในสภาวะต่างๆ pinMode(D3, INPUT_PULLUP);//กำหนดโหมดใช้งานให้กับขา D3 เป็นขา กดปุ่ม ค้าง เพื่อตั้งค่า AP config // ให้ LED ทั้งหมดดับก่อน digitalWrite(D0, LOW);//ให้หลอด LED สีฟ้าดับก่อน //-------------------------------// Serial.begin(115200); //-------------------------------// EEPROM.begin(512); //ต้องการให้รู้ว่า ค่า Ft ที่เป็น Float ที่เก็บใน EEPROM มีค่า = ค่าที่ถูกป้อนมาจาก Bylnk จริงๆหรือปล่าว Ft = EEPROM.get(0, Ft_2); Serial.print("Ft in Void setup : "); Serial.println(Ft); //ต้องการให้รู้ว่า ค่า วันที่ ที่เป็น Float ที่เก็บใน EEPROM มีค่า = ค่าที่ถูกป้อนมาจาก Bylnk จริงๆหรือปล่าว Rst_D = EEPROM.get(20, Rst_D2); Serial.print("Day in Void setup : "); Serial.println(Rst_D); //ต้องการให้รู้ว่า ค่า ชั่วโมง ที่เป็น Float ที่เก็บใน EEPROM มีค่า = ค่าที่ถูกป้อนมาจาก Bylnk จริงๆหรือปล่าว Rst_H = EEPROM.get(30, Rst_H2); Serial.print("Hour in Void setup : "); Serial.println(Rst_H); //ต้องการให้รู้ว่า ค่า นาที ที่เป็น Float ที่เก็บใน EEPROM มีค่า = ค่าที่ถูกป้อนมาจาก Bylnk จริงๆหรือปล่าว Rst_M = EEPROM.get(40, Rst_M2); Serial.print("Minute in Void setup : "); Serial.println(Rst_M); lcd.begin(20, 4); lcd.clear(); #ifdef ARDUINO_ARCH_ESP8266 Wire.begin(4, 5); // GPIO4 = D2 and GPIO5 = D1 on ESP8266 #else Wire.begin(); #endif //rtc.set(0, 46, 11, 3, 3, 3, 20);//ใช้เฉพาะตั้งเวลา ถ้าจะตั้งก็ เอา // ออก เมื่อตั้งได้ตรงแล้วก็เอา // ใส่กลับไปเหมือนเดิม // RTCLib::set(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year) //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 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 //************************** 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 > -1; i--) { // นับเวลาถอยหลัง 5 วินาทีก่อนกดปุ่ม AP Config digitalWrite(D0, HIGH); delay(500); digitalWrite(D0, LOW); delay(500); Serial.print (String(i) + " ");//แสดงข้อความใน Serial Monitor } if (digitalRead(D3) == LOW) { digitalWrite(D0, LOW); Serial.println("Button Pressed");//แสดงข้อความใน Serial Monitor wifiManager.resetSettings();//ให้ล้างค่า SSID และ Password ที่เคยบันทึกไว้ // wifiManager.autoConnect(); ใช้สร้างชื่อแอคเซสพอยต์อันโนมัติจาก ESP + ChipID if (!wifiManager.autoConnect("PUYIOT AP CONFIG")) { 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.......OK!)");//แสดงข้อความใน 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 Serial.println("gateway"); delay(100); Serial.println(WiFi.gatewayIP()); Serial.println("subnetMask"); delay(100); Serial.println(WiFi.subnetMask()); Serial.println("SSID"); delay(100); Serial.println(WiFi.SSID()); Serial.println("Password"); delay(100); Serial.println(WiFi.psk()); // Blynk.config(blynk_token);////เริ่มการเชื่อมต่อ Blynk Server แบบปกติ Blynk.config(blynk_token, server, port); ////เริ่มการเชื่อมต่อ Blynk Server*********สำหรับ Server local ที่แจกให้ เพิ่ม, server, port แค่นี้จบ timer.setInterval(30000L, reconnecting); //Function reconnect Scheduler.start(&Task_1_task); Scheduler.start(&Task_2_task); Scheduler.start(&Task_3_task); Scheduler.start(&Task_4_task); Scheduler.begin(); } //------------------------------------------------------------------------------------------------------------------------// //********************************************* จบ void setup **************************************************// //------------------------------------------------------------------------------------------------------------------------// //------------------------------------------------------------------------------------------------------------------------// //********************************************* void Loop ***************************************************// //------------------------------------------------------------------------------------------------------------------------// void loop() { } //------------------------------------------------------------------------------------------------------------------------// //********************************************* จบ 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 }