มาสร้างชุด แสดงสถานะสัญญาณ WiFi + Internet + ESP32 กันเถอะ

สำหรับโครงงานในกระทู้นี้ผมก็จะแสดงรายละเอียดเพิ่มเติมในการสร้างชุดแสดงสถานะสัญญาณ WiFi + Internet โดยใช้ ESP32 กันครับ

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

ความต้องการของ Project
ARDUINO IDE 1.8.7-1.8.9
Board Manager ESP32 Version 1.0.3
Library

Code (Update 24_01_2563 11:37)

#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 
//------------------------------------------------------------------------------------------------------------------------//


//------------------------------        การกำหนดค่าในส่วนของ 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;
//------------------------------------------------------------------------------------------------------------------------//


//-------------------------------------------IO Extender ---PCF8574-------------------------------------------------------//
#include "PCF8574.h"                   //โหลดไลบารี่  ของ PCF8574  มาใช้งาน
//PCF8574 pcf8574_3(0x3C);//ตัวที่ 3
//PCF8574 pcf8574_2(0x3A); //ตัวที่ 2
PCF8574 pcf8574_1(0x38); //ตัวที่ 1
unsigned long timeElapsed;
//------------------------------------------------------------------------------------------------------------------------//




long rssi;
int rssiled;


//---LED แสดงสถานะ Internet โดยแนวคิดคือ วนลูป loop ให้ ESP8266 ติดต่อ www.google.co.th ไปเรื่อยๆ ถ้า LED ติด แสดงว่า Internet มา --//

const char* host = "www.google.co.th";    //ต้องการให้ส่งการติดต่อไปยัง Website นี้


TaskHandle_t Task1;
TaskHandle_t Task2;




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

void setup() {

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


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

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

  pcf8574_1.begin();//เริ่ม Begin ก่อนแล้วค่อยกำหนดขา
  timeElapsed = millis();
  pcf8574_1.pinMode(P0, OUTPUT);
  pcf8574_1.pinMode(P1, OUTPUT);
  pcf8574_1.pinMode(P2, OUTPUT);
  pcf8574_1.pinMode(P3, OUTPUT);
  pcf8574_1.pinMode(P4, OUTPUT);
  //  pcf8574_1.pinMode(P5, OUTPUT);

  pcf8574_1.digitalWrite(P0, 1);
  pcf8574_1.digitalWrite(P1, 1);
  pcf8574_1.digitalWrite(P2, 1);
  pcf8574_1.digitalWrite(P3, 1);
  pcf8574_1.digitalWrite(P4, 1);
  //  pcf8574_1.digitalWrite(P5, 1);










  Serial.begin(115200);
  //-------------------------------//





  //*************************    การ อ่าน  เขียนค่า 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 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.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 1
  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 */
    1);          /* pin task to core 1 */
  delay(500);


  //create a task that will be executed in the Task1code() function, with priority 1 and executed on core 1
  xTaskCreatePinnedToCore(
    Task2code,   /* Task function. */
    "Task2",     /* name of task. */
    10000,       /* Stack size of task */
    NULL,        /* parameter of the task */
    1,           /* priority of the task ตัวเลขน้อยสำคัญน้อย*/
    &Task2,      /* Task handle to keep track of created task */
    1);          /* pin task to core 1 */
  delay(500);



}


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




//Task1_code
void Task1code( void * pvParameters ) {

  //  pcf8574_1.begin();//เริ่ม Begin ก่อนแล้วค่อยกำหนดขา
  //  timeElapsed = millis();
  //  pcf8574_1.pinMode(P0, OUTPUT);
  //  pcf8574_1.pinMode(P1, OUTPUT);
  //  pcf8574_1.pinMode(P2, OUTPUT);
  //
  //
  //  pcf8574_1.digitalWrite(P0, 1);
  //  pcf8574_1.digitalWrite(P1, 1);
  //  pcf8574_1.digitalWrite(P2, 1);



  for (;;) {


    rssi = WiFi.RSSI();

    rssiled = ((((rssi * 100) / -127) - 100) * -1);// ทำให้เป็น % ความแรงของ WiFi จะดูง่ายกว่า

    if (rssi < 0  ) {
      //เชคระดับสัญญาณ WiFi >= 60%
      if (rssiled >= 60  ) {

        pcf8574_1.digitalWrite(P0, 0);
        delay(20);

      } else  {
        pcf8574_1.digitalWrite(P0, 1);
        delay(20);

      }
      //เชคระดับสัญญาณ WiFi >= 50%
      if (rssiled >= 50  ) {
        pcf8574_1.digitalWrite(P1, 0);
        delay(20);

      } else  {
        pcf8574_1.digitalWrite(P1, 1);
        delay(20);

      }
      //เชคระดับสัญญาณ WiFi 0-30%
      if (rssiled >= 30  ) {
        pcf8574_1.digitalWrite(P2, 0);
        delay(20);


      } else  {
        pcf8574_1.digitalWrite(P2, 1);
        delay(20);
      }
    }

    //Serial.println(rssi);
    if (rssi == 0  ) {
      pcf8574_1.digitalWrite(P0, 1);
      pcf8574_1.digitalWrite(P1, 1);
      pcf8574_1.digitalWrite(P2, 1);

    }


    delay(500);
    yield();



  }
}








//Task2_code
void Task2code( void * pvParameters ) {

  //  Serial.print("Task2 running on core ");
  //  Serial.println(xPortGetCoreID());
  //  pcf8574_1.begin();//เริ่ม Begin ก่อนแล้วค่อยกำหนดขา
  //  timeElapsed = millis();
  //  pcf8574_1.pinMode(P3, OUTPUT);



  for (;;) {

    WiFiClient client;
    if (client.connect(host, 80))
    {
      //Serial.println("connected");
      pcf8574_1.digitalWrite(P3, 0);
      client.stop();
      delay(500);
    }
    else {
      //Serial.println("connection failed!");
      pcf8574_1.digitalWrite(P3, 1);
      client.stop();

    }
    delay(2000);


  }
}












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


void loop() {


  //-----------------------------------------------------------------------------------------------------------//
  if (Blynk.connected())
  {
    Blynk.run();
    digitalWrite(Ledblynk, HIGH);
    pcf8574_1.digitalWrite(P4, 0);

  } else {

    digitalWrite(Ledblynk, LOW);
    pcf8574_1.digitalWrite(P4, 1);
    delay(200);
    digitalWrite(Ledblynk, HIGH);
    pcf8574_1.digitalWrite(P4, 0);
    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

}

ทดสอบ ESP32 WiFiManager ว่าใช้งานได้ครอบคลุมทุกเงื่อนไขหรือไม่ เป็นการทำให้สมาชิก https://eleceasy.com/ ที่สนใจเรื่องนี้ได้มั่นใจครับว่า มันใช้งานได้แน่นอน Code ทุก Post เกี่ยวกับเรื่องนี้ ผม Update ใหม่หมดแล้วนะครับ สมาชิกหรือผู้ที่แวะเข้ามาดูสามารถ Copy ใหม่ได้

1 Like

อ.พอรู้วิธี reconnect wifi esp32 ไหมครับ คือผมเชื่อมเน็ตและเน็ตหลุดไปมันไม่ยอมเชื่อมต่อกลับมาให้ครับ

ผมทำไว้ให้แล้วครับ ดูจาก post นี้ได้เลยครับ

image

จุดสำคัญคือ

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 และใช้งานได้แล้ว ได้ ระบบจะทำงานปกติ

มีวิธีแบบไม่ต้องให้มันรีเซ็ตไหมครับ

ยังไงครั้งแรกก็ต้องเข้าไป รีเซต เพื่อตั้งค่า WiFi ก่อนครับ จากนั้นก็ไม่ต้องแล้ว (ในกรณี ที่ใช้ Code ที่ผม Post ไปนะครับ)

ผมลองจำลองสถานะการณ์คือใช้ไปเรื่อยๆแล้วลองดับไวฟายดูพอเปิดวายฟายมาใหม่มันไม่เชื่อมต่อให้ครับ

ใช้ code ของคุณ หรือของที่ผม Post ไว้ให้หรือครับ ทดสอบเหมือนเลขฐาน 2 00 01 10 11 เลขตัวหน้าคือ Router WiFi ตัวหลัง คือ Node MCU 0 ตัดไฟออก 1 คือ จ่ายไฟเข้าไป ผมกระทู้ที่ผมโพสต์ ผมทำ ไว้แล้วนะครับ

กรณีนี้คือผมเอาไปเปิดปิดไฟสี่แชลแนลผ่านblynkครับ ใช่ไปเรื่อยๆแล้วเกิดไวฟายดับ แต่ไฟไม่ดับ มันก็ยังทำงานต่อไป พอไวฟายมามันไม่เชื่อมต่อให้ครับ

ขอดูcode. หน่อยครับ​ ใช้esp32น่ะครับ​

#if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE 0
#else
#define ARDUINO_RUNNING_CORE 1
#endif

#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>
#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 <IRremote.h>
//------------------------------------------------------------------------------------------------------------------------//
#include <BlynkSimpleEsp32.h>          //  Blynk_Release_v0.6.1 
//------------------------------------------------------------------------------------------------------------------------//

//------------------------------        การกำหนดค่าในส่วนของ Blynk         ------------------------------------------------//
#define BLYNK_DEBUG
#define BLYNK_PRINT Serial        // ใส่ความคิดเห็นในส่วนนี้เพื่อปิดการใช้งานพิมพ์และประหยัดพื้นที่

boolean ok =false;

int blynkIsDownCount = 0;        //Integer Variable ตัวแปรชื่อ blynkIsDownCount ใช้เก็บเลขจำนวนเต็ม โดยเริ่มต้นให้มีค่า = 0
char blynk_token[34] = "";//ใส่ Blynk_token ของเราที่ Blynk ส่งมาทาง Email ตอน Create Project ใหม่
char mqtt_server[40]  = "blynk-cloud.com";
char mqtt_port[6]     = "8442";
//----------------------------------  กำหนดหมายเลขของขาของ Node MCU ESP 32 --------------------------------------------//

 int Ledblynk = 2;                     // ใช้ไฟ LED สีฟ้า ของบอร์ด MCU ESP32 ให้มีสัญญาณไฟกระพริบ ตาม Code ที่เขียน
 int AP_Config = 33;                // ใช้เป็นปุ่มกด เพื่อเข้า AP Config ได้ตามความต้องการของผู้ใช้
int sw1 = 23;
int RECV_PIN = 27;

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

bool shouldSaveConfig = false;
//callback notifying us of the need to save config
void saveConfigCallback () {
  Serial.println("Should save  blynk config");
  shouldSaveConfig = true;
}
//------------------------------------------------------------------------------------------------------------------------//


IRrecv irrecv(RECV_PIN);
decode_results results;

BlynkTimer timer1;  //เรียกใช้การตั้งเวลาของ Blynk
//ฟังชั่นเปิดใช้งาน BlynkTimer ซึ่งทำหน้าที่คล้าย ๆ interrupt timer หมายถึงเมื่อครบเวลาตามที่กำหนดไว้โปรแกรมหลักจะกระโดด
//ไปทำงานในโปรแกรมตอบสนองที่กำหนดไว้
//กรณีนี้จะนำฟังชั่นที่เปิดใช้งาน BlynkTimer ไปใช้ในการ เชื่อมต่อซ้ำ (reconnecting)
WidgetLED led1(V0);
void checkPhysicalButton();
void check1();
int ledState = LOW;
int btnState = HIGH;

BLYNK_CONNECTED() {
  //Blynk.syncVirtual(V1); 
  Blynk.virtualWrite(V1,digitalRead(Ledblynk));
}

BLYNK_WRITE(V1) {
  ledState = param.asInt();
  digitalWrite(2, ledState);
}

void checkPhysicalButton()
{
  if (digitalRead(sw1) == LOW or ok == true ) {
    if (btnState != LOW  or ok == true) {
      ledState = !ledState;
      digitalWrite(Ledblynk, ledState);
      Blynk.virtualWrite(V1, ledState);
      ok = false;
    }
    btnState = LOW;
  } else {
    btnState = HIGH;
  }
    
     
}
void check1(){
  if(digitalRead(Ledblynk)==1){
        led1.on();
      }else{
       led1.off();
     }
}

//------------------------------------------------------------------------------------------------------------------------//
//*********************************************       void setup        **************************************************//
//------------------------------------------------------------------------------------------------------------------------//
void Taskir(void *pvParameters);
void Taskreconnectwifi(void *pvParameters);
void Taskreconnect(void *pvParameters);
void setup() {
 
  pinMode(Ledblynk, OUTPUT);      //กำหนดโหมดใช้งานให้กับขา Ledblynk เป็นขา สัญญาณไฟ ในสภาวะต่างๆ
  pinMode(sw1,INPUT_PULLUP);
  pinMode(AP_Config, INPUT_PULLUP);//กำหนดโหมดใช้งานให้กับขา AP_Config เป็นขา กดปุ่ม ค้าง เพื่อตั้งค่า AP config
  // ให้ LED ทั้งหมดดับก่อน
  digitalWrite(Ledblynk, LOW);//ให้หลอด LED สีฟ้าดับก่อน
  Serial.begin(115200);
  Serial.println("mounting blynk FS...");//แสดงข้อความใน Serial Monitor

  if (SPIFFS.begin(true)) {
    Serial.println("mounted blynk file system");//แสดงข้อความใน Serial Monitor

    if (SPIFFS.exists("/config.json")) {
      //file exists, reading and loading
      Serial.println("reading blynk config file");//แสดงข้อความใน Serial Monitor
      File configFile = SPIFFS.open("/config.json", "r");

      if (configFile) {
        Serial.println("opened blynk 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 blynk json");//แสดงข้อความใน Serial Monitor
          strcpy(blynk_token, json["blynk_token"]);

        } else {
          Serial.println("failed to load blynk json config");//แสดงข้อความใน Serial Monitor
        }
      }
    }
  } else {
    Serial.println("failed blynk to mount FS");//แสดงข้อความใน Serial Monitor
  }
  //end read
  delay(500);
  Serial.println("mounting line FS...");//แสดงข้อความใน Serial Monitor

  if (SPIFFS.begin(true)) {
    Serial.println("mounted line file system");//แสดงข้อความใน Serial Monitor

    if (SPIFFS.exists("/config1.json")) {
      //file exists, reading and loading
      Serial.println("reading line config file");//แสดงข้อความใน Serial Monitor
      File configFile1 = SPIFFS.open("/config1.json", "r");

      if (configFile1) {
        Serial.println("opened line 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 server json");//แสดงข้อความใน Serial Monitor
          strcpy(mqtt_server, json["mqtt_server"]);
        } else {
          Serial.println("failed to load server json config");//แสดงข้อความใน Serial Monitor
        }
      }
    }
  } else {
    Serial.println("failed line to mount FS");//แสดงข้อความใน Serial Monitor
  }
  //end read

  delay(500);
Serial.println("mounting line FS...");//แสดงข้อความใน Serial Monitor

  if (SPIFFS.begin(true)) {
    Serial.println("mounted line file system");//แสดงข้อความใน Serial Monitor

    if (SPIFFS.exists("/config2.json")) {
      //file exists, reading and loading
      Serial.println("reading line config file");//แสดงข้อความใน Serial Monitor
      File configFile2 = SPIFFS.open("/config2.json", "r");

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

        configFile2.readBytes(buf2.get(), size);
        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.parseObject(buf2.get());
        json.printTo(Serial);
        if (json.success()) {
          Serial.println("\nparsed port json");//แสดงข้อความใน Serial Monitor
          strcpy(mqtt_port, json["mqtt_port"]);
        } else {
          Serial.println("failed to load port json config");//แสดงข้อความใน Serial Monitor
        }
      }
    }
  } else {
    Serial.println("failed line to mount FS");//แสดงข้อความใน Serial Monitor
  }
  //end read
  delay(500);
  //*************************   จบการ อ่าน     **********//

  //**************************        AP AUTO CONNECT   ********************************************//
  
  WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server , 40);
  WiFiManagerParameter custom_mqtt_port  ("port", "mqtt port", mqtt_port, 6);
  WiFiManagerParameter custom_blynk_token("blynk", "blynk token", blynk_token, 34);
  WiFiManager wifiManager;
  //set config save notify callback
  wifiManager.setSaveConfigCallback(saveConfigCallback);
  wifiManager.addParameter(&custom_blynk_token);
  wifiManager.addParameter(&custom_mqtt_server);
  wifiManager.addParameter(&custom_mqtt_port);
  delay(500);

  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) == 0) {
    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(120);
  //ใช้ได้ 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("Supong ESP32 AP")) {
      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());
  delay(500);
  strcpy(mqtt_server, custom_mqtt_server.getValue());
  delay(500);
  strcpy(mqtt_port, custom_mqtt_port.getValue());
  delay(500);

  //save the custom parameters to FS
  if (shouldSaveConfig) {
    Serial.println("saving blynk 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 blynk config file for writing");//แสดงข้อความใน Serial Monitor

    }
    json.printTo(Serial);
    json.printTo(configFile);
    configFile.close();
    //end save
  }
  delay(500);
 
  if (shouldSaveConfig) {
    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();
    json["mqtt_server"] = mqtt_server;
    File configFile1 = SPIFFS.open("/config1.json", "w");

    if (!configFile1) {
      Serial.println("failed to open line config file for writing");//แสดงข้อความใน Serial Monitor

    }
    json.printTo(Serial);
    json.printTo(configFile1);
    configFile1.close();
  }
  if (shouldSaveConfig) {
    Serial.println("saving line config");//แสดงข้อความใน Serial Monitor
    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();
    json["mqtt_port"] = mqtt_port;
    File configFile2 = SPIFFS.open("/config2.json", "w");
    
    if (!configFile2) {
      Serial.println("failed to open line config file for writing");//แสดงข้อความใน Serial Monitor
    }
    json.printTo(Serial);
    json.printTo(configFile2);
    configFile2.close();
  }
  delay(500);
  //**************************    จบ    AP AUTO CONNECT   *****************************************//

 // WiFi.mode(WIFI_STA); WiFi.begin();
/*Serial.println("local ip"); //แสดงข้อความใน Serial Monitor
  Serial.println(WiFi.localIP());//แสดงข้อความใน Serial Monitor
  Serial.println("gateway");
  Serial.println(WiFi.gatewayIP());
  Serial.println("subnetMask");
  Serial.println(WiFi.subnetMask());
  */
 
  // Blynk.config(blynk_token);////เริ่มการเชื่อมต่อ Blynk Server แบบปกติ
  Blynk.config(blynk_token,mqtt_server,atoi(mqtt_port));
  Blynk.connect(5000);
  Serial.println(blynk_token);
  Serial.println(mqtt_server);
  Serial.println(mqtt_port);
  ////เริ่มการเชื่อมต่อ Blynk Server*********สำหรับ Server local ที่แจกให้ เพิ่ม, server, port  แค่นี้จบ
  //timer1.setInterval(30000L, reconnecting);  //Function reconnect
  //ตั้งเวลาส่งข้อมูลให้ Blynk Server ทุกๆ 30 วินาที
  timer1.setInterval(100L, checkPhysicalButton);
  timer1.setInterval(100L, check1);

  xTaskCreatePinnedToCore(Taskir,"Taskir",2000,NULL,2,NULL,ARDUINO_RUNNING_CORE);
  xTaskCreatePinnedToCore(Taskreconnectwifi,"reconnectwifi",15000,NULL,1,NULL,ARDUINO_RUNNING_CORE);
  xTaskCreatePinnedToCore(Taskreconnect,"reconnect",3000,NULL,1,NULL,ARDUINO_RUNNING_CORE);
}

//------------------------------------------------------------------------------------------------------------------------//
//*********************************************   จบ  void setup    แล้วมึงอย่าพึ่งตาลายน่ะพ่อรูปหล่อลื่น    **************************************************//
//------------------------------------------------------------------------------------------------------------------------//
//------------------------------------------------------------------------------------------------------------------------//
//*********************************************       void Loop        ***************************************************//
//------------------------------------------------------------------------------------------------------------------------//
void loop() {

  //-----------------------------------------------------------------------------------------------------------//
  if (Blynk.connected())
  {
    Blynk.run();
  } 
  //-----------------------------------------------------------------------------------------------------------//
  timer1.run();//ให้เวลาของ Blynk ทำงาน
}

//------------------------------------------------------------------------------------------------------------------------//
//*********************************************      จบ void Loop       **************************************************//
//------------------------------------------------------------------------------------------------------------------------//
void Taskir(void *pvParameters){
   (void)pvParameters;
   Serial.println("Enabling IRin");
   irrecv.enableIRIn(); // Start the receiver
   Serial.println("Enabled IRin");
   for(;;){
     if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
      if(results.value == 0xFF18E7){
      ok = true;
   Serial.println("SSID");
  Serial.println(WiFi.SSID());
  Serial.println("Password");
  Serial.println(WiFi.psk());
      }
    irrecv.resume(); // Receive the next value
  }
   vTaskDelay(10);
  }
}
void Taskreconnectwifi (void *pvParameters){
  (void) pvParameters;
  for (;;)
  {
  if (WiFi.status() != WL_CONNECTED) {
   WiFi.reconnect();//ใช้ในกรณีเชื่อมเน็ตแล้วแต่เน็ตเกิดดับไปแล้วเน็ตมาใหม่มันก็จะพยายามเชื่อมต่อ
  }
   vTaskDelay(1000);
  }
}
void Taskreconnect(void *pvParameters){
  (void) pvParameters;
  for (;;)
  {
  if (!Blynk.connected())
  {
    blynkIsDownCount++;
    BLYNK_LOG("blynk server is down! %d  times", blynkIsDownCount);
    Serial.println(" รีเฟรช ");
    Blynk.connect(5000);
  }
   vTaskDelay(5000);
  }
}

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

เอาเป็นว่า concept เป็นตามนี้ก่อนนะครับ " เปิดปิดไฟสี่แชลแนลผ่านblynk"

@111118 ผมว่าควรหันมาทำ WiFi Manager ให้ เสถียรก่อนดีมั๊ยครับ สำหรับโปรเจคนี้ ถ้าใช้ Relay 4 ตัว เราไม่ต้องแบ่ง task ก็ได้ครับ สังเกตดูคนที่ทำโปรเจค ส่วนใหญ่จะตกม้าตาย เรื่อง WiFi manager กันเป็นส่วนใหญ่ ถ้าคุณไล่เชค โพสต์ของผมส่วนใหญ่ ผมจะลงข้อมูลเกี่ยวกับเรื่องพวกนี้เอาไว้เยอะ จนผมเองก็เริ่มหาข้อมูลไม่ค่อยจะเจอแล้ว :grin: ถ้าคุณต้องการไล่ไปทีละขั้นตอน ก็ Download ไปลองใช้งานดู ไปทีละขั้นตอน เดี๋ยวงานก็สำเร็จครับ

ESP32
ความต้องการของ Project (เพื่อป้องกันความผิดพลาดเรื่องของ Version และตรวจสอบย้อนหลังได้)

  1. Arduino IDE Version 1.8.7 อันนี้ไม่ต้องหาเพราะผมรวมไฟล์ไปในโปรเจคนี้แล้ว
  2. WiFiManager Version 0.14.0 อันนี้ไม่ต้องหาเพราะผมรวมไฟล์ไปในโปรเจคนี้แล้ว
  3. Blynk Version 0.5.4 หรือที่คุณมีอยู่แล้วก็น่าจะได้ครับ
  4. ArduinoJson Version 5.13.3 อันนี้ไม่ต้องหาเพราะผมรวมไฟล์ไปในโปรเจคนี้แล้ว

เริ่มทดลองใช้ก่อนนะครับ

  1. อย่าลืม ตามนี้นะครับ

const int Ledblynk = 2; // ใช้ไฟ LED สีฟ้า ของบอร์ด MCU ESP32 ให้มีสัญญาณไฟกระพริบ ตาม Code ที่เขียน อันนี้จำเป็นนะครับ เาจะได้รูว่าตอนนี้มันอยู่ในสถานะอะไร
const int AP_Config = 23; // ใช้เป็นปุ่มกด เพื่อเข้า AP Config ได้ตามความต้องการของผู้ใช้ หรือคุณจะเปลี่ยน port ใน code ที่ผมให้ไปก็ได้
2. ช่วงไฟกระพริบ 5 วินาที ให้กดปุ่มค้างต่อนะครับ แล้วลองเปิด WiFi ดู ว่ามันขึ้นชื่อ SSID ของเราหรือยัง ถ้าขึ้นแล้วค่อยปล่อยปุ่ม
3. wifiManager.setTimeout(90); ผมตั้งการหมดเวลาในการเข้าใช้ WiFimanager ไว้ 90 วินาที นะครับ ถ้าป้อนเกิน 90 วินาที มีจะเริ่มต้นใหม่ เราก็ต้องกดปุ่ม AP Config ใหม่ หรือคุณจะเปลี่ยนเวลาใหม่ก็ได้ (เอาที่ชอบ)

ต้องแยกให้ออกก่อนนะครับ WiFi มันไม่ได้ดับ แต่เน็ตมันหลุด WiFi มันก็ต่อได้ปกติ เพียงแต่ Blynk ไม่สามารถเรียกไปยัง server ได้รึป่าว ใช่เคสนี้หรือไม่??

น่าจะครับ มีวิธีแก้ไขไหมครับ

Guru Meditation Error: Core  1 panic'ed (Cache disabled but cached memory region accessed)
16:37:08.961 -> Core 1 register dump:
16:37:08.961 -> PC      : 0x400dcf3c  PS      : 0x00060034  A0      : 0x40084bc8  A1      : 0x3ffbe7b0  
16:37:08.961 -> A2      : 0x00000001  A3      : 0x00000002  A4      : 0x000000ff  A5      : 0x4008b734  
16:37:08.961 -> A6      : 0x00000000  A7      : 0x1300044c  A8      : 0x800816b4  A9      : 0x3ff5f024  
16:37:08.961 -> A10     : 0x3ffbec88  A11     : 0x20000000  A12     : 0x00000400  A13     : 0x00000000  
16:37:08.961 -> A14     : 0x3ffc1b48  A15     : 0xffffffff  SAR     : 0x00000011  EXCCAUSE: 0x00000007  
16:37:09.008 -> EXCVADDR: 0x00000000  LBEG    : 0x00000000  LEND    : 0x00000000  LCOUNT  : 0x00000000  
16:37:09.008 -> Core 1 was running in ISR context:
16:37:09.008 -> EPC1    : 0x40086e7b  EPC2    : 0x00000000  EPC3    : 0x00000000  EPC4    : 0x400dcf3c
16:37:09.008 -> 
16:37:09.008 -> Backtrace: 0x400dcf3c:0x3ffbe7b0 0x40084bc5:0x3ffbe7d0 0x40086e78:0x3ffba190 0x40082fe3:0x3ffba1b0 0x40088fd1:0x3ffba1d0
16:37:09.008 -> 
16:37:09.008 -> Rebooting...
16:37:09.008 -> ets Jun  8 2016 00:22:57
16:37:09.008 -> 
16:37:09.008 -> rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
16:37:09.008 -> configsip: 0, SPIWP:0xee
16:37:09.008 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
16:37:09.070 -> mode:DIO, clock div:1
16:37:09.070 -> load:0x3fff0018,len:4
16:37:09.070 -> load:0x3fff001c,len:1044
16:37:09.070 -> load:0x40078000,len:8896
16:37:09.070 -> load:0x40080400,len:5816
16:37:09.070 -> entry 0x400806ac

@111118 ทำไฮไลท์โค้ตให้ด้วยครับ

อ.มีวิธีดึงค่าไอดีกับไวฟาย และรหัสที่บันทึกลงในความจำesp32 ไหมครับ ผมไม่รู้ว่า lib wifimanagerมันบันทึกไอดีและรหัสผ่านไวฟายไว้ในส่วนไหนของesp32

Serial.println();
  Serial.print("local ip : ");
  Serial.println(WiFi.localIP());
  delay(100);
  Serial.print("gateway : ");
  Serial.println(WiFi.gatewayIP());
  delay(100);
  Serial.print("subnetMask : ");
  Serial.println(WiFi.subnetMask());
  delay(100);
  Serial.print("SSID : ");
  Serial.println(WiFi.SSID());
  delay(100);
  Serial.println("Password : ");
  Serial.println(WiFi.psk());
  delay(100);