Chapter 14. OLED와 RTC를 이용한 스마트 시계
고해상도 0.96인치 OLED와 정밀 시간 모듈(RTC)을 이용해 나만의 탁상시계를 만듭니다. I2C 버스 하나에 두 개의 장치를 연결하는 방법(Daisy Chain)을 학습합니다.
I2C 병렬 연결: OLED와 RTC의 SDA/SCL을 Pico의 GP8/GP9에 공통으로 연결합니다. OLED는 보통 0x3C, DS3231은 0x68 주소를 사용합니다.
14.1 준비물과 연결 핀
I2C는 여러 장치를 같은 선에 연결할 수 있습니다. 중요한 것은 모든 장치의 SDA는 SDA끼리, SCL은 SCL끼리 묶고 주소가 겹치지 않는지 확인하는 것입니다.
| 장치 | Pico 2 W 핀 | 역할 |
|---|---|---|
| OLED SDA / SCL | GP8 / GP9 | 시간 표시 |
| DS3231 SDA / SCL | GP8 / GP9 | 정밀 시간 유지 |
| VCC / GND | 3V3, GND | 공통 전원 |
14.2 DS3231 기반 스마트 시계 소스 코드
사전 준비: Thonny 패키지 관리자에서 ssd1306 라이브러리를 설치해야 합니다.
import machine
import ssd1306
import time
DS3231_ADDR = 0x68
OLED_ADDR = 0x3C
i2c = machine.I2C(0, sda=machine.Pin(8), scl=machine.Pin(9), freq=400000)
oled = ssd1306.SSD1306_I2C(128, 64, i2c, addr=OLED_ADDR)
def bcd_to_dec(value):
return (value >> 4) * 10 + (value & 0x0F)
def dec_to_bcd(value):
return ((value // 10) << 4) | (value % 10)
def set_ds3231(year, month, day, weekday, hour, minute, second):
data = bytearray(7)
data[0] = dec_to_bcd(second)
data[1] = dec_to_bcd(minute)
data[2] = dec_to_bcd(hour)
data[3] = dec_to_bcd(weekday)
data[4] = dec_to_bcd(day)
data[5] = dec_to_bcd(month)
data[6] = dec_to_bcd(year - 2000)
i2c.writeto_mem(DS3231_ADDR, 0x00, data)
def read_ds3231():
data = i2c.readfrom_mem(DS3231_ADDR, 0x00, 7)
second = bcd_to_dec(data[0] & 0x7F)
minute = bcd_to_dec(data[1])
hour = bcd_to_dec(data[2] & 0x3F)
weekday = bcd_to_dec(data[3])
day = bcd_to_dec(data[4])
month = bcd_to_dec(data[5] & 0x1F)
year = 2000 + bcd_to_dec(data[6])
return year, month, day, weekday, hour, minute, second
def draw_clock(now):
year, month, day, weekday, hour, minute, second = now
oled.fill(0)
oled.text("SMART CLOCK", 18, 0)
oled.hline(0, 12, 128, 1)
oled.text(f"{year}-{month:02d}-{day:02d}", 18, 22)
oled.text(f"{hour:02d}:{minute:02d}:{second:02d}", 30, 42)
oled.show()
devices = i2c.scan()
print("I2C devices:", [hex(addr) for addr in devices])
if DS3231_ADDR not in devices:
oled.fill(0)
oled.text("RTC not found", 12, 24)
oled.text("Check wiring", 14, 42)
oled.show()
raise RuntimeError("DS3231 not found")
# 최초 1회만 시간을 맞출 때 사용하고, 맞춘 뒤에는 주석 처리하세요.
# set_ds3231(2026, 6, 2, 2, 12, 0, 0)
print("Smart Clock 가동...")
while True:
now = read_ds3231()
draw_clock(now)
time.sleep(1)
💡 I2C 주소 확인
OLED는 보통 0x3C, RTC는 0x68 주소를 가집니다. Chapter 9의 스캔 코드를 활용해 두 장치가 모두 인식되는지 먼저 확인하세요.
14.3 동작 흐름
프로그램은 먼저 I2C 버스에서 OLED와 DS3231이 보이는지 확인합니다. RTC가 연결되어 있으면 DS3231의 BCD 형식 시간 데이터를 읽어 사람이 읽는 숫자로 바꾸고, OLED에 날짜와 시간을 1초마다 다시 그립니다. 한 번 시간을 맞춘 뒤에는 DS3231의 배터리가 시간을 계속 유지합니다.