AirOwl: 실시간 공기질 모니터링으로 더 건강한 호흡을
부품 및 소모품
| Arduino 101 (Genuino 101) |
1 |
| 미세먼지 센서 ZH03A |
1 |
| Adafruit Flora RGB 네오픽셀 LED 4개 팩 |
1 |
| 점퍼 와이어 |
10 |
| 10kΩ 저항 |
3 |
앱 및 온라인 서비스
- Blynk (BLE 연동)
- Arduino IDE
프로젝트 개요
AirOwl은 실시간 공기질 모니터링 장치입니다. 센서에서 데이터를 읽어 Arduino/Genuino 101의 BLE를 통해 Blynk 앱으로 전송합니다. "우리가 마시는 공기"를 알 수 있게 해주는 프로젝트입니다.
인간 활동이 환경에 영향을 미치므로, 주변 환경을 파악하고 적절히 대응할 수 있는 장치를 만들기로 했습니다.
공기질 확인 3가지 방법
- Blynk 앱 (BLE) - 게이지로 PM1, PM2.5, PM10 수치 실시간 표시
- AirOwl 눈 색상:
- 🟢 초록: 안전함
- 🔵 파랑: 주의 필요
- 🔴 빨강: 위험
- 시리얼 모니터 - 수치 상세 확인
회로도 및 설계
GitHub: 회로도 및 설계 파일
미세먼지 센서 데이터시트: ZH03A 데이터시트
제작 순서
- 회로도대로 배선
- 필요 라이브러리 설치 후 코드 업로드
- Blynk 앱 설정:
- 앱 설치 (플레이스토어/앱스토어)
- 계정 생성 → 새 프로젝트 → 보드 선택 (Arduino 101) → 프로젝트명 입력
- 인증 키 이메일로 수신
- 작업 공간에서 BLE 위젯 + 게이지 3개 추가 (핀 V1, V2, V3)
- 블루투스 켜고 시뮬레이션 시작
브레드보드 프로토타이핑용 회로도
브레드보드로 테스트하실 분을 위한 회로도도 제공됩니다.
PCB 설계
회로도, 보드 파일, 3D 이미지 모두 GitHub에 있습니다: AirOwl_Genuino101
코드
/* Copyright (C) 2017 Anith Patel and Sohil Patel. GNU FDL 1.3+ */
#include <BlynkSimpleCurieBLE.h>
#include <CurieBLE.h>
#define BLYNK_SERIAL Print
byte data[24];
unsigned int PM1 = 0, PM25 = 0, PM10 = 0, count = 0;
const int PIN1 = 3, PIN2 = 5, PIN3 = 6;
char auth[] = "Auth key"; // Blynk 인증 키 입력
BLEPeripheral blePeripheral;
void setup() {
blePeripheral.setLocalName("Airowl");
blePeripheral.setDeviceName("Airowl");
blePeripheral.setAppearance(384);
Blynk.begin(blePeripheral, auth);
blePeripheral.begin();
Serial1.begin(9600); // 센서 UART
Serial.begin(9600);
pinMode(PIN1, OUTPUT);
pinMode(PIN2, OUTPUT);
pinMode(PIN3, OUTPUT);
}
void loop() {
Blynk.run();
blePeripheral.poll();
Serial.println("PM1 농도: "); Serial.println(PM1/count);
Serial.println("PM2.5 농도: "); Serial.println(PM25/count);
Serial.println("PM10 농도: "); Serial.println(PM10/count);
delay(500);
WriteData();
// 평균값으로 LED 색상 결정
unsigned int avg = (PM1 + PM25 + PM10) / 3;
if (avg <= 100) LedColor(0, 255, 0); // 초록
else if (avg <= 300) LedColor(255, 0, 0); // 빨강
else LedColor(0, 0, 255); // 파랑
delay(500);
}
void LedColor(int red, int blue, int green) {
analogWrite(PIN1, red);
analogWrite(PIN2, blue);
analogWrite(PIN3, green);
}
void getWinsenData() {
byte i = 0;
int checksum = 0;
Serial1.flush();
while (Serial1.available()) {
data[i] = Serial1.read();
if (i <= 21) checksum += data[i];
if (i == 23) {
if (checksum == ((256 * data[22]) + data[23])) {
if (data[0] == 66 && data[1] == 77) {
PM1 += ((data[4] * 256) + data[5]);
PM25 += ((data[6] * 256) + data[7]);
PM10 += ((data[8] * 256) + data[9]);
count++;
Serial1.flush();
break;
}
} else break;
}
i++;
delay(10);
}
}
void WriteData() {
getWinsenData();
Blynk.virtualWrite(V1, PM1/count);
Blynk.virtualWrite(V2, PM25/count);
Blynk.virtualWrite(V3, PM10/count);
delay(1000);
}
커스텀 파트 및 인클로저
3D 프린팅 파일: GitHub AirOwl
회로도
AirOwl Genuino 101 회로도