สำหรับความน่าเชื่อถือ ในการนำไปใช้งานของ Project ตัวนี้อยู่ที่ 15 วันนะครับ คือเรื่องของตัว code ในการควบคุมก็ไม่ได้มีปัญหาแต่อย่างใด แต่จะมีปัญหาในเรื่องของตำแหน่งการติดตั้ง ,ลักษณะการติดตั้งภายในของตัวเซ็นเซอร์ต่างๆ ,การเดินสาย ,เรื่องของการระบายอากาศ ซึ่งจะต้องระบายทั้งความชื้นและอุณหภูมิ เพื่อให้ผลลัพธ์ออกมาได้ใกล้เคียง สำหรับใครที่ต้องการจะนำตัวอย่างไปลองทำดูก็ต้องปรับเปลี่ยนไปตามสภาพของสถานที่ที่เราจะไปติดตั้งด้วยนะครับ ขอให้มีความสุขกับการทำงานทุกคนครับ
CODE อาจจะดูไม่เรียบร้อยเท่าไหร่ ต้องขออภัยด้วยครับ
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
#include <FS.h>
#include <DNSServer.h>
#include <ArduinoJson.h>
#include <BlynkSimpleEsp8266.h>
#include <Wire.h>
#include <ClosedCube_OPT3001.h>
ClosedCube_OPT3001 opt3001;
#define OPT3001_ADDRESS 0x44
#include <DHT.h>
#define DHTTYPE DHT21
#define DHTPIN D6
DHT dht(DHTPIN, DHTTYPE);
#include <Scheduler.h>
//------------------------------------------------------------------------------------------------
#define BLYNK_DEBUG
#define BLYNK_PRINT Serial // Comment this out to disable prints and save space
WidgetLED led_1(V52); //แสดงสถานะ ติด 3 วินาที แล้วดับ ใช้ในการแสดง เมื่อกดปุ่มจาก App Blynk เพื่อมา Reset Node MCU ESP8266
WidgetLED led_2(V42); //แสดงสถานะพัดลม on/off
WidgetLED led_3(V43); //แสดงสถานะพัดลม on/off
#define D0 16 // ใช้ไฟ LED สีฟ้า ของบอร์ด MCU ESP8266 ให้มีสัญญาณไฟกระพริบ ตาม Code ที่เขียน
#define D3 0 // ใช้เป็นปุ่มกด เพื่อเข้า AP Config ได้ตามความต้องการของผู้ใช้
#define D8 15 //พัดลมทำงาน เมื่อเกิดความชื้นเกิน 95%
#define D7 13 //เชคสัญญาณจาก Microphone Soensor
//#define D5 14
//const int capteur_D = D5;
float h ;
float t ;
//--Humid Fan
int v4;
int v5;
//--Temp Fan
int v6;
int v7;
int tempMenu = 0;
int humidMenu = 0;
//------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------------
int blynkIsDownCount = 0;
char blynk_token[34] = "YkNarC2Yub7M2OnncPbP-tk7UVBIeFMqgD";
bool shouldSaveConfig = false;
//-------------------------------------------------------------------------------------------------------------------------------------------
BlynkTimer timer;
//-------------------------------------------------------------------------------------------------------------------------------------------
//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;
//***************************************************************
//------------------------ ตั้งค่าการรีเซ็ตบอร์ดแบบอัตโนมัติ โดยกำหนดค่าเป็นวินาที นาที ชั่วโมง 24 ชั่วโมง วันได้ ---------------------//
const long oneSecond = 1000; // 1000 มิลลิวินาที = 1 วินาทีเท่ากับ
const long oneMinute = oneSecond * 60; // 1 นาที = 1 วินาที x 60 วินาที
const long oneHour = oneMinute * 60; // 1 ชั่วโมง = 1 นาที x 60 นาที
const long oneDay = oneHour * 24; // 1 วัน = 1 ชั่วโมง x 24 ชั่วโมง
const long twoDay = oneDay * 2; // 2 วัน = 1 วัน x 2 วัน
const long threeDay = oneDay * 3; // 3 วัน = 1 วัน x 3 วัน
const long fourDay = oneDay * 4; // 4 วัน = 1 วัน x 4 วัน
const long fiveDay = oneDay * 5; // 5 วัน = 1 วัน x 5 วัน
const long sixDay = oneDay * 6; // 6 วัน = 1 วัน x 6 วัน
const long sevenDay = oneDay * 7; // 7 วัน = 1 วัน x 7 วัน
//------------------------------------------------------------------------------------------------------------------------//
int timereset;
int BlynkresetMCU;
//------------------------------------------------------------------------------------------------------------------------//
BLYNK_WRITE(V50)// ตั้งเวลา Reset board mcu esp8266 ตามการป้อนค่าตัวเลข
{
timereset = param.asInt();
//Serial.println(timereset);
}
//------------------------------------------------------------------------------------------------------------------------//
BLYNK_WRITE(V51)//Reset board mcu esp8266 ภายใน 5 วินาที
{
int pinValue = param.asInt();
if (pinValue == 1) {
BlynkresetMCU = 1;
}
if (pinValue == 0) {
}
}
//------------------------------------------------------------------------------------------------------------------------//
BLYNK_WRITE(V6)// ตั้งค่า ความชื้น ให้พัดลมทำงาน
{
v6 = param.asInt();
}
//------------------------------------------------------------------------------------------------------------------------//
BLYNK_WRITE(V7)// ตั้งค่า อุณหภูมิ ให้พัดลมทำงาน
{
v7 = param.asInt();
}
//------------------------------------------------------------------------------------------------------------------------//
BLYNK_WRITE(V4)// ตั้งค่า ความชื้น ให้พัดลมทำงาน
{
v4 = param.asInt();
}
//------------------------------------------------------------------------------------------------------------------------//
BLYNK_WRITE(V5)// ตั้งค่า อุณหภูมิ ให้พัดลมทำงาน
{
v5 = param.asInt();
}
//------------------------------------------------------------------------------------------------------------------------//
//Timer selection temp control option
BLYNK_WRITE(V2)
{
int pinValue = param.asInt();
if (pinValue == 1) {
Blynk.virtualWrite(V8, 1); //temp menu
tempMenu = 1;
humidMenu = 0;
led_2.off();
}
if (pinValue == 0) {
Blynk.virtualWrite(V8, 0);//humidmenu
tempMenu = 0;
humidMenu = 1;
led_3.off();
}
}
//------------------------------------------------------------------------------------------------------------------------//
//ปุ่มเลือกเมนู
BLYNK_WRITE(V8) {
int pinValue = param.asInt();
if (pinValue == 1) {//ถ้าเลือก Temp Menu LED Humid จะต้อง Off
tempMenu = 1;
humidMenu = 0;
led_2.off();//LED Humid Off
}
if (pinValue == 0) {//ถ้าเลือก Humid Menu LED Temp จะต้อง Off
tempMenu = 0;
humidMenu = 1;
led_3.off();//LED Temp Off
}
}
//------------------------------------------------------------------------------------------------------------------------//
class Task_1 : public Task {
protected:
void setup() { }
void loop() {
int sensorValue = analogRead(A0);
//Blynk.virtualWrite(V1, sensorValue);
if (sensorValue >= 0 && sensorValue <= 512 )
{
Blynk.virtualWrite(V1, "\xF0\x9F\x8C\x82");
Blynk.virtualWrite(V3, 0);
//Blynk.virtualWrite(V1, "ฝนไม่ตก");
delay(10);
}
else
{
Blynk.virtualWrite(V1, "\xE2\x98\x94");
//Blynk.virtualWrite(V1, "ฝนตก");
Blynk.virtualWrite(V3, 5);
delay(10);
}
delay(1000);
}
} Task_1_task;
class Task_2 : public Task {
protected:
void setup() {
configureSensor();
printResult("High-Limit", opt3001.readHighLimit());
printResult("Low-Limit", opt3001.readLowLimit());
}
void loop() {
OPT3001 result = opt3001.readResult();
printResult("OPT3001", result);
delay(500);//เดิม
delay(1000);//ใหม่
}
void configureSensor() {
OPT3001_Config newConfig;
newConfig.RangeNumber = B1100;
newConfig.ConvertionTime = B0;
newConfig.Latch = B1;
newConfig.ModeOfConversionOperation = B11;
OPT3001_ErrorCode errorConfig = opt3001.writeConfig(newConfig);
if (errorConfig != NO_ERROR)
printError("OPT3001 configuration", errorConfig);
else {
OPT3001_Config sensorConfig = opt3001.readConfig();
}
}
void printResult(String text, OPT3001 result) {
if (result.error == NO_ERROR) {
// Serial.print(text);
// Serial.print(": ");
// Serial.print(result.lux);
// Serial.println(" lux");
Blynk.virtualWrite(V0, result.lux);
//Blynk.virtualWrite(V41, (((result.lux * 100) / 83865.60)));
//int LightValue = result.lux;
int light = map(result.lux, 0.01, 27000, 0, 100); //ค่าตั้งเอาเองนะครับ แดดแต่ละที่ไม่เหมอนกัน
//int light = map(result.lux,0.01, 83865.60, 0, 100);
Blynk.virtualWrite(V41, light);
//https://apps.timwhitlock.info/emoji/tables/unicode
//"\xE2\x9B\x85"Sun behind
//"\xE2\x98\x80" :black sun with rays
//"\xE2\x98\x81" cloud
//"\xF0\x9F\x8C\x9C" last quarter moon with face
}
else {
printError(text, result.error);
}
//ตั้งค่าระดับแสงเองได้ครับ แสงแต่ละที่ไม่เหมือนกัน ของผม ผมใช้การสังเกตุจากการอ่านค่าแสงที่กำหนดในครั้งแรกก่อน จากนั้นจึงปรับตามจริงครับ
if (result.lux < 50 ) {
Blynk.virtualWrite(V40, "\xF0\x9F\x8C\x9C");//ดวงจันทร์
}
//if (result.lux > 50 and result.lux <= 1000) {
if (result.lux > 50 and result.lux <= 3500) {
Blynk.virtualWrite(V40, "\xE2\x98\x81");//มีเมฆ
}
//if (result.lux > 1000 and result.lux <= 10000 ) {
if (result.lux > 3500 and result.lux <= 9000 ) {
Blynk.virtualWrite(V40, "\xE2\x9B\x85");//ดวงอาทิตย์ซ่อนหลังเมฆ
}
if (result.lux > 9000 and result.lux <= 13000 ) {
Blynk.virtualWrite(V40, "\xE2\x98\x80");//ดวงอาทิตย์ส่องเต็ม
}
if (result.lux > 13000 and result.lux <= 27000 ) {
Blynk.virtualWrite(V40, "\xE2\x98\x80", " \xF0\x9F\x98\xAC");//ดวงอาทิตย์ส่องเต็มเริ่มร้อนมาก
}
if (result.lux > 27000 ) {
Blynk.virtualWrite(V40, "\xE2\x98\x80", " \xF0\x9F\x98\xB1");//ดวงอาทิตย์ส่องเต็มร้อนมาก
}
}
void printError(String text, OPT3001_ErrorCode error) {
// Serial.print(text);
// Serial.print(": [ERROR] Code #");
// Serial.println(error);
Blynk.virtualWrite(V0, error);
}
private:
uint8_t state;
} Task_2_task;
class Task_3 : public Task {
public:
void setup() {
}
void loop() {
//--------------------------------------------------------------------------------------------------------
if (Blynk.connected())
{
Blynk.run();
digitalWrite(D0, HIGH);
//-----// ถ้าเชื่อมต่ Blynk Server ไม่ได้-----ไฟ LED สีน้ำเงินบนบอร์ด จะกระพริบ---------------------------------
//----//หลอด LED สีแดงติดกระพริบแสดงว่ากำลังค้นหา WiFi ----------------------------------------------------
} else {
digitalWrite(D0, LOW);
delay(200);
digitalWrite(D0, HIGH);
delay(100);
}
//--------------------------------------------------------------------------------------------------------
timer.run();//ให้เวลาของ Blynk ทำงาน
delay(100);
//---------Reset Board Node MCU ESP 8266------------//
if (BlynkresetMCU == 1) {
led_1.on();
delay(3000);
led_1.off();
delay(1500);
ESP.restart();
}
//-------------------------------------------------//
}
} Task_3_task;
class Task_4 : public Task {
protected:
void setup() { }
void loop() {
//ถ้ามีค่าเป็น 0 แล้ว reset 1 ครั้ง จะไม่มีการ Reset อีกต่อไป
if (timereset == 1) {
Blynk.virtualWrite(V53, "1 Day Reset" );
//delay(oneMinute1);
delay(oneDay);
ESP.restart();
//digitalWrite(D7, LOW);//ให้ D7 เป็น 1 ตอนทำงาน LOW = 0
}
if (timereset == 2) {
Blynk.virtualWrite(V53, "2 Days Reset" );
//delay(oneMinute2);
delay(twoDay );
ESP.restart();
//digitalWrite(D7, LOW);//ให้ D7 เป็น 1 ตอนทำงาน LOW = 0
}
if (timereset == 3) {
Blynk.virtualWrite(V53, "3 Days Reset" );
//delay(oneMinute3);
delay(threeDay);
ESP.restart();
//digitalWrite(D7, LOW);//ให้ D7 เป็น 1 ตอนทำงาน LOW = 0
}
if (timereset == 4) {
Blynk.virtualWrite(V53, "4 ays. Reset" );
delay(fourDay);
ESP.restart();
//digitalWrite(D7, LOW);//ให้ D7 เป็น 1 ตอนทำงาน LOW = 0
}
if (timereset == 5) {
Blynk.virtualWrite(V53, "5 Days Reset" );
delay(fiveDay);
ESP.restart();
//digitalWrite(D7, LOW);//ให้ D7 เป็น 1 ตอนทำงาน LOW = 0
}
if (timereset == 6) {
Blynk.virtualWrite(V53, "6 Days Reset" );
delay(sixDay);
ESP.restart();
//digitalWrite(D7, LOW);//ให้ D7 เป็น 1 ตอนทำงาน LOW = 0
}
if (timereset == 7) {
Blynk.virtualWrite(V53, "7 Days Reset" );
delay(sevenDay);
ESP.restart();
//digitalWrite(D7, LOW);//ให้ D7 เป็น 1 ตอนทำงาน LOW = 0
}
}
} Task_4_task;
class Task_5 : public Task {
protected:
void setup() { }
void loop() {
h = dht.readHumidity();
t = dht.readTemperature();
if (isnan(h) || isnan(t)) {
//Serial.println("Failed to read from DHT sensor!");
return;
}
// Serial.print("Humidity is: ");
// Serial.println(h);
//
Serial.print("Temperature is: ");
Serial.println(t);
Blynk.virtualWrite(V18, h);
Blynk.virtualWrite(V17, t);
if (tempMenu == 1) {
if ( t > v6 && t <= v7 ) {
Blynk.virtualWrite(V17, t);
//Blynk.virtualWrite(V10, 1);
digitalWrite(D8, HIGH);
led_3.on();
}
else
{
Blynk.virtualWrite(V17, t);
//Blynk.virtualWrite(V10, 0);
digitalWrite(D8, LOW);
led_3.off();
}
}
if (humidMenu == 1) {
if ( h > v4 && h <= v5 ) {
Blynk.virtualWrite(V18, h);
//Blynk.virtualWrite(V10, 1);
digitalWrite(D8, HIGH);
led_2.on();
}
else
{
Blynk.virtualWrite(V18, h);
//Blynk.virtualWrite(V10, 0);
digitalWrite(D8, LOW);
led_2.off();
}
}
delay(2000);
}
} Task_5_task;
//*****************************************************************************************************
//******************************* void setup *********************************************
//*****************************************************************************************************
void setup() {
//****************************************************************************************************
pinMode(D0, OUTPUT);//กำหนดโหมดใช้งานให้กับขา D0 เป็นขา สัญญาณไฟ ในสภาวะต่างๆ
pinMode(D3, INPUT_PULLUP);//กำหนดโหมดใช้งานให้กับขา D3 เป็นขา กดปุ่ม ค้าง เพื่อตั้งค่า AP config
pinMode(D8, OUTPUT);
pinMode(D7, INPUT);
//pinMode(capteur_D, INPUT);
// ให้ LED ทั้งหมดดับก่อน
digitalWrite(D0, LOW); //ให้หลอด LED สีฟ้าดับก่อน
digitalWrite(D8, LOW); //ให้พัดลมไม่ทำงานก่อน
//***************************************************************************************************
Serial.begin(115200);
opt3001.begin(OPT3001_ADDRESS);
dht.begin();
// timer.setInterval(1500L, Sensor);
//************************* การ อ่าน เขียนค่า 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
Scheduler.start(&Task_1_task);
Scheduler.start(&Task_2_task);
Scheduler.start(&Task_3_task);
Scheduler.start(&Task_4_task);
Scheduler.start(&Task_5_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
//Serial.println(".");//per debug //แสดงข้อความใน Serial Monitor
}
ก็ต้องรอดูความเสถียร ของระบบกันต่อครับ ว่าจะไปต่อได้หรือไม่ งานนี้ผมว่าค่อนข้างเอาเรื่องอยู่ เพราะอากาศทางภาคใต่้ มันค่อนข้างแปรปรวน