สวัสดีครับ สำหรับบทความนี้ผมจะทำการทดสอบเซนเซอร์วัดความเข้มแสงด้วย ESP 8266 + อ่านค่าจาก Blynk
สำหรับตัวเซ็นเซอร์จะใช้รุ่นนี้ครับ MCU-3001 OPT3001 Ambient Light lux meter Sensor
สเปคตามนี้ครับ
-
มีวงจรกรองแสงที่แม่นยำ
-
ตั้งค่าอัตโนมัติเต็มรูปแบบ
-
วัดความเข้มแสงได้ช่วงกว้างตั้งแต่ 0.01 lux ถึง 83,000 lux
-
ใช้ไฟเลี้ยง 3.3V กระแสไฟใช้งานต่ำเพียง 1.8 μA
อาจจะมีหลายท่านสงสัยว่าจะเอาเซ็นเซอร์ตัวนี้ไปทำอะไร ก็จะบอกว่าแล้วแต่ไอเดียลักษณะงานที่จะใช้ โดยโครงงานต่างๆที่ผมทำขึ้นมา ส่วนใหญ่จะเริ่มต้นใช้ภายในบ้าน แล้วค่อยขยายออกไปข้างนอก โดยเซ็นเซอร์ตัวนี้ผมมีจุดประสงค์ก็คือผมอยากจะเช็คสภาพแวดล้อมที่บ้าน โดย Monitor ผ่านสมาร์ทโฟนก็คือ App blynk นั่นเอง ก็คือผมอยากจะรู้ว่าที่บ้านแสงแดดเป็นยังไงบ้าง แสงแดดจ้า แดดร่มหรือครึ้ม หรือเข้าสู่ตอนกลางคืนแล้ว จะบอกว่าผมจะไม่ใช้เซ็นเซอร์ตัวนี้ตัวเดียว แต่จะมีเซ็นเซอร์อีก 2 ตัวเข้ามาเกี่ยวข้องก็คือ เซ็นเซอร์วัดอุณหภูมิและความชื้น และเซ็นเซอร์บอกระดับความแรงของฝนตก ซึ่งตรงนี้ก็กำลังศึกษาอยู่ว่าควรจะใช้เซ็นเซอร์ตัวไหนที่จะเหมาะกับที่บ้าน และมีไอเดียว่าเมื่อเราสามารถเช็คสภาพอากาศจากเซ็นเซอร์ทั้ง 3 ตัวได้ เราก็สามารถที่จะประเมินได้ว่า ขณะนี้สภาพอากาศที่บ้านเป็นอย่างไร เช่นฝนตกแต่แดดออก หรือฝนตกฟ้ามืด หรืออื่นๆ ซึ่ง Project ที่นำมาเสนอ ผมอยากจะเก็บข้อมูลเอาไว้ในเว็บไซต์นี้ ส่วนหนึ่งและอีกส่วนหนึ่ง ถ้าผู้ที่เข้ามาอ่านในกระทู้นี้แล้วเกิดมีไอเดียที่แตกยอดออกไปก็ถือว่าโครงการที่ผมทำ มีประโยชน์ต่อบุคคลที่สนใจครับ ส่วนใครมีไอเดียอะไร ก็ โพสท์ แนะนำมาได้เลยครับ
ลองชมคลิปดูครับ สั้นๆ
Code เบื้องต้น รอพัฒนาต่อ
#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 ..มาใช้งาน
#include <Wire.h>
#include <ClosedCube_OPT3001.h>
ClosedCube_OPT3001 opt3001;
#define OPT3001_ADDRESS 0x44
//------------------------------------------------------------------------------------------------
#define BLYNK_DEBUG
#define BLYNK_PRINT Serial // Comment this out to disable prints and save space
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------------
int blynkIsDownCount = 0; //Integer Variable ตัวแปรชื่อ blynkIsDownCount ใช้เก็บเลขจำนวนเต็ม โดยเริ่มต้นให้มีค่า = 0
char blynk_token[34] = "YkNarC2Yub7M2OcPbPnnn7UVBIeFMqgD";
//Character Variable ตัวแปรที่ใช้เก็บอักขระ
bool shouldSaveConfig = false;
BlynkTimer timer; //เรียกใช้การตั้งเวลาของ Blynk
//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;
//***************************************************************
//*****************************************************************************************************
//******************************* void setup *********************************************
//*****************************************************************************************************
void setup() {
//****************************************************************************************************
pinMode(D0, OUTPUT);//กำหนดโหมดใช้งานให้กับขา D0 เป็นขา สัญญาณไฟ ในสภาวะต่างๆ
pinMode(D3, INPUT_PULLUP);//กำหนดโหมดใช้งานให้กับขา D3 เป็นขา กดปุ่ม ค้าง เพื่อตั้งค่า AP config
// ให้ LED ทั้งหมดดับก่อน
digitalWrite(D0, LOW);//ให้หลอด LED สีฟ้าดับก่อน
//***************************************************************************************************
Serial.begin(115200);
opt3001.begin(OPT3001_ADDRESS);
//************************* การ อ่าน เขียนค่า 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 วินาที)
configureSensor();
printResult("High-Limit", opt3001.readHighLimit());
printResult("Low-Limit", opt3001.readLowLimit());
}
//*****************************************************************************************************
//******************************* จบ void setup *********************************************
//*****************************************************************************************************
//*****************************************************************************************************
//******************************* void loop *************************************************
void loop() {
OPT3001 result = opt3001.readResult();
printResult("OPT3001", result);
delay(3000);
//--------------------------------------------------------------------------------------------------------
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(200);
digitalWrite(D0, HIGH);
delay(100);
}
//--------------------------------------------------------------------------------------------------------
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
}
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();
// Serial.println("OPT3001 Current Config:");
// Serial.println("------------------------------");
//
// Serial.print("Conversion ready (R):");
// Serial.println(sensorConfig.ConversionReady, HEX);
//
// Serial.print("Conversion time (R/W):");
// Serial.println(sensorConfig.ConvertionTime, HEX);
//
// Serial.print("Fault count field (R/W):");
// Serial.println(sensorConfig.FaultCount, HEX);
//
// Serial.print("Flag high field (R-only):");
// Serial.println(sensorConfig.FlagHigh, HEX);
//
// Serial.print("Flag low field (R-only):");
// Serial.println(sensorConfig.FlagLow, HEX);
//
// Serial.print("Latch field (R/W):");
// Serial.println(sensorConfig.Latch, HEX);
//
// Serial.print("Mask exponent field (R/W):");
// Serial.println(sensorConfig.MaskExponent, HEX);
//
// Serial.print("Mode of conversion operation (R/W):");
// Serial.println(sensorConfig.ModeOfConversionOperation, HEX);
//
// Serial.print("Polarity field (R/W):");
// Serial.println(sensorConfig.Polarity, HEX);
//
// Serial.print("Overflow flag (R-only):");
// Serial.println(sensorConfig.OverflowFlag, HEX);
//
// Serial.print("Range number (R/W):");
// Serial.println(sensorConfig.RangeNumber, HEX);
//
// Serial.println("------------------------------");
}
}
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);
//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 <= 2000) {
Blynk.virtualWrite(V40, "\xE2\x98\x81");
}
if (result.lux > 2000 and result.lux <= 20000 ) {
Blynk.virtualWrite(V40, "\xE2\x9B\x85");
}
if (result.lux > 20000 and result.lux <= 80000 ) {
Blynk.virtualWrite(V40, "\xE2\x98\x80");
}
}
void printError(String text, OPT3001_ErrorCode error) {
Serial.print(text);
Serial.print(": [ERROR] Code #");
Serial.println(error);
Blynk.virtualWrite(V0, error);
}