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

가스·공기 · 난이도 보통

MQ-135 공기질 센서를 Rs/R0로 읽고 CO₂ ppm 환산을 믿지 않는 이유

MQ-135는 암모니아·벤젠·알코올·연기 등에 함께 반응하는 공기질 센서예요. 데이터시트 식으로 Rs를 구해 바깥 공기 R0와 비교하는 피코 코드, 인터넷의 CO₂ ppm 환산이 근거가 약한 이유, CO₂ 센서와 나란히 기록하는 탐구를 정리했어요.

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

이 센서로 무엇을 잴 수 있나

MQ-135는 한웨이 데이터시트에서 건물·사무실의 공기질 관리 장치용으로 소개하는 산화주석 센서예요. 반응하는 기체로 암모니아(NH₃), 질소산화물, 알코올, 벤젠, 연기, CO₂ 등을 들어요. 감지 범위는 암모니아 10~300ppm, 벤젠 10~1000ppm, 알코올 10~300ppm으로 적혀 있어요. CO₂는 감도 곡선에는 그려져 있지만 감지 범위 표에는 없어요.

이 센서는 여러 기체를 하나로 묶어 "공기가 바깥보다 얼마나 달라졌나"를 보여 줘요. 수업 중 창문을 닫았을 때와 열었을 때, 시간대에 따라 교실 공기가 어떻게 달라지는지를 비율로 기록할 수 있어요. CO₂ 센서와 나란히 기록하면 "MQ-135가 CO₂를 대신할 수 있나"라는 질문에도 데이터로 답할 수 있어요.

원리

데운 산화주석 막의 저항(Rs)이 기체에 닿으면 내려가고, 모듈은 Rs와 부하 저항(RL)을 5V에 직렬로 이어 RL의 전압을 AO로 내보내요. 데이터시트 식 Rs = (Vc ÷ VRL − 1) × RL로 AO 전압을 저항으로 되돌릴 수 있어요. 이 글의 코드는 이 식으로 Rs를 kΩ 단위로 구해요.

데이터시트에서 기준 Ro는 "깨끗한 공기 속 100ppm 암모니아에서의 저항"이고, 그때 Rs는 30~200kΩ이에요. 같은 모델끼리도 6배 넘게 다를 수 있다는 뜻이에요. 곡선은 RL 20kΩ 조건이고, 감도를 맞출 때는 100ppm 암모니아나 50ppm 알코올을 쓰고 RL은 20kΩ 근처(10~47kΩ)로 고르라고 권해요. 우리는 이런 표준 가스가 없으니, 바깥 공기에서 잰 Rs를 우리만의 기준 R0로 삼고 Rs/R0를 봐요. 1보다 작아질수록 반응한 기체가 많다는 뜻이에요.

히터는 5V, 33Ω(±5%)이라 약 0.15A를 써요. 사용 온도는 −10~45℃, 예열은 24시간 넘게 하라고 적혀 있어요.

준비물

  • 라즈베리파이 피코와 USB 케이블
  • MQ-135 모듈(VCC·GND·DO·AO)
  • 10kΩ, 20kΩ 저항 1개씩, 브레드보드, 점퍼선
  • 멀티미터(VBUS 전압과 모듈의 RL 확인)
  • (탐구 1) MH-Z19B 같은 CO₂ 센서

배선

MQ-135 공기질 센서를 Rs/R0로 읽고 CO₂ ppm 환산을 믿지 않는 이유: 브레드보드에 피코와 센서를 꽂은 배선 그림
시나브로 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. 공기질: 암모니아·벤젠·연기·CO₂ 경향 MQ-135 꽂기: 다리 VCC · GND · AO를 아래쪽 j24 · j25 · j26에 차례로 꽂아요. 다리가 브레드보드에 바로 안 들어가면 암-수 점퍼선으로 같은 칸에 이어요.
  5. 빨간 선(5V 전원): 공기질: 암모니아·벤젠·연기·CO₂ 경향 VCC 줄 i24 → 아래쪽 + 줄(5V)
  6. 검은 선(GND): 공기질: 암모니아·벤젠·연기·CO₂ 경향 GND 줄 i25 → 아래쪽 − 줄(GND)
  7. 저항 10kΩ(색띠 갈색·검정·주황): g26 ↔ g28 (AO 다리 칸 → 나눔 칸 28열)
  8. 저항 20kΩ(색띠 빨강·검정·주황): i28 ↔ 아래쪽 − 줄(GND)
  9. 초록 선: 나눔 칸 h28 → 피코 31번 핀(GP26) 옆 칸 a11. 5V 신호가 3.3V 아래로 줄어 피코가 안전해요.
  10. 마지막 확인: ① 위쪽 + 줄(3.3V)과 아래쪽 + 줄(5V)이 서로 이어지지 않았나요? ② 모든 부품의 GND가 − 줄에 이어졌나요? ③ 5V 신호 다리는 저항을 거쳐 피코에 이어졌나요? ④ 긴 브레드보드는 + − 줄이 가운데에서 끊긴 것도 있어요(빨간·파란 선이 끊겨 있으면 짧은 선으로 이어요). ⑤ 그림과 한 칸씩 비교한 뒤 USB를 꽂아요.
모듈 핀 피코 핀 비고
VCC VBUS (40번) 히터·측정 회로 5V
GND GND (38번) 공통 접지
AO GP26 (31번) 10kΩ·20kΩ 분압 뒤 연결
DO 연결 안 함

공기가 탁할수록 Rs가 작아져 AO가 5V 쪽으로 올라가요. 피코 ADC는 3.3V까지라 AO 쪽에 10kΩ, GND 쪽에 20kΩ을 두어 2/3로 줄여요. 이 글은 Rs를 직접 계산하니 한 가지를 더 챙겨요. 분압 저항 두 개(합 30kΩ)는 AO와 GND 사이에 RL과 나란히 붙어요. 그래서 실제 부하는 RL × 30 ÷ (RL + 30)kΩ이 되고, 코드는 이 값으로 Rs를 계산해요.

코드

from machine import ADC, Pin
import time

mq135 = ADC(Pin(26))           # AO → 10kΩ/20kΩ 분압 → GP26
VC = 5.0                       # VBUS 전압(멀티미터로 재서 고치기)
RL = 1.0                       # 모듈의 부하 저항(kΩ). 모르면 그대로: ratio는 RL과 상관없어요
RL = RL * 30 / (RL + 30)       # 분압 저항 30kΩ이 RL과 나란히 붙은 효과
R0 = 0                         # 바깥 공기에서 잰 Rs(kΩ). 0이면 처음 30초로 정함

def rs_kohm():
    s = 0
    for i in range(32):
        s += mq135.read_u16()
    v = s / 32 * 3.3 / 65535 * 1.5
    if v < 0.01:
        return 0
    return (VC / v - 1) * RL   # 데이터시트 식 Rs = (Vc/VRL - 1) × RL

if R0 == 0:
    print("R0를 재요(30초). 창밖 공기에서 시작하세요")
    total = 0
    for i in range(30):
        total += rs_kohm()
        time.sleep(1)
    R0 = total / 30
print(f"R0 = {R0:.2f} kΩ  ← 적어 두고 다음부터 R0에 넣기")

avg = 1.0
while True:
    rs = rs_kohm()
    ratio = rs / R0 if R0 > 0 else 0
    avg = avg * 0.95 + ratio * 0.05      # 천천히 따라가는 평균
    print(f"DATA: rs_kohm={rs:.2f}, ratio={ratio:.3f}, ratio_avg={avg:.3f}")
    time.sleep(1)
  • RL에는 모듈의 부하 저항을 kΩ으로 넣어요. 전원을 끄고 멀티미터로 재거나 저항 표시를 읽어요. 몰라도 ratio는 맞아요. RL이 분자와 분모에 똑같이 들어가 나누면 사라지기 때문이에요. rs_kohm의 절댓값만 틀려져요.
  • R0가 0이면 처음 30초의 평균을 R0로 정해요. 창밖 공기에서 시작하고, 출력된 R0를 적어 두었다가 다음부터 코드에 넣으면 날마다 같은 기준을 쓸 수 있어요.
  • ratio_avg는 새 값에 0.05의 무게만 주는 평균이라 한순간의 변화보다 큰 흐름을 보여 줘요.

값 해석과 보정

ratio가 0.8이면 바깥 공기 때보다 Rs가 20% 작다는 뜻이에요. 어떤 기체 때문인지는 이 센서만으로는 알 수 없어요.

계산 예를 들면, VBUS 5.0V에서 AO가 1.0V이고 실제 부하가 0.97kΩ이면 Rs = (5.0 ÷ 1.0 − 1) × 0.97 ≈ 3.9kΩ이에요. 깨끗한 공기에서 AO가 아주 낮게 나오는지도 확인해요. 피코 ADC는 실제로 12비트라 3.3V를 4096칸으로 나누고, 분압을 되돌리면 AO 기준 한 칸이 약 1.2mV예요. AO가 0.1V라면 80칸 남짓으로 변화를 그려야 해서 계단처럼 보여요. 이럴 때는 부하 저항이 더 큰 모듈이 낫고, 데이터시트가 권하는 RL도 10~47kΩ이에요.

인터넷에는 MQ-135로 CO₂ ppm을 계산하는 예제가 많아요. 흔히 바깥 공기의 CO₂를 약 400ppm으로 가정해 R0를 정하고, 감도 곡선에서 뽑은 식에 비율을 넣어요. 하지만 데이터시트는 CO₂ 감지 범위를 정하지 않았고, 센서는 알코올이나 암모니아 같은 다른 기체에도 함께 반응해요. 그래서 그 ppm은 CO₂만의 값이라고 할 근거가 약해요. CO₂가 궁금하면 적외선 방식 CO₂ 센서를 쓰고, MQ-135는 비율로만 기록해요.

R0를 언제 다시 잴지도 정해 둬요. 데이터시트에는 온도와 습도(33%RH, 85%RH)에 따라 Rs/Ro가 달라지는 그래프가 있어요. 계절이 바뀌거나 비율이 바깥 공기에서도 1에서 크게 벗어나면 R0를 다시 재요.

자주 하는 실수

  1. CO₂ ppm 숫자를 보고서에 그대로 쓰기. 위에서 본 것처럼 근거가 약해요. "MQ-135 비율"이라고 정확히 이름 붙여요.
  2. R0를 교실 안에서 잡기. 이미 사람이 오래 머문 공기를 기준 1.0으로 삼으면, 나중에 공기가 더 나빠져도 변화가 작게 보여요.
  3. 새 센서로 바로 하루 기록 시작하기. 데이터시트는 24시간 넘는 예열을 요구해요. 첫날 기록은 예열 과정이 섞여요.
  4. RL을 모른 채 rs_kohm을 다른 센서와 비교하기. 절댓값은 RL을 맞게 넣었을 때만 의미가 있어요. 센서끼리는 ratio로 비교해요.

이 센서로 잴 수 있는 탐구

1. MQ-135 비율은 CO₂를 따라갈까 - 질문: 창문을 닫고 수업할 때와 연 뒤에, MQ-135 비율과 CO₂ 농도가 함께 움직일까? - 바꾸는 것: 시간(창문 닫음 30분, 창문 엶 20분) - 재는 것: ratio_avg(비율), CO₂ 센서의 co2(ppm) - 방법: 두 센서를 같은 책상에 나란히 두고 1분 간격으로 기록해요. 산점도를 그려 관계를 보고, 다른 날 두 번 더 해서 같은 모양이 나오는지 확인해요.

2. R0를 어디서 잡느냐에 따라 결과가 얼마나 달라질까 - 질문: 같은 교실 공기라도 R0를 잡은 장소에 따라 비율이 얼마나 달라질까? - 바꾸는 것: R0를 잰 장소(창밖, 복도, 교실 안) - 재는 것: 같은 시각 교실 공기의 ratio(비율) - 방법: 같은 날 세 장소에서 R0를 30초씩 재서 적어 둬요. 교실에서 기록한 rs_kohm을 세 R0로 각각 나누어 비교해요.

3. 하루 중 언제 교실 공기가 가장 달라질까 - 질문: 등교 전, 2교시, 점심 직후, 하교 후 중 언제 비율이 가장 낮을까? - 바꾸는 것: 시간대 - 재는 것: 시간대별 10분 평균 ratio(비율), 그때 교실의 사람 수(명)와 창문 상태 - 방법: 같은 자리, 같은 R0로 5일 동안 기록하고 시간대별로 평균을 내요.

안전

  • 반응을 보려고 기체를 만들지 않아요. 암모니아수를 쓰거나 세제를 섞지 마세요. 락스와 암모니아가 든 세제를 섞으면 유독한 기체가 생겨요.
  • 히터가 뜨거워요. 켠 채로 만지지 마세요.
  • 이 장치는 인증받은 실내 공기질 측정기가 아니에요. 법정 실내공기질 판정이나 환기 기준 판단에 쓰지 마세요.
  • 배선은 USB를 뽑고 바꾸고, VBUS 선이 GP 핀에 닿지 않게 해요.

더 알아보기

글쓴이

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