การเช็คปริมาตรน้ำ ในถังเก็บน้ำแบบ 3 ระดับ ผ่านแอพพลิเคชั่น blynk

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

จากไดอะแกรมของภาพก็ไม่มีอะไรที่ยุ่งยากและซับซ้อนใครสนใจก็สามารถต่ออุปกรณ์ได้ตามนี้

คือในส่วนของ Blink Application ผมจะวาง Concept เอาไว้ว่า คนที่นำไปใช้งานสามารถที่จะกำหนดค่าพารามิเตอร์ของถังเก็บน้ำได้ด้วยตนเอง จะไม่มีการกำหนดค่าลงไปในส่วนของโปรแกรม แต่จะให้โปรแกรมรับค่าตัวเลขพารามิเตอร์ของถังเก็บน้ำจากผู้ใช้งานโดยตรง ซึ่งการทำเช่นนี้จะเป็นการสร้างความยืดหยุ่นให้กับผู้ใช้งานได้ในระดับหนึ่ง

ก็เห็นว่าในแถบ setting ผู้ใช้งานสามารถกำหนดพารามิเตอร์ได้ดังนี้

  1. กดปุ่มบวกหรือลบในหัวข้อเส้นรอบวงของถัง ส่วนนี้ในแนวคิดของผมคือบางส่วนที่มีการติดตั้งถังเก็บน้ำไปแล้วเราไม่สามารถที่จะเช็คเส้นผ่าศูนย์กลางหรือรัศมีของถังได้โดยตรงดังนั้นวิธีที่ง่ายที่สุดก็คือการวัดเส้นรอบวงของถังแล้วกำหนดให้ส่วนของโปรแกรมคำนวณออกมาเป็นพื้นที่ของก้นถังได้
  2. กดปุ่มบวกหรือลบในหัวข้อความสูงของถัง หลังจากที่กำหนดค่าลงไปแล้วไปที่ Tap Water Tank โปรแกรมจะคำนวณและแสดงตัวเลขออกมาเป็นปริมาตรของน้ำที่อยู่ในถังทั้งหมด
  3. สำหรับข้อที่ 3 4 และ 5 กดปุ่มบวกหรือลบจะเป็นการกำหนดระยะความสูงในการติดตั้งตัวเซ็นเซอร์เช็คระดับน้ำ ว่าจากพื้นถึงเซ็นเซอร์ตัวแรกเป็นระยะกี่เมตร จากตัวแรกถึงตัวที่สองเป็นระยะกี่เมตร และจากตัวที่ 2 ถึงตัวที่ 3 เป็นระยะกี่เมตร ถ้าผู้ใช้งานกำหนดค่าระยะลงไปเสร็จเรียบร้อยแล้วให้คำนวณกลับมาด้วยว่าได้เท่ากับระยะความสูงทั้งหมดที่กำหนดค่าจากข้อ 2 หรือไม่ถ้าไม่ตรงให้ปรับแก้ใหม่
  4. เมื่อกำหนดค่าทุกอย่างเสร็จเรียบร้อยแล้วให้กดปุ่ม Generate Volume เพื่อให้ Sync ค่าปัจจุบันที่เรากำหนด
  5. จากนั้นให้ไปที่ Tap Water Tank เราจะเห็นว่า ค่าพารามิเตอร์ต่างๆที่เรากำหนดเอาไว้จะมาแสดงในหน้านี้

ข้อมูลที่ผู้ใช้งานจะป้อนเข้าไป


#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 D3 0                     // ใช้เป็นปุ่มกด เพื่อเข้า AP Config ได้ตามความต้องการของผู้ใช้

WidgetLED led_L1(V1); //LOW
WidgetLED led_L2(V2);//Meduim
WidgetLED led_L3(V3);//HIGH
WidgetLED led_pump(V4);

int blynkIsDownCount = 0;                                     //Integer Variable ตัวแปรชื่อ blynkIsDownCount ใช้เก็บเลขจำนวนเต็ม โดยเริ่มต้นให้มีค่า = 0
char blynk_token[34] = "YkNarC2Yub7M2OcPbP-xx7UVBIeFMqgD";    //ใส่ 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;
}
//-------------------------------------------------------------------------------------------------------------------------------------------


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




float stepValue3;
float volumetank3;
float stepValue4;
float volumetank4;
float stepValue5;
float volumetank5;


#define D4 2   //LOW
#define D5 14  //Meduim
#define D6 12  // HIGH


//คำนวณพื้นที่ก้นถัง จากเส้นรอบวงถัง
//------------------------------------------------------------------------------------------------------------------------//
BLYNK_WRITE(V10) {
  //  param.asInt()   param.asFloat()
  switch (param.asInt()) {
    case 0:
      Blynk.virtualWrite(V20, param.asFloat() );
      stepValue1 = param.asFloat();
      r = stepValue1 / 6.2857;
      areatank = 3.1428 * r * r;
      Blynk.virtualWrite(V22, areatank );


      break;
    case 1:
      Blynk.virtualWrite(V20, param.asFloat() );
      stepValue1 = param.asFloat();
      r = stepValue1 / 6.2857;
      areatank = 3.1428 * r * r;
      Blynk.virtualWrite(V22, areatank );

      break;
    case 2:
      Blynk.virtualWrite(V20, param.asFloat() );
      stepValue1 = param.asFloat();
      r = stepValue1 / 6.2857;
      areatank = 3.1428 * r * r;
      Blynk.virtualWrite(V22, areatank );

      break;
    case 3:
      Blynk.virtualWrite(V20, param.asFloat() );
      stepValue1 = param.asFloat();
      r = stepValue1 / 6.2857;
      areatank = 3.1428 * r * r;
      Blynk.virtualWrite(V22, areatank );

      break;
    case 4:
      Blynk.virtualWrite(V20, param.asFloat() );
      stepValue1 = param.asFloat();
      r = stepValue1 / 6.2857;
      areatank = 3.1428 * r * r;
      Blynk.virtualWrite(V22, areatank );

      break;
    case 5:
      Blynk.virtualWrite(V20, param.asFloat() );
      stepValue1 = param.asFloat();
      r = stepValue1 / 6.2857;
      areatank = 3.1428 * r * r;
      Blynk.virtualWrite(V22, areatank );

      break;
    case 6:
      Blynk.virtualWrite(V20, param.asFloat() );
      stepValue1 = param.asFloat();
      r = stepValue1 / 6.2857;
      areatank = 3.1428 * r * r;
      Blynk.virtualWrite(V22, areatank );

      break;
    case 7:
      Blynk.virtualWrite(V20, param.asFloat() );
      stepValue1 = param.asFloat();
      r = stepValue1 / 6.2857;
      areatank = 3.1428 * r * r;
      Blynk.virtualWrite(V22, areatank );

      break;
    case 8:
      Blynk.virtualWrite(V20, param.asFloat() );
      stepValue1 = param.asFloat();
      r = stepValue1 / 6.2857;
      areatank = 3.1428 * r * r;
      Blynk.virtualWrite(V22, areatank );

      break;
    case 9:
      Blynk.virtualWrite(V20, param.asFloat() );
      stepValue1 = param.asFloat();
      r = stepValue1 / 6.2857;
      areatank = 3.1428 * r * r;
      Blynk.virtualWrite(V22, areatank );

      break;
    case 10:
      Blynk.virtualWrite(V20, param.asFloat() );
      stepValue1 = param.asFloat();
      r = stepValue1 / 6.2857;
      areatank = 3.1428 * r * r;
      Blynk.virtualWrite(V22, areatank );

      break;
  }
}
//คำนวณปริมาตรน้ำทั้งหมดของถัง
BLYNK_WRITE(V11) {
  // receive the step value as param.asInt() and then use switch to run different code
  switch (param.asInt()) {
    case 0:
      Blynk.virtualWrite(V21, param.asFloat() );
      stepValue2 = param.asFloat();
      volumetank = areatank * stepValue2;
      Blynk.virtualWrite(V16, volumetank );
      break;
    case 1:
      Blynk.virtualWrite(V21, param.asFloat() );
      stepValue2 = param.asFloat();
      volumetank = areatank * stepValue2;
      Blynk.virtualWrite(V16, volumetank );
      break;
    case 2:
      Blynk.virtualWrite(V21, param.asFloat() );
      stepValue2 = param.asFloat();
      volumetank = areatank * stepValue2;
      Blynk.virtualWrite(V16, volumetank );
      break;
    case 3:
      Blynk.virtualWrite(V21, param.asFloat() );
      stepValue2 = param.asFloat();
      volumetank = areatank * stepValue2;
      Blynk.virtualWrite(V16, volumetank );
      break;
    case 4:
      Blynk.virtualWrite(V21, param.asFloat() );
      stepValue2 = param.asFloat();
      volumetank = areatank * stepValue2;
      Blynk.virtualWrite(V16, volumetank );
      break;
    case 5:
      Blynk.virtualWrite(V21, param.asFloat() );
      stepValue2 = param.asFloat();
      volumetank = areatank * stepValue2;
      Blynk.virtualWrite(V16, volumetank );
      break;
    case 6:
      Blynk.virtualWrite(V21, param.asFloat() );
      stepValue2 = param.asFloat();
      volumetank = areatank * stepValue2;
      Blynk.virtualWrite(V16, volumetank );
      break;
    case 7:
      Blynk.virtualWrite(V21, param.asFloat() );
      stepValue2 = param.asFloat();
      volumetank = areatank * stepValue2;
      Blynk.virtualWrite(V16, volumetank );
      break;
    case 8:
      Blynk.virtualWrite(V21, param.asFloat() );
      stepValue2 = param.asFloat();
      volumetank = areatank * stepValue2;
      Blynk.virtualWrite(V16, volumetank );
      break;
    case 9:
      Blynk.virtualWrite(V21, param.asFloat() );
      stepValue2 = param.asFloat();
      volumetank = areatank * stepValue2;
      Blynk.virtualWrite(V16, volumetank );
      break;
    case 10:
      Blynk.virtualWrite(V21, param.asFloat() );
      stepValue2 = param.asFloat();
      volumetank = areatank * stepValue2;
      Blynk.virtualWrite(V16, volumetank );
      break;
  }
}

//คำนวณปริมาตรน้ำในระดับ LOW
BLYNK_WRITE(V12) {
  // receive the step value as param.asInt() and then use switch to run different code
  switch (param.asInt()) {
    case 0:
      Blynk.virtualWrite(V30, param.asFloat() );
      stepValue3 = param.asFloat();
      volumetank3 = areatank * stepValue3;

      break;
    case 1:
      Blynk.virtualWrite(V30, param.asFloat() );
      stepValue3 = param.asFloat();
      volumetank3 = areatank * stepValue3;

      break;
    case 2:
      Blynk.virtualWrite(V30, param.asFloat() );
      stepValue3 = param.asFloat();
      volumetank3 = areatank * stepValue3;

      break;
    case 3:
      Blynk.virtualWrite(V30, param.asFloat() );
      stepValue3 = param.asFloat();
      volumetank3 = areatank * stepValue3;

      break;
    case 4:
      Blynk.virtualWrite(V30, param.asFloat() );
      stepValue3 = param.asFloat();
      volumetank3 = areatank * stepValue3;

      break;
    case 5:
      Blynk.virtualWrite(V30, param.asFloat() );
      stepValue3 = param.asFloat();
      volumetank3 = areatank * stepValue3;

      break;

  }
}

//คำนวณปริมาตรน้ำในระดับ Medium
BLYNK_WRITE(V13) {
  // receive the step value as param.asInt() and then use switch to run different code
  switch (param.asInt()) {
    case 0:
      Blynk.virtualWrite(V31, param.asFloat() );
      stepValue4 = param.asFloat();
      volumetank4 = areatank * (stepValue3 + stepValue4) ;

      break;
    case 1:
      Blynk.virtualWrite(V31, param.asFloat() );
      stepValue4 = param.asFloat();
      volumetank4 = areatank * (stepValue3 + stepValue4) ;

      break;
    case 2:
      Blynk.virtualWrite(V31, param.asFloat() );
      stepValue4 = param.asFloat();
      volumetank4 = areatank * (stepValue3 + stepValue4) ;

      break;
    case 3:
      Blynk.virtualWrite(V31, param.asFloat() );
      stepValue4 = param.asFloat();
      volumetank4 = areatank * (stepValue3 + stepValue4) ;

      break;
    case 4:
      Blynk.virtualWrite(V31, param.asFloat() );
      stepValue4 = param.asFloat();
      volumetank4 = areatank * (stepValue3 + stepValue4) ;

      break;
    case 5:
      Blynk.virtualWrite(V31, param.asFloat() );
      stepValue4 = param.asFloat();
      volumetank4 = areatank * (stepValue3 + stepValue4) ;

      break;

  }
}


//คำนวณปริมาตรน้ำในระดับ High

BLYNK_WRITE(V14) {
  // receive the step value as param.asInt() and then use switch to run different code
  switch (param.asInt()) {
    case 0:
      Blynk.virtualWrite(V32, param.asFloat() );
      stepValue5 = param.asFloat();
      volumetank5 = areatank * (stepValue3 + stepValue4 + stepValue5);


      break;
    case 1:
      Blynk.virtualWrite(V32, param.asFloat() );
      stepValue5 = param.asFloat();
      volumetank5 = areatank * (stepValue3 + stepValue4 + stepValue5);

      break;
    case 2:
      Blynk.virtualWrite(V32, param.asFloat() );
      stepValue5 = param.asFloat();
      volumetank5 = areatank * (stepValue3 + stepValue4 + stepValue5);

      break;
    case 3:
      Blynk.virtualWrite(V32, param.asFloat() );
      stepValue5 = param.asFloat();
      volumetank5 = areatank * (stepValue3 + stepValue4 + stepValue5);

      break;
    case 4:
      Blynk.virtualWrite(V32, param.asFloat() );
      stepValue5 = param.asFloat();
      volumetank5 = areatank * (stepValue3 + stepValue4 + stepValue5);

      break;
    case 5:
      Blynk.virtualWrite(V32, param.asFloat() );
      stepValue5 = param.asFloat();
      volumetank5 = areatank * (stepValue3 + stepValue4 + stepValue5);

      break;

  }
}


//รีเซต หลังการกำหนดขนาด ถังเก็บน้ำ
BLYNK_WRITE(V19)
{
  int pinValue = param.asInt();
  if (pinValue == 1) {
    volumetank = areatank * stepValue2;
    Blynk.virtualWrite(V16, volumetank );
    volumetank3 = areatank * stepValue3 ;
    volumetank4 = areatank * (stepValue3 + stepValue4) ;
    volumetank5 = areatank * (stepValue3 + stepValue4 + stepValue5);
  }


  if (pinValue == 0) {

  }
}




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

void setup() {



  //****************************************************************************************************

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

  // ให้ LED ทั้งหมดดับก่อน
  digitalWrite(D0, LOW);//ให้หลอด LED สีฟ้าดับก่อน

  pinMode(D4, INPUT_PULLUP);
  pinMode(D5, INPUT_PULLUP);
  pinMode(D6, INPUT_PULLUP);

  //***************************************************************************************************

  Serial.begin(115200);

  //*************************    การ อ่าน  เขียนค่า WiFi + Password ]ลงใน Node MCU ESP8266   ************

  //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(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........:)");//แสดงข้อความใน 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.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() {

  int L1 = digitalRead(D4);
  int L2 = digitalRead(D5);
  int L3 = digitalRead(D6);

//ระดับน้ำต่ำ  แจ้งเตือน
  if (L1 == 1 && L2 == 1 && L3 == 1) {
    Blynk.virtualWrite(V15, ((volumetank3 * 100) / volumetank5) / 2 );
    Blynk.virtualWrite(V24, "ระดับน้ำต่ำ!" );
    Blynk.virtualWrite(V23, "<", volumetank3 );
    led_L1.off();
    led_L2.off();
    led_L3.off();

  }

//ระดับน้ำต่ำ LOW
  if (L1 == 0 && L2 == 1 && L3 == 1) {
    Blynk.virtualWrite(V15, ((volumetank3 * 100) / volumetank5) );
    Blynk.virtualWrite(V24, " " );
    Blynk.virtualWrite(V23, volumetank3 );
    led_L1.on();
    led_L2.off();
    led_L3.off();

  }


//ระดับน้ำปานกลาง  Medium
  if (L1 == 0 && L2 == 0 && L3 == 1) {
    Blynk.virtualWrite(V15, ((volumetank4 * 100) / volumetank5) );
    Blynk.virtualWrite(V24, " " );
    Blynk.virtualWrite(V23, volumetank4 );
    led_L1.on();
    led_L2.on();
    led_L3.off();

  }




//ระดับน้ำสูง  HIGH
  if (L1 == 0 && L2 == 0 && L3 == 0) {
    Blynk.virtualWrite(V15, ((volumetank5 * 100) / volumetank5) );
    Blynk.virtualWrite(V24, " " );
    Blynk.virtualWrite(V23, volumetank5 );
    led_L1.on();
    led_L2.on();
    led_L3.on();

  }


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

  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(100);
    digitalWrite(D0, HIGH);
    delay(50);

  }
  //--------------------------------------------------------------------------------------------------------



  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
}

ในส่วนของการทำงานผมจะทำเป็นคลิปให้ชมครับ

2 Likes

อยากรู้ว่า การใช้ water Level sensor กับ ultrasonic Sensor ในโจทย์การวัดระดับความลึกของน้ำ อย่างไหนเหมาะสมมากกว่ากันครับ

รู้สึกว่าเจ้า water level sensor จะใช้ได้กับถังหรือวัสดุที่โปร่งใส่ เพื่อการตรวจจับความแตกต่างระหว่างสี ของน้ำ ผมไม่แน่ใจว่าถ้าน้ำใส่ๆ นี้เมื่อถึงจุดจับ มันจะสามารถจับได้ไหมว่าน้ำมาแล้วนะ

ถ้าจะเอาไปใช้ในงานอุสาหกรรมทั่วไป หากถังเป็นวัสดุทึบแสงแต่ต้องการเอาไปใช้จริงๆ ก็อาจจะต้องออกแบบถังมาให้ติดเซ็นเซอได้ด้วย เช่นตรงจุดที่จะวัดต้องใส่ หรือโปร่งแสง เพื่อติดเซ็นเซอร์ก็เป็นได้ หรือถังน้ำโปร่งแสง ก็อาจจะใช้ได้

ส่วน ultrasonic อาจจะได้เปรียบตรงการติดตั้ง กับวัสดุถังทึบแสงอะไรก็ได้ เพราะใช้สัญญาณวัดระยะ น้ำที่ใกล้เข้ามา แต่ ถ้าเอามาติดในถังน้ำแล้วต้องติดไว้อย่างนั้น 24 ชั่วโมง ผมก็ไม่แน่ใจว่า ตัวเซนเซอร์จะทนต่อไอน้ำในถังนั้นได้หรือป่าว อาจจะพังหรือรวนก่อนถึงอายุการใช้งานจริงๆ ก็ได้ หรือใช้ได้อาจจะต้องเปลี่ยนบ่อย ซะอย่างนั้น ซึ่งข้อนี้ผมว่า water Level sensor ได้เปรียบ

ในส่วนของการเลือกใช้ อุปกรณ์ ผมยังหาข้อมูลอยู่ครับ สมัยก่อน(ไม่แน่ใจสมัยนี้ยังใช้อยู่หรือปล่าว)ประมาณสัก 15-20 ปี ที่แล้ว การเชคระดับน้ำ หรือสารเคมีในถัง ในโรงงานอุตสาหกรรมที่มีระบบน้ำ (ผมเจอจากโรงงานญี่ปุ่นหลายๆ ที่) เค้านิยมต่อ ต่อท่อใส (อาจเป็นแบบแก้วหรือ พลาสติกแบบใสแล้วแต่ชนิดและคุณลักษณะที่จะนำไปใช้) โดยการต่อเข้ากับถัง เพื่อวัดระดับน้ำครับโดยการเช็กระดับน้ำจะมีฝ่ายซ่อมบำรุงมาจดข้อมูลของระดับน้ำในแต่ละวันแล้วเอาไปทำกราฟวิเคราะห์ข้อมูลต่อ
ในปัจจุบันเทคโนโลยีก้าวหน้ามากขึ้นการตรวจสอบระดับน้ำก็น่าจะมีอุปกรณ์ที่ทันสมัยสามารถตรวจเช็คระดับน้ำแบบ Real Time ได้ โดยการเข้าถึงข้อมูลไม่จำเป็นต้องอยู่ในห้องควบคุมเพียงอย่างเดียวผู้ที่เกี่ยวข้องกับระบบสามารถดูจากที่ไหนก็ได้
ในส่วนของการใช้ Ultra Sonic ผมก็กำลังคิดอยู่เหมือนกันเพราะมันน่าที่จะบอกปริมาตรของน้ำในถังได้ค่อนข้างละเอียดครับ ก็คงต้องดูลักษณะของงานที่ใช้ และปัจจัย ด้านอื่นๆ ด้วยครับ

2 Likes

แบบเดิมที่ตั้งใจว่าจะทำ แต่กำลังศศึกษาข้อมูลอยู่

แบบที่ใช้ในโรงงาน เป็นถังแบบ Indoor หรือกึ่ง Indoor ครับ


Search ข้อมูล แล้วเจอมา
ขอบคุณ ที่มา https://pantip.com/topic/37004854

อันนี้เค้า Modofy มาแล้วครับ

2 Likes

การสร้าง app blynk ต้องทำยังไงบ้างครับ ผมไม่เคยสร้างครับ

ศึกษาวิธีการสร้าง และการใช้งาน App Blynk ได้ตาม Web site ต่างๆ มีเยอะครับ แต่เราต้องมีเป้าหมายก่อนว่าเราจะเอาไปใช้ในงานอะไร เพื่อจำกัดขอบเขตในการค้นหามูลครับ

เริ่มจากอ่านกระทู้นี้ครับ

เยี่ยมเลยครับ เห็นงี้แล้วมองภาพออกเลย ผมเดินไปดู ตามถังทีมีขายไม่ค่อยเห็นมีขีดใสบอกระดับน้ำสักเท่าไหร่แต่ในงานจริง ที่เกษตรกรใช้ก็เคยเห็นมาบ้างแต่ถังไม่ใหญ่มาก

แบบนี้ใช้กับ OUTDOOR ไม่ได้นะครับ เพราะจะเกิดตะไคร่น้ำ เนื่องจากโดนแสงแดด

อ่อ จริงๆ มันก็มีหลายปัจจัยที่ต้องคำนึงถึง การล้างทำความสะอาดก็สำคัญเช่นกัน 555

1 Likes

แต่ดูจากทรงแล้วแค่แพรนถอดเปลี่ยนเลยน่าจะสะดวกกว่ารึป่าวครับ สมมติเอาไปใช้งานก็ต้องไว้นอกบ้าน หาที่บังแดดปิดตรงสายยางสักหน่อย ถ้าตระไคร่ขึ้นก็ถอดเปลี่ยนไปเลย สะดวกและเร็วกว่าถอดล้าง

หรือไม่ก็ใช้วิธี เซาะท่อ สวมท่อระดับน้ำ หมุนเพื่อหลบแดด

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

แต่ถ้าคิดในแง่ธุรกิจคงลำบากสักนิด เพราะอาจต้องแย่ง line ผลิตออกไปอีกหนึ่งส่วนเพื่อ ทำแทบโปร่งแสงเพื่อดูระดับน้ำได้ จากที่แค่ขึ้นรูปด้วยเครื่อง เดียวจบ ก็อาจเป็นการเพื่อ คอส ทำให้ราคาทีบขึ้นไปสูงเกิน

เอะ อย่างงี้ก็ได้หรอ 555 จริงครับ ง่ายดี เอาจริงๆ ดูกันไม่กี่ครั้งหลอก อยากดูเมื่อไหร่ก็หมุนเอา :rofl:

ส่วนใหญ่จะทำเป็นถังไฟเบอร์กลาส์หล่อเป็นหน้าแปลนสำเร็จตามสั่งครับ ส่วนขีดบอกระดับก็ พ่นสีเป็นขีดบอกระดับเอา ทีหลัง ส่วนภาพที่เขียนมานั้น ก็ป้องกันให้เกิดตะไคร่น้ำช้าลงครับ

ภาพรวมน่าจะออกแนวๆ นี้ครับ แค่เขียนคร่าวๆ นะครับ

1 Likes

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

1 Likes

น่าสนใจมากครับ​ ส่วนใหญ่เป็นงาน outdoor​ ถังตั้งกลางแดดเลย​ นี่ถ้า​ ปักเสาทำหลังคาสักนิด​ น่าจะทำให้​ อุณหภูมิของน้ำลดลงได้เยอะ​ ท่อโดนแดด​แรงๆ​อาจทำให้เสื่อมสภาพเร็ว​เกิดการเสียรูปได้ครับ​ แก้ไขโดยการทาสีที่ท่อ​ ส่วนถังมีฝาปิดไม่โดนแดดก็ไม่เกิดตะไคร่นำ้อยู่แล้ว


ใช้ตัวนี้ได้มั้ยครับ รู้ทุกระดับ

1 Likes