การใช้อุณหภูมิและความชื้น ควบคุมการทำงานของพัดลม แบบต่อเนื่องแบบไม่มีสะดุด

หลังจากที่ได้ทดสอบการใช้อุณหภูมิและความชื้นควบคุมการทำงานของพัดลมปรากฏว่ามันให้ผลลัพธ์การทำงานแบบไม่ต่อเนื่องคือทำแล้วหยุด หยุดแล้วทำ เนื่องจากว่าในกรณีที่อุณหภูมิอยู่ในค่าที่กำหนดจะทำงาน แต่ค่าความชื้นไม่อยู่ในค่าที่กำหนดมันจึงไม่ทำงาน และเมื่อมันวนลูปมามันจะทำงานแล้วหยุดทำงานแล้วหยุดเป็นระยะๆ

ผมจึงได้ทำการปรับปรุงตัว code ใหม่เพื่อให้มีการทำงานที่ต่อเนื่องโดยมีหลักการคือจะแบ่งสถานะการทำงานของอุณหภูมิและความชื้นออกเป็น 4 สถานะ ลักษณะคล้ายกับเลขฐาน 2

T H FAN
0 0 OFF
0 1 ON
1 0 ON
1 1 ON

โดย 0 หมายถึงค่าอุณหภูมิ หรือ ความชื้น อยู่นอกเหนือค่าที่กำหนดไว้ พัดลมจะไม่ทำงาน
และ 1 หมายถึงค่าอุณหภูมิ หรือ ความชื้นอยู่ในค่าที่กำหนดไว้พัดลมจะทำงาน
ดังนั้นถ้าดูในตารางถ้าสถานะใดที่มีค่าเป็น 1 พัดลมจะทำงานทั้งหมด

ผมจะเขียน โดยใช้ Node mcu esp8266 โดยรับการตั้งค่าค่าอุณหภูมิ และ ความชื้น จาก ฺBlynk Application

/*Arduino mega 2560   ->   ESP8266
        12   (RX)     ->       D7 (GPIO 13) (TX)
        13   (TX)     ->       D6 (GPIO 12) (RX)
       GND            ->      GND
*/
//-------------------------------------------------------------------------------------------------------------------------//
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include "WiFiManager.h"
#include <FS.h>
#include <DNSServer.h>
#include "ArduinoJson.h"
#include <ESP8266HTTPClient.h>
//----------------------------------------------------------

//Blynk------------
#include <BlynkSimpleEsp8266.h>
#define BLYNK_DEBUG
#define BLYNK_PRINT Serial
int blynkIsDownCount = 0;
char blynk_tokencenter[34] = "G00ONuMPlpCKF21o9BbUiGS7igTLXPAK";

//----------------------------------------------------------
BlynkTimer timer;

//***********สำหรับ Server local ที่แจกให้ เพิ่ม **** แค่ 2 บรรทัดนี้
char server[] = "oasiskit.com";
int port = 8080;



//------------------------------------------------------------------------------------------------------------------------//

#include "TridentTD_LineNotify.h"
char line_token[45] = "QerWyEZdBShylI3iTTxKz1Pk8Zo1vLy2NQa7AXFgYLM";
//QerWyEZdBShylI3iTTxKz1Pk8Zo1vLy2NQa7AXFgYLM
int blynk_Connect = 0;
int Line1_status = 0;
int Line2_status = 0;
//------------------------------------------------------------------------------------------------------------------------//

#define D0 16 // ใช้ไฟ LED สีฟ้า ของบอร์ด MCU ESP8266 ให้มีสัญญาณไฟกระพริบ ตาม Code ที่เขียน 
#define D4 2 // ใช้เป็นปุ่มกด เพื่อเข้า AP Config ได้ตามความต้องการของผู้ใช้

//------------------------------------------------------------------------------------------------------------------------//

bool shouldSaveConfig1 = false;
void saveConfigCallback1 () {
  shouldSaveConfig1 = true;
  Serial.println("Should save  All Data config");
}
//-----------------------------------------------------------------------------------------------------------------------//

String IP;

#include <EEPROM.h>

//-----------------------------------------------------------------------------------//


#include "DHT.h"
#define DHTTYPE DHT21
#define DHTPIN  D7
DHT dht(DHTPIN, DHTTYPE);
float h ;
float t ;

int Relay_fan = D6;

int Temp = 0;
int Humid = 0;


//Temp
float tmax;
String t_max1;
float t_max2;

float tmin;
String t_min1;
float t_min2;

//Humid
float hmax;
String h_max1;
float h_max2;


float hmin;
String h_min1;
float h_min2;




WidgetLED led_1(V3);



int ThingSpeakcount = 0;










//------------------------------------------------------//
BLYNK_CONNECTED()
{

  Blynk.syncAll();//ให้ซิงค์ข้อมูลทั้งหมดล่าสุดจาก Blynk Server

}//end Blynk connect



BLYNK_WRITE(V10)

{
  t_max1 = param.asString();//รับค่าข้อความจาก Blynk เข้ามา เก็บในรูปแบบ String

  t_max2 = t_max1.toFloat();//แปลงค่าจาก String เป็น Float

  EEPROM.put(0, t_max2); //เขียนค่า
  EEPROM.commit(); //จบการเขียน

  tmax = EEPROM.get(0, t_max2);//อ่าน ค่า
  Serial.println(tmax);

  delay(100);

}



BLYNK_WRITE(V11)

{
  t_min1 = param.asString();//รับค่าข้อความจาก Blynk เข้ามา เก็บในรูปแบบ String

  t_min2 = t_min1.toFloat();//แปลงค่าจาก String เป็น Float

  EEPROM.put(10, t_min2); //เขียนค่า
  EEPROM.commit(); //จบการเขียน

  tmin = EEPROM.get(10, t_min2);//อ่าน ค่า
  Serial.println(tmin);

  delay(100);

}




BLYNK_WRITE(V12)

{
  h_max1 = param.asString();//รับค่าข้อความจาก Blynk เข้ามา เก็บในรูปแบบ String

  h_max2 = h_max1.toFloat();//แปลงค่าจาก String เป็น Float

  EEPROM.put(20, h_max2); //เขียนค่า
  EEPROM.commit(); //จบการเขียน

  hmax = EEPROM.get(20, h_max2);//อ่าน ค่า
  Serial.println(hmax);

  delay(100);

}



BLYNK_WRITE(V13)

{
  h_min1 = param.asString();//รับค่าข้อความจาก Blynk เข้ามา เก็บในรูปแบบ String

  h_min2 = h_min1.toFloat();//แปลงค่าจาก String เป็น Float

  EEPROM.put(30, h_min2); //เขียนค่า
  EEPROM.commit(); //จบการเขียน

  hmin = EEPROM.get(30, h_min2);//อ่าน ค่า
  Serial.println(hmin);

  delay(100);

}















//------------------------------------------------------------------------------------------------------------------------//
//*********************************************       void setup        **************************************************//
//------------------------------------------------------------------------------------------------------------------------//

void setup() {

  //-------IO NODE MCU Esp8266-------//
  pinMode(D0, OUTPUT);      //กำหนดโหมดใช้งานให้กับขา D0 เป็นขา สัญญาณไฟ ในสภาวะต่างๆ
  pinMode(D4, INPUT_PULLUP);//กำหนดโหมดใช้งานให้กับขา D4 เป็นขา กดปุ่ม ค้าง เพื่อตั้งค่า AP config
  pinMode(Relay_fan, OUTPUT);

  digitalWrite(Relay_fan, 1);//ให้ Relay off ก่อน
  Serial.begin(115200);

  dht.begin();




  //-----------------------------------------------------------------------------------------------------------------------//
  //read configuration from FS json
  Serial.println("mounting  FS...");


  if (SPIFFS.begin()) {

    //---------------------------------------------------------------------------------//

    Serial.println("mounted Data file system");


    if (SPIFFS.exists("/config1.json")) {
      //file exists, reading and loading
      Serial.println("reading Data config file");
      File configFile1 = SPIFFS.open("/config1.json", "r");

      if (configFile1) {
        Serial.println("opened Data config file");
        size_t size = configFile1.size();
        // Allocate a buffer to store contents of the file.
        std::unique_ptr<char[]> buf1(new char[size]);

        configFile1.readBytes(buf1.get(), size);
        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.parseObject(buf1.get());
        json.printTo(Serial);
        if (json.success()) {
          Serial.println("\nparsed  json");

          strcpy(blynk_tokencenter, json["blynk_tokencenter"]);

          strcpy(line_token, json["line_token"]);


        } else {
          Serial.println("failed to load Data file json config");
        }
      }
    }
    //---------------------------------------------------------------------------------//



  } else {
    Serial.println("failed to mount FS");

  }
  //end read


  delay(1000);


  //-----------------------------------------------------------------------------------------------------------------------//

  WiFiManagerParameter custom_text0("<p> </p>");
  WiFiManagerParameter custom_textA("<label>A: Blynk Token center</label>");

  WiFiManagerParameter custom_text1("<label>1: ID Line กลุ่ม</label>");


  WiFiManagerParameter custom_blynk_tokencenter("blynk_tokencenter", "blynk_tokencenter", blynk_tokencenter, 34);
  WiFiManagerParameter custom_line_token("line_token", "line_token", line_token, 45);





  //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(saveConfigCallback1);

  wifiManager.addParameter(&custom_text0);
  wifiManager.addParameter(&custom_textA);
  wifiManager.addParameter(&custom_blynk_tokencenter);

  wifiManager.addParameter(&custom_text0);
  wifiManager.addParameter(&custom_text1);
  wifiManager.addParameter(&custom_line_token);


  delay(1000);

  for (int i = 5; i > -1; i--) {  // นับเวลาถอยหลัง 5 วินาทีก่อนกดปุ่ม AP Config

    digitalWrite(D0, LOW);
    delay(500);
    digitalWrite(D0, HIGH);
    delay(500);
    Serial.print (String(i) + " ");


  }

  if (digitalRead(D4) == LOW) {
    digitalWrite(D0, LOW);
    Serial.println("Button Pressed");



    wifiManager.resetSettings();//ให้ล้างค่า SSID และ Password ที่เคยบันทึกไว้


    // wifiManager.autoConnect(); ใช้สร้างชื่อแอคเซสพอยต์อันโนมัติจาก ESP + ChipID

    if (!wifiManager.autoConnect("Lighting Ctrl 2")) {
      Serial.println("failed to connect and hit timeout");
      delay(3000);


      //reset and try again, or maybe put it to deep sleep
      ESP.reset();
      delay(5000);
    }

  }




  Serial.println(": เชื่อมต่อ WiFi สำเร็จ!)");

  strcpy(blynk_tokencenter, custom_blynk_tokencenter.getValue());
  strcpy(line_token, custom_line_token.getValue());
  delay(1000);

  if (shouldSaveConfig1) {
    //Serial.println("saving config");//แสดงข้อความใน Serial Monitor

    //------------------------------------------------------------------

    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();

    //------------------------------------------------------------------

    Serial.println("saving blynk_tokencenter_ config");
    json["blynk_tokencenter"] = blynk_tokencenter;
    File configFile1 = SPIFFS.open("/config1.json", "w");

    //------------------------------------------------------------------
    Serial.println("saving line token config");
    json["line_token"] = line_token;
    File configFile2 = SPIFFS.open("/config1.json", "w");
    //------------------------------------------------------------------


    if (!configFile1) {
      Serial.println("failed to open  config file for writing");

    }
    json.printTo(Serial);
    //-------------------------------------
    //--Write Close blynk_tokencenter
    json.printTo(configFile1);
    configFile1.close();
    //-------------------------------------
    //--Write Close Line token
    json.printTo(configFile2);
    configFile2.close();
  }

  delay(1000);
  //-----------------------------------------------------------------

  //-----------------------------------------------------------------------------------------------------------------------//
  Serial.println("-----------------------------------");
  Serial.println();
  Serial.print("local ip   : ");
  delay(100);
  Serial.println(WiFi.localIP());
  delay(100);
  Serial.print("gateway    :");
  delay(100);
  Serial.println(WiFi.gatewayIP());
  Serial.print("subnetMask :");
  delay(100);
  Serial.println(WiFi.subnetMask());
  Serial.print("SSID       :");
  delay(100);
  Serial.println(WiFi.SSID());
  Serial.print("Password   :");
  delay(100);
  Serial.println(WiFi.psk());
  //-----------------------------------------------------------------------------------------------------------------------//
  //Print เพื่อเชคว่าค่าที่บันทึกไว้ยังอยู่หรือไม่
  Serial.println("-----------------------------------");
  Serial.println("เชคว่าค่าที่บันทึกไว้ยังอยู่หรือไม่");
  Serial.println();

  IP = WiFi.localIP().toString();
  Serial.print("IP to String = ");
  Serial.println(IP);


  //  Blynk.config(blynk_tokencenter);//เริ่มการเชื่อมต่อ Blynk Server แบบปกติ
  Blynk.config(blynk_tokencenter, server, port);
  //เริ่มการเชื่อมต่อ Blynk Server*********สำหรับ Server local
  //ที่แจกให้ เพิ่ม, server, port  แค่นี้จบ


  timer.setInterval(30000L, reconnecting);

  timer.setInterval(2000L, checkT_H);

  //timer.setInterval(5000L, ThingSpeak);

  LINE.setToken(line_token);

  EEPROM.begin(512);

  tmax = EEPROM.get(0, t_max2);
  Serial.print("tmax in Void setup : ");
  Serial.println(tmax);

  tmin = EEPROM.get(10, t_min2);
  Serial.print("tmin in Void setup : ");
  Serial.println(tmin);

  hmax = EEPROM.get(20, h_max2);
  Serial.print("hmax in Void setup : ");
  Serial.println(hmax);

  hmin = EEPROM.get(30, h_min2);
  Serial.print("hmin in Void setup : ");
  Serial.println(hmin);

}//end setup

//------------------------------------------------------------------------------------------------------------------------//
//*********************************************   จบ  void setup        **************************************************//
//------------------------------------------------------------------------------------------------------------------------//









//------------------------------------------------------------------------------------------------------------------------//
//*********************************************       void Loop        ***************************************************//
//------------------------------------------------------------------------------------------------------------------------//


void loop() {







  //------------- Blynk Connect ---------------//
  if (Blynk.connected())
  {
    Blynk.run();
    digitalWrite(D0, LOW);

  } else {
    digitalWrite(D0, LOW);
    delay(100);
    digitalWrite(D0, HIGH);
    delay(300);

    Serial.println(WiFi.localIP());
    delay(100);

  }


  timer.run();//ให้เวลาของ Blynk ทำงาน




   ThingSpeakcount++;

   
  if (ThingSpeakcount == 10) {
    ThingSpeak();
  }

  if (ThingSpeakcount == 11) {
    ThingSpeakcount = 0;
  }

  Serial.println(ThingSpeakcount);



  delay(500);
}//Loop






//--------------------------------------------------------------------------------------------------------


void reconnecting()
{
  if (!Blynk.connected())
  {
    blynkIsDownCount++;
    BLYNK_LOG("blynk server is down! %d  times", blynkIsDownCount);
    Blynk.connect(5000);
  }
}
//--------------------------------------------------------------------------------------------------------


void checkT_H()
{ loop:
  t = dht.readTemperature();
  h = dht.readHumidity();


  //-----------------ถ้าอ่านค่าไม่ได้ ให้  t = 0 ,h = 0 เพื่อสะดวกในการวิเคราะห์ค่า---------
  if (isnan(h) || isnan(t)) {
    //Serial.println("Failed to read from DHT sensor!");
    //delay(500);
    //display.clear();
    //display.drawString(5, 0, "Failed DHT22");
    //t = 0;
    //h = 0;
    Serial.println("***อ่านค่าไม่ได้***");
    delay(1000);
    goto loop ;
  }
  //---------------------------------------------------------------------
  else {
    //Serial.println("อ่านค่าได้แล้ว");
    //    Serial.print("temp : ");
    //    Serial.println(t);
    //    Serial.print("Humid :");
    //    Serial.println(h);


    Blynk.virtualWrite(V1, t);
    Blynk.virtualWrite(V2, h);




    if ( t > tmin && t <= tmax ) {

      Temp = 1;

    }  else   {

      Temp = 0;
    }

    if ( h > hmin && h <= hmax ) {

      Humid = 1;

    }  else   {

      Humid = 0;
    }


    //ใช้หลักการทำงานแบบ 4 สถานะ


    if ( Temp == 1 && Humid == 1 ) {//temp  ปกติ    humit  ปกติ

      digitalWrite(Relay_fan, 0);//FAN ON
      led_1.on();

    }


    if ( Temp == 0 && Humid == 1 ) {//temp  ผิดปกติ    humit  ปกติ

      digitalWrite(Relay_fan, 0);//FAN ON
      led_1.on();

    }



    if ( Temp == 1 && Humid == 0 ) {//temp  ปกติ    humit  ผิดกติ

      digitalWrite(Relay_fan, 0);//FAN ON
      led_1.on();

    }


    if ( Temp == 0 && Humid == 0 ) {//temp  ผิดปกติ    humit  ผิดกติ

      digitalWrite(Relay_fan, 1);//FAN  OFF
      led_1.off();


    }



    return;//ถ้าไม่ใส่มันจะไม่ return ค่า =0,h=0
  }


}




//--------------------------------------------------------------------------------------------------------
//gชคค่าได้ที่ https://thingspeak.com/channels/1184686/private_show
void ThingSpeak()
{

  // ThingSpeak Settings //
  char thingSpeakAddress[] = "api.thingspeak.com";
  String writeAPIKey = "BCSYVMLSGQWMELCL"; // คีย์จากเมนู key Api แบบ Write API Key
  WiFiClient client;

  String tempA = (String) t; // แปลงเป็น string
  String humA = (String) h; // แปลงเป็น string
  //  String Light_ = (String) light; // แปลงเป็น string
  //  String Rainy = (String) rain; // แปลงเป็น string
  String data = "field1=" + tempA + "&field2=" + humA ;
  //String data = "field1=" + temp + "&field2=" + hum + "&field3=" + Light_ + "&field4=" + Rainy;

  if (client.connect(thingSpeakAddress, 80)) {
    client.print("POST /update HTTP/1.1\n");
    client.print("Host: api.thingspeak.com\n");
    client.print("Connection: close\n");
    client.print("X-THINGSPEAKAPIKEY: " + writeAPIKey + "\n");
    client.print("Content-Type: application/x-www-form-urlencoded\n");
    client.print("Content-Length: ");
    client.print(data.length());
    client.print("\n\n");
    client.print(data); //
  }

  //Serial.println("ThingSpeakloop");
  delay(5000);

}

//--------------------------------------------------------------------------------------------------------

สำหรับ Code ตัวนี้ผมจะเช็คสถานะของอินเตอร์เน็ตโดยการส่งข้อมูล อุณหภูมิและความชื้น เข้าไปยัง ThingSpeak โดยวิเคราะห์ข้อมูลได้ว่า
ในขณะที่ Blynk Application หลุดการเชื่อมต่อ เราจะไม่ทราบสาเหตุว่าเกิดจากอินเทอร์เน็ต OFF หรือ ON กันแน่
ดังนั้นให้เราไปเช็คที่ ThingSpeak ถ้าอุณหภูมิและความชื้น มีการเคลื่อนไหวอยู่แสดงว่าอินเตอร์เน็ตมาแต่ Blynk Application ไม่สามารถเชื่อมต่อเข้ากับเซิร์ฟเวอร์ได้เอง

หรืออีกนัย หนึ่งการเขียนโค้ดมี Bug อาจจะต้องมีการตรวจสอบโค้ดและตำแหน่งการวางโค้ด ต่างๆ ใหม่ และทดสอบ อย่างละเอียดถี่ถ้วน

1 Like