วันศุกร์ที่ 22 เมษายน พ.ศ. 2559

วิธีดึงเวลาสากล จาก Internet มาใช้งานกับ ESP8266

วิธีดึงเวลาสากล จาก Internet มาใช้งานกับ ESP8266


      สำหรับนักพัฒนา เรื่องของเวลาถือเป็นเรื่องที่น่าเบื่อ และน่ารำคาญ พอสมควร สำหรับงานที่ต้องการเสถียรภาพของเวลา เช่น การตั้งเวลาเพื่อควสบคุมอุปกรณ์ต่างๆ หรือการบันทึกข้อมูลจากฐานเวลา เป็นต้น อุปกรณ์ที่ใช้นับเวลา โดยทั่วไปนั้น คือ โมดูลนาฬิกา (Real Time Clock Module) ซึ่งก็พอมีให้เลือกอยู่หลายชนิดด้วยกัน ตั้งแต่ราคาถูกๆ ซึ่งก็ใช้งานได้ตามสภาพ ไปจนถึงราคาแพงๆ


        แต่ทุกวันนี้อุปกรณ์ Microcontroller เข้าสู่ยุคของ Internet of things แล้ว ในเมื่ออุปกรณ์ควบคุมสามารถเชื่อมต่อกับ Internet ได้ เวลาก็ไม่ใช่ปัญหาอีกต่อไป บทความนี้จะเป็นการนำNode MCU หรือ ESP8266 มาตั้งเวลา โดยไม่ต้องใช้โมดูลนาฬิกา แต่จะเป็นการดึงเอาเวลาสากลจาก Server มาใช้งานแทน

       เตรียม ESP8266 หรือ Node MCU ของท่านให้พร้อม แล้วมาเริ่มกันเลย..!!

          1) สำหรับใครที่ยังไม่ได้ติดตั้ง ESP8266 บน Arduino IDE ก่อนอื่นให้ติดตั้ง Board ESP8266 ก่อน ดูวิธีการติดตั้งได้จาก บทความ การใช้งาน NodeMCU + Arduino IDE + Blynk App

          2) เมื่อติดตั้งเสร็จแล้ว ให้ Copy หรือ เขียน Code ตามตัวอย่าง


          3) ทำการ Upload Program ให้เรียบร้อย แล้วเปิด Serial Monitor


         โปรแกรมก็จะแสดง วัน และเวลาปัจจุบัน ออกทาง Serial Monitor เพียงเท่านี้เราก็จะได้เวลาปัจจุบันโดยไม่ต้องต่อ RTC แล้ว

         แล้วเราจะ ดึงค่าเวลา ต่างๆ มาใช้ยังไง ????? ง่ายมากครับ ให้สังเกตุที่บรรทัด  struct tm* p_tm = localtime(&now)  ซึ่งเป็น Struct เก็บค่าตัวแปรต่างๆไว้ ดังนี้


struct tm {
   int tm_sec;         /* วินาที,  range 0 to 59          */
   int tm_min;         /* นาที, range 0 to 59           */
   int tm_hour;        /* ชั่วโมง, range 0 to 23             */
   int tm_mday;        /* วันที่, range 1 to 31  */
   int tm_mon;         /* เดือน, range 0 to 11             */
   int tm_year;        /* ปีคริสศักราช ตั้งแต่ 1900   */
   int tm_wday;        /* วัน, range 0 to 6    */
   int tm_yday;        /* วันใน 1 ปี, range 0 to 365  */
   int tm_isdst;       /* daylight saving time             */
};

        เราสามารถนำค่า Parameter ต่างๆ ไปใช้งานได้เลย โดยใช้ตัวแปร p_tm->tm_hour (ตัวแปรเก็บค่าชั่วโมง) คราวนี้ ผมจะลองดึงเฉพาะ วินาที แสดงออกทาง Serial Monitor โดยเพิ่มโค้ด Serial.Print (p_tm -> tm_sec) เข้าไป ตามตัวอย่าง


void loop()
{
  //configTime(timezone, dst, "pool.ntp.org", "time.nist.gov");    //แสดงเวลาปัจจุบัน
  time_t now = time(nullptr);
  struct tm* p_tm = localtime(&now);
  Serial.print("Sec = ");
  Serial.print(p_tm->tm_sec);
  Serial.println("");
  delay(1000);
}

       ทดสอบการทำงาน


      เพียงเท่านี้เราก็สามารถเลือกค่าเวลาต่างๆ ไปใช้ในการ แสเงเวลา หรือตั้งเวลา ได้เลย โดยไม่ต้องเสียเงินซื้อ RTC Module อีกต่อไป.....


*********************************************************************************
 Montien Ngamkaew 
*********************************************************************************

12 ความคิดเห็น:

  1. สอบถามหน่อยครับ เกี่ยวกับการควบคุมการปิดเปิดไฟ ด้วยการตั้งเวลา (รับค่าเวลาจาก server มาใช้แทนโมดูลนาฬิกา)
    คือ ตอนนี้สามารถแสดงเวลาออกมาที่ serial monitor ได้แล้ว แต่ไม่สามารถเอาค่าไปตั้งเป็นเวลาเปิดปิดได้ เช่น ให้ไฟเปิดตั้งแต่ 17 - 24 น น่ะครับ
    (ลองใช้ tm_sec หรือ p_tm->tm_sec ก็ไม่ได้ครับ)
    ไม่ทราบว่าต้องตั้งค่าอย่างไร จึงจะสามารถเปิดปิดไฟได้ครับ

    ตอบลบ
    คำตอบ
    1. if((p_tm->tm_hour==12) && (p_tm->tm_min==12) &&( p_tm->tm_sec==30))
      {
      digitalWrite(LED,HIGH);
      delay(5000);
      digitalWrite(LED,LOW);
      }

      ลบ
    2. แล้วจะให้รับค่า hour min sec จาก Anto.io ต้องเขียนcode ยังไงครับ

      ลบ
  2. ดึงเวลาสากล มาใช้ร่วมกับเปิดปิด servo ใน blynk ยังไงได้บ้างคะ

    ตอบลบ
  3. เปิด MOniter ขึ้นมาแล้ว ไม่มีวันและเวลาบอกเลยครับ

    ตอบลบ
  4. ถ้าถึงเวลาที่กำหนดแล้วให้แจ้งเข้าไลน์ละครับ

    ตอบลบ
    คำตอบ
    1. ทำได้หรือยังครับ ว่าจะทำเหมือนกัน

      ลบ
  5. ความคิดเห็นนี้ถูกผู้เขียนลบ

    ตอบลบ
  6. ถ้าต้องการหน่วย เป็น ms ทำไงคตรับ

    ตอบลบ
  7. configTime(timezone, dst, "th.pool.ntp.org", "asia.pool.ntp.org");
    time_t now = time(nullptr);
    struct tm* p_tm = localtime(&now);
    delay(1000);
    Serial.print("TIME ");
    Serial.print(p_tm->tm_hour);
    Serial.print(":");
    Serial.print(p_tm->tm_min);
    Serial.print(":");
    Serial.print(p_tm->tm_sec);
    Serial.println("");
    Serial.print("DAY ");
    Serial.print(p_tm->tm_mday,DEC);
    Serial.print("/");
    Serial.print(p_tm->tm_mon,DEC);
    Serial.print(":");
    Serial.print(p_tm->tm_year,DEC);
    Serial.println("");
    Serial.print(p_tm->tm_wday,DEC);
    Serial.print("/");
    Serial.print(p_tm->tm_yday,DEC);
    Serial.print("/");
    Serial.print(p_tm->tm_isdst,DEC);
    Serial.println("");



    if((p_tm->tm_hour==20) && (p_tm->tm_min==35) &&(p_tm->tm_sec==00))
    {
    digitalWrite(D5,HIGH);
    Serial.print("STATE ON");
    }
    else if ((p_tm->tm_hour==20) && (p_tm->tm_min==40) &&(p_tm->tm_sec==00))
    {
    digitalWrite(D5,LOW);
    }

    Serial.println("");
    delay(3000);

    }

    ตอบลบ
  8. แจกฟรี ใช้งานได้ เลย ctrl relay sw D5,D6,D7

    // Date, Time and Alarm functions using a DS3231 RTC connected via I2C and Wire lib
    // ESP-12E PIN SCL - D1(GPIO5) // SDA - D2(GPIO4) VOLT - 3.3-5V
    // SW auto ----> D5, D6, D7
    #include
    #include // not used here, but needed to prevent a RTClib compile error
    #include
    RTC_DS3231 RTC;
    #include

    #include
    const char* WIFI_SSID = "..........";
    const char* WIFI_PWD = "........";
    int timezone = 7;
    char ntp_server1[20] = "3.th.pool.ntp.org";
    char ntp_server2[20] = "1.asia.pool.ntp.org";
    char ntp_server3[20] = "0.asia.pool.ntp.org";
    int dst = 0;
    bool displayTime = 0;

    void setup () {

    WiFi.begin(WIFI_SSID, WIFI_PWD);
    configTime(timezone * 3600, dst, ntp_server1, ntp_server2, ntp_server3);
    delay(1000);
    Serial.begin(115200);
    pinMode(D5, OUTPUT);

    Wire.begin();
    RTC.begin();
    RTC.adjust(DateTime(__DATE__, __TIME__));
    if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    RTC.adjust(DateTime(__DATE__, __TIME__));
    }
    DateTime now = RTC.now();
    RTC.setAlarm1Simple(22, 15);
    RTC.turnOnAlarm(1);
    if (RTC.checkAlarmEnabled(1)) {
    Serial.println("Alarm Enabled");
    }
    }


    void loop () {


    DateTime now = RTC.now();

    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour());
    Serial.print(':');
    Serial.print(now.minute());
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    Serial.print("Tempeature = ");
    Serial.print(RTC.getTemperature()); // คำสั่งดึงอุณหภูมิออกมาแสดง
    Serial.println(" C");
    Serial.print("TeST = ");
    Serial.print(analogRead(A0)); // คำสั่งดึงอุณหภูมิออกมาแสดง
    Serial.println("Lux");


    if (now.hour() == 9 && now.minute() == 20 ) { //ถ้าชั่วโมงเท่ากับ 22 และนาทีเท่ากับ 19 จะสั่งให้เปิดไฟ LED
    digitalWrite(D5, HIGH); // สั่งให้ LED ติดสว่าง
    Serial.print("Relay ON");
    }
    else if (now.hour() == 9 && now.minute() == 30 )
    {
    digitalWrite(D5, LOW); // สั่งให้ LED ดับ
    }


    Serial.println();
    delay(3000);
    }

    ตอบลบ