การรีเซ็ตโหนด mcu esp 8266 แบบตั้งเวลาให้ Reset อัตโนมัติแทนการกดปุ่มที่บอร์ด แบบไม่ง้อ Code

สวัสดีครับทุกท่านสำหรับวันนี้นะครับผมก็จะนำเสนอไอเดียเกี่ยวกับเรื่องของ การรีเซ็ตบอร์ดของ node mcu esp 8266 โดยไม่ต้องใช้คำสั่ง ESP.reset() หรือ ESP.restart() เพราะการทำวิธีนี้ผมลองศึกษาดูแล้วปรากฏว่าเมื่อใช้คำสั่งนี้ เมื่อถึงเวลาที่เราตั้งค่าเอาไว้เราจะต้องมีการกดปุ่มรีเซ็ตแบบ Manual ที่บอร์ด 1 ครั้ง จากนั้นเมื่อครบรอบเวลาครั้งต่อไปมันจะทำการรีเซ็ต บอร์ดของ node mcu esp 8266 ให้แบบอัตโนมัติ แต่ปัญหามันติดอยู่ที่ว่าถ้าเราต้องการตั้งเวลาไป 15 ชั่วโมงเราต้องรอเวลาให้ครบ 15 ชั่วโมงก่อนแล้วจึงมากดปุ่มรีเซ็ต เพื่อให้รอบต่อไปในการทำงานเป็นแบบอัตโนมัติ

จากสาเหตุดังกล่าวผมจึงคิดวิธีการว่าผมเพียงแค่ต้องการที่จะตั้งเวลาเอาไว้และเมื่อถึงเวลาก็ให้มัน Reset บอร์ดของ node mcu esp 8266เลยโดยไม่ต้องใช้คำสั่ง ESP.reset() หรือ ESP.restart() และไม่ต้องไปกดปุ่มรีเซ็ตบอร์ด ในครั้งแรก ดังนั้นแนวคิดของผมคือทำอย่างไรให้เราไม่ต้องไปกดปุ่ม Reset บอร์ดในครั้งแรก ดังนั้นจึงเกิดเป็นแนวคิด โดยการใช้ทรานซิสเตอร์เข้ามาช่วย เพื่อจะทำให้การทำงานเป็นแบบอัตโนมัติเหมือนกดปุ่ม Reset บอร์ดจริงๆ ยังไงเดี๋ยวลองชมคลิปผลลัพธ์ที่ได้ก่อนนะครับ

1 Likes

จากที่ได้อธิบายไปก็เขียนได้ diagram ได้ตามนี้ ในส่วนของตัวโค้ชนั้นผมจะนำเสนอเป็นบางส่วนเพื่อให้นำไปศึกษาการใช้งานดูนะครับ ในส่วนของ Push button switch อาจจะต่อหรือไม่ต่อก็ได้แต่ถ้าต่อก็แนะนำให้ใช้โค้ดที่ผมลงในบทความก่อนๆดูนะครับ

#define D5 14

void setup() {
  pinMode(D5, OUTPUT);
  digitalWrite(D5, HIGH);//ให้ D5 เป็น 0

}

void loop() {
  delay(10000);
  digitalWrite(D5, LOW);//ให้ D5 เป็น 1
}

มีแค่นี้ครับ อิ…อิ… เอาไว้ทดลองว่าได้ผลหรือไม่ แต่จริงๆแล้วมันได้ผลครับ ผมรับประกัน เพราะผมต้องการเอาไปใช้งานจริง ไม่ได้ทำไว้ทดลองครับ
ที่นี้การเขียนโค้ดง่ายๆแบบนี้มันก็ไม่มีปัญหาใช่ไหมครับ แต่ถ้าเกิดว่าเรามีโค้ดยาวๆขึ้นมา การหน่วงเวลาที่ 10 วินาทีจะทำให้โปรแกรมเกิดการหน่วงเวลา ซึ่งจะทำให้ โค้ดตัวอื่นๆไม่สามารถจะทำงานได้เลย ดังนั้นเราจึงจำเป็นที่จะต้องให้ Node MCU Esp 8266 ทำงานแบบ Multi Task นั่นเอง เพื่อไม่ทำให้เกิดการหน่วงของ code ที่ใช้กับอุปกรณ์ตัวอื่น
ตัวอย่าง Code ครับ

//*********************************************************************************************
//NodeMCU V2 จะมี LED อยู่ 2 ตัวคือบนชิพ ESP8266 (D4) และบนบอร์ด (D0)
//NodeMCU V3 จะมี LED อยู่ 1 ตัวคือบนชิพ ESP8266 (D4) ซึ่งไม่มีบนบอร์ดเหมือน V2
//เลือกบอร์ดเป็น NodeMCU 1.0 ความเร็วอัพโหลดจะเป็น 115200 และ LED_BUILTIN จะเป็น D0
//*********************************************************************************************

#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 <time.h>//NTP Server

#include <Scheduler.h>

#include <LCD.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
//------------ LCD ---------------------------
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

byte Wifibase[8] = //icon for termometer
{
  B11111,
  B10101,
  B10101,
  B01110,
  B00100,
  B00100,
  B00100,
  B00100
};
byte WifiL1[8] = //icon for termometer
{
  B00110,
  B00110,
  B00110,
  B00110,
  B00110,
  B00110,
  B00110,
  B00110
};

byte WifiL2[8] = //icon for termometer
{
  B01110,
  B01110,
  B01110,
  B01110,
  B01110,
  B01110,
  B01110,
  B01110
};


byte WifiL3[8] = //icon for termometer
{
  B11110,
  B11110,
  B11110,
  B11110,
  B11110,
  B11110,
  B11110,
  B11110
};

byte intrnetok[8] = //icon for termometer
{
  B01110,
  B10101,
  B10101,
  B10101,
  B10101,
  B10101,
  B01110,
  B00100
};




byte blynk[8] = //icon for termometer
{
  B01110,
  B10101,
  B10101,
  B10101,
  B10101,
  B10101,
  B01110,
  B00100
};

#include "PCF8574.h"
PCF8574 pcf8574_3(0x3C);//ตัวที่ 3
PCF8574 pcf8574_2(0x3A); //ตัวที่ 2
PCF8574 pcf8574_1(0x38); //ตัวที่ 1
unsigned long timeElapsed;


#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 ได้ตามความต้องการของผู้ใช้

#define D7 13                     //เชคสัญญาณ Internet เชคระดับสัญญาณ WiFi

#define D4 2                     //เชคระดับสัญญาณ WiFi 0-30%
#define D5 14                    //เชคระดับสัญญาณ WiFi >=50%
#define D6 12                    //เชคระดับสัญญาณ WiFi >=60%


#define D9 3


//------------------------------------------------------------------------------------------------
long rssi;
int rssiled;
//------------------------------------------------------------------------------------------------


//LED แสดงสถานะ Internet โดยแนวคิดคือ วนลูป loop ให้ ESP8266 ติดต่อ www.google.co.th ไปเรื่อยๆ LED ก็จะติด แสดงว่า Internet มา
const char* host = "www.google.co.th";    //ต้องการให้ส่งการติดต่อไปยัง Website นี้


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

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


int timezone = 7;

char ntp_server1[20] = "ntp.ku.ac.th";
char ntp_server2[20] = "fw.eng.ku.ac.th";
char ntp_server3[20] = "time.uni.net.th";

int dst = 0;


class RssiTask : public Task {
  protected:
    void loop()  {
      rssi = WiFi.RSSI();
      rssiled = ((((rssi * 100) / -127) - 100) * -1);// ทำให้เป็น % ความแรงของ WiFi จะดูง่ายกว่า
      //Blynk.virtualWrite(V5, ( ((rssi * 100) / -127) - 100) * -1);   // ทำให้เป็น % ความแรงของ WiFi จะดูง่ายกว่า

      //เชคระดับสัญญาณ WiFi >= 60%
      if (rssiled >= 60  ) {
        digitalWrite(D6, HIGH);
        lcd.setCursor(0, 0);
        lcd.write(3);
        delay(10);

      } else  {
        digitalWrite(D6, LOW);
        lcd.setCursor(0, 0);
        lcd.print((char)0x20);//ว่าง ไม่มีสี
        delay(10);

      }
      //เชคระดับสัญญาณ WiFi >= 50%
      if (rssiled >= 50  ) {
        digitalWrite(D5, HIGH);
        lcd.setCursor(0, 1);
        lcd.write(2);
        delay(10);

      } else  {
        digitalWrite(D5, LOW);
        lcd.setCursor(0, 1);
        lcd.print((char)0x20);
        delay(10);

      }
      //เชคระดับสัญญาณ WiFi 0-30%
      if (rssiled >= 30  ) {
        digitalWrite(D4, HIGH);
        lcd.setCursor(0, 2);
        lcd.write(1);
        delay(10);

      } else  {
        digitalWrite(D4, LOW);
        lcd.setCursor(0, 2);
        lcd.print((char)0x20);
        delay(10);

      }

      yield();
      delay(200);
    }

} rssi_print_task;




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

class InternetTask : public Task {
  protected:
    void loop()  {

      //----------------------------------------------------------------------------------------------------------------------------
      //เพื่อป้องกันไม่ให้ มีการติดต่อ ถี่เกินไป จะกำหนดให้ วน loop ปกติเป็นจำนวน n ครั้ง ตัวอย่าง i=100 จะวน 100 รอบปกติก่อน แล้วจึงมาที่  WiFiClient client; 1 ครั้ง
      //Client เป็นการกำหนดให้ ESP8266 ทำหน้าที่เป็นเครื่องลูกข่าย โดยเชื่อมต่อไปยังเครื่องแม่ข่ายด้วยไอพีแอดเดรสและพอร์ตที่กำหนดไว้เพื่อขอใช้บริการนั้นๆ
      //WiFiClient(); คือ การประกาศสร้าง object ของ WifiClient
      //เป็นฟังก์ชั่นสำหรับสั่งให้ ESP8266 เชื่อมต่อกับ Server ด้วย URL และ Port
      //host = สำหรับกำหนด URL ของ Server ที่ต้องการเชื่อมต่อ host
      //port = สำหรับกำหนด Port ที่ Server เปิดรับอยู่ 80

      WiFiClient client;
      if (client.connect(host, 80))
      {
        //Serial.println("connected");
        digitalWrite(D7, HIGH);
        client.stop();
        delay(100);

        lcd.setCursor(11, 3);
        lcd.write(5);
      }
      else {
        //Serial.println("connection failed!");
        digitalWrite(D7, LOW);
        client.stop();

        lcd.setCursor(11, 3);
        lcd.print((char)0x20);
      }

      delay(4000);
    }
} internet_print_task;

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

class BlynkTask : public Task {
  protected:
    void loop()  {

      //--------------------------------------------------------------------------------------------------------
      if (Blynk.connected())
      {
        Blynk.run();

        digitalWrite(D0, HIGH);

        lcd.setCursor(19, 3);
        lcd.write(6);



      } else {

        digitalWrite(D0, LOW);

        lcd.setCursor(19, 3);
        lcd.print((char)0x20);
        delay(200);

        digitalWrite(D0, HIGH);

        lcd.setCursor(19, 3);
        lcd.write(6);

        delay(100);

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


      timer.run();//ให้เวลาของ Blynk ทำงาน

      delay(100);

    }
} blynk_task;

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



class DMTTask : public Task {
  protected:
    void setup() {

      configTime(timezone * 3600, dst, ntp_server1, ntp_server2, ntp_server3);
      //Serial.println("Waiting for time");
      while (!time(nullptr)) {
        //Serial.print(".");
        delay(500);
      }
      //Serial.println();
      //Serial.println("Now: " + NowString());


    }

    void loop() {
      lcd.setCursor(0, 0);
      lcd.print(NowString());

      lcd.setCursor(10, 0);
      lcd.print(NowString2());

      delay(1000);
    }



    //NTP SERVER
    String NowString() {
      time_t now = time(nullptr);
      struct tm* newtime = localtime(&now);

      String tmpNow = "";
      tmpNow += " ";
      tmpNow += String(newtime->tm_hour);
      tmpNow += ":";
      tmpNow += String(newtime->tm_min);
      tmpNow += ":";
      tmpNow += String(newtime->tm_sec);
      return tmpNow;
    }

    String NowString2() {
      time_t now = time(nullptr);
      struct tm* newtime = localtime(&now);

      String tmpNow = "";
      tmpNow += String(newtime->tm_mday);

      tmpNow += "-";
      tmpNow += String(newtime->tm_mon + 1);
      tmpNow += "-";
      tmpNow += String(newtime->tm_year + 2443);//+ อีก 2443 จะได้เป็น พ.ศ.
      return tmpNow;


    }

} DMT_task;


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


/**class PbTask : public Task {
  protected:
    void setup() {

      pcf8574_3.begin();
      pcf8574_2.begin();
      pcf8574_1.begin();
      timeElapsed = millis();

      pcf8574_1.pinMode(P1, OUTPUT);
      pcf8574_1.digitalWrite(P1, 1);

      pcf8574_3.pinMode(P0, INPUT);

      pcf8574_3.pinMode(P2, INPUT);
      pcf8574_3.pinMode(P3, INPUT);
      pcf8574_3.pinMode(P4, INPUT);
      pcf8574_3.pinMode(P5, INPUT);
      pcf8574_3.pinMode(P6, INPUT);
      pcf8574_3.pinMode(P7, INPUT);


      pcf8574_2.pinMode(P0, OUTPUT);
      pcf8574_2.pinMode(P1, INPUT);
      pcf8574_2.pinMode(P2, OUTPUT);
      pcf8574_2.pinMode(P3, OUTPUT);
      pcf8574_2.pinMode(P4, OUTPUT);
      pcf8574_2.pinMode(P5, OUTPUT);
      pcf8574_2.pinMode(P6, OUTPUT);
      pcf8574_2.pinMode(P7, OUTPUT);
      pcf8574_2.digitalWrite(P0, 1);
      pcf8574_1.digitalWrite(P1, 1);
      pcf8574_2.digitalWrite(P2, 1);
      pcf8574_2.digitalWrite(P3, 1);
      pcf8574_2.digitalWrite(P4, 1);
      pcf8574_2.digitalWrite(P5, 1);
      pcf8574_2.digitalWrite(P6, 1);
      pcf8574_2.digitalWrite(P7, 1);


    }

    void loop() {
      uint8_t value0 = pcf8574_3.digitalRead(P0);
      uint8_t value1 = pcf8574_2.digitalRead(P1);
      uint8_t value2 = pcf8574_3.digitalRead(P2);
      uint8_t value3 = pcf8574_3.digitalRead(P3);
      uint8_t value4 = pcf8574_3.digitalRead(P4);
      uint8_t value5 = pcf8574_3.digitalRead(P5);
      uint8_t value6 = pcf8574_3.digitalRead(P6);
      uint8_t value7 = pcf8574_3.digitalRead(P7);

      if (value0 == 1) {
        pcf8574_2.digitalWrite(P0, 0);
      }
      else {
        pcf8574_2.digitalWrite(P0, 1);
      }


      if (value1 == 1) {
        pcf8574_1.digitalWrite(P1, 0);
      }
      else {
        pcf8574_1.digitalWrite(P1, 1);
      }



      if (value2 == 1) {
        pcf8574_2.digitalWrite(P2, 0);
      }
      else {
        pcf8574_2.digitalWrite(P2, 1);
      }


      if (value3 == 1) {
        pcf8574_2.digitalWrite(P3, 0);
      }
      else {
        pcf8574_2.digitalWrite(P3, 1);
      }


      if (value4 == 1) {
        pcf8574_2.digitalWrite(P4, 0);
      }
      else {
        pcf8574_2.digitalWrite(P4, 1);
      }


      if (value5 == 1) {
        pcf8574_2.digitalWrite(P5, 0);
      }
      else {
        pcf8574_2.digitalWrite(P5, 1);
      }

      if (value6 == 1) {
        pcf8574_2.digitalWrite(P6, 0);
      }
      else {
        pcf8574_2.digitalWrite(P6, 1);

      }



      if (value7 == 1) {
        pcf8574_2.digitalWrite(P7, 0);
      }
      else {
        pcf8574_2.digitalWrite(P7, 1);
      }

      delay(100);
    }



  } Pb_task;


**/






class Esprestart : public Task {
  protected:
    void setup() {

      pinMode(D9, OUTPUT);
      digitalWrite(D9, HIGH);//ให้ D9 เป็น 0 

    }
    void loop()  {
      delay(10000);
      digitalWrite(D9, LOW);//ให้ D9 เป็น 1 
      //delay(2000);
     // digitalWrite(D9, HIGH);//ให้ PinRx เป็น 0 ไม่มีไฟจ่ายจะลง Ground แทน

    }
} esprestart;

























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

void setup() {

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


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

  pinMode(D9, OUTPUT);
  digitalWrite(D9, HIGH);//ให้ D9 เป็น 1 คือมีแรงดัน 5vdc จ่ายเข้าไปก่อน โดยการต่อ R330Ohm เข้า Ground จะได้มี Load ไม่ short cirrcuit



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



  lcd.begin(20, 4);


  lcd.createChar(1, WifiL1);
  lcd.createChar(2, WifiL2);
  lcd.createChar(3, WifiL3);
  lcd.createChar(4, Wifibase);
  lcd.createChar(5, intrnetok);
  lcd.createChar(6, blynk);



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

  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);
  lcd.clear();
  lcd.setCursor(0, 0);//กำหนดตำแหน่งที่0 ของแถวที่ 0 (อยู่ข้างบนสุดของจอ LCD)
  lcd.print("Wait 5 Sec AP Config"); //แถวที่ 0  ตำแหน่งที่  0  ให้แสดงตัวอักษร

  for (int i = 5; i > -1; i--) {
    digitalWrite(D0, HIGH);
    delay(500);
    digitalWrite(D0, LOW);
    delay(500);
    Serial.print (String(i) + " ");//แสดงข้อความใน Serial Monitor
    lcd.setCursor(10, 1);
    lcd.print(String(i) + " ");
    lcd.setCursor(0, 2);
    lcd.print("Button Press->config");

  }


  if (digitalRead(D3) == LOW) {
    digitalWrite(D0, HIGH);
    Serial.println("Button Pressed");//แสดงข้อความใน Serial Monitor
    lcd.clear();
    lcd.setCursor(4, 0);
    lcd.print("Button Pressed");
    lcd.setCursor(0, 1);
    lcd.print("Smartphone AP Config ");
    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.......OK!)");//แสดงข้อความใน Serial Monitor
  strcpy(blynk_token, custom_blynk_token.getValue());
  lcd.clear();
  lcd.setCursor(2, 2);
  lcd.print("Connected....OK!");
  delay(1000);


  //save the custom parameters to FS
  if (shouldSaveConfig) {
    Serial.println("saving config");//แสดงข้อความใน Serial Monitor
    lcd.setCursor(4, 1);
    lcd.print("saving config");
    delay(1000);
    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
      lcd.setCursor(4, 1);
      lcd.print("Failed> open config");
      delay(1000);
    }
    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

  lcd.clear();
  lcd.setCursor(2, 1);//กำหนดตำแหน่งที่0 ของแถวที่ 0 (อยู่ข้างบนสุดของจอ LCD)
  lcd.print("IP :"); //แถวที่ 0  ตำแหน่งที่  0  ให้แสดงตัวอักษร
  lcd.setCursor(6, 1);
  lcd.print(WiFi.localIP()); //แถวที่ 0  ตำแหน่งที่  0  ให้แสดงตัวอักษร




  // 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 วินาที)







  char_menu1(); //สร้าง Function
  Scheduler.start(&blynk_task);
  Scheduler.start(&rssi_print_task);
  Scheduler.start(&internet_print_task);
  Scheduler.start(&DMT_task);
  Scheduler.start(&esprestart);
  //Scheduler.start(&Pb_task);
  Scheduler.begin();

}


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


void char_menu1() {

  lcd.setCursor(0, 3);
  lcd.write(4);

  lcd.setCursor(13, 3);
  lcd.print("Blynk");

  lcd.setCursor(2, 3);
  lcd.print("Internet");

  lcd.setCursor(2, 2);
  lcd.print("PUYIOT");

}





//*****************************************************************************************************
//*******************************     void loop       *************************************************


void loop() {//Loop นี้จะใใช้งานไม่ได้ถ้าทำเป็น MultiTask แล้ว
}

//*******************************   จบ  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
}
1 Likes

อย่างนี้ก็ได้หรอ บางทีผมก็แอบกังวนอยู่ในๆ ว่าหากรันยาวๆ มันอาจจะ error ได้ การรีเซตในช่วงเวลา ที่ไม่ได้ ทำงานใน process ใดๆ เลย ก็เป็นอีกทางเลือกที่หน้าสนใจ ขนาดมือถือ แรงๆ สเถียรสูงหลายยี่ห้อ ใช้ไปนานๆ ยังต้องรีเซตใหม่เลย นับประสาอะไรกับ esp เล้า ขอบคุณมากครับพี่ ชี่ทางสว่างเลยครับ

ได้ครับ เรื่องเล็กๆ น้อย ๆ ที่เป็นพื้นฐานแบบนี้ เราต้องเอาให้ได้ก่อน แล้วพัฒนาต่อยอดไปเรื่อยๆ

ลืมไปครับ Code ตั้งเวลา


const long oneSecond = 1000;  // a second is a thousand milliseconds
const long oneMinute = oneSecond * 60;
const long oneHour   = oneMinute * 60;
const long fourHour   = oneHour * 4;
const long oneDay    = oneHour * 24;

 

void setup() {

      pinMode(D9, OUTPUT);
      digitalWrite(D9, HIGH);//ให้ D9 เป็น 0

    }
    void loop()  {
      delay(fourHour);
      digitalWrite(D9, LOW);//ให้ D9 เป็น 1
      //delay(2000);
      // digitalWrite(D9, HIGH);//ให้ PinRx เป็น 0 ไม่มีไฟจ่ายจะลง Ground แทน

    }
3 Likes

ทรานซิสเตอร์ทำหน้าที่เหมือนสวิทช์น่าจะนำไปประยุกต์ใช้ได้กับบอร์ดarduino อื่นได้ ที่มีขารีเซ็ต
ดีครับ

Diagram ตัวนี้ ผมปรับเปลี่ยนใหม่ กำลังทดสอบการใช้งานอยู่ ในรูปจะมี LED Switch บ้าง ผมแค่ทดสอบนะครับ แต่ผลลัพธ์ ตาม Diagram ครับ


1 Likes

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

แล้วตอนนี้ทำอะไรเสร็จแล้วบ้าง ติดปัญหาอะไรอยู่ตอนนี้

ติดปัญหาตรงที่คำนวณค่าไฟฟ้า แบบเซ็ดค่าft ได้ และก็กราฟครับ ส่วนอินพุตเหลือเขียนโปรแกรมสั่งตั่งเวลาในการหยอดเหรียญและสั่งปิดเปิดดีเลย์ครับ ถ้าพี่พอให้คำแนะนำหนือช่วยได้ขอ id.line ไว้ติดต่อได้ไหมครับ

ตัวอย่างนะครับ ที่ผมใช้อยู่

ไฟฟ้า.xlsx (284.5 KB)

สร้างการคำนวณด้วย Excel ก่อน (ชื่อ Sheet “การคำนวณ”)เพื่อทดสอบว่าตรงหรือไม่ จากนั้นก็เอาไปเขียน code ครับ

 voltage = pzem.voltage();
    current = pzem.current();
    power = pzem.power();
    energy = pzem.energy();
    frequency = pzem.frequency();
    pf = pzem.pf();


    //1.2 อัตราปกติปริมาณการใช้พลังงานไฟฟ้าเกินกว่า 150 หน่วยต่อเดือน
    //ที่บ้านเราใช้ค่านี้ ประเภท 1125 คือ ใช้ไฟฟ้าเกิน 150 หน่วย/เดือน อัตราค่าบริการ 38.22 บาท/เดือน

    //1 -  150 หน่วยละ 3.2484  บาท

    if (energy >= 1 && energy <= 150) {
      kWh_1 = energy * 3.2484;
    }
    if (energy > 150) {
      kWh_1 = 150 * 3.2484;
    }

    //หน่วยที่  151    -  400 หน่วยละ 4.2218  บาท

    if (energy >= 151 && energy <= 400) {
      kWh_2 = (energy - 150) * 4.2218;
    }
    if (energy > 400) {
      kWh_2 = 250 * 4.2218;
      //401        -- >   หน่วยละ 4.4217  บาท
      kWh_3 = (energy - 400) * 4.4217;
    }

    //รวมค่าใช้จ่ายทั้งหมด
    kWh_T = kWh_1 + kWh_2 + kWh_3;
    kWh_T1 = kWh_T + 38.22 + (energy * Ft_float);

    Electric_bill = kWh_T1 + (kWh_T1 * 0.07);

ส่วนการ เซ็ดค่าft ประจำเดือน ผมใช้ วิธีการตั้งค่าผ่าน Text input ของ Blynk ครับ โดยเข้าไปเชคค่า ft ที่นี่่ก่อน
https://www.erc.or.th/ERCWeb2/Front/StaticPage/StaticPage.aspx?p=186&Tag=ค่าไฟฟ้าโดยอัตโนมัติ%20(Ft)&muid=23&prid=114";

จากนั้นป้อนเข้าไปใน Text input ของ Blynk แล้วให้เก็บไว้ใน Eeprom ของ ESP แล้ว get ค่า ออกมาคำนวณต่อครับ

BLYNK_WRITE(V28)//ค่า  Ft  ที่ตั้งจาก Blynk เข้าเครื่อง  สร้าง Text input ที่ Blynk App
{
  Ft_st = param.asString();//รับค่าข้อความจาก Blynk เข้ามา เก็บในรูปแบบ String
  Ft_float = Ft_st.toFloat();//แปลงค่าจาก String เป็น float
  EEPROM.put(200, Ft_float); //เขียนค่า Ft_float  ที่เป็น float  ลงใน Address xxx
  EEPROM.commit(); //จบการเขียน
  Ft_float = EEPROM.get(200, Ft_float);//อ่าน ค่า Ft_float ที่เป็น float จาก Address xxx มาใช้งาน
}

ย้อนกลับไปดู code ข้างบน บรรทัด kWh_T1 = kWh_T + 38.22 + (energy * Ft_float);

พี่เคยใช้ netpie ไหมครับ ทำแบบที่พี่ทำใน blynk เซ็ดค่า ft อะครับ ผมงมตรงนี้อยู่และครับพี่

ที่ผมแนะนำไป มีหลักการคือ หาระบบ การเชื่อมต่อ ที่สามารถป้อนข้อมูล เข้ามาใน ESP ของเราให้ได้เท่านั้นเองครับ แต่รูปแบบการนำข้อมูลเข้า ก็แล้วแต่ใครจะรู้ว่าระบบอะไรสามารถนำข้อมูลเข้า ESP ได้
netpie ผมไม่เคยใช้ครับ ใช้แต่ Blynk

ตัวอย่างครับ

1 Likes

ขอคำแนะนำหน่อยได้ไหมครับ
ผมทำโปรเจค ให้ esp32 ดึงว่าค่าเวลามาจาก server แล้วตั้งเวลาว่า 10 โมงเช้า จ่าย 1 ออกมา
4 โมงเย็นจ่าย 0 ออกมา แต่ในช่วงนี้บอร์ดจะมีคำสั่งให้ reset บอร์ด ซึ่งเมื่อ reset แล้ว ค่า 1 ที่จ่ายออกมาจะกลายเป็น 0 ก่อนถึงเวลาที่กำหนด ตือ 4 โมงเย็น ควรใช้คำสั่งแบบไหนดีครับ ผมลองแล้วมันยังไม่เวิร์คครับ

ขอบคุณครับ

1 Likes

ควรมีการเก็บคำสั่งปัจจุบันไว้ใน EEPROM ครับ หากมีการรีเซตเมื่อเริ่มทำงานใหม่เราก็ให้ไปอ่านค่าเดิมก่อนดับจาก EEPROM ก่อน

1 Likes

ขอบคุณครับ