Chapter 04: 센서 입문 - 세상을 느끼다¶
🎯 이 장에서 배우는 것¶
- [ ] 아날로그와 디지털 신호의 차이를 설명할 수 있다
- [ ] ADC를 사용하여 센서 값을 읽을 수 있다
- [ ] Grove 조도 센서로 밝기를 측정할 수 있다
- [ ] DHT11 센서로 온도와 습도를 측정할 수 있다
- [ ] 센서 값에 따라 LED를 자동 제어할 수 있다
💡 왜 이걸 배우나요?¶
지금까지 버튼은 눌렀다(1) / 안 눌렀다(0) 두 가지만 구분했어. 하지만 세상은 그렇게 단순하지 않지!
- 방이 조금 어두운지, 많이 어두운지
- 온도가 25도인지, 30도인지
- 소리가 작은지, 큰지
이런 "정도"를 알려면 센서가 필요해. 센서는 세상의 다양한 정보를 숫자로 바꿔주는 장치야.
실제로 어디에 쓰일까? 🤔 - 🌡️ 에어컨이 "덥다"를 아는 방법 → 온도 센서 - 📱 스마트폰 화면 밝기 자동 조절 → 조도 센서 - 🚗 자동차 후방 감지 → 초음파 센서
이번 장에서 센서를 배우면, 피코가 세상을 느끼기 시작해!
📚 핵심 개념¶
개념 1: 디지털 신호 vs 아날로그 신호¶
비유로 시작: 디지털 신호는 마치 계단과 같아요. 1층, 2층, 3층... 딱딱 끊어지지. 아날로그 신호는 마치 경사로와 같아요. 부드럽게 연속으로 이어져.
정확한 정의: - 디지털 신호: 0과 1, 두 가지 상태만 있는 신호 (ON/OFF) - 아날로그 신호: 연속적인 값을 가지는 신호 (0~100% 사이 모든 값)
예시로 확인:
디지털: 버튼 → 눌림(1) 또는 안눌림(0)
아날로그: 볼륨 다이얼 → 0%, 30%, 75%, 100%... 무한한 값
쉽게 말하면: 디지털은 "예/아니오", 아날로그는 "정도"를 표현해!
개념 2: ADC (Analog-to-Digital Converter)¶
비유로 시작: ADC는 마치 통역사와 같아요. 센서가 말하는 "아날로그 언어"를 컴퓨터가 이해하는 "디지털 숫자"로 바꿔줘.
정확한 정의: ADC는 연속적인 아날로그 전압을 디지털 숫자로 변환하는 장치야. 피코의 ADC는 16비트라서 0~65535 범위의 숫자로 바꿔줘.
예시로 확인:
센서 전압 → ADC 변환 → 디지털 값
0V → → 0
1.65V → 피코 ADC → 32768 (중간값)
3.3V → → 65535 (최대값)
쉽게 말하면: ADC는 센서의 "느낌"을 컴퓨터가 읽을 수 있는 "숫자"로 바꿔줘!
개념 3: 센서의 종류¶
오늘 사용할 센서: | 센서 | 종류 | 측정 대상 | 연결 포트 | |------|------|----------|----------| | Grove 조도 센서 | 아날로그 | 빛의 밝기 | A0 | | Grove DHT11 | 디지털 | 온도, 습도 | D16 |
🔨 따라하기¶
Step 1: 조도 센서로 밝기 읽기¶
목표: Grove 조도 센서를 연결하고 밝기 값을 읽어보자!
회로 연결:
┌─────────────────────────────────────────────────────┐
│ Pico 2W + Grove Shield │
│ │
│ ┌─────────────┐ │
│ │ A0 포트 │◄──── Grove 조도 센서 │
│ │ (아날로그) │ (노란색 케이블) │
│ └─────────────┘ │
│ │
│ Grove 케이블을 A0 포트에 연결하면 끝! │
└─────────────────────────────────────────────────────┘
코드:
# === WHAT: 조도 센서 값 읽기 ===
# 조도 센서로 현재 밝기를 측정해서 출력하는 코드야
# --- WHY: 왜 필요한지 ---
# 방이 얼마나 밝은지 알아야 자동 조명 같은 걸 만들 수 있어!
# HOW: 어떻게 동작하는지
from machine import ADC, Pin # ADC: 아날로그 값을 읽는 기능
import time
# Grove 조도 센서는 A0 포트에 연결
# A0 = GPIO26번 핀
light_sensor = ADC(Pin(26)) # ADC 객체 생성
# 무한 반복
while True:
# 센서 값 읽기 (0 ~ 65535)
light_value = light_sensor.read_u16()
# 결과 출력
print("밝기:", light_value)
# 0.5초 대기
time.sleep(0.5)
실행 결과:
밝기: 45230
밝기: 45180
밝기: 12450 ← 손으로 가렸을 때
밝기: 11890
밝기: 58920 ← 손전등 비췄을 때
밝기: 59100
여기서 잠깐! 🤔
read_u16()이 뭐야? -
read_u16()은 16비트 unsigned(양수만) 정수로 읽어라는 뜻이야 - u = unsigned(부호 없음), 16 = 16비트 - 그래서 결과가 0 ~ 65535 범위로 나와!
Step 2: 밝기 값을 퍼센트로 변환하기¶
목표: 0~65535 숫자는 직관적이지 않으니, 0~100%로 바꿔보자!
코드:
# === WHAT: 밝기를 퍼센트로 변환 ===
# 센서 값을 사람이 이해하기 쉬운 퍼센트로 바꾸는 코드야
# --- WHY: 왜 필요한지 ---
# "45230"보다 "69%"가 훨씬 이해하기 쉽잖아!
# HOW: 어떻게 동작하는지
from machine import ADC, Pin
import time
light_sensor = ADC(Pin(26))
while True:
# 원본 값 읽기
raw_value = light_sensor.read_u16()
# 퍼센트로 변환 (0~65535 → 0~100)
# 공식: (현재값 / 최대값) * 100
percent = (raw_value / 65535) * 100
# 소수점 1자리까지 출력
print(f"밝기: {percent:.1f}%")
time.sleep(0.5)
실행 결과:
밝기: 69.0%
밝기: 68.9%
밝기: 19.0% ← 손으로 가렸을 때
밝기: 18.1%
여기서 잠깐! 🤔
f-string 포맷팅 -
f"밝기: {percent:.1f}%"-.1f= 소수점 1자리까지 표시 -.2f= 소수점 2자리까지 표시 - 이게 없으면69.0324756...같이 길게 나와!
Step 3: DHT11 온습도 센서 사용하기¶
목표: DHT11 센서로 온도와 습도를 측정해보자!
회로 연결:
┌─────────────────────────────────────────────────────┐
│ Pico 2W + Grove Shield │
│ │
│ ┌─────────────┐ │
│ │ D16 포트 │◄──── Grove DHT11 센서 │
│ │ (디지털) │ (흰색 센서 모듈) │
│ └─────────────┘ │
│ │
│ Grove 케이블을 D16 포트에 연결! │
└─────────────────────────────────────────────────────┘
라이브러리 설치가 필요해! 📦
DHT11은 특별한 통신 방식을 써서 라이브러리가 필요해. Thonny에서 설치하자:
- Thonny 메뉴 → 도구 → 패키지 관리
- 검색창에
dht입력 micropython-dht선택 → 설치
코드:
# === WHAT: DHT11 온습도 센서 읽기 ===
# 현재 온도와 습도를 측정해서 출력하는 코드야
# --- WHY: 왜 필요한지 ---
# 스마트 홈, 식물 관리, 기상 관측에 온습도는 필수!
# HOW: 어떻게 동작하는지
from machine import Pin
import dht # DHT 센서 라이브러리
import time
# DHT11 센서 객체 생성 (D16 포트 = GPIO16)
sensor = dht.DHT11(Pin(16))
while True:
try:
# 센서 측정 명령
sensor.measure()
# 측정된 값 읽기
temp = sensor.temperature() # 온도 (섭씨)
humidity = sensor.humidity() # 습도 (%)
# 결과 출력
print(f"온도: {temp}°C, 습도: {humidity}%")
except Exception as e:
# 센서 읽기 실패 시
print("센서 읽기 실패:", e)
# DHT11은 최소 1초 간격 필요
time.sleep(2)
실행 결과:
온도: 24°C, 습도: 55%
온도: 24°C, 습도: 56%
온도: 25°C, 습도: 54%
여기서 잠깐! 🤔
try-except가 뭐야? - DHT11 센서는 가끔 읽기에 실패해 (통신 오류) -
try: 이 코드를 시도해봐 -except: 실패하면 이렇게 해 - 에러가 나도 프로그램이 멈추지 않아!왜 2초나 기다려? - DHT11은 저가형 센서라 측정에 시간이 걸려 - 최소 1초 이상 간격을 줘야 정확한 값이 나와 - DHT22(고급형)는 0.5초면 돼
Step 4: 센서 값으로 LED 자동 제어하기¶
목표: 어두우면 LED가 켜지는 자동 야간등을 만들어보자!
회로 연결:
┌─────────────────────────────────────────────────────┐
│ 연결 정리 │
│ │
│ A0 포트 ◄──── Grove 조도 센서 │
│ D18 포트 ◄──── Grove LED │
└─────────────────────────────────────────────────────┘
코드:
# === WHAT: 자동 야간등 ===
# 어두우면 LED가 켜지고, 밝으면 LED가 꺼지는 코드야
# --- WHY: 왜 필요한지 ---
# 현관등, 복도등처럼 자동으로 켜지는 조명의 원리야!
# HOW: 어떻게 동작하는지
from machine import ADC, Pin
import time
# 센서와 LED 설정
light_sensor = ADC(Pin(26)) # A0 포트
led = Pin(18, Pin.OUT) # D18 포트
# 임계값 설정 (이 값보다 어두우면 LED ON)
# 밝기 30% 이하면 어둡다고 판단
THRESHOLD = 30
while True:
# 밝기 읽고 퍼센트 변환
raw = light_sensor.read_u16()
brightness = (raw / 65535) * 100
# 조건 판단
if brightness < THRESHOLD:
# 어두우면 LED 켜기
led.on()
status = "🌙 어두움 → LED ON"
else:
# 밝으면 LED 끄기
led.off()
status = "☀️ 밝음 → LED OFF"
print(f"밝기: {brightness:.1f}% | {status}")
time.sleep(0.5)
실행 결과:
밝기: 68.5% | ☀️ 밝음 → LED OFF
밝기: 67.9% | ☀️ 밝음 → LED OFF
밝기: 25.3% | 🌙 어두움 → LED ON ← 손으로 가림
밝기: 18.7% | 🌙 어두움 → LED ON
밝기: 52.1% | ☀️ 밝음 → LED OFF ← 손 뗌
여기서 잠깐! 🤔
THRESHOLD(임계값)를 왜 따로 만들어? - 숫자
30이 코드 여러 곳에 있으면 수정하기 힘들어 - 맨 위에THRESHOLD = 30으로 정의하면 한 번만 바꾸면 돼! - 대문자로 쓰면 "이건 설정값이야"라는 표시
Step 5: 환경 모니터링 시스템 만들기¶
목표: 조도 + 온습도를 함께 측정하는 환경 모니터를 만들어보자!
코드:
# === WHAT: 환경 모니터링 시스템 ===
# 조도, 온도, 습도를 한번에 측정해서 보여주는 코드야
# --- WHY: 왜 필요한지 ---
# 내 방의 환경 데이터를 수집하면 쾌적한 환경을 만들 수 있어!
# HOW: 어떻게 동작하는지
from machine import ADC, Pin
import dht
import time
# 센서 설정
light_sensor = ADC(Pin(26)) # 조도 센서 (A0)
dht_sensor = dht.DHT11(Pin(16)) # 온습도 센서 (D16)
print("=" * 40)
print("🏠 환경 모니터링 시스템 시작!")
print("=" * 40)
count = 1 # 측정 횟수
while True:
# 조도 측정
light_raw = light_sensor.read_u16()
brightness = (light_raw / 65535) * 100
# 온습도 측정
try:
dht_sensor.measure()
temp = dht_sensor.temperature()
humidity = dht_sensor.humidity()
# 결과 출력
print(f"\n📊 측정 #{count}")
print(f" 💡 밝기: {brightness:.1f}%")
print(f" 🌡️ 온도: {temp}°C")
print(f" 💧 습도: {humidity}%")
# 환경 평가
if temp < 18:
print(" ❄️ 좀 춥네요!")
elif temp > 28:
print(" 🔥 좀 덥네요!")
else:
print(" ✅ 쾌적해요!")
except:
print(f"\n📊 측정 #{count}")
print(f" 💡 밝기: {brightness:.1f}%")
print(" ⚠️ 온습도 센서 읽기 실패")
count += 1
time.sleep(3) # 3초마다 측정
실행 결과:
========================================
🏠 환경 모니터링 시스템 시작!
========================================
📊 측정 #1
💡 밝기: 65.3%
🌡️ 온도: 24°C
💧 습도: 55%
✅ 쾌적해요!
📊 측정 #2
💡 밝기: 18.7%
🌡️ 온도: 24°C
💧 습도: 56%
✅ 쾌적해요!
📊 측정 #3
💡 밝기: 64.1%
🌡️ 온도: 25°C
💧 습도: 54%
✅ 쾌적해요!
📝 전체 코드¶
파일명: environment_monitor.py
# === 환경 모니터링 시스템 (완성본) ===
# 조도, 온도, 습도를 측정하고 LED로 알림하는 시스템
#
# 하드웨어 연결:
# - Grove 조도 센서 → A0 포트
# - Grove DHT11 → D16 포트
# - Grove LED → D18 포트
from machine import ADC, Pin
import dht
import time
# === 하드웨어 설정 ===
light_sensor = ADC(Pin(26)) # 조도 센서 (A0 = GPIO26)
dht_sensor = dht.DHT11(Pin(16)) # 온습도 센서 (D16)
led = Pin(18, Pin.OUT) # LED (D18)
# === 설정값 ===
LIGHT_THRESHOLD = 30 # 이 값 이하면 어두움 (%)
TEMP_LOW = 18 # 이 값 이하면 추움 (°C)
TEMP_HIGH = 28 # 이 값 이상이면 더움 (°C)
# === 초기화 ===
print("=" * 45)
print("🏠 스마트 환경 모니터링 시스템")
print("=" * 45)
print(f"📌 어두움 기준: {LIGHT_THRESHOLD}% 이하")
print(f"📌 쾌적 온도: {TEMP_LOW}°C ~ {TEMP_HIGH}°C")
print("-" * 45)
count = 1
# === 메인 루프 ===
while True:
# 조도 측정
light_raw = light_sensor.read_u16()
brightness = (light_raw / 65535) * 100
# 어두우면 LED 켜기
if brightness < LIGHT_THRESHOLD:
led.on()
light_status = "🌙 어두움 (LED ON)"
else:
led.off()
light_status = "☀️ 밝음"
# 온습도 측정
try:
dht_sensor.measure()
temp = dht_sensor.temperature()
humidity = dht_sensor.humidity()
# 온도 평가
if temp < TEMP_LOW:
temp_status = "❄️ 추움"
elif temp > TEMP_HIGH:
temp_status = "🔥 더움"
else:
temp_status = "✅ 쾌적"
# 결과 출력
print(f"\n📊 측정 #{count}")
print(f" 💡 밝기: {brightness:.1f}% | {light_status}")
print(f" 🌡️ 온도: {temp}°C | {temp_status}")
print(f" 💧 습도: {humidity}%")
except Exception as e:
print(f"\n📊 측정 #{count}")
print(f" 💡 밝기: {brightness:.1f}% | {light_status}")
print(f" ⚠️ 온습도 센서 오류: {e}")
count += 1
time.sleep(3)
⚠️ 자주 하는 실수¶
실수 1: ADC 핀 번호 혼동¶
증상: 센서 값이 항상 0이거나 이상한 값이 나옴
원인: Grove Shield의 포트 이름과 실제 GPIO 번호가 달라!
해결:
# 잘못된 코드 ❌
light_sensor = ADC(Pin(0)) # A0라서 0번?
# 올바른 코드 ✅
light_sensor = ADC(Pin(26)) # A0 포트 = GPIO26!
Grove Shield 포트 매핑: | Grove 포트 | GPIO 번호 | |-----------|----------| | A0 | GPIO26 | | A1 | GPIO27 | | A2 | GPIO28 |
실수 2: DHT11 측정 간격 너무 짧음¶
증상: "센서 읽기 실패" 메시지가 자주 뜸
원인: DHT11은 최소 1초 이상 간격이 필요해!
해결:
# 잘못된 코드 ❌
while True:
sensor.measure()
print(sensor.temperature())
time.sleep(0.1) # 0.1초는 너무 짧아!
# 올바른 코드 ✅
while True:
sensor.measure()
print(sensor.temperature())
time.sleep(2) # 2초 이상 권장
실수 3: dht 라이브러리 미설치¶
증상: ImportError: no module named 'dht'
원인: dht 라이브러리가 설치되지 않음
해결:
1. Thonny 메뉴 → 도구 → 패키지 관리
2. dht 검색
3. 설치 클릭
# 에러 메시지
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ImportError: no module named 'dht'
# 해결: 패키지 관리에서 dht 설치 후 다시 실행!
실수 4: try-except 없이 DHT 사용¶
증상: 프로그램이 가끔 멈춤
원인: DHT 센서는 가끔 통신 오류가 발생해
해결:
# 잘못된 코드 ❌
while True:
sensor.measure() # 여기서 에러나면 프로그램 종료!
print(sensor.temperature())
# 올바른 코드 ✅
while True:
try:
sensor.measure()
print(sensor.temperature())
except:
print("측정 실패, 다시 시도...")
time.sleep(2)
✅ 스스로 점검하기¶
1. 아날로그와 디지털의 차이는?¶
버튼은 ( ) 신호, 조도 센서는 ( ) 신호를 출력해.
2. ADC의 역할은?¶
ADC는 ( ) 신호를 ( ) 신호로 변환해줘.
3. 피코 ADC의 범위는?¶
read_u16() 함수는 ( ) ~ ( ) 범위의 값을 반환해.
4. DHT11 측정 간격은?¶
DHT11 센서는 최소 ( )초 이상 간격을 줘야 해.
5. A0 포트의 GPIO 번호는?¶
Grove Shield의 A0 포트는 GPIO( )번이야.
정답 확인
1. 버튼은 **(디지털)** 신호, 조도 센서는 **(아날로그)** 신호를 출력해. 2. ADC는 **(아날로그)** 신호를 **(디지털)** 신호로 변환해줘. 3. `read_u16()` 함수는 **(0)** ~ **(65535)** 범위의 값을 반환해. 4. DHT11 센서는 최소 **(1)** 초 이상 간격을 줘야 해. (2초 권장) 5. Grove Shield의 A0 포트는 GPIO**(26)**번이야.🚀 더 해보기¶
도전 1: 밝기 레벨 표시기 ⭐¶
밝기에 따라 다른 메시지를 출력해봐!
0~20%: "🌑 아주 어두움"
21~40%: "🌒 어두움"
41~60%: "🌓 보통"
61~80%: "🌔 밝음"
81~100%: "🌕 아주 밝음"
힌트: if-elif-else를 여러 개 써봐!
도전 2: 불쾌지수 계산기 ⭐⭐¶
온도와 습도로 불쾌지수를 계산해봐!
불쾌지수 = 0.81 × 온도 + 0.01 × 습도 × (0.99 × 온도 - 14.3) + 46.3
| 불쾌지수 | 체감 |
|---|---|
| ~67 | 쾌적 😊 |
| 68~74 | 보통 😐 |
| 75~79 | 불쾌 😣 |
| 80~ | 매우 불쾌 😫 |
도전 3: 데이터 로깅 시스템 ⭐⭐⭐¶
측정 데이터를 파일로 저장해봐!
# 힌트: 파일 쓰기
with open("data.txt", "a") as f:
f.write(f"{temp},{humidity},{brightness}\n")
나중에 엑셀에서 열어서 그래프를 그려볼 수 있어!
🔗 다음 장으로¶
이번 장에서 배운 것: - ✅ 아날로그 vs 디지털 신호의 차이 - ✅ ADC로 센서 값 읽기 (0~65535) - ✅ 조도 센서로 밝기 측정 - ✅ DHT11로 온도/습도 측정 - ✅ 센서 + LED로 자동 야간등 만들기
다음 장 예고: 🎨 출력의 마법 - 세상에 표현하다
지금까지 세상의 정보를 "읽는" 방법을 배웠어. 다음 장에서는 세상에 "표현"하는 방법을 배워볼 거야!
- RGB LED로 무지개 색 만들기 🌈
- 부저로 멜로디 연주하기 🎵
- 서보모터로 움직임 만들기 🤖
센서가 느낀 정보를 다양한 방법으로 표현해보자!