홍창민정보·인공지능 교사

가스·공기 · 난이도 보통

PPD42NS 먼지 센서로 30초 LOW 펄스 비율을 재서 입자 수 세기

PPD42NS는 1µm보다 큰 입자가 지나갈 때 출력이 LOW가 되는 시간을 모아 입자 수를 세는 센서예요. 4.0V 넘는 출력의 분압, time_pulse_us로 30초 LOW 비율을 구하는 피코 코드, 개/0.01ft³ 단위를 µg/m³와 섞지 않는 법을 정리했어요.

글 홍창민 · 갱신 2026-10-31 · 읽는 데 약 8분 · 가상 실행 확인 (실물 미확인)

이 센서로 무엇을 잴 수 있나

PPD42NS는 일본 신에이(Shinyei)의 입자 센서예요. 사양서에 따르면 약 1µm보다 큰 입자를 감지하고, 측정 범위는 공기 1L에 0~28,000개, 곧 0.01ft³(283mL)에 0~8,000개예요. 전원은 5V(±10%), 소비 전류는 90mA, 사용 온도는 0~45℃예요. Seeed의 Grove Dust Sensor가 이 센서를 쓴 제품이에요.

중요한 점은 무게가 아니라 개수를 센다는 거예요. Seeed 위키도 "무게를 다는 방식이 아니라 세는 방식이고, 단위는 개/L 또는 개/0.01ft³"라고 강조해요. 그래서 이 센서로는 칠판 지우개를 턴 뒤 입자가 얼마나 늘었는지, 공기청정기가 얼마나 빨리 줄이는지, 쉬는 시간과 수업 시간의 차이처럼 같은 센서로 잰 개수의 변화를 비교해요.

원리

센서 안에는 빛을 내는 부품과 받는 부품이 있고, 그 사이로 공기가 지나가요. 입자가 지나가며 빛을 흩뜨리면 출력 핀이 잠깐 LOW가 돼요. 사양서 그래프에 적힌 LOW 펄스 폭은 10~90ms예요. 입자가 많을수록 LOW인 시간이 길어지니, 일정한 시간 동안 LOW였던 시간의 합을 그 시간으로 나눈 비율(LPO, Low Pulse Occupancy)이 농도에 비례해요. 사양서는 이 단위 시간을 30초로 잡았어요.

공기는 팬 없이 흘러요. Seeed 위키 설명대로 안에 든 히터가 공기를 데워 위로 올려 보내는 흐름을 만들어요. 센서를 세워 두어야 하는 이유예요.

LPO 비율을 개수로 바꾸는 식은 Seeed 예제가 쓴 곡선 근사식이에요.

개수(개/0.01ft³) = 1.1 × r³ − 3.8 × r² + 520 × r + 0.62 (r는 LPO 비율, %)

사양서 그래프는 담배 연기로 시험한 결과이고, 위아래 한계 곡선이 따로 그려져 있어 센서마다 차이가 있어요.

준비물

  • 라즈베리파이 피코와 USB 케이블
  • PPD42NS 또는 Grove Dust Sensor
  • 10kΩ, 20kΩ 저항 1개씩, 브레드보드, 점퍼선(5핀 커넥터용)
  • (탐구) 분필이 묻은 칠판 지우개, 공기청정기, 줄자

배선

PPD42NS 먼지 센서로 30초 LOW 펄스 비율을 재서 입자 수 세기: 브레드보드에 피코와 센서를 꽂은 배선 그림
시나브로 PICO 브레드보드 작업대와 같은 계산으로 그린 배선이에요. 위 + 줄은 3.3V, 아래 + 줄은 5V예요.
브레드보드 따라 꽂기 순서 (10단계)
  1. 피코를 브레드보드 가운데 홈에 걸쳐 꽂아요. USB 단자가 왼쪽을 보게 하고, 1번 핀이 f2, 40번 핀이 e2에 들어가요. 다리가 홈 양쪽에 모두 들어갔는지 옆에서 봐요.
  2. 빨간 선: 피코 40번 핀(VBUS) 옆 칸 a2 → 아래쪽 + 줄(5V). 이제 이 줄 전체가 5V예요. 위쪽 + 줄(3.3V)과 아래쪽 + 줄(5V)은 절대 서로 잇지 않아요.
  3. 검은 선: 피코 3번 핀(GND) 옆 칸 j4 → 아래쪽 − 줄(GND). 이제 이 줄 전체가 GND예요.
  4. 미세먼지 입자 수 PPD42NS 꽂기: 다리 3 VCC · 1 GND · 4 P1를 아래쪽 j24 · j25 · j26에 차례로 꽂아요. 다리가 브레드보드에 바로 안 들어가면 암-수 점퍼선으로 같은 칸에 이어요.
  5. 빨간 선(5V 전원): 미세먼지 입자 수 3 VCC 줄 i24 → 아래쪽 + 줄(5V)
  6. 검은 선(GND): 미세먼지 입자 수 1 GND 줄 i25 → 아래쪽 − 줄(GND)
  7. 저항 10kΩ(색띠 갈색·검정·주황): g26 ↔ g28 (4 P1 다리 칸 → 나눔 칸 28열)
  8. 저항 20kΩ(색띠 빨강·검정·주황): i28 ↔ 아래쪽 − 줄(GND)
  9. 초록 선: 나눔 칸 h28 → 피코 20번 핀(GP15) 옆 칸 j21. 5V 신호가 3.3V 아래로 줄어 피코가 안전해요.
  10. 마지막 확인: ① 위쪽 + 줄(3.3V)과 아래쪽 + 줄(5V)이 서로 이어지지 않았나요? ② 모든 부품의 GND가 − 줄에 이어졌나요? ③ 5V 신호 다리는 저항을 거쳐 피코에 이어졌나요? ④ 긴 브레드보드는 + − 줄이 가운데에서 끊긴 것도 있어요(빨간·파란 선이 끊겨 있으면 짧은 선으로 이어요). ⑤ 그림과 한 칸씩 비교한 뒤 USB를 꽂아요.
모듈 핀 피코 핀 비고
1 GND GND (38번) 공통 접지
3 +5V VBUS (40번) 90mA, 리플 30mV 이내 권장
4 P1 GP15 (20번) 10kΩ·20kΩ 분압 뒤 연결
2 P2 연결 안 함 더 큰 입자용 출력
5 T1 연결 안 함 P2 문턱 조정용

Grove 케이블이라면 빨강이 5V, 검정이 GND, 노랑이 P1이고 흰색은 쓰지 않아요.

사양서는 출력 HIGH를 4.0V 넘게(새 판은 4.5V), LOW를 0.7V 아래로 적어요. HIGH가 피코 GPIO의 3.3V를 넘으니 P1 쪽에 10kΩ, GND 쪽에 20kΩ을 두고 가운데를 GP15에 연결해 2/3로 낮춰요. 4.0V는 약 2.7V, 4.5V는 3.0V가 되어 피코가 HIGH로 읽기에 충분해요. 이 HIGH 값은 입력 임피던스 200kΩ 조건에서 잰 것이라, 분압 저항을 너무 작게 하면 HIGH가 처질 수 있어요. 합이 30kΩ보다 작은 조합은 쓰지 마세요.

코드

from machine import Pin, time_pulse_us
import time

p1 = Pin(15, Pin.IN)           # 4번 핀 P1 → 10kΩ/20kΩ 분압 → GP15
WINDOW_MS = 30000              # 데이터시트가 권하는 단위 시간 30초
n = 0

print("센서를 세운 채 켜고, 처음 1분(첫 사용은 3분) 값은 기록에서 빼요")
while True:
    low_us = 0
    t0 = time.ticks_ms()
    while time.ticks_diff(time.ticks_ms(), t0) < WINDOW_MS:
        t = time_pulse_us(p1, 0, 200000)   # LOW 펄스 길이(µs). 음수는 시간 초과
        if t > 0:
            low_us += t
    spent = time.ticks_diff(time.ticks_ms(), t0)   # 실제로 흐른 시간(ms)
    ratio = low_us / (spent * 10)          # LOW였던 시간 비율(%)
    pcs = 1.1 * ratio ** 3 - 3.8 * ratio ** 2 + 520 * ratio + 0.62
    n += 1
    print(f"DATA: lpo={ratio:.2f}, pcs_cf={pcs:.0f}, pcs_l={pcs * 3.53:.0f}")
    if n <= 2:
        print("  ↑ 예열 구간 값")
  • time_pulse_us(p1, 0, 200000)은 P1이 LOW로 있었던 시간을 µs로 돌려줘요. 0.2초 안에 LOW가 시작되지 않거나 끝나지 않으면 음수(−2, −1)를 돌려주므로 더하지 않아요.
  • 30초 동안 LOW 시간을 모은 뒤, 실제로 흐른 시간(spent)으로 나눠요. µs ÷ (ms × 10)을 하면 바로 퍼센트가 돼요.
  • pcs_cf는 개/0.01ft³, pcs_l은 개/L예요. 0.01ft³가 283mL라서 1000 ÷ 283 ≈ 3.53을 곱해요.
  • 첫 두 창(1분)은 예열 구간으로 표시해요. 사양서의 안정화 시간은 켠 뒤 1분이고, Seeed 위키는 처음 쓸 때 3분 예열을 권해요.

값 해석과 보정

pcs_l은 개수 농도라서 미세먼지 예보의 µg/m³(PM10, PM2.5)와 바로 비교할 수 없어요. 입자의 크기와 밀도를 모르면 개수를 무게로 바꿀 수 없기 때문이에요. 결과를 발표할 때는 "개/L"를 꼭 붙이고, 예보 값과는 오르내림의 경향만 견줘요.

30초 한 창의 값은 꽤 흔들려요. 펄스 하나가 10~90ms라서 입자가 적을 때는 30초 안에 몇 개 안 들어오기 때문이에요. 변화를 판단할 때는 창 4~10개를 평균 내고, 평균에 쓴 창 수를 함께 적어요.

식에는 상수 0.62가 있어서 LPO가 0%여도 0.62가 나와요. 이 숫자는 "거의 없음"으로 읽어요. 사양서 그래프는 0.01ft³에 8,000개까지만 그려져 있으니, 그보다 큰 값은 식을 넘겨 짐작한 숫자예요.

보정에 쓸 표준 장비가 없으니, 같은 센서를 같은 자리, 같은 방향으로 두고 비교해요. 센서를 바꾸면 기준도 다시 잡아요.

자주 하는 실수

  1. 센서를 눕혀 두기. 히터가 만드는 위쪽 공기 흐름이 생기지 않아요. 같은 계열의 PPD42NJ 사양서는 ±3° 안으로 세우라고 적어요.
  2. µg/m³로 착각하기. 위에서 본 것처럼 단위가 달라요.
  3. 1초마다 비율을 계산하기. 펄스가 길게는 90ms라 1초 창에는 몇 개만 걸려서 값이 널뛰어요. 사양서대로 30초 이상 모아요.
  4. 앞쪽 창으로 빛이 들어가게 두기. PPD42NJ 사양서는 앞 창을 덮어 감지부를 완전히 어둡게 하라고 적어요. 창가 햇빛을 피해요.
  5. 렌즈를 알코올로 닦기. 같은 사양서는 물을 묻힌 면봉으로만 닦으라고 해요.

이 센서로 잴 수 있는 탐구

1. 칠판 지우개를 털면 입자는 얼마나 늘고 언제 돌아올까 - 질문: 지우개를 턴 곳과 센서 사이 거리에 따라 최고 입자 수와 회복 시간이 달라질까? - 바꾸는 것: 거리(1m, 3m) - 재는 것: 최고 pcs_l(개/L), 털기 전 평균으로 돌아오기까지 걸린 시간(분) - 방법: 털기 전 다섯 창(2분 30초) 평균을 기준으로 잡고, 지우개를 두 번 털어요. 거리마다 3번, 시도 사이는 10분 넘게 쉬어요.

2. 공기청정기는 입자를 얼마나 빨리 줄일까 - 질문: 공기청정기 세기에 따라 입자 수가 절반이 되는 시간이 달라질까? - 바꾸는 것: 세기(약, 강). 청정기와 센서 거리 2m 고정 - 재는 것: 처음 평균의 절반이 될 때까지 걸린 시간(분) - 방법: 창문을 닫은 교실에서 다섯 창 평균을 낸 뒤 켜고 30분 기록해요. 세기마다 다른 날 2번 해요.

3. 쉬는 시간과 수업 시간 중 언제 입자가 많을까 - 질문: 사람이 많이 움직이는 쉬는 시간에 입자 수가 더 많을까? - 바꾸는 것: 시간대(수업 중, 쉬는 시간, 점심시간) - 재는 것: 시간대별 평균 pcs_l(개/L) - 방법: 교실 뒤쪽 책상 높이에 세워 두고 5일 동안 기록해 시간대별로 평균을 내요.

안전

  • 연기를 만들지 않아요. 제조사는 담배 연기로 시험하지만, 학교에서는 향, 담배, 종이를 태우지 않아요.
  • 분필 가루를 센서에 직접 불어 넣지 말고, 털 때 들이마시지 않게 해요. 천식이 있는 친구는 그 시간에 자리를 옮겨요.
  • 이 센서는 인증받은 미세먼지 측정기가 아니에요. 미세먼지 경보나 건강 판단에 쓰지 마세요.
  • P1을 분압 없이 GP15에 꽂지 마세요. 배선은 USB를 뽑고 바꿔요.

더 알아보기

  • 사양서: Shinyei "Specification sheet of PPD42NS"(감지 크기, 범위, 출력 수준, 핀 배치, 30초 단위 시간), 같은 계열의 "PPD42NJ" 사양서(설치 각도, 앞 창 가림, 렌즈 관리)
  • 제품 자료: Seeed Studio "Grove - Dust Sensor" 위키(계산식, 3분 예열, 세워 두기)
  • 라이브러리: 따로 없어요. MicroPython machine.time_pulse_us
  • 기초 글: 분압 회로, 피코 핀 지도, 센서 값의 신뢰도, 잴 수 있는 탐구 주제 고르기
글쓴이

홍창민 · 울산 학성고등학교 정보·인공지능 교사. 수업에 쓰는 도구(시나브로 PICO 웹 IDE, 학교 AI 서버 등)를 직접 만들어 운영해요. 소개 보기 · 고칠 곳 알려 주기