Search Code

ESP32 튜토리얼 53/55 - LCD 인터넷 시계 만들기 | SunFounder의 ESP32 IoT 학습 키트

ESP32 튜토리얼 53/55 - LCD 인터넷 시계 만들기 | SunFounder의 ESP32 IoT 학습 키트

이 튜토리얼에서는 SunFounder의 ESP32 마이크로컨트롤러를 사용하여 인터넷에 연결된 LCD 시계를 만들어 보겠습니다. 이 시계는 인터넷을 통해 현재 시간에 자동으로 동기화되며, 12시간 또는 24시간 형식으로 시간을 표시하고 요일, 날짜, 월도 함께 표시합니다. 네트워크 시간 프로토콜(NTP)을 사용하면 수동 조정 없이도 시계가 정확하게 유지됩니다.

esp32-53-internet-clock-main

이 프로젝트는 ESP32의 내장 Wi-Fi 기능을 활용하여 NTP 서버에서 현재 시간을 가져옵니다. 시간을 표시하기 위해 액정 디스플레이(LCD)를 사용하며, 사용자 기본 설정에 따라 형식을 지정할 수 있습니다. 단계에 대한 자세한 설명이 필요하면 (비디오 00:30)의 영상을 참조하세요.

하드웨어 설명

이 프로젝트의 주요 구성 요소는 ESP32 마이크로컨트롤러, 20x4 LCD 디스플레이, 전원 공급 장치입니다. ESP32는 내장 Wi-Fi와 Bluetooth를 갖춘 강력한 마이크로컨트롤러로 IoT 프로젝트에 적합합니다. LCD는 시간과 날짜를 표시하는 데 사용되며 다양한 디스플레이 크기로 구성할 수 있습니다.

LCD는 I2C 프로토콜로 작동하므로 두 개의 전선(SDA 및 SCL)을 통한 통신이 가능합니다. 이렇게 하면 배선이 간단해지고 ESP32에서 필요한 핀 수가 줄어듭니다. NTP 서버 연결은 ESP32의 Wi-Fi 기능을 사용하여 실시간 업데이트가 가능합니다.

 

  • 올바른 공급 전압(5V)을 확인하세요.
  • 안정성을 위해 전원 핀 근처에 디커플링 커패시터를 사용하세요.
  • 버스 충돌을 피하기 위해 I2C 연결에 주의하세요.
  • LCD의 I2C 주소(0x27 또는 0x3F)를 확인하세요.
  • 정확한 연결을 위해 Wi-Fi 자격 증명을 확인하세요.
  • 코드에서 일광 절약 시간제 조정을 처리하세요.
  • 지리적 위치에 맞는 올바른 NTP 서버를 사용하세요.
  • 디스플레이를 업데이트하기 전에 항상 LCD를 지우세요.

배선 지침

ESP32-11_LCD-wiring

ESP32와 LCD를 배선하려면 먼저 전원 핀을 연결하세요. LCD의 VCC를 ESP32의 5V 핀에 연결하고 LCD의 GND 핀을 ESP32의 GND 핀에 연결합니다. I2C 통신을 위해 LCD의 SDA 핀을 ESP32의 GPIO 21에 연결하고 SCL 핀을 GPIO 22에 연결합니다. 통신 문제를 피하기 위해 연결이 안전한지 확인하세요.

배선을 설정할 때 쉽게 연결할 수 있도록 암-수 점퍼 와이어를 사용하세요. LCD에 다른 I2C 주소나 핀 구성이 있는 경우 코드를 그에 맞게 조정하세요. 필요한 경우 (비디오 05:30)의 영상에서 대체 배선 옵션을 참조하세요.

코드 예제 및 설명

코드는 LCD를 초기화하고 NTP 서버에서 시간 데이터를 가져오기 위해 Wi-Fi 연결을 설정합니다. ssidpassword와 같은 주요 식별자는 Wi-Fi 네트워크에 연결하는 데 사용되며, ntpServer1ntpServer2는 사용할 NTP 서버를 지정합니다.

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

이 코드 조각은 네트워크 자격 증명과 서버 주소를 보여줍니다. Wi-Fi SSID와 비밀번호를 정확히 입력해야 합니다. 실수가 있으면 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에 현재 시간, 요일, 날짜가 표시됩니다. loop() 함수 덕분에 시간은 5초마다 업데이트됩니다. NTP 서버 연결에 실패하면 Serial Monitor에 시간을 아직 사용할 수 없다는 메시지가 표시됩니다 (비디오 12:00).

일반적인 문제로는 잘못된 배선, 잘못된 I2C 주소, 잘못된 Wi-Fi 자격 증명이 있습니다. 모든 연결이 안전한지, NTP 서버가 네트워크에서 연결 가능한지 확인하세요.

비디오 타임스탬프

  • 00:00 시작
  • 2:10 소개
  • 5:15 배선 설명
  • 7:32 Arduino 코드 설명
  • 18:43 Arduino IDE에서 ESP32 보드 및 COM 포트 선택
  • 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)