12 스마트디바이스실습 12주차 - shinhw0219/SmartDevice_4 GitHub Wiki
-
정의: 유기 발광 다이오드 방식, 자체 발광 → 백라이트 불필요
-
특징: 얇고 저전력, 밝고 선명한 화질
-
크기·해상도 : 보통 0.96″, 1.3″, 1.5″, 해상도: 128×64 / 128×32
-
색상: 단색(흰색, 파랑 등) 또는 컬러 (본 강의는 단색)
-
정의: 직렬 통신 프로토콜, 2개 선(SDA, SCL)으로 다수 슬레이브 제어
-
SDA: 데이터 전송
-
SCL: 클럭 신호
-
속도 표준: 100 kHz
-
속도 패스트: 400 kHz
-
주소 지정: 기본 0x3C (모듈별 상이)
-
Adafruit_SSD1306: OLED 드라이버
-
Adafruit_GFX: 그래픽 처리
-
설치: IDE → 라이브러리 관리자에서 검색·설치
-
ESP32 → SDA/SCL 로 명령·데이터 전송
-
OLED 모듈(주소 0x3C) 수신 → 화면 출력
-
연결 확인: SDA/SCL 배선, I²C 주소
-
전원 안정성: 3.3 V 또는 5 V (모듈 사양 준수)
-
에러 대응: “SSD1306 오류” 발생 시 주소·배선 점검
- 정의: 인터넷 상에서 컴퓨터 시계를 동기화하는 프로토콜
- 목적: 네트워크에 연결된 장치들의 시간을 정확하게 맞춰 로그·통신·보안 정합성 유지
-
클라이언트 → 서버 요청
UDP 패킷으로 시간 요청 -
서버 → 클라이언트 응답
UTC 기반 시각을 전달 -
지연 시간 보정
왕복 지연(RTT)을 계산해 실제 시각 보정
- Stratum 0: 원자시계, GPS 수신기 등 최상위 시간 소스
- Stratum 1: Stratum 0에 직접 연결된 서버
-
Stratum 2+: 상위 Stratum 서버로부터 동기화받음
(일반적으로 Stratum 2~4 사용)
항목 | 값 |
---|---|
프로토콜 | UDP |
포트 | 123 (UDP) |
시간 형식 | 64-bit 타임스탬프 (32-bit 초 + 32-bit 소수) |
코드는 NTP_example.ino
를 참조하세요.
- 인터넷 연결: 안정적인 네트워크 필요
- 방화벽: UDP 123 포트 허용
- 보안: 인증되지 않은 서버 사용 시 위험
- 동기화 주기: 1시간~1일 간격 권장
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void setup() {
Serial.begin(9600);
// OLED 디스플레이 초기화
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("SSD1306 오류");
while (true);
}
// OLED 디스플레이 클리어
display.clearDisplay();
}
void loop() {
// "Hello, World!"를 크기가 다른 세 개의 텍스트로 표시
display.clearDisplay();
// 크기 6의 폰트로 텍스트 표시
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println("Hello, World!");
// 크기 8의 폰트로 텍스트 표시
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0, 15);
display.println("Arduino");
display.display();
delay(2000);
}
#include <WiFi.h> // WiFi 통신을 위한 라이브러리
#include <time.h> // 시간과 관련된 함수를 위한 라이브러리
#include <Adafruit_GFX.h> // 디스플레이를 위한 그래픽 라이브러리
#include <Adafruit_SSD1306.h> // SSD1306 OLED 디스플레이를 위한 라이브러리
// SSD1306 디스플레이 객체 초기화
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &Wire, -1);
const char* ssid = "Your_SSID"; // 여기에 사용하는 WiFi 네트워크 이름 (SSID)을 입력하세요
const char* password = "Your_Password"; // 여기에 사용하는 WiFi 네트워크 비밀번호를 입력하세요
int GMTOffset = 60 * 60 * 9; // 시간 오프셋 설정, 한국은 UTC/GMT +9입니다.
int daylightOffset = 0; // 국가에서 서머타임을 사용하는 경우 오프셋 값을 설정하세요.
const String weekDays[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; // 요일 이름 배열
void setup() {
Serial.begin(115200); // 디버깅을 위한 시리얼 통신 시작
// SSD1306 디스플레이 초기화
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 초기화 실패"));
while (1)
; // 디스플레이 초기화에 실패하면 프로그램 실행 중지
}
delay(2000); // 2초 동안 대기
display.clearDisplay(); // 디스플레이 지우기
display.setTextSize(1); // 텍스트 크기를 1로 설정
display.setCursor(0, 0); // 커서 위치를 디스플레이 왼쪽 위 모서리로 설정
display.setTextColor(WHITE); // 텍스트 색상을 흰색으로 설정
WiFi.begin(ssid, password); // 제공된 SSID와 비밀번호를 사용하여 WiFi 네트워크에 연결
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting...");
}
Serial.println("Connected to Wi-Fi!");
// 시간 설정을 위한 NTP 서버 설정
configTime(GMTOffset, daylightOffset, "pool.ntp.org", "time.nist.gov");
}
void loop() {
// 현재 시간 가져오기
time_t rawtime = time(nullptr);
struct tm* timeinfo = localtime(&rawtime);
// 시리얼 모니터에 날짜 출력
Serial.print(timeinfo->tm_mday);
Serial.print("/");
Serial.print(timeinfo->tm_mon + 1);
Serial.print("/");
Serial.print(timeinfo->tm_year + 1900);
Serial.print(" ");
// 시리얼 모니터에 시간 출력
Serial.print("Time: ");
Serial.print(timeinfo->tm_hour);
Serial.print(":");
Serial.print(timeinfo->tm_min);
Serial.print(":");
Serial.println(timeinfo->tm_sec);
// OLED 디스플레이 초기화
display.clearDisplay();
display.setTextSize(3);
display.setTextColor(WHITE);
display.setCursor(0, 0);
// 시간 출력
if (timeinfo->tm_hour < 10)
display.print("0");
display.print(timeinfo->tm_hour);
display.print(":");
if (timeinfo->tm_min < 10)
display.print("0");
display.print(timeinfo->tm_min);
display.print(":");
// 초 출력
display.setTextSize(2);
display.setCursor(102, 5);
if (timeinfo->tm_sec < 10)
display.print("0");
display.print(timeinfo->tm_sec);
// 날짜 출력
display.setTextSize(1);
display.setCursor(0, 25);
display.print(timeinfo->tm_mday);
display.print("/");
display.print(timeinfo->tm_mon + 1);
display.print("/");
display.print(timeinfo->tm_year + 1900);
display.print(" ");
display.print(weekDays[timeinfo->tm_wday]);
// 디스플레이에 표시
display.display();
delay(1000);
}