# 필요한 라이브러리 가져오기
import machine
import time
from pico_i2c_lcd import I2cLcd
# --- 1. LCD 설정 ---
try:
# I2C 통신 설정 (SDA=GP0, SCL=GP1)
i2c = machine.I2C(0, sda=machine.Pin(0), scl=machine.Pin(1), freq=100000)
# 연결된 I2C 장치의 주소 스캔
I2C_ADDR = i2c.scan()[0]
# LCD 객체 초기화 (16x2 크기)
lcd = I2cLcd(i2c, I2C_ADDR, 2, 16)
# 시작 메시지 출력
lcd.clear()
lcd.putstr("Keypad Ready!")
time.sleep(1)
lcd.clear()
print("LCD가 성공적으로 연결되었습니다.")
except Exception as e:
print(f"LCD 연결 오류: {e}")
print("LCD 연결을 확인해주세요. 주소를 찾을 수 없습니다.")
lcd = None # LCD가 없어도 코드가 멈추지 않도록 함
# --- 2. 키패드 설정 ---
# 키패드 문자 매핑
keys = [
['1','2','3','A'],
['4','5','6','B'],
['7','8','9','C'],
['*','0','#','D'],
]
# 키패드 핀 번호 (GPIO 핀 번호)
col_pins = [10, 11, 12, 13] # C1~C4
row_pins = [21, 20, 19, 18] # R1~R4
# 핀 객체 초기화
# 열(Column)은 PULL_UP 입력
cols = [machine.Pin(p, machine.Pin.IN, machine.Pin.PULL_UP) for p in col_pins]
# 행(Row)은 출력
rows = [machine.Pin(p, machine.Pin.OUT) for p in row_pins]
# --- 3. LED 및 상태 변수 초기화 ---
# LED 핀 설정 (GP15)
led_external = machine.Pin(15, machine.Pin.OUT)
led_external.value(0) # LED를 끈 상태로 시작
# 이전에 눌린 키 상태 (NameError 방지를 위해 루프 밖에 선언)
pressed_prev = [[False]*4 for _ in range(4)]
# LCD 커서 위치 관리
current_col = 0
current_row = 0
print("키패드 스캔을 시작합니다...")
# --- 4. 메인 루프 ---
while True:
# 현재 눌린 키 상태
pressed_now = [[False]*4 for _ in range(4)]
# 키패드 스캔
for ri, r in enumerate(rows):
r.value(0) # 현재 행(row)을 LOW로 활성화
time.sleep_us(200) # 안정화 시간
for ci, c in enumerate(cols):
if c.value() == 0: # 키가 눌렸다면 (col이 LOW가 됨)
pressed_now[ri][ci] = True
r.value(1) # 현재 행(row)을 HIGH로 비활성화
# 입력 처리 (누르고 있어도 1번만 눌린 것처럼)
for ri in range(4):
for ci in range(4):
# '현재'는 눌렸고 '이전'에는 안 눌렸을 때 (즉, 키를 누르는 순간)
if pressed_now[ri][ci] and not pressed_prev[ri][ci]:
# --- 💡 LED 피드백 (여기 추가!) ---
led_external.value(1) # LED 켜기
time.sleep_ms(50) # 0.05초 동안 잠시 켜둠
led_external.value(0) # LED 끄기
# -------------------------------
key = keys[ri][ci] # 눌린 키 문자
print(key) # Thonny Shell에도 출력 (디버깅용)
# LCD가 성공적으로 연결되었을 때만 LCD에 출력
if lcd:
if key == '#':
# '#' 키: 화면 지우기
lcd.clear()
current_col = 0
current_row = 0
elif key == 'D':
# 'D' 키: 다음 줄로 이동 (줄 바꿈)
current_row = (current_row + 1) % 2 # 0 -> 1, 1 -> 0
current_col = 0
lcd.move_to(current_col, current_row)
else:
# 다른 모든 키: 현재 위치에 문자 출력
lcd.move_to(current_col, current_row)
lcd.putstr(key)
# 커서 위치를 한 칸 뒤로 이동
current_col += 1
# 만약 16번째 칸을 넘어가면 다음 줄 처음으로 이동
if current_col >= 16:
current_col = 0
current_row = (current_row + 1) % 2
lcd.move_to(current_col, current_row)
# 현재 키 상태를 '이전' 상태로 저장
pressed_prev = pressed_now
# CPU 부하를 줄이기 위해 짧은 지연
time.sleep_ms(20)