Chapter 6: 조건과 반복 - 자동화의 시작¶
🎯 이 장에서 배우는 것¶
- [ ] if/elif/else를 활용한 다중 조건을 구현할 수 있다
- [ ] while 무한루프로 지속적인 모니터링을 할 수 있다
- [ ] 센서→조건→출력 연결로 자동 야간등을 만들 수 있다
- [ ] break와 continue로 루프를 제어할 수 있다
💡 왜 이걸 배우나요?¶
지금까지 우리는 버튼을 누르면 LED가 켜지고, 센서 값을 읽어서 화면에 출력하는 것을 배웠어. 근데 생각해봐. 너희가 자고 있을 때 방이 어두워지면 자동으로 무드등이 켜진다면? 온도가 30도가 넘으면 알아서 선풍기가 돌아간다면?
이게 바로 자동화야! 🤖
우리 주변의 스마트 가전들이 전부 이 원리로 동작해: - 🚗 자동차 후방 센서: 거리가 가까우면 → 경고음 - 🏠 현관 자동 조명: 어두워지면 + 사람 감지 → 불 켜짐 - 🌡️ 에어컨: 온도가 설정값보다 높으면 → 가동
이 모든 게 "조건문 + 반복문" 조합이야. 오늘 이걸 마스터하면 너도 자동화 시스템을 만들 수 있어!
📚 핵심 개념¶
개념 1: if/elif/else - 여러 갈래 길에서 선택하기¶
비유로 시작: 자판기를 생각해봐. 동전을 넣으면 금액에 따라 살 수 있는 음료가 달라지지? 500원이면 물만, 1000원이면 주스도, 1500원이면 커피까지. 이렇게 여러 조건을 순서대로 확인하는 게 if/elif/else야.
정확한 정의: if는 첫 번째 조건을 검사하고, elif(else if의 줄임말)는 앞의 조건이 거짓일 때 다음 조건을 검사해. else는 모든 조건이 거짓일 때 실행되는 "나머지" 상황이야.
예시로 확인:
money = 1000
if money >= 1500:
print("커피 구매 가능!")
elif money >= 1000:
print("주스 구매 가능!")
elif money >= 500:
print("물 구매 가능!")
else:
print("금액이 부족해요")
쉽게 말하면: 위에서부터 조건을 하나씩 확인하다가, 처음으로 True가 나오면 그 블록만 실행하고 끝!
개념 2: while 무한루프 - 계속 감시하는 보초병¶
비유로 시작: 경비원을 생각해봐. 건물 입구에서 24시간 계속 "이상 없나?" 확인하잖아. while 무한루프는 바로 이 경비원 같은 거야. 계속 반복하면서 뭔가 변화가 있는지 감시해.
정확한 정의: while True:는 조건이 항상 참이므로 무한히 반복해. 피지컬 컴퓨팅에서는 이걸로 센서 값을 계속 읽어서 모니터링하는 게 기본 패턴이야.
예시로 확인:
while True: # 무한 반복!
sensor_value = read_sensor() # 센서 읽기
print(sensor_value) # 출력
time.sleep(1) # 1초 대기
쉽게 말하면: "영원히 반복해!" 그래서 피코가 꺼질 때까지 계속 실행돼.
개념 3: break와 continue - 루프 탈출 비상구¶
비유로 시작: 놀이공원 회전목마를 타고 있는데, 갑자기 비가 오면? break로 완전히 내리거나, continue로 "이번 바퀴는 패스!" 할 수 있어.
정확한 정의:
- break: 루프를 완전히 종료하고 빠져나감
- continue: 이번 반복만 건너뛰고 다음 반복으로
예시로 확인:
count = 0
while True:
count += 1
if count == 3:
continue # 3은 건너뛰기
if count > 5:
break # 5 넘으면 종료
print(count) # 출력: 1, 2, 4, 5
쉽게 말하면: break는 "그만!", continue는 "패스!"
🔨 따라하기¶
Step 1: 다중 조건으로 밝기 레벨 판단하기¶
목표: 조도 센서 값에 따라 "매우 밝음/밝음/보통/어두움/매우 어두움" 5단계로 분류하기
준비물: - 라즈베리파이 피코 2W - Grove Shield - Grove 조도 센서 (A0 포트 연결)
회로 연결:
코드:
# === WHAT: 조도 센서로 밝기 레벨 판단하기 ===
# 조도 센서 값을 읽어서 5단계로 분류해 출력하는 코드
# --- WHY: 왜 필요한지 ---
# 단순히 숫자만 보면 어두운지 밝은지 감이 안 와
# 사람이 이해하기 쉬운 "레벨"로 변환하면 직관적!
# HOW: 어떻게 동작하는지
from machine import ADC, Pin # ADC: 아날로그를 디지털로 변환
import time
# 조도 센서 설정 (A0 = GP26)
light_sensor = ADC(Pin(26))
# 밝기 레벨 기준값 (0~65535 범위에서)
VERY_BRIGHT = 50000 # 이 이상이면 매우 밝음
BRIGHT = 35000 # 이 이상이면 밝음
NORMAL = 20000 # 이 이상이면 보통
DIM = 10000 # 이 이상이면 어두움
# 이 미만이면 매우 어두움
# 센서 값 한 번 읽기
light_value = light_sensor.read_u16()
print(f"조도 센서 값: {light_value}")
# 다중 조건으로 레벨 판단
if light_value >= VERY_BRIGHT:
level = "☀️ 매우 밝음"
elif light_value >= BRIGHT:
level = "🌤️ 밝음"
elif light_value >= NORMAL:
level = "⛅ 보통"
elif light_value >= DIM:
level = "🌥️ 어두움"
else:
level = "🌑 매우 어두움"
print(f"밝기 레벨: {level}")
실행 결과:
조도 센서 값: 42000
밝기 레벨: 🌤️ 밝음
여기서 잠깐! 🤔
왜 if를 5번 쓰지 않고 elif를 썼을까?
만약 전부 if로 쓰면:
if light_value >= 50000: # ✅ True라면
level = "매우 밝음"
if light_value >= 35000: # ✅ 이것도 True! (50000 > 35000이니까)
level = "밝음" # 덮어씌워짐!
elif는 앞의 조건이 True면 아예 검사를 안 해서 이런 문제가 없어!
Step 2: while 무한루프로 실시간 모니터링¶
목표: 조도 센서 값을 1초마다 계속 읽어서 출력하기
코드:
# === WHAT: 조도 센서 실시간 모니터링 ===
# 1초마다 센서 값을 읽어서 밝기 레벨을 계속 출력
# --- WHY: 왜 필요한지 ---
# 센서 값은 계속 변해! 손으로 가리면 어두워지고,
# 전등 켜면 밝아지고. 이걸 "실시간"으로 봐야 의미있지
# HOW: 어떻게 동작하는지
from machine import ADC, Pin
import time
# 센서 설정
light_sensor = ADC(Pin(26))
# 기준값 (상수로 정의 - 대문자 관례)
VERY_BRIGHT = 50000
BRIGHT = 35000
NORMAL = 20000
DIM = 10000
def get_light_level(value):
"""밝기 값을 레벨 문자열로 변환하는 함수"""
if value >= VERY_BRIGHT:
return "☀️ 매우 밝음"
elif value >= BRIGHT:
return "🌤️ 밝음"
elif value >= NORMAL:
return "⛅ 보통"
elif value >= DIM:
return "🌥️ 어두움"
else:
return "🌑 매우 어두움"
# 무한 모니터링 시작!
print("=== 조도 모니터링 시작 ===")
print("(Ctrl+C 또는 Thonny 정지 버튼으로 종료)")
print()
while True:
# 센서 값 읽기
light_value = light_sensor.read_u16()
# 레벨 판단
level = get_light_level(light_value)
# 출력 (같은 줄에 덮어쓰기)
print(f"\r값: {light_value:5d} | 레벨: {level} ", end="")
# 1초 대기
time.sleep(1)
실행 결과:
=== 조도 모니터링 시작 ===
(Ctrl+C 또는 Thonny 정지 버튼으로 종료)
값: 42000 | 레벨: 🌤️ 밝음
여기서 잠깐! 🤔
\r과 end=""가 뭐야?
- \r: 커서를 줄 맨 앞으로 이동 (줄바꿈 없이!)
- end="": print 끝에 줄바꿈 안 함
이 둘을 조합하면 같은 줄에서 값이 계속 업데이트되는 효과! 마치 디지털 시계처럼 🕐
Step 3: 자동 야간등 만들기 - 센서→조건→출력 연결!¶
목표: 어두워지면 자동으로 LED가 켜지는 스마트 야간등 만들기
준비물 추가: - Grove LED (D18 포트 연결)
회로 연결:
코드:
# === WHAT: 자동 야간등 ===
# 어두워지면 LED가 켜지고, 밝아지면 LED가 꺼지는 자동화 시스템
# --- WHY: 왜 필요한지 ---
# 매번 스위치 누르기 귀찮잖아!
# 센서가 알아서 판단해서 자동으로 켜고 끄면 편하지
# HOW: 어떻게 동작하는지
from machine import ADC, Pin
import time
# === 하드웨어 설정 ===
light_sensor = ADC(Pin(26)) # 조도 센서 (A0 = GP26)
led = Pin(18, Pin.OUT) # LED (D18 = GP18)
# === 기준값 설정 ===
# 이 값보다 어두우면 LED 켜기!
DARK_THRESHOLD = 15000
# 히스테리시스: 경계값에서 깜빡임 방지
# "끌 때는 좀 더 밝아야 꺼" 라는 의미
LIGHT_THRESHOLD = 20000
# === 상태 변수 ===
led_on = False # 현재 LED 상태 추적
# === 메인 루프 ===
print("=== 🌙 자동 야간등 시작 ===")
print(f"어두움 기준: {DARK_THRESHOLD} 이하")
print(f"밝음 기준: {LIGHT_THRESHOLD} 이상")
print()
while True:
# 센서 값 읽기
light_value = light_sensor.read_u16()
# 조건 판단 및 LED 제어
if light_value < DARK_THRESHOLD and not led_on:
# 어둡고, LED가 꺼져있으면 → 켜기
led.on()
led_on = True
print(f"💡 LED ON! (밝기: {light_value})")
elif light_value > LIGHT_THRESHOLD and led_on:
# 밝고, LED가 켜져있으면 → 끄기
led.off()
led_on = False
print(f"🌑 LED OFF! (밝기: {light_value})")
# 현재 상태 표시
status = "💡 ON" if led_on else "🌑 OFF"
print(f"\r밝기: {light_value:5d} | LED: {status} ", end="")
# 0.5초마다 확인
time.sleep(0.5)
실행 결과:
=== 🌙 자동 야간등 시작 ===
어두움 기준: 15000 이하
밝음 기준: 20000 이상
밝기: 42000 | LED: 🌑 OFF
(센서를 손으로 가리면...)
💡 LED ON! (밝기: 8500)
밝기: 8500 | LED: 💡 ON
(손을 떼면...)
🌑 LED OFF! (밝기: 43000)
밝기: 43000 | LED: 🌑 OFF
여기서 잠깐! 🤔
히스테리시스(Hysteresis)가 뭐야?
에어컨을 생각해봐. 25도로 설정하면: - 25도가 되면 꺼지고 - 바로 25.1도가 되면 다시 켜지고 - 또 25도가 되면 꺼지고...
이러면 계속 켜졌다 꺼졌다 깜빡이겠지? 😵
그래서 실제 에어컨은: - 24도가 되면 끄고 (여유있게!) - 26도가 되면 켜기
이 "여유 구간"이 히스테리시스야. 우리 야간등도 같은 원리!
📝 전체 코드¶
# === 자동 야간등 완성 버전 ===
# 조도 센서로 밝기를 감지해서 자동으로 LED를 켜고 끄는 시스템
# 히스테리시스 적용으로 안정적인 동작 보장
from machine import ADC, Pin
import time
# ========================================
# 하드웨어 설정
# ========================================
light_sensor = ADC(Pin(26)) # 조도 센서 (A0 포트 = GP26)
led = Pin(18, Pin.OUT) # LED (D18 포트 = GP18)
# ========================================
# 설정값 (환경에 맞게 조절하세요!)
# ========================================
DARK_THRESHOLD = 15000 # 이 값 이하면 "어둡다"
LIGHT_THRESHOLD = 20000 # 이 값 이상이면 "밝다"
CHECK_INTERVAL = 0.5 # 확인 주기 (초)
# ========================================
# 밝기 레벨 판단 함수
# ========================================
def get_brightness_level(value):
"""밝기 값을 5단계 레벨로 변환"""
if value >= 50000:
return "☀️ 매우 밝음", 5
elif value >= 35000:
return "🌤️ 밝음", 4
elif value >= 20000:
return "⛅ 보통", 3
elif value >= 10000:
return "🌥️ 어두움", 2
else:
return "🌑 매우 어두움", 1
# ========================================
# 메인 프로그램
# ========================================
def main():
"""자동 야간등 메인 함수"""
led_on = False # LED 상태 추적
print("=" * 40)
print("🌙 자동 야간등 시스템")
print("=" * 40)
print(f"어두움 기준: {DARK_THRESHOLD} 이하 → LED ON")
print(f"밝음 기준: {LIGHT_THRESHOLD} 이상 → LED OFF")
print(f"확인 주기: {CHECK_INTERVAL}초")
print("-" * 40)
print("Ctrl+C 또는 정지 버튼으로 종료")
print("=" * 40)
print()
while True:
# 1. 센서 값 읽기
light_value = light_sensor.read_u16()
# 2. 레벨 판단
level_text, level_num = get_brightness_level(light_value)
# 3. LED 제어 (히스테리시스 적용)
if light_value < DARK_THRESHOLD and not led_on:
led.on()
led_on = True
print(f"\n💡 LED 켜짐! (밝기: {light_value})")
elif light_value > LIGHT_THRESHOLD and led_on:
led.off()
led_on = False
print(f"\n🔌 LED 꺼짐! (밝기: {light_value})")
# 4. 상태 출력
led_status = "💡 ON " if led_on else "⚫ OFF"
bar = "█" * level_num + "░" * (5 - level_num) # 그래픽 바
print(f"\r[{bar}] {light_value:5d} {level_text:12s} | LED: {led_status}", end="")
# 5. 대기
time.sleep(CHECK_INTERVAL)
# 프로그램 시작
if __name__ == "__main__":
main()
⚠️ 자주 하는 실수¶
실수 1: elif 대신 if를 연속으로 사용¶
증상: 조건이 여러 개 맞아서 원하지 않는 결과가 나옴
원인: if는 독립적으로 각각 검사하지만, elif는 앞 조건이 거짓일 때만 검사함
해결:
# ❌ 잘못된 코드
score = 85
if score >= 60:
grade = "D"
if score >= 70:
grade = "C"
if score >= 80:
grade = "B" # 85점인데 B만 출력됨?
if score >= 90:
grade = "A"
# 결과: grade = "B" (맞긴 한데... 위험한 코드!)
# ✅ 올바른 코드
score = 85
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B" # 여기서 멈춤!
elif score >= 70:
grade = "C"
elif score >= 60:
grade = "D"
else:
grade = "F"
# 결과: grade = "B" (안전하고 명확!)
실수 2: while 루프에서 time.sleep() 빼먹기¶
증상: 피코가 멈추거나 Thonny가 응답 없음
원인: CPU가 쉬지 않고 100% 풀가동하면서 다른 작업(통신 등)을 못함
해결:
# ❌ 잘못된 코드
while True:
value = sensor.read_u16()
print(value)
# sleep 없음 → CPU 폭주!
# ✅ 올바른 코드
while True:
value = sensor.read_u16()
print(value)
time.sleep(0.1) # 최소 0.1초라도!
실수 3: 조건문에서 = 와 == 혼동¶
증상: SyntaxError 또는 예상치 못한 동작
원인: =는 값 할당, ==는 비교 연산자
해결:
# ❌ 잘못된 코드
if light_value = 1000: # SyntaxError!
print("어둡다")
# ✅ 올바른 코드
if light_value == 1000: # 같은지 비교
print("정확히 1000이다")
if light_value < 1000: # 작은지 비교
print("어둡다")
실수 4: 무한루프 탈출 못하기¶
증상: 프로그램이 영원히 안 끝남, Thonny 정지 버튼도 안 먹힘
원인: 무한루프 안에 탈출 조건이 없음
해결:
# ❌ 위험한 코드 (탈출구 없음)
while True:
do_something()
# ✅ 안전한 코드 (버튼으로 종료 가능)
from machine import Pin
button = Pin(20, Pin.IN, Pin.PULL_DOWN)
while True:
if button.value() == 1: # 버튼 누르면
print("종료!")
break # 탈출!
do_something()
time.sleep(0.1)
✅ 스스로 점검하기¶
1. 사실 확인 질문¶
다음 코드의 출력 결과는?
x = 75
if x >= 90:
print("A")
elif x >= 80:
print("B")
elif x >= 70:
print("C")
else:
print("D")
2. 적용 질문¶
온도가 28도 이상이면 "덥다", 18도 이하면 "춥다", 그 사이면 "쾌적하다"를 출력하는 코드를 작성해봐.
3. 이유 질문¶
자동 야간등에서 DARK_THRESHOLD와 LIGHT_THRESHOLD를 같은 값(예: 둘 다 15000)으로 설정하면 어떤 문제가 생길까?
정답 확인
**1번 답**: `C` - 75는 90 이상? ❌ - 75는 80 이상? ❌ - 75는 70 이상? ✅ → "C" 출력! **2번 답**:temp = 25 # 예시 온도
if temp >= 28:
print("덥다")
elif temp <= 18:
print("춥다")
else:
print("쾌적하다")
🚀 더 해보기¶
도전 1: 3단계 야간등 (쉬움) ⭐¶
어두움 정도에 따라 LED 밝기를 3단계로 조절해봐!
- 매우 어두움 → LED 최대 밝기
- 어두움 → LED 중간 밝기
- 밝음 → LED 끄기
힌트: PWM으로 LED 밝기 조절 (5차시 복습!)
from machine import PWM
led_pwm = PWM(Pin(18))
led_pwm.freq(1000)
led_pwm.duty_u16(32768) # 50% 밝기
도전 2: 버튼으로 모드 전환 (중간) ⭐⭐¶
버튼을 누를 때마다 모드가 바뀌는 야간등을 만들어봐! - 모드 1: 자동 모드 (센서로 제어) - 모드 2: 항상 켜짐 - 모드 3: 항상 꺼짐
힌트: 모드 변수와 버튼 토글
mode = 1 # 1, 2, 3 순환
if button.value() == 1:
mode = mode + 1
if mode > 3:
mode = 1
time.sleep(0.3) # 디바운싱
도전 3: 움직임 감지 야간등 (어려움) ⭐⭐⭐¶
조도 센서 + 초음파 센서를 조합한 스마트 야간등! - 어두울 때만 활성화 - 사람이 가까이 오면(50cm 이내) LED 켜짐 - 10초 동안 움직임 없으면 자동으로 꺼짐
힌트: 시간 추적 변수 사용
import time
last_motion_time = time.ticks_ms() # 마지막 움직임 시간
# 움직임 감지되면
last_motion_time = time.ticks_ms() # 시간 갱신
# 10초 지났는지 확인
if time.ticks_diff(time.ticks_ms(), last_motion_time) > 10000:
# 10초 지남!
🔗 다음 장으로¶
이번 장에서 우리는:
- ✅ if/elif/else로 여러 조건을 순차적으로 검사하는 법
- ✅ while True로 센서를 계속 모니터링하는 법
- ✅ 센서→조건→출력을 연결해서 자동화 시스템 만드는 법
- ✅ 히스테리시스로 안정적인 동작 보장하는 법
이걸 배웠어!
지금까지의 코드를 보면 비슷한 패턴이 계속 반복되지 않아? 센서 읽기, LED 제어, 상태 출력...
다음 장 "함수로 정리"에서는 이런 반복되는 코드를 함수로 깔끔하게 정리하는 법을 배울 거야. 마치 레고 블록처럼 조립해서 쓸 수 있게! 🧱
코드가 길어져도 걱정 없이 관리할 수 있는 비결을 알려줄게! 🚀