ค้นหาโค้ด

บทเรียน ESP32 53/55 - สร้างนาฬิกาอินเทอร์เน็ตบนจอ LCD | ชุดเรียนรู้ IoT ESP32 ของ SunFounder

บทเรียน ESP32 53/55 - สร้างนาฬิกาอินเทอร์เน็ตบนจอ LCD | ชุดเรียนรู้ IoT ESP32 ของ SunFounder

ในบทช่วยสอนนี้ เราจะสร้างนาฬิกา LCD ที่เชื่อมต่ออินเทอร์เน็ตโดยใช้ไมโครคอนโทรลเลอร์ ESP32 จาก SunFounder นาฬิกานี้จะซิงโครไนซ์กับเวลาปัจจุบันผ่านอินเทอร์เน็ตโดยอัตโนมัติ โดยแสดงเวลาในรูปแบบ 12 ชั่วโมงหรือ 24 ชั่วโมง พร้อมกับวันในสัปดาห์ วันที่ และเดือน การใช้ Network Time Protocol (NTP) ช่วยให้แน่ใจว่านาฬิกายังคงแม่นยำโดยไม่ต้องปรับด้วยตนเอง

esp32-53-internet-clock-main

โปรเจกต์นี้ใช้ความสามารถ Wi-Fi ในตัวของ ESP32 เพื่อดึงเวลาปัจจุบันจากเซิร์ฟเวอร์ NTP เราจะใช้ Liquid Crystal Display (LCD) เพื่อแสดงเวลา ซึ่งสามารถจัดรูปแบบได้ตามความต้องการของผู้ใช้ หากต้องการคำอธิบายเพิ่มเติมเกี่ยวกับขั้นตอนใด ๆ โปรดดูวิดีโอที่ (ในวิดีโอที่ 00:30)

อธิบายฮาร์ดแวร์

ส่วนประกอบหลักสำหรับโปรเจกต์นี้ประกอบด้วยไมโครคอนโทรลเลอร์ ESP32 จอแสดงผล LCD ขนาด 20x4 และแหล่งจ่ายไฟ ESP32 เป็นไมโครคอนโทรลเลอร์ที่ทรงพลังพร้อม Wi-Fi และบลูทูธในตัว ทำให้เหมาะสำหรับโปรเจกต์ IoT LCD ใช้เพื่อแสดงเวลาและวันที่ และสามารถกำหนดค่าสำหรับขนาดจอแสดงผลที่แตกต่างกันได้

LCD ทำงานผ่านโปรโตคอล I2C ซึ่งช่วยให้สื่อสารผ่านสายสองเส้น (SDA และ SCL) ซึ่งช่วยลดความซับซ้อนของการเดินสายและลดจำนวนพินที่จำเป็นบน ESP32 การเชื่อมต่อกับเซิร์ฟเวอร์ NTP ทำได้โดยใช้ความสามารถ Wi-Fi ของ ESP32 ทำให้สามารถอัปเดตแบบเรียลไทม์ได้

 

  • ตรวจสอบให้แน่ใจว่าแรงดันไฟฟ้าของแหล่งจ่ายไฟถูกต้อง (5 V)
  • ใช้ตัวเก็บประจุแยกสัญญาณใกล้กับพินจ่ายไฟเพื่อความเสถียร
  • ระมัดระวังกับการเชื่อมต่อ I2C เพื่อหลีกเลี่ยงความขัดแย้งของบัส
  • ตรวจสอบที่อยู่ I2C ของ LCD (0x27 หรือ 0x3F)
  • ตรวจสอบข้อมูลประจำตัว Wi-Fi เพื่อการเชื่อมต่อที่แม่นยำ
  • จัดการการปรับเวลาออมแสงในโค้ดของคุณ
  • ใช้เซิร์ฟเวอร์ NTP ที่ถูกต้องสำหรับตำแหน่งทางภูมิศาสตร์ของคุณ
  • ล้างหน้าจอ LCD ก่อนอัปเดตการแสดงผลเสมอ

คำแนะนำการเดินสายไฟ

ESP32-11_LCD-wiring

ในการเดินสายไฟ ESP32 กับ LCD ให้เริ่มต้นด้วยการเชื่อมต่อพินจ่ายไฟ เชื่อมต่อ VCC ของ LCD เข้ากับพิน 5V บน ESP32 และพิน GND ของ LCD เข้ากับพิน GND บน ESP32 สำหรับการสื่อสาร I2C ให้เชื่อมต่อพิน SDA ของ LCD เข้ากับ GPIO 21 บน ESP32 และพิน SCL เข้ากับ GPIO 22 ตรวจสอบให้แน่ใจว่าการเชื่อมต่อแน่นหนาเพื่อหลีกเลี่ยงปัญหาการสื่อสาร

เมื่อตั้งค่าการเดินสายไฟ ให้ใช้สายจัมเปอร์แบบ male-to-female เพื่อการเชื่อมต่อที่ง่ายดาย หาก LCD ของคุณมีที่อยู่ I2C หรือการกำหนดค่าพินที่แตกต่างกัน ให้ปรับโค้ดตามนั้น โปรดดูวิดีโอที่ (ในวิดีโอที่ 05:30) สำหรับตัวเลือกการเดินสายไฟอื่น ๆ หากจำเป็น

ตัวอย่างโค้ดและคำอธิบาย

โค้ดเริ่มต้น LCD และตั้งค่าการเชื่อมต่อ Wi-Fi เพื่อดึงข้อมูลเวลาจากเซิร์ฟเวอร์ NTP ตัวระบุสำคัญ เช่น ssid และ password ใช้เพื่อเชื่อมต่อกับเครือข่าย Wi-Fi ในขณะที่ ntpServer1 และ ntpServer2 ระบุเซิร์ฟเวอร์ NTP ที่จะใช้

const char* ssid = "dars";
const char* password = "llllllllllllll";
const char* ntpServer1 = "pool.ntp.org";
const char* ntpServer2 = "time.nist.gov";

ตัวอย่างนี้แสดงข้อมูลประจำตัวเครือข่ายและที่อยู่เซิร์ฟเวอร์ ตรวจสอบให้แน่ใจว่าคุณป้อน SSID และรหัสผ่าน Wi-Fi ของคุณอย่างถูกต้อง เนื่องจากข้อผิดพลาดใด ๆ จะป้องกันไม่ให้ ESP32 เชื่อมต่อกับอินเทอร์เน็ต

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

void printLocalTime() {
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)) {
    Serial.println("No time available (yet)");
    return;
  }
  char timeHour[5];
  strftime(timeHour, 5, "%H", &timeinfo);

โค้ดนี้ตรวจสอบว่าเวลาท้องถิ่นพร้อมใช้งานหรือไม่และดึงชั่วโมง ชั่วโมงที่จัดรูปแบบแล้วจะถูกใช้เพื่อแสดงเวลาปัจจุบันบน LCD หากเวลายังไม่พร้อมใช้งาน จะพิมพ์ข้อความไปยัง Serial Monitor

สุดท้าย ฟังก์ชัน setup() เริ่มต้น LCD และเชื่อมต่อกับ Wi-Fi นอกจากนี้ยังกำหนดค่าการตั้งค่าเซิร์ฟเวอร์ NTP และตั้งค่าฟังก์ชันเรียกกลับสำหรับการซิงโครไนซ์เวลา

void setup() {
  Serial.begin(115200);
  lcd.init(); // initialize the lcd 
  lcd.backlight(); // Turns on the LCD backlight.
  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);

ข้อความนี้เริ่มต้น Serial Monitor สำหรับการดีบัก ตั้งค่า LCD และพยายามเชื่อมต่อกับเครือข่าย Wi-Fi ที่ระบุ สถานะการเชื่อมต่อจะถูกพิมพ์ไปยัง Serial Monitor เพื่อให้คุณสามารถตรวจสอบการเชื่อมต่อได้

การสาธิต / สิ่งที่คาดหวัง

เมื่อตั้งค่าสำเร็จ LCD จะแสดงเวลาปัจจุบัน วันในสัปดาห์ และวันที่ คุณสามารถคาดหวังให้เวลาอัปเดตทุก 5 วินาที ต้องขอบคุณฟังก์ชัน loop() หากการเชื่อมต่อกับเซิร์ฟเวอร์ NTP ล้มเหลว ข้อความจะปรากฏบน Serial Monitor เพื่อระบุว่าเวลายังไม่พร้อมใช้งาน (ในวิดีโอที่ 12:00)

ข้อผิดพลาดทั่วไป ได้แก่ การเดินสายไฟที่ไม่ถูกต้อง ที่อยู่ I2C ที่ผิด และข้อมูลประจำตัว Wi-Fi ที่ไม่ถูกต้อง ตรวจสอบให้แน่ใจว่าการเชื่อมต่อทั้งหมดแน่นหนาและเซิร์ฟเวอร์ NTP สามารถเข้าถึงได้จากเครือข่ายของคุณ

ไทม์สแตมป์ของวิดีโอ

  • 00:00 เริ่มต้น
  • 2:10 บทนำ
  • 5:15 อธิบายการเดินสายไฟ
  • 7:32 อธิบายโค้ด Arduino
  • 18:43 การเลือกบอร์ด ESP32 และพอร์ต COM ใน Arduino IDE
  • 20:27 การสาธิตนาฬิกาอินเทอร์เน็ต

ภาพ

ESP32-11_LCD-wiring
ESP32-11_LCD-wiring
ESP32-11_LCD-wiring-schematic
ESP32-11_LCD-wiring-schematic
esp32-53-internet-clock-main
esp32-53-internet-clock-main
854-ESP32 Tutorial 53/55- Internet Clock
ภาษา: C++

/*
Internet Clock using SunFounder's IoT ESP32 Learning kit
Full video instruction https://youtu.be/0KnuNqfiVug
📚⬇️ Download and resource page https://robojax.com/RJT686
Internet Clock for ESP32
Written by Ahamd Shasmhiri on Dec 31, 2023 at 19:29
www.Robojax.com

*/
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
//SDA->21,SCL->22 
LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

const bool showSeconds = true;//set to "true" to show seconds and "false" to hide
const bool showShortMonth = false;//December = false, Dec=true
const bool show24Hours = true;//true to have 18:30 or false to have 6:30

#include <WiFi.h>
#include "time.h"
#include "sntp.h"
#include "TZ.h"
//TZ.h is taken from https://github.com/esp8266/Arduino/blob/master/cores/esp8266/TZ.h


const char* ssid       = "dars";
const char* password   = "llllllllllllll";

const char* ntpServer1 = "pool.ntp.org";
const char* ntpServer2 = "time.nist.gov";
const long  gmtOffset_sec = -5 * 3600;
const int   daylightOffset_sec = 3600;


const String months[][2] ={
            "January","Jan",
            "February","Feb",
            "March","Mar",
            "April","Apr",
            "May","May",
            "June","Jun",
            "July","Jul",
            "August","Aug",
            "September","Sep",
            "October","Oct",
            "November","Nov",
            "December","Dec"
      };


void printLocalTime()
{
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    Serial.println("No time available (yet)");
    return;
  }


  //Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S 12Hours: %I:%M:%S");

    // get time format HH:MM
  char timeHour[5];
  strftime(timeHour,5, "%H", &timeinfo);
  String hourString = String(timeHour);//convert timeHour to string
  char timeMinute[3];
  strftime(timeMinute,3, "%M", &timeinfo); 
  String minuteString = String(timeMinute);  
  //Serial.println(hourString);
  if(!show24Hours)
  {
    if(hourString.toInt()  >= 12) 
    {
       minuteString =  minuteString + "PM";
    }else{
       minuteString =  minuteString + "AM";      
    }
 
  }



  char timeSeconds[3];
  strftime(timeSeconds,3, "%S", &timeinfo);  

  char timeDayofWeek[10];
  strftime(timeDayofWeek, 10 , "%A", &timeinfo);  

  char timeMonth[10];
  strftime(timeMonth, 10 , "%B", &timeinfo); 
  String Month = String(timeMonth);
  if(showShortMonth)
  {
  for(int m=0; m <12; m++)
  {

    if(Month == months[m][0] )
    {
      Month = months[m][1];
      //Serial.println(months[m][1]);
    }
  }
  }

  char timeDayofMonth[3];
  strftime(timeDayofMonth,3 , "%d", &timeinfo);   

  char timeYear[5];
  strftime(timeYear, 5 , "%Y", &timeinfo);   


  String time = String(timeHour) + ":" +  minuteString ;
  if(showSeconds) time = time +":" + String(timeSeconds);//add seconds if showSeconds=true
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(time);
  lcd.print(" ");
  lcd.print(String(timeDayofWeek));
  //
  lcd.setCursor(0, 1);
  lcd.print(timeDayofMonth);

  lcd.print(" ");
  lcd.print(Month);

  lcd.print(" ");
  lcd.print(timeYear);





}

// Callback function (get's called when time adjusts via NTP)
void timeavailable(struct timeval *t)
{
  Serial.println("Got time adjustment from NTP!");
  printLocalTime();
}

void setup()
{
  Serial.begin(115200);
  lcd.init();// initialize the lcd 
  lcd.backlight(); // Turns on the LCD backlight.
  lcd.print("Internet Clock"); 
  delay(3000);//waif 3 seconds
  // set notification call-back function
  sntp_set_time_sync_notification_cb( timeavailable );

  /**
   * NTP server address could be aquired via DHCP,
   *
   * NOTE: This call should be made BEFORE esp32 aquires IP address via DHCP,
   * otherwise SNTP option 42 would be rejected by default.
   * NOTE: configTime() function call if made AFTER DHCP-client run
   * will OVERRIDE aquired NTP server address
   */
  sntp_servermode_dhcp(1);    // (optional)

  /**
   * This will set configured ntp servers and constant TimeZone/daylightOffset
   * should be OK if your time zone does not need to adjust daylightOffset twice a year,
   * in such a case time adjustment won't be handled automagicaly.
   */
// configTime(gmtOffset_sec, daylightOffset_sec, ntpServer1, ntpServer2);

  /**
   * A more convenient approach to handle TimeZones with daylightOffset 
   * would be to specify a environmnet variable with TimeZone definition including daylight adjustmnet rules.
   * A list of rules for your zone could be obtained from https://github.com/esp8266/Arduino/blob/master/cores/esp8266/TZ.h
   */
   
  //configTzTime(TZ_America_Toronto, ntpServer1, ntpServer2);
  configTzTime(TZ_America_Toronto, ntpServer1, ntpServer2);  

  //connect to WiFi
  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
  }
  Serial.println(" CONNECTED");

}

void loop()
{
  delay(5000);
  printLocalTime();     // it will take some time to sync time :)
}

สิ่งที่คุณอาจต้องการ

แหล่งข้อมูลและเอกสารอ้างอิง

ไฟล์📁

ไฟล์ที่ต้องการ (.h)