สำหรับในหัวข้อนี้ผมจะลองมาใช้งาน ESP32 NodeMCU Wi-Fi and Bluetooth กันบ้างดีกว่าหลังจากที่นำ WiFi Manager มาร่วมใช้งานได้แล้วต่อไปก็จะนำตัวเซ็นเซอร์ที่เป็นอุณหภูมิและความชื้นที่ใช้การสื่อสารแบบ i2c นำมาร่วมใช้งานด้วยกัน พร้อมกันนั้นจะมีการตั้งค่าการควบคุมใน Application blynk พร้อมส่งข้อความไปที่ Line notify โดยถ้าอุปกรณ์ทำงาน เข้าเงื่อนไขของ Temp หรือ Humid Line ส่งข้อความจะส่งแยกกัน แต่ถ้าเข้าเงื่อนไขทั้งคู่พร้อมกัน Line จะส่งข้อความมา 2 ครั้ง โดยแบ่งงานกันทำแบบ Multicore ชุด WiFi Managerและชุดหลัก จะทำงานบน Core1 ส่วน เซ็นเซอร์ที่เป็นอุณหภูมิและความชื้นจะทำงานบน Core0 ครับ
ความต้องการของ Project
ARDUINO IDE 1.8.7
Board Manager ESP32 Version 1.0.3
Library
- Arduino json Version 5.13.5
- Blynk Version 0.6.1
- WIFIMANAGER-ESP32-master
-GitHub - zhouhan0126/WIFIMANAGER-ESP32: wifimanager-esp32
- arduino-SHTC3
- https://www.arduinoall.net/arduino-tutor/code/arduino-SHTC3.rar
- TridentTD_LineNotify
Diagram การต่อสาย
Code ok (UP Date 23_01_2563 : 23:50)
//อ้างจาก https://randomnerdtutorials.com/esp32-dual-core-arduino-ide/
#include <FS.h> //this needs to be first, or it all crashes and burns...
#include <SPIFFS.h>//เพิ่ม
#include <WiFi.h> //https://github.com/esp8266/Arduino
#include <WiFiClient.h>
//needed for library
#include <DNSServer.h>
#include <WebServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
#include <ArduinoJson.h> //Ver 5.13.4 //https://github.com/bblanchon/ArduinoJson
//------------------------------------------------------------------------------------------------------------------------//
#include <BlynkSimpleEsp32.h> // Blynk_Release_v0.6.1
//------------------------------------------------------------------------------------------------------------------------//
#include <TridentTD_LineNotify.h>
#define LINE_TOKEN "QerWyEZdBShylI3iTTxKz1Pk8Zo1vLy2NQa7AXFgYLM"
//------------------------------ การกำหนดค่าในส่วนของ Blynk ------------------------------------------------//
#define BLYNK_DEBUG
#define BLYNK_PRINT Serial
int blynkIsDownCount = 0;
char blynk_token[34] = "lE0j-VJUuIZ3mBZYfpcHqCT36ak29gdU";//ใส่ Blynk_token ของเราที่ Blynk ส่งมาทาง Email ตอน Create Project ใหม่
BlynkTimer timer; //เรียกใช้การตั้งเวลาของ Blynk
//---------------------------------- กำหนดหมายเลขของขาของ Node MCU ESP32 --------------------------------------------//
const int Ledblynk = 2; // ใช้ไฟ LED สีฟ้า ของบอร์ด MCU ESP32 ให้มีสัญญาณไฟกระพริบ ตาม Code ที่เขียน
const int AP_Config = 23; // ใช้เป็นปุ่มกด เพื่อเข้า AP Config ได้ตามความต้องการของผู้ใช้
//------------------------------------------------------------------------------------------------------------------------//
bool shouldSaveConfig = false;
//callback notifying us of the need to save config
void saveConfigCallback () {
Serial.println("Should save config");
shouldSaveConfig = true;
}
//------------------------------------------------------------------------------------------------------------------------//
//-------------สำหรับ Server local ที่แจกให้ เพิ่ม **** แค่ 2 บรรทัดนี้-------------- (ถ้าเป็น Blynk Server ปกติไม่ต้องใส่) ----------//
char server[] = "oasiskit.com";
int port = 8080;
//------------------------------------------------------------------------------------------------------------------------//
TaskHandle_t Task1;
const int led1 = 2;
const int led2 = 4;
float temp; //รับค่าการอ่าน Temp
float humid; //รับค่าการอ่าน Humid
//Temp Sensor
#include <Arduino.h>
#include "SHTC3.h"
SHTC3 s(Wire);
//--Humid control
int v1; // Humid Min
int v2; // Humid Max
//--Temp control
int v3; // Temp Min
int v4; // Temp Max
WidgetLED led_1(V5);
//------------------------------------------------------------------------------------------------------------------------//
BLYNK_WRITE(V1)// Humid Min รับการตั้งค่ามาจาก Widget Vertical Slider ของ Blynk
{
v1 = param.asInt();
}
//------------------------------------------------------------------------------------------------------------------------//
BLYNK_WRITE(V2)// Humid Max รับการตั้งค่ามาจาก Widget Vertical Slider ของ Blynk
{
v2 = param.asInt();
}
//------------------------------------------------------------------------------------------------------------------------//
BLYNK_WRITE(V3)// Temp Min รับการตั้งค่ามาจาก Widget Vertical Slider ของ Blynk
{
v3 = param.asInt();
}
//------------------------------------------------------------------------------------------------------------------------//
BLYNK_WRITE(V4)// Temp Max รับการตั้งค่ามาจาก Widget Vertical Slider ของ Blynk
{
v4 = param.asInt();
}
//------------------------------------------------------------------------------------------------------------------------//
//------------------------------------------------------------------------------------------------------------------------//
//********************************************* void setup **************************************************//
//------------------------------------------------------------------------------------------------------------------------//
void setup() {
//-------IO NODE MCU Esp32-------//
pinMode(Ledblynk, OUTPUT); //กำหนดโหมดใช้งานให้กับขา Ledblynk เป็นขา สัญญาณไฟ ในสภาวะต่างๆ
pinMode(AP_Config, INPUT_PULLUP);//กำหนดโหมดใช้งานให้กับขา AP_Config เป็นขา กดปุ่ม ค้าง เพื่อตั้งค่า AP config
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
// ให้ LED ทั้งหมดดับก่อน
digitalWrite(Ledblynk, LOW);//ให้หลอด LED สีฟ้าดับก่อน
//-------------------------------//
Serial.begin(115200);
//-------------------------------//
Wire.begin();
LINE.setToken(LINE_TOKEN);
//************************* การ อ่าน เขียนค่า WiFi + Password ]ลงใน Node MCU ESP32 ************//
//read configuration from FS json
Serial.println("mounting FS...");//แสดงข้อความใน Serial Monitor
if (SPIFFS.begin(true)) {
Serial.println("mounted file system");
if (SPIFFS.exists("/config.json")) {
//file exists, reading and loading
Serial.println("reading config file");
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");
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
Serial.println(blynk_token);
//************************* จบการ อ่าน เขียนค่า WiFi + Password ]ลงใน Node MCU ESP32 **********//
//************************** 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 > -1; i--) { // นับเวลาถอยหลัง 5 วินาทีก่อนกดปุ่ม AP Config
digitalWrite(Ledblynk, HIGH);
delay(500);
digitalWrite(Ledblynk, LOW);
delay(500);
Serial.print (String(i) + " ");//แสดงข้อความใน Serial Monitor
}
if (digitalRead(AP_Config) == LOW) {
digitalWrite(Ledblynk, HIGH);
Serial.println("Button Pressed");//แสดงข้อความใน Serial Monitor
// wifiManager.resetSettings();//ให้ล้างค่า SSID และ Password ที่เคยบันทึกไว้
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); //load the flash-saved configs
esp_wifi_init(&cfg); //initiate and allocate wifi resources (does not matter if connection fails)
delay(2000); //wait a bit
if (esp_wifi_restore() != ESP_OK)
{
Serial.println("WiFi is not initialized by esp_wifi_init ");
} else {
Serial.println("WiFi Configurations Cleared!");
}
//continue
//delay(1000);
//esp_restart(); //just my reset configs routine...
}
wifiManager.setTimeout(60);
//ใช้ได้ 2 กรณี
//1. เมื่อกดปุ่มเพื่อ Config ค่า AP แล้ว จะขึ้นชื่อ AP ที่เราตั้งขึ้น
// ช่วงนี้ให้เราทำการตั้งค่า SSID+Password หรืออื่นๆทั้งหมด ภายใน 60 วินาที ก่อน AP จะหมดเวลา
// ไม่เช่นนั้น เมื่อครบเวลา 60 วินาที MCU จะ Reset เริ่มต้นใหม่ ให้เราตั้งค่าอีกครั้งภายใน 60 วินาที
//2. ช่วงไฟดับ Modem router + MCU จะดับทั้งคู่ และเมื่อมีไฟมา ทั้งคู่ก็เริ่มทำงานเช่นกัน
// โดยปกติ Modem router จะ Boot ช้ากว่า MCU ทำให้ MCU กลับไปเป็น AP รอให้เราตั้งค่าใหม่
// ดังนั้น AP จะรอเวลาให้เราตั้งค่า 60 วินาที ถ้าไม่มีการตั้งค่าใดๆ เมื่อครบ 60 วินาที MCU จะ Reset อีกครั้ง
// ถ้า Modem router Boot และใช้งานได้ภายใน 60 วินาที และหลังจากที่ MCU Resset และเริ่มทำงานใหม่
// ก็จะสามารถเชื่อมต่อกับ Modem router ที่ Boot และใช้งานได้แล้ว ได้ ระบบจะทำงานปกติ
if (!wifiManager.autoConnect("PUYIOT ทดสอบ ESP32 ")) {
Serial.println("failed to connect and hit timeout");//แสดงข้อความใน Serial Monitor
delay(3000);
//reset and try again, or maybe put it to deep sleep
ESP.restart();//แก้ เดิม ESP.reset(); ใน Esp8266
delay(5000);
}
Serial.println("Connected.......OK!)");//แสดงข้อความใน Serial Monitor
strcpy(blynk_token, custom_blynk_token.getValue());
//save the custom parameters to FS
if (shouldSaveConfig) {
Serial.println("saving config");
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
Serial.println("gateway");
delay(100);
Serial.println(WiFi.gatewayIP());
Serial.println("subnetMask");
delay(100);
Serial.println(WiFi.subnetMask());
Serial.println("SSID");
delay(100);
Serial.println(WiFi.SSID());
Serial.println("Password");
delay(100);
Serial.println(WiFi.psk());
// 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 วินาที
//create a task that will be executed in the Task1code() function, with priority 1 and executed on core 0
xTaskCreatePinnedToCore(
Task1code, /* Task function. */
"Task1", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task ตัวเลขน้อยสำคัญน้อย*/
&Task1, /* Task handle to keep track of created task */
0); /* pin task to core 0 */
delay(500);
}//end void setup
//------------------------------------------------------------------------------------------------------------------------//
//********************************************* จบ void setup **************************************************//
//------------------------------------------------------------------------------------------------------------------------//
//Task1_code
void Task1code( void * pvParameters ) {
Serial.print("Task1 running on core ");
Serial.println(xPortGetCoreID());
int linenotify = 0;
int linenotify1 = 0;
int Temp;
int Humid;
// Serial.println("viod setup");
// Serial.println(linenotify);
for (;;) {
s.begin(true);
s.sample();
temp = s.readTempC();
humid = s.readHumidity();
Blynk.virtualWrite(V7, s.readTempC());
Blynk.virtualWrite(V8, s.readHumidity());
delay(1500);
//แยกว่า อุปกรณ์ทำงาน โดยเข้าเงื่อนไขของ Temp หรือ Humid ถ้าเข้าเงื่อนไขทั้งคู่ ก็ Line ส่งข้อความ 2 ครั้ง
if ( (temp > v3 && temp < v4) ) {
Temp = 1;
}
else {
Temp = 0;
}
delay(50);
if ((linenotify == 0) && (Temp == 1) ) {
// led_1.on();
String LineText;
String string1 = "อุปกรณ์ทำงาน ตาม Temp. ที่ตั้งไว้ ";
String string2 = "Temp (°C)";
String string3 = "|";
String string4 = "|";
String string5 = "|";
LineText = string1 + string2 + string3 + v3 + string4 + temp + string5 + v4 ;
LINE.notify(LineText);
delay(200);
linenotify = 1;
// Serial.println("if 1");
// Serial.println(linenotify);
}
if ((linenotify == 1) && (Temp == 1) ) {
// led_1.on();
delay(30);
// Serial.println("if 2");
// Serial.println(linenotify);
}
if ((linenotify == 1) && (Temp == 0) ) {
linenotify = 0;
// Serial.println("if 2");
// Serial.println(linenotify);
}
if ((linenotify == 0) && (Temp == 0) ) {
// led_1.off();
linenotify = 0;
// Serial.println("if 2");
// Serial.println(linenotify);
}
delay(150);
//---------------------------------------------------------
if ( (humid > v1 && humid < v2) ) {
Humid = 1;
}
else {
Humid = 0;
}
delay(100);
if ((linenotify1 == 0) && (Humid == 1) ) {
// led_1.on();
String LineText;
String string11 = "อุปกรณ์ทำงาน ตาม Humid. ที่ตั้งไว้ ";
String string12 = "Humid (%)";
String string13 = "|";
String string14 = "|";
String string15 = "|";
LineText = string11 + string12 + string13 + v1 + string14 + humid + string15 + v2 ;
LINE.notify(LineText);
delay(200);
linenotify1 = 1;
// Serial.println("if 1");
// Serial.println(linenotify);
}
if ((linenotify1 == 1) && (Humid == 1) ) {
// led_1.on();
// Serial.println("if 2");
// Serial.println(linenotify);
}
if ((linenotify1 == 1) && (Humid == 0) ) {
linenotify1 = 0;
// Serial.println("if 2");
// Serial.println(linenotify);
}
if ((linenotify1 == 0) && (Humid == 0) ) {
// led_1.off();
linenotify1 = 0;
// Serial.println("if 2");
// Serial.println(linenotify);
}
delay(150);
if ( (Temp == 1 && Humid == 1) or (Temp == 0 && Humid == 1) or (Temp == 1 && Humid == 0) ) {
led_1.on();
delay(50);
}
else {
led_1.off();
delay(50);
}
}
}
//------------------------------------------------------------------------------------------------------------------------//
//********************************************* void Loop ***************************************************//
//------------------------------------------------------------------------------------------------------------------------//
void loop() {
//-----------------------------------------------------------------------------------------------------------//
if (Blynk.connected())
{
Blynk.run();
digitalWrite(Ledblynk, HIGH);
} else {
digitalWrite(Ledblynk, LOW);
delay(200);
digitalWrite(Ledblynk, 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
}