เชื่อมต่อ blynk ซักพักจะหลุด

รอผลครับส่วนใหญ่ผมก็ใช่วิธีนี้แหละ ตัดไปทีละส่วนแล้ววิเคราะห์ผลที่ได้

@phoenix298 ได้ผลอย่างไรบ้างครับ

เมื่อวานงานยุ่งเลยไม่ได้มาอัพเดท ตอนนี้ตัดโค้ดแยกออกมาแล้ว แต่เจอปัญหาใหม่ลองปิดไฟไวแล้วไม่เชื่อมต่อเอง ส่วนปัญหาก่อนหน้าเดี๋ยวช่วงบ่ายน่าจะได้ผลพอประมาณเปิดทิ้งไว้ 4 ชั่วโมง เดี๋ยวมีรูปมาอัพให้ดูครับ

มาอัพเดทแล้วครับ เริ่มจาก code ก่อนเลย

// *** (1) LIBRARY INCLUDE ***

//ไลบรารี่เกี่ยวกับ WIFI
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiClientSecure.h>

//ไลบรารี่ของ BLYNK
#include <BlynkSimpleEsp32.h>

//ไลบรารี่ของเซ็นเซอร์ dht22
#include <SimpleDHT.h>

//ไลบรารี่ Firebase สำหรับ ESP32
#include <time.h>

// ArduinoJson
#include <ArduinoJson.h>

// *** (2) SYSTEM CONFIGURATION ***//WIFI CONFIG
char ssid[] = "xxx";
char pass[] = "xxx";

//BLYNK TOKEN
char auth[] = "xxx";
char server[] = "blynk.iot-cm.com";
unsigned int port = 8080;

//LINE TOKEN
#define TokenLine "xxx"

/* ---------------------------------------------------------------*/

// *** TIMER CONFIG ***
//ตั้งเวลาส่งข้อมูลให้ BLYNK SERVER ทุกๆ 2 นาที
//120 Secounds = 120000 Milliseconds
#define sendSensorTime 120000L

//ตั้งเวลาส่งข้อมูลให้ BLYNK SERVER ทุกๆ 3 นาที
//180 Secound = 180000 Milliseconds
#define sendSensor2Time 180000L

//ตั้งเวลาให้เช็คว่า Blynk เชื่อมต่ออยู่หรือไม่ทุกๆ 15 วินาที
#define checkConnectionTime 15000L

//ตั้งเวลาให้เช็คว่า Wifi เชื่อมต่ออยู่หรือไม่ทุกๆ 10 วินาที
#define checkWifiTime 10000L

// *** (3) ประกาศ function *** //

void sendSensor() ;
void sendSensor2();
void checkWifi();
void CheckConnection();
void NotifyLine(String t);
String NowString();
void Getdht22(int *dht);
int WifiPercentSignal();
int LdrPercentValue();

// *** (4) GPIO PIN SETUP ***

//กำหนดให้เซ็นเซอร์ dht22 ใช้ขา GPIO ที่ 32
#define DHTPin 32

//กำหนดให้เซ็นเซอร์วัดความชื้นในดิน ใช้ขา GPIO ที่ 34
//#define SoilSensorPin 34

//กำหนดให้เซ็นเซอร์วัดความเข้มของแสง ใช้ขา GPIO ที่ 34
#define LdrSensorPin 34

//กำหนดให้สวิตซ์ปุ่มกด ใช้ขา GPIO ที่ 25
#define SwitchPin 25

//กำหนดให้หลอดไฟ LED แสดงสถานะการส่งข้อมูล blynk server ใช้ขา GPIO ที่ 26
#define LEDSensorPin 26

//กำหนดให้ขาอ้างอิงการสั่งรดน้ำต้นไม้ ใช้ขา GPIO ที่ 27
#define WateringPin 27

//กำหนดให้หลอดไฟ LED บนบอร์ดแสดงสถานะ WIFI ใช้ขา GPIO ที่ 2
#define LEDWiFiPin 2

//กำหนดขาอ้างอิงการรดน้ำต้นไม้ ใช้ขา GPIO ที่ 14
#define LEDWateringPin 17

//กำหนดหให้ขาควบคุม Relay ใช้ขา GPIO ที่ 5
#define RelayPin 16

// *** (5) BLYNK PARAMETER SETUP ***//ตั้งค่าตัวแปรระบบของ BLYNK
#define BLYNK_PRINT Serial

//การกำหนดขา Vitual Pin ที่สร้างขึ้นให้กับ Widget ต่างๆ ใน Blynk Mobile APP
#define Widget_Humidity V1
#define Widget_Temperature V2
#define Widget_SoilRawValue V3
#define Widget_SoilLevel V4
#define Widget_LightRawValue V5
#define Widget_LightLevel V6
#define Widget_WateringButton V7
#define Widget_SendSensorStatus V8
#define Widget_WateringStatus V9
#define Widget_WifiSignal V10
#define Widget_WifiRawValue V11
#define Widget_Terminal V12
WidgetLED LEDSensor(Widget_SendSensorStatus);
WidgetLED LEDWatering(Widget_WateringStatus);
WidgetTerminal terminal(Widget_Terminal);


// *** (6) NTP SERVER SETUP ***
char ntp_server1[20] = "time.navy.mi.th";
char ntp_server2[20] = "clock.nectec.or.th";
char ntp_server3[20] = "th.pool.ntp.org";

// *** (7) GENAREL SETUP ***//ระบุรุ่นเซ็นเซอร์วัดความชื้นสัมพัทธ์และอุณมหภูมิเป็นรุ่น dht22
SimpleDHT22 dht22;

//เรียกใช้การตั้งเวลาของ Blynk
BlynkTimer timer;

//กำหนดตัวแปรเริ่มต้น
int WifiSignal;
bool isFirstConnect = true;
byte oldtemperature;
byte oldhumidity;
int CurrentSoilValue;
int MapReadSoilValue;
int CurrentWiFiSignal;
int MapReadLightValue;
int CurrentLightValue;
int dhtdata[2];
bool PumpStat = false;

// *** (8) BLYNK CONNECTED FUNCTION ***

BLYNK_CONNECTED() {
  //ให้หลอดไฟ LED บนบอร์ดสีน้ำเงินติดเพื่อเป็นการแสดงสถานะว่าการเชื่อมต่อเสร็จสมบูรณ์
  digitalWrite(LEDWiFiPin, HIGH);
  
    //ถ้าเป็นการเชื่อมต่อ Blynk Server ครั้งแรกหลังบอร์ดรีบูต
    if(isFirstConnect) {   
    //ให้ซิงค์ข้อมูลทั้งหมดล่าสุดจาก Blynk Server
    Blynk.syncAll();   
    //ให้ซิงค์สถานะของขา Virtual V7
    Blynk.syncVirtual(Widget_WateringButton);   
    isFirstConnect = false; 
    }
}

// *** (9) BLYNK BUTTON FUNCTION ***

BLYNK_WRITE(Widget_WateringButton) { 
    //ค่าที่ได้จาก Widget_WateringButton (V7) จะเป็น 0 และ 1 ถ้ามีการปดปุ่ม
  if (param.asInt() == 1) {   
    //ป้องกันไม่ให้กดซ้ำ
      if (digitalRead(WateringPin) != LOW && PumpStat == false) {      
        //เรียกใช้ฟังก์ชันรดน้ำ
        digitalWrite(WateringPin, LOW);   
      } //if
  } //if
  else {
    digitalWrite(WateringPin, HIGH);  
  }
}


// *** (10) FUNCTION SETUP() ***
void setup() {
  //เรียกใช้งาน Serial Monitor
  Serial.begin(115200);
  
  /* -------------------------------------------------------------- */
  //กำหนดโหมดใช้งานให้กำขา GPIO
  pinMode(LEDWiFiPin, OUTPUT);
  pinMode(LEDSensorPin, OUTPUT);
  pinMode(LEDWateringPin, OUTPUT);
  pinMode(WateringPin, OUTPUT);
  pinMode(RelayPin, OUTPUT);
  pinMode(SwitchPin, INPUT_PULLUP);
  
  /* -------------------------------------------------------------- */
  //ตั้งสถานะเริ่มต้นให้กับขา GPIO เพื่อป้องกันการทำงานเองตอนที่บอร์ด ESP32 รีบูต
  digitalWrite(LEDWiFiPin, LOW);
  digitalWrite(LEDSensorPin, LOW);
  digitalWrite(LEDWateringPin, LOW);
  digitalWrite(LEDWateringPin, LOW);
  digitalWrite(RelayPin, HIGH);
  Serial.println("Setting IO Done.");

  /* -------------------------------------------------------------- */
  
  timer.setInterval(checkWifiTime, checkWifi);

  //ตั้งเวลาส่งข้อมูลให้ BLYNK SERVER
  timer.setInterval(sendSensorTime, sendSensor);
  
  //ตั้งเวลาส่งข้อมูลให้ BLYNK SERVER
  timer.setInterval(sendSensor2Time, sendSensor2);
  
  //ตั้งเวลาให้เช็คว่า Blynk เชื่อมต่ออยู่หรือไม่
  timer.setInterval(checkConnectionTime, CheckConnection);


  /* -------------------------------------------------------------- */
  
  //ทำการเชื่อมต่อ WiFi
  Blynk.begin(auth, ssid, pass, server, port);   

  /* -------------------------------------------------------------- */
  //แสดงข้อความใน Serial Monitor
  Serial.println();
  Serial.println("Welcom to smartfram IoT");
  Serial.print("WiFi Connected: ");
  Serial.println(WiFi.localIP());
  Serial.print("WiFi signal RSSI: ");
  Serial.print(WiFi.RSSI());
  Serial.println("dBm");
  
  /* -------------------------------------------------------------- */
  //ดึงเวลาจากอินเตอร์เน็ตจาก NTP Time Server
  configTime(7 * 3600, 0, ntp_server1, ntp_server2, ntp_server3);
  
  //แสดงข้อความใน Serial Monitor
  Serial.println("Waiting for time.");
  while (!time(nullptr)) {
    Serial.print(".");
    delay(100);
  }
  //แสดงข้อความใน Serial Monitor
  Serial.println();
  Serial.println("Current time: " + NowString());
 

}

// *** (11) FUNCTION LOOP() ***
void loop() {
  Blynk.run();
  timer.run();
}

// *** (12) FUNCTION SENDSENSOR() ***

void sendSensor() {
  //ให้หลอดไฟ LED ติด
  if(Blynk.connected()){
    digitalWrite(LEDWiFiPin, HIGH);
    
    //ให้หลอดไฟ LED บน BLYNK MOBILE APP ติด
    LEDSensor.on();
    
    //แสดงข้อความใน Serial Monitor
    Serial.print(NowString());
    Serial.println(", Send data to blynk server");
    
    /* -------------------------------------------------------------- */
   
    //อ่านข้อมูลเซ็นเซอร์ dht22
    Getdht22(dhtdata);
    Blynk.virtualWrite(Widget_Humidity, dhtdata[0]);
    Blynk.virtualWrite(Widget_Temperature, dhtdata[1]);
    
    /* -------------------------------------------------------------- */
    //แสดงข้อความใน Serial Monitor
    Serial.print(NowString());
    Serial.println(", Send dht22 / Soil sensors to blynk server.");
    
    /* -------------------------------------------------------------- */
    
    //ให้หลอด LED ที่แสดงสถานะดับ
    digitalWrite(LEDWiFiPin, LOW);
    
    //ให้หลอดไฟ LED บน BLYNK MOBILE APP ดับ
    LEDSensor.off();
  }else{
    Serial.println("can't sendSensor1 Blynk not connect");
  }
}


// *** (13) FUNCTION SENDSENSOR2() ***
void sendSensor2() {
  if(Blynk.connected()){
    //ให้หลอดไฟ LED ติด
    digitalWrite(LEDWiFiPin, HIGH);
    
    //ให้หลอดไฟ LED บน BLYNK MOBILE APP ติด
    LEDSensor.on();
    
    //แสดงข้อความใน Serial Monitor
    Serial.print(NowString());
    Serial.println(", Send data to blynk server");
    
    /* -------------------------------------------------------------- */
    //แสดงข้อความใน Serial Monitor
    Serial.print(NowString());
    Serial.print(", Wifi Signal: ");
    Serial.print(WifiPercentSignal());
    Serial.println("%");
    
    /* -------------------------------------------------------------- */
    //อัพเดทข้อมูลไปยัง Blynk server
    Blynk.virtualWrite(Widget_LightRawValue, analogRead(LdrSensorPin));
    Blynk.virtualWrite(Widget_LightLevel, LdrPercentValue());
    Blynk.virtualWrite(Widget_WifiSignal, WifiPercentSignal());
    Blynk.virtualWrite(Widget_WifiRawValue, WiFi.RSSI());
    
    /* -------------------------------------------------------------- */
    //แสดงข้อความใน Serial Monitor
    Serial.print(NowString());
    Serial.println(", Send LDR sensors / WIFI to blynk server.");
    
    /* -------------------------------------------------------------- */
    //ให้หลอด LED ที่แสดงสถานะดับ
    digitalWrite(LEDWiFiPin, LOW);
    
    //ให้หลอด LED บน app Blynk ดับ
    LEDSensor.off();
  }else{
    Serial.println("can't sendSensor1 Blynk not connect");
  }
}

// *** (15) CHECK CONNECTION ***
//เช็คการเชือมต่อของ blynk
void CheckConnection(){  
  //ถ้าไม่สามารถ connect ไปยัง blynk server ได้
  if(!Blynk.connected()){    
    //แสดงข้อความบนคอนโซล
    Serial.println("Not connected to Blynk server.");
    Serial.println("Connecting to Blynk server...");
    Blynk.disconnect();
    delay(1000);
    Blynk.connect();  
    // try to connect to server  
  }
}

// *** (16) SEND LINENOTIFY ***

void NotifyLine(String t) {
  WiFiClientSecure client;  
  if(!client.connect("notify-api.line.me", 443)) {
    Serial.println("Connection failed");    
    return;
  }
  String req = "";
  req += "POST /api/notify HTTP/1.1\r\n";
  req += "Host: notify-api.line.me\r\n";
  req += "Authorization: Bearer " + String(TokenLine) + "\r\n";
  req += "Cache-Control: no-cache\r\n";
  req += "User-Agent: ESP32\r\n";
  req += "Content-Type: application/x-www-form-urlencoded\r\n";
  req += "Content-Length: " + String(String("message=" + t).length()) + "\r\n";
  req += "\r\n";
  req += "message=" + t;Serial.println(req);
  client.print(req);
  //vTaskDelay(20 / portTICK_PERIOD_MS);
  delay(20);
  Serial.println("-------------"); 
  while(client.connected()) {  
    String line = client.readStringUntil('\n');  
    if(line == "\r") {    
    break;
    }
  }
}


// *** (17) CURRENT DATETIME ***
String NowString() {
  int getcount = 1;
  time_t now = time(nullptr);
  struct tm* newtime = localtime(&now);
  String myyear = String(newtime->tm_year + 1900);  
  
  //ถ้าปียังเป็นปี 1970 ให้ดึงค่าเวลาใหม่ พยายามสูงสุด 4 ครั้ง
  while(myyear == "1970" && getcount <= 4) {    
    time_t now = time(nullptr);
    struct tm* newtime = localtime(&now);
    myyear = String(newtime->tm_year + 1900);   
    delay(100);   
    getcount++;
  }
  String tmpTime = "";
  String tmpNow = "";
  tmpNow += String(newtime->tm_year + 1900);
  tmpNow += "-";
  if(newtime->tm_mon < 10) tmpNow += "0";
  tmpNow += String(newtime->tm_mon + 1);
  tmpNow += "-";
  if(newtime->tm_mday < 10) tmpNow += "0";
  tmpNow += String(newtime->tm_mday);
  tmpNow += " ";

  if(newtime->tm_hour < 10) tmpNow += "0";
  tmpNow += String(newtime->tm_hour);
  tmpNow += ":";
  if(newtime->tm_min < 10) tmpNow += "0";
  tmpNow += String(newtime->tm_min);
  tmpNow += ":";
  if(newtime->tm_sec < 10) tmpNow += "0";
  tmpNow += String(newtime->tm_sec);
  return tmpNow;
}

// *** (18) FUNCTION Getdht22 ***

void Getdht22(int *dht) {
  //กำหนดค่าตัวแปรอุณหภูมิ
  byte temperature = 0;
  
  //กำหนดค่าความชื้นสัมสัทธ์
  byte humidity = 0;int count = 1;
  
  //อ่านค่าจากเซ็นเซอร์ dht22
  dht22.read(DHTPin, &temperature, &humidity, NULL);
  
  //ถ้าค่าอุณหภูมิ = 0 ให้อ่านค่าจากเซ็นเซอร์ใหม่ 4 ครั้ง
  while(temperature == 0 && count <= 4) {  
    //แสดงข้อความใน Serial Monitor
    Serial.print(NowString());
    Serial.println(", dht22 get failed ");
    Serial.print(count);  
    
    //อ่านค่าจากเซ็นเซอร์ dht22
    dht22.read(DHTPin, &temperature, &humidity, NULL);  
    //vTaskDelay(1500/ portTICK_PERIOD_MS);  
    delay(1500);
    
    //ส่งข้อความให้ line notify แจ้งเตือน
    if(count == 4) NotifyLine("dht22 get failed 4 times.");  
    
    count++;
  }
  //นำข้อมูล temperature & humidity ครั้งที่ผ่านมาแสดง
  if(temperature == 0) temperature = oldtemperature;
  if(humidity == 0) humidity = oldhumidity;
  
  //แสดงข้อความใน Serial Monitor
  Serial.print(NowString());
  Serial.print(", Humidity: ");
  Serial.print(humidity);
  Serial.print("% | ");
  Serial.print("Temperature: ");
  Serial.print(temperature);
  Serial.println("C");
  
  //เก็บสำรองข้อมูล temperature & humidity
  oldtemperature = temperature;
  oldhumidity = humidity;
  
  dht[0] = humidity;
  dht[1] = temperature;
}

// *** (19) FUNCTION WifiPercentSignal ***
int WifiPercentSignal() {
  //หาค่าสัญญาณ RSSI ของ WIFI แล้ว MAP ให้อยู่ในรูปของเปอร์เซ็นต์
  CurrentWiFiSignal = WiFi.RSSI();
  
  if(CurrentWiFiSignal > -40) CurrentWiFiSignal = -40;
  if(CurrentWiFiSignal < -90) CurrentWiFiSignal = -90;
  
  WifiSignal = map(CurrentWiFiSignal, -90, -40, 0, 100);
  
  return WifiSignal;
}

// *** (21) FUNCTION LdrPercentValue ***

int LdrPercentValue() {
  //อ่านค่าจากเซ็นเซอร์อนาล๊อก LDR
  CurrentLightValue = analogRead(LdrSensorPin);
  
  if(CurrentLightValue > 4000) CurrentLightValue = 4000;
  if(CurrentLightValue < 100) CurrentLightValue = 100;
  
  //แม๊พค่าให้อยู่ในรูปของเปอร์เซ็นต์
  MapReadLightValue = map(CurrentLightValue, 4000, 100, 0, 100);
  
  //แสดงข้อความใน Serial Monitor
  Serial.print(NowString());
  Serial.print(", Light sensor value: ");
  Serial.println(MapReadLightValue);
  
  return MapReadLightValue;
}

void checkWifi (){
   if(WiFi.status() != WL_CONNECTED) {      
      digitalWrite(LEDWiFiPin, HIGH);
      Serial.println("WiFi Disconnected.");      
      WiFi.begin((char*)ssid, (char*)pass);
      delay(5000);
      if(WiFi.status() == WL_CONNECTED) { 
        Serial.print("connect to SSID : ");
        Serial.print(ssid);
        Serial.println(" success.");
        digitalWrite(LEDWiFiPin, LOW);
      }
   } 
}
// *** (1) LIBRARY INCLUDE ***

//ไลบรารี่เกี่ยวกับ WIFI
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiClientSecure.h>

//ไลบรารี่ของ BLYNK
#include <BlynkSimpleEsp32.h>

//ไลบรารี่ของเซ็นเซอร์ dht22
#include <SimpleDHT.h>

//ไลบรารี่ Firebase สำหรับ ESP32
#include <time.h>

// ArduinoJson
#include <ArduinoJson.h>

// *** (2) SYSTEM CONFIGURATION ***//WIFI CONFIG
char ssid[] = "Wifi-Me";
char pass[] = "pop123456";

//BLYNK TOKEN
char auth[] = "10UT3OVtzGJUBPIURjDSIHcRwHCfwm3q";
char server[] = "blynk.iot-cm.com";
unsigned int port = 8080;

//LINE TOKEN
#define TokenLine "NqjSVAzZ432y0B68YLU7oSGQqpheJGzYgxmMIrH1w9N"

/* ---------------------------------------------------------------*/

// *** WATERING CONFIG ***

//ค่าเปอร์เซ็นต์ความชื้นในดินที่ต้องการให้เร่ิมรดน้ำต้นไม้
#define PercentWatering 40

//ตั้งระยะเวลาการรดน้ำต้นไม้แต่ละครั้ง
//15000 = 15 วินาที
#define TimeWatering 15000

/* ---------------------------------------------------------------*/
// *** TIMER CONFIG ***
//ตั้งเวลาส่งข้อมูลให้ BLYNK SERVER ทุกๆ 2 นาที
//120 Secounds = 120000 Milliseconds
#define sendSensorTime 120000L

//ตั้งเวลาส่งข้อมูลให้ BLYNK SERVER ทุกๆ 3 นาที
//180 Secound = 180000 Milliseconds
#define sendSensor2Time 180000L

//ตั้งเวลาให้เช็คว่า Blynk เชื่อมต่ออยู่หรือไม่ทุกๆ 15 วินาที
#define checkConnectionTime 15000L

//ตั้งเวลาให้เช็คว่า Wifi เชื่อมต่ออยู่หรือไม่ทุกๆ 10 วินาที
#define checkWifiTime 10000L

//ส่งข้อมูลเข้า MQTT ทุกๆ 5 นาที
#define sendMQTTTime 60000L

// *** (3) ประกาศ function *** //

void sendSensor() ;
void sendSensor2();
void checkWifi();
void CheckConnection();
void NotifyLine(String t);
String NowString();
void Getdht22(int *dht);
int WifiPercentSignal();
int LdrPercentValue();

//void Task4(void *p);

// *** (4) GPIO PIN SETUP ***

//กำหนดให้เซ็นเซอร์ dht22 ใช้ขา GPIO ที่ 32
#define DHTPin 32

//กำหนดให้เซ็นเซอร์วัดความชื้นในดิน ใช้ขา GPIO ที่ 34
//#define SoilSensorPin 34

//กำหนดให้เซ็นเซอร์วัดความเข้มของแสง ใช้ขา GPIO ที่ 34
// Node32lite
//#define LdrSensorPin 34
// Lolin D32
#define LdrSensorPin 34

//กำหนดให้สวิตซ์ปุ่มกด ใช้ขา GPIO ที่ 25
#define SwitchPin 25

//กำหนดให้หลอดไฟ LED แสดงสถานะการส่งข้อมูล blynk server ใช้ขา GPIO ที่ 26
#define LEDSensorPin 26

//กำหนดให้ขาอ้างอิงการสั่งรดน้ำต้นไม้ ใช้ขา GPIO ที่ 27
#define WateringPin 27

//กำหนดให้หลอดไฟ LED บนบอร์ดแสดงสถานะ WIFI ใช้ขา GPIO ที่ 2
#define LEDWiFiPin 2

//กำหนดขาอ้างอิงการรดน้ำต้นไม้ ใช้ขา GPIO ที่ 14
#define LEDWateringPin 17

//กำหนดหให้ขาควบคุม Relay ใช้ขา GPIO ที่ 5
#define RelayPin 16

// *** (5) BLYNK PARAMETER SETUP ***//ตั้งค่าตัวแปรระบบของ BLYNK
//#define BLYNK_TIMEOUT_MS  750
//#define BLYNK_HEARTBEAT   17
#define BLYNK_PRINT Serial

//การกำหนดขา Vitual Pin ที่สร้างขึ้นให้กับ Widget ต่างๆ ใน Blynk Mobile APP
#define Widget_Humidity V1
#define Widget_Temperature V2
#define Widget_SoilRawValue V3
#define Widget_SoilLevel V4
#define Widget_LightRawValue V5
#define Widget_LightLevel V6
#define Widget_WateringButton V7
#define Widget_SendSensorStatus V8
#define Widget_WateringStatus V9
#define Widget_WifiSignal V10
#define Widget_WifiRawValue V11
#define Widget_Terminal V12
WidgetLED LEDSensor(Widget_SendSensorStatus);
WidgetLED LEDWatering(Widget_WateringStatus);
WidgetTerminal terminal(Widget_Terminal);


// *** (6) NTP SERVER SETUP ***
char ntp_server1[20] = "time.navy.mi.th";
char ntp_server2[20] = "clock.nectec.or.th";
char ntp_server3[20] = "th.pool.ntp.org";

// *** (7) GENAREL SETUP ***//ระบุรุ่นเซ็นเซอร์วัดความชื้นสัมพัทธ์และอุณมหภูมิเป็นรุ่น dht22
SimpleDHT22 dht22;

//เรียกใช้การตั้งเวลาของ Blynk
BlynkTimer timer;

//กำหนดตัวแปรเริ่มต้น
int WifiSignal;
bool isFirstConnect = true;
byte oldtemperature;
byte oldhumidity;
int CurrentSoilValue;
int MapReadSoilValue;
int CurrentWiFiSignal;
int MapReadLightValue;
int CurrentLightValue;
int dhtdata[2];
bool PumpStat = false;

// The ESP32 has an internal blue LED at D2 (GPIO 02)
// กำหนด LED_BUILTIN GPIO 02
//int LED_BUILTIN = 2;

// *** (8) BLYNK CONNECTED FUNCTION ***

BLYNK_CONNECTED() {
  //ให้หลอดไฟ LED บนบอร์ดสีน้ำเงินติดเพื่อเป็นการแสดงสถานะว่าการเชื่อมต่อเสร็จสมบูรณ์
  digitalWrite(LEDWiFiPin, HIGH);
  
    //ถ้าเป็นการเชื่อมต่อ Blynk Server ครั้งแรกหลังบอร์ดรีบูต
    if(isFirstConnect) {   
    //ให้ซิงค์ข้อมูลทั้งหมดล่าสุดจาก Blynk Server
    Blynk.syncAll();   
    //ให้ซิงค์สถานะของขา Virtual V7
    Blynk.syncVirtual(Widget_WateringButton);   
    isFirstConnect = false; 
    }
}

// *** (9) BLYNK BUTTON FUNCTION ***

BLYNK_WRITE(Widget_WateringButton) { 
    //ค่าที่ได้จาก Widget_WateringButton (V7) จะเป็น 0 และ 1 ถ้ามีการปดปุ่ม
  if (param.asInt() == 1) {   
    //ป้องกันไม่ให้กดซ้ำ
      if (digitalRead(WateringPin) != LOW && PumpStat == false) {      
        //เรียกใช้ฟังก์ชันรดน้ำ
        digitalWrite(WateringPin, LOW);   
      } //if
  } //if
  else {
    digitalWrite(WateringPin, HIGH);  
  }
}


// *** (10) FUNCTION SETUP() ***
void setup() {
  //เรียกใช้งาน Serial Monitor
  Serial.begin(115200);
  
  /* -------------------------------------------------------------- */
  //กำหนดโหมดใช้งานให้กำขา GPIO
  pinMode(LEDWiFiPin, OUTPUT);
  pinMode(LEDSensorPin, OUTPUT);
  pinMode(LEDWateringPin, OUTPUT);
  pinMode(WateringPin, OUTPUT);
  pinMode(RelayPin, OUTPUT);
  pinMode(SwitchPin, INPUT_PULLUP);
  
  /* -------------------------------------------------------------- */
  //ตั้งสถานะเริ่มต้นให้กับขา GPIO เพื่อป้องกันการทำงานเองตอนที่บอร์ด ESP32 รีบูต
  digitalWrite(LEDWiFiPin, LOW);
  digitalWrite(LEDSensorPin, LOW);
  digitalWrite(LEDWateringPin, LOW);
  digitalWrite(LEDWateringPin, LOW);
  digitalWrite(RelayPin, HIGH);
  Serial.println("Setting IO Done.");

  /* -------------------------------------------------------------- */
  
  //TASK4: ลูปเช็คการเชื่อมต่อ WiFi และให้เชื่อมต่อใหม่เองแบบอัตโนมัติ
  //xTaskCreate(&Task4, "Task4", 3000, NULL, 10, NULL);

  /* -------------------------------------------------------------- */
  timer.setInterval(checkWifiTime, checkWifi);

  //ตั้งเวลาส่งข้อมูลให้ BLYNK SERVER
  timer.setInterval(sendSensorTime, sendSensor);
  
  //ตั้งเวลาส่งข้อมูลให้ BLYNK SERVER
  timer.setInterval(sendSensor2Time, sendSensor2);
  
  //ตั้งเวลาให้เช็คว่า Blynk เชื่อมต่ออยู่หรือไม่
  timer.setInterval(checkConnectionTime, CheckConnection);
  
  //ตั้งเวลาส่งข้อมูลเข้า Google Firebase
  //timer.setInterval(sendFirebaseTime, sendFirebase);


  
  /* -------------------------------------------------------------- */
  //ทำการเชื่อมต่อ Google Firebase
  //Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
  
  /* -------------------------------------------------------------- */
  
  //ทำการเชื่อมต่อ WiFi
  //Blynk.connectWiFi(ssid, pass);
  //Blynk.connectWiFi(ssid, pass);
  Blynk.begin(auth, ssid, pass, server, port);   
  //Blynk.connect();
  /* -------------------------------------------------------------- */
  //แสดงข้อความใน Serial Monitor
  Serial.println();
  Serial.println("Welcom to smartfram IoT");
  Serial.print("WiFi Connected: ");
  Serial.println(WiFi.localIP());
  Serial.print("WiFi signal RSSI: ");
  Serial.print(WiFi.RSSI());
  Serial.println("dBm");
  
  /* -------------------------------------------------------------- */
  //ดึงเวลาจากอินเตอร์เน็ตจาก NTP Time Server
  configTime(7 * 3600, 0, ntp_server1, ntp_server2, ntp_server3);
  
  //แสดงข้อความใน Serial Monitor
  Serial.println("Waiting for time.");
  while (!time(nullptr)) {
    Serial.print(".");
  //vTaskDelay(100 / portTICK_PERIOD_MS);}
    delay(100);
  }
  //แสดงข้อความใน Serial Monitor
  Serial.println();
  Serial.println("Current time: " + NowString());
  
  /* -------------------------------------------------------------- */
  //ทำการเชื่อมต่อ BLYNK SERVER
  //Blynk.config(auth, server, port);
  //Blynk.connect();
  /* -------------------------------------------------------------- */
}

// *** (11) FUNCTION LOOP() ***
void loop() {
  Blynk.run();
  timer.run();
}

// *** (12) FUNCTION SENDSENSOR() ***

void sendSensor() {
  //ให้หลอดไฟ LED ติด
  if(Blynk.connected()){
    digitalWrite(LEDWiFiPin, HIGH);
    
    //ให้หลอดไฟ LED บน BLYNK MOBILE APP ติด
    LEDSensor.on();
    
    //แสดงข้อความใน Serial Monitor
    Serial.print(NowString());
    Serial.println(", Send data to blynk server");
    
    /* -------------------------------------------------------------- */
    
    //อ่านข้อมูลเซ็นเซอร์ dht22
    Getdht22(dhtdata);
    Blynk.virtualWrite(Widget_Humidity, dhtdata[0]);
    Blynk.virtualWrite(Widget_Temperature, dhtdata[1]);
    //Blynk.virtualWrite(Widget_SoilRawValue, analogRead(SoilSensorPin));
    //Blynk.virtualWrite(Widget_SoilLevel, SoilPercentValue());
    
    /* -------------------------------------------------------------- */
    //แสดงข้อความใน Serial Monitor
    Serial.print(NowString());
    Serial.println(", Send dht22 / Soil sensors to blynk server.");
    
    /* -------------------------------------------------------------- */
    
    //ให้หลอด LED ที่แสดงสถานะดับ
    digitalWrite(LEDWiFiPin, LOW);
    
    //ให้หลอดไฟ LED บน BLYNK MOBILE APP ดับ
    LEDSensor.off();
  }else{
    Serial.println("can't sendSensor1 Blynk not connect");
  }
}


// *** (13) FUNCTION SENDSENSOR2() ***
void sendSensor2() {
  if(Blynk.connected()){
    //ให้หลอดไฟ LED ติด
    digitalWrite(LEDWiFiPin, HIGH);
    
    //ให้หลอดไฟ LED บน BLYNK MOBILE APP ติด
    LEDSensor.on();
    
    //แสดงข้อความใน Serial Monitor
    Serial.print(NowString());
    Serial.println(", Send data to blynk server");
    
    /* -------------------------------------------------------------- */
    //แสดงข้อความใน Serial Monitor
    Serial.print(NowString());
    Serial.print(", Wifi Signal: ");
    Serial.print(WifiPercentSignal());
    Serial.println("%");
    
    /* -------------------------------------------------------------- */
    //อัพเดทข้อมูลไปยัง Blynk server
    Blynk.virtualWrite(Widget_LightRawValue, analogRead(LdrSensorPin));
    Blynk.virtualWrite(Widget_LightLevel, LdrPercentValue());
    Blynk.virtualWrite(Widget_WifiSignal, WifiPercentSignal());
    Blynk.virtualWrite(Widget_WifiRawValue, WiFi.RSSI());
    
    /* -------------------------------------------------------------- */
    //แสดงข้อความใน Serial Monitor
    Serial.print(NowString());
    Serial.println(", Send LDR sensors / WIFI to blynk server.");
    
    /* -------------------------------------------------------------- */
    //ให้หลอด LED ที่แสดงสถานะดับ
    digitalWrite(LEDWiFiPin, LOW);
    
    //ให้หลอด LED บน app Blynk ดับ
    LEDSensor.off();
  }else{
    Serial.println("can't sendSensor1 Blynk not connect");
  }
}

// *** (15) CHECK CONNECTION ***
//เช็คการเชือมต่อของ blynk
void CheckConnection(){  
  //ถ้าไม่สามารถ connect ไปยัง blynk server ได้
  if(!Blynk.connected()){    
    //แสดงข้อความบนคอนโซล
    Serial.println("Not connected to Blynk server.");
    Serial.println("Connecting to Blynk server...");
    Blynk.disconnect();
    delay(1000);
    Blynk.connect();  
    // try to connect to server  
  }
}

// *** (16) SEND LINENOTIFY ***

void NotifyLine(String t) {
  WiFiClientSecure client;  
  if(!client.connect("notify-api.line.me", 443)) {
    Serial.println("Connection failed");    
    return;
  }
  String req = "";
  req += "POST /api/notify HTTP/1.1\r\n";
  req += "Host: notify-api.line.me\r\n";
  req += "Authorization: Bearer " + String(TokenLine) + "\r\n";
  req += "Cache-Control: no-cache\r\n";
  req += "User-Agent: ESP32\r\n";
  req += "Content-Type: application/x-www-form-urlencoded\r\n";
  req += "Content-Length: " + String(String("message=" + t).length()) + "\r\n";
  req += "\r\n";
  req += "message=" + t;Serial.println(req);
  client.print(req);
  //vTaskDelay(20 / portTICK_PERIOD_MS);
  delay(20);
  Serial.println("-------------"); 
  while(client.connected()) {  
    String line = client.readStringUntil('\n');  
    if(line == "\r") {    
    break;
    }
  }
}


// *** (17) CURRENT DATETIME ***
String NowString() {
  int getcount = 1;
  time_t now = time(nullptr);
  struct tm* newtime = localtime(&now);
  String myyear = String(newtime->tm_year + 1900);  
  
  //ถ้าปียังเป็นปี 1970 ให้ดึงค่าเวลาใหม่ พยายามสูงสุด 4 ครั้ง
  while(myyear == "1970" && getcount <= 4) {    
    time_t now = time(nullptr);
    struct tm* newtime = localtime(&now);
    myyear = String(newtime->tm_year + 1900);   
    //vTaskDelay(100 / portTICK_PERIOD_MS); 
    delay(100);   
    getcount++;
  }
  String tmpTime = "";
  String tmpNow = "";
  tmpNow += String(newtime->tm_year + 1900);
  tmpNow += "-";
  if(newtime->tm_mon < 10) tmpNow += "0";
  tmpNow += String(newtime->tm_mon + 1);
  tmpNow += "-";
  if(newtime->tm_mday < 10) tmpNow += "0";
  tmpNow += String(newtime->tm_mday);
  tmpNow += " ";

  if(newtime->tm_hour < 10) tmpNow += "0";
  tmpNow += String(newtime->tm_hour);
  tmpNow += ":";
  if(newtime->tm_min < 10) tmpNow += "0";
  tmpNow += String(newtime->tm_min);
  tmpNow += ":";
  if(newtime->tm_sec < 10) tmpNow += "0";
  tmpNow += String(newtime->tm_sec);
  return tmpNow;
}

// *** (18) FUNCTION Getdht22 ***

void Getdht22(int *dht) {
  //กำหนดค่าตัวแปรอุณหภูมิ
  byte temperature = 0;
  
  //กำหนดค่าความชื้นสัมสัทธ์
  byte humidity = 0;int count = 1;
  
  //อ่านค่าจากเซ็นเซอร์ dht22
  dht22.read(DHTPin, &temperature, &humidity, NULL);
  
  //ถ้าค่าอุณหภูมิ = 0 ให้อ่านค่าจากเซ็นเซอร์ใหม่ 4 ครั้ง
  while(temperature == 0 && count <= 4) {  
    //แสดงข้อความใน Serial Monitor
    Serial.print(NowString());
    Serial.println(", dht22 get failed ");
    Serial.print(count);  
    
    //อ่านค่าจากเซ็นเซอร์ dht22
    dht22.read(DHTPin, &temperature, &humidity, NULL);  
    //vTaskDelay(1500/ portTICK_PERIOD_MS);  
    delay(1500);
    
    //ส่งข้อความให้ line notify แจ้งเตือน
    if(count == 4) NotifyLine("dht22 get failed 4 times.");  
    
    count++;
  }
  //นำข้อมูล temperature & humidity ครั้งที่ผ่านมาแสดง
  if(temperature == 0) temperature = oldtemperature;
  if(humidity == 0) humidity = oldhumidity;
  
  //แสดงข้อความใน Serial Monitor
  Serial.print(NowString());
  Serial.print(", Humidity: ");
  Serial.print(humidity);
  Serial.print("% | ");
  Serial.print("Temperature: ");
  Serial.print(temperature);
  Serial.println("C");
  
  //เก็บสำรองข้อมูล temperature & humidity
  oldtemperature = temperature;
  oldhumidity = humidity;
  
  dht[0] = humidity;
  dht[1] = temperature;
}

// *** (19) FUNCTION WifiPercentSignal ***
int WifiPercentSignal() {
  //หาค่าสัญญาณ RSSI ของ WIFI แล้ว MAP ให้อยู่ในรูปของเปอร์เซ็นต์
  CurrentWiFiSignal = WiFi.RSSI();
  
  if(CurrentWiFiSignal > -40) CurrentWiFiSignal = -40;
  if(CurrentWiFiSignal < -90) CurrentWiFiSignal = -90;
  
  WifiSignal = map(CurrentWiFiSignal, -90, -40, 0, 100);
  
  return WifiSignal;
}

// *** (21) FUNCTION LdrPercentValue ***

int LdrPercentValue() {
  //อ่านค่าจากเซ็นเซอร์อนาล๊อก LDR
  CurrentLightValue = analogRead(LdrSensorPin);
  
  if(CurrentLightValue > 4000) CurrentLightValue = 4000;
  if(CurrentLightValue < 100) CurrentLightValue = 100;
  
  //แม๊พค่าให้อยู่ในรูปของเปอร์เซ็นต์
  MapReadLightValue = map(CurrentLightValue, 4000, 100, 0, 100);
  
  //แสดงข้อความใน Serial Monitor
  Serial.print(NowString());
  Serial.print(", Light sensor value: ");
  Serial.println(MapReadLightValue);
  
  return MapReadLightValue;
}

void checkWifi (){
   if(WiFi.status() != WL_CONNECTED) {      
      digitalWrite(LEDWiFiPin, HIGH);
      Serial.println("WiFi Disconnected.");      
      WiFi.begin((char*)ssid, (char*)pass);
      delay(5000);
      if(WiFi.status() == WL_CONNECTED) { 
        Serial.print("connect to SSID : ");
        Serial.print(ssid);
        Serial.println(" success.");
        digitalWrite(LEDWiFiPin, LOW);
      }
   } 
}

ภาพการใช้งานลองประมาณ 4 ชั่วโมงปกติเดี๋ยวจะลองปล่อยข้ามคืนดูอีกที ตัดการใช้งาน freeos ออก
เริ่มต้น 11.14

ถึง 15.16 ยังปกติ

จากนั้นจำลองเน็ตหลุด โดยใช้ router block connecttion ตามรูปที่วงไว้

ลองต่อเน็ตกลับคืนใช้ได้ปกติ

จากนั้นจำลองการรีบูท router โดยการปิด interface wlan ที่ router จะ ping ไม่เจอ มี log ขึ้นตามที่วงไว้ในรูป

ลองเปิด interface wlan ที่ router ping เจอ แต่เจอปัญหา blynk ไม่เชื่อมต่อเอง ลองมาหลายรอบก็ยังใช้ไม่ได้

1 Likes

อยากรู้ว่า ถ้าเชื่อมต่อ กับ server blynk หลักจะเป็นเหมือนกันไหม ปัญหามาจาก server free ที่ใช้รึป่าวครับ มัน loss ไปบางช่วง

ผมมีอีกตัวที่ใช้ wemos server เดียวกันเลยใช้เปิดคอมไม่เคยหลุดเลยครับ

ตอนนี้คาดเดาว่าเกิดจากอะไรครับ

ไม่แน่ใจครับว่าจะเกิดจาก wifi หรือเปล่าผมว่าจะลองใช้ code example จากหน้าเว็บเค้าแล้วคืนนี้จะปล่อยทิ้งไว้ดูครับว่าจะเป็นหรือเปล่า

อยากรู้ว่า code basic connect จะหลุดเหมือนกันไหม ถ้าไม่หลุดแสดงว่าเป็นที่ code ที่เอามา อาจมีปัญหา แต่ถ้าหลุดเหมือนกันแสดงว่าเป็นที่ server

มาอัพเดทครับตอนนี้ปรับคือ
ย้าย #define BLYNK_PRINT Serial ไปไว้บนสุด

แล้วตรง check connection ของ blynk มาไว้ในส่วนของ freertos

void Task6(void *p) {  
  for(;;) {    
    if(!Blynk.connected()){    
      //แสดงข้อความบนคอนโซล
      Serial.println("Not connected to Blynk server.");
      Serial.println("Connecting to Blynk server...");
      Blynk.disconnect();
      //delay(1000);
      vTaskDelay(1000 / portTICK_PERIOD_MS);
      if(WiFi.status() == WL_CONNECTED){
        Blynk.config(auth, server, port);
        Blynk.connect();  
      }
      // try to connect to server  
    }
    vTaskDelay(10000 / portTICK_PERIOD_MS); 
  } //while
}

เปิดมาตั้งแต่เมื่อวานเย็น ถึงเช้ายังปกติดี ได้ผลเป็นที่น่าพอใจ เดี๋ยวคลีนโค้ดแล้วใส่ส่วนอื่นเพิ่ม

1 Likes

เยี่ยมเลยเหมือนว่าจะได้เค้าของปัญหาแบบลางๆ แล้วสินะครับ ประเด็นก็คือ ชุดคำสั่งมีการทำงานที่หลากหลายขั้นตอน ซึ่งการใช้ timer.setInterval แยกการทำงานออกเป็นส่วนๆ ก็จริง แต่มันก็เหมือนแค่จำลอง freetos แบบเสมือน ถ้ามีการทำงานแต่ละส่วนมาก

อาจจะให้เกิด กรณี dead time ขึ้นหรือเวลา ในแต่ละ timer.setInterval ชนกัน ทำให้บางครั้ง CheckConnection() ทำงานไม่ได้ ทำให้หลุด การแยก tesk ออกไปจึงเป็นการแยก ออกจะ process โดยอิสระ ซึ่งจะไม่เกิดกรณี dead time แน่นอน ทำให้ไม่หลุดก็เป็นได้ครับ

การจะทดสอบสมมติฐานนี้ อย่างที่บอกไป ตัดทุก process ออกไปก่อนให้เหลือแต่ CheckConnection() หรือยุบรวม timer.setInterval ให้เหลือน้อยที่สุด

ถือว่าไหวพริบการแก้ไขปัญหาดีเยี่ยมเลยครับ ขอบคุณที่แชร์แนวทางการแก้ไขปัญหา อย่างละเอียดยิบ เชื่อว่าต้องเป็นประโยชน์แก่คนอื่นๆ ต่อไปอย่างแน่นอน

ตอนนี้รอผล ปิด issue อยากรู้ว่ามันจะเป็นอีกไหม :grin:

ผมขอดูไฟลทั้งหมดได้ไหมครับ

กำลังติดปัญหาเดียวกันเลยครับ ขอบคุณครับสำหรับแนวทางการแก้ปัญหา

แก้ไขได้หรือยังครับ

กำลังทดสอบโดยการแยกการทำงานของโปรแกรม โดยใช้ freertos ครับ เช่น ส่วนที่ใช้แสดงเวลา ,ส่วนที่ตรวจสอบการเชื่อมต่อครับ ได้ผลยังไงจะแจ้งให้ทราบ
ขอบคุณครับ

ปัญหาที่ผมเจอ คือ Heartbeat Timeout บ่อยมาก จากการทดลองแก้ไขสาเหตุหนึ่งน่าเกิดจากการให้อุปกรณ์อ่านเวลาจาก Server ทุกๆ 1 วินาที นำไปแสดงผลที่ GLCD และส่งเวลาไปแสดงค่าในแอปอีก ซึ่งวนๆ ซ้ำๆ ไปเรื่อยๆ สักพักก็เกิด Heartbeat Timeout ผมเลยให้ทำงานในส่วนนี้น้อยลง คือ แสดงเวลา จากหลักวินาที เป็นอัพค่าทุกๆ นาที ก็ทำให้ปัญหานี้ลดลงไปครับ และส่วนหนึ่งไม่แน่ใจว่าเกิดจากสัญญาณอินเตอร์เน็ตไม่ค่อยเสถียรหรือไม่ เพราะยังเกิดขึ้นอยู่บ้าง แต่นานๆ ที พอรับได้ครับ

1 Likes

ปัญหาน่าจากคล้ายๆ อินพุตแลค จากการ stream Vdo game Spec สูงๆ อยากลอง 5G ดูว่าจะเป็นเหมือนกันไหม