본문 바로가기
Hardware/MCU(Arduino,ESP8266)

아두이노 미세먼지 측정기 만들기 (PMS7003센서 사용기)

by lovey25 2019. 3. 11.
반응형

개요

미세먼지 농도를 측정하는 아두이노 프로젝트입니다. 제법 정밀한 센서로 알려져 있는 PMS7003센서를 사용하고 아두이노를 이용해서 센서를 동작하고 데이터를 확인하도록 하겠습니다.

준비물

    • PMS7003 센서
    • 아두이노 우노 R3
    • 아두이노 업로드 및 전원용 USB케이블
    • 점프케이블
    • 빵판

PMS7003 센서 특징

PMS7003센서는 공기중의 부유 미세입자의 농도를 측정하는 센서입니다. 그리고 측정된 결과는 디지털 인터페이스(UART)로 출력합니다.

datasheet의 성능요약 테이블을 살펴보겠습니다.

측정가능한 최소 입자크기는 0.3마이크론 까지인데 보시는것 처럼 측정효율이 많이 떨어집니다. 그래서 실질적인 측정가능 입자크기는 최소 0.5마이크론으로 봐야 겠습니다.

측정 농도의 범위는 PM2.5를 기준으로 0~500ug/m3 의 범위가 유효측정범위라고 합니다. 우리나라 기준으로 미세먼지는 보통 100 미만일때가 많고 요즘처럼 미세먼지가 극성일때는 200이상까지도 가죠. 그래서 일반적인 대기환경 측정용으로는 적당한 성능입니다. 

PMS7003센서는 레이저의 산란을 측정해서 미세입자의 농도를 계산하는 원리로 작동한다고 합니다. Datasheet 설명으로는 산란된 빛을 측정해서 Mie산란 이론을 바탕으로 미세입자의 크기, 농도를 계산한다고 하네요. 미산란이 뭔지 궁금하니 살짝 찾아봤습니다.

Mie산란이란?

Mie산란(미산란)에 대한 겉핥기 입니다. 산란이라는 현상은 크게 레일리 산란과 미산란으로 나눌수 있습니다. 그중 미산란이라는 것은 빛의 파장 범위가 입자의 크기와 비슷할 때 발생하는 현상으로 빛이 입자에 맞고 사방으로 퍼지는데 이때 붉은파장이나 푸른파장등 파장의 길이와 상관없이 모든색의 빛이 산란되는 현상을 말합니다. 그래서 안개가 끼거나 미세먼지가 많은날 공기가 회색빛이 되는거라고 하네요. 미산란은 빛의 색과는 관계없이 입자의 농도나 크기에 따라 산란도가 달라지기 때문에 이를 이용한 방식인것 같습니다.  그럼 여기서 알수 있는것이 미산란을 이용한 측정한 방법의 단점은 공기중 먼지입자 외에도 수증기 입자에 대해서도 반응해서 수증기가 많은 공간에서는 먼지만의 농도를 측정하는건 어려울 것 같네요.

이와는 대조적인 현상인 레일리 산란에 대해서도 뭔지만 알고 넘어가죠. 레일리 산란은 빛의 파장과 비교했을 때 입자의 크기가 작은경우 나타나는 현상으로 파장의 길이가 긴 빛은 산란이 되지 않고 입자를 투과해서 진행을 하는 반면 파장이 짧은 빛은 입자에서 산란이 쉽게되는 현상을 말합니다. 저녁노을이 붉어지는 이유가 바로 이 레일리 산란때문이라고 하네요. 하늘이 푸른색으로 보이고, 저녁노을이 붉어지는 현상을 바로 이 레일리 산란으로 설명할수 있다고 하네요. 

PMS7003센서의 측정데이터

PMS7003의 측정방법에는 2가지가 있습니다.

    • Active mode: 측정값을 연속적으로 시리얼로 보내주는 모드. 기본 설정값
    • Passive mode: 사용자의 요청이 있을때만 측정해서 측정결과를 보내주는 모드

사용 용도에 따라서 모드를 선택해서 사용할 수 있는데요. 저는 패시브로 사용해 보겠습니다.  패시브 모드를 사용할 때 주의할 점이 있는데 대기중인 센서가 다시 작동을 하게 될때 30초이상 부팅시간을 가진 후 측정을 해야 정확한 결과를 얻을 수있다고 합니다. 내부에 있는 팬으로 공기를 유입시키는데 아마도 유동 안정화를 기다려야 하는가 봅니다.

센서의 Datasheet

p564008-PMS7003 series data manua_English_V2.5.pdf
다운로드

미세먼지측정용 아두이노 펌웨어 코딩

VS에서 새로운 프로젝트 만들기로 시작합니다.

맨먼저 할일은 필요한 라이브러리를 먼저 추가하는것입니다. 프로젝트에 라이브러리를 추가하려면 다음과 같이 Visual Micro 메뉴를 사용하면 됩니다.

여기서 vMicro >> Add Library >> Download and Install Arduino Library 메뉴로 이동을 합니다. 그럼 라이브러리를 관리하는 창이 열리는데 여기서 이미 설치된 라이브러리를 추가할 수도 있고 새로운 라이브러리를 찾아서 설치할 수 도 있습니다. (Visual Micro Explorer메뉴로 들어가도 됩니다.)

1. 아두이노 소프트웨어시리얼 라이브러리

아두이노 우노에는 시리얼을 한 개 포트만  지원합니다.  그래서 그 하나의 시리얼 포트를 센서 데이터를 받는데 사용해 버리면 디버깅이나 펌웨어 업로드 등을 하는데 방해가 되기 때문에 소프트웨어시리얼을 사용하려 합니다.

소프트웨어시리얼 라이브러리는 아마도 기본으로 설치가 되어 있었던거 같은데요. 라이브러리 관리 창에서 SoftwareSerial 을 선택해 줍니다.

이렇게 라이브러리를 선택해 주면 자동으로 코드에 해당 라이브러리 헤더파일이 인클루드 됩니다.

2. PMS 센서 라이브러리

다음으로 PMS 센서 라이브러리를 추가합니다.

PMS7003센서는 많이 사용이 되는 센서이기 때문에 인터넷에서 사용예제를 쉽게 찾을 수 있는데요. 대부분의 분들께서는 라이브러리를 사용하지 않고 직접 구현하는 방식을 선호하시더라구요. 물런 직접 구현하는것이 불필요한 코드가 들어가지 않아 메모리 사용량도 줄일 수 있고하는 이점이 있지만 저는 특별한 이유가 없는한 전문가분들께서 잘 만들어 놓으신 라이브러리를 사용하는 걸 좋아합니다. 느무 편해요 ㅎ

똑같이 라이브러리 관리창에서 "PMS"라고 검색을 했습니다. 여러 라이브러리 들이 나오는데 전 "PMS Library by Mariusz Kacki  Version 1.1.0" 로 선택을 했습니다. 뭐 별 이유는 없습니다. 

선택을 하면 이렇게 라이브러리를 설치하겠냐는 확인창이 뜨고 확인을 누르면 설치가 됩니다. 설치라는 것이 별거 없이 라이브러리 압축파일을 받아서 라이브러리 저장폴더에 저장하는게 다입니다.

설치가 끝나고 나면 라이브러리 관리창 "Rescan"버튼을 눌러주면 설치된 라이브러리들을 싹 훑어서 다시 불러오고 "Installed" 탭으로 가서 "PMS"라고 검색해 보시면 설치한 라이브러리가 위의 오른쪽 그림처럼 보이게 됩니다. 이제 위에서 소프트웨어시리얼 라이브러리용 헤더파일을 추가한것과같이 해당 라이브러리를 클릭해서 PMS 라이브러리 헤더를 코드에 추가를 해 줍니다.

코딩

펌웨어 코딩은 다음과 같습니다. PMS라이브러리에 있는 예제소스를 참고해서 의도한 루프만 살짝 변경해서 작성하였습니다.

소스에 대한 설명은 주석으로 대신하겠습니다.

/*
 Name:		PMS_Monitor.ino
 Created:	2019-03-05 오후 3:40:07
 Author:	kwonkyo
  PMS7003 센서를 사용해서 미세입자농도를 측정하고, 측정된 Data를 시리얼모니터로 확인하는 코드입니다. 
  아두이노가 시리얼모니터와 연결된 상태에서 전원이 들어가면, 시리얼 모니터에서 사용자 입력을 기다립니다. 사용자가 정수값을 입력하면 센서가 켜지고 센서 부팅에 필요한 시간만큼 기다렸다가 준비가 되면 입력된 횟수 만큼 측정을 연속적으로 하고 대기상태로 들어갑니다. (PMS라이브러리 예제 참조)
*/

#include <PMS.h>
#include <SoftwareSerial.h>

// 소프트웨어시리얼 포트를 설정하고 PMS7003센서 통신용으로 연결
#define SoftRX 7
#define SoftTX 6
SoftwareSerial mySerial(SoftRX, SoftTX);
PMS pms(mySerial);

// 디버깅용 시리얼은 하드웨어시리얼 포트를 사용합니다.
#define DEBUG_OUT Serial

// 측정 간격 설정
// :::|------|------|------|::::::::::|------|------|------|:::::::::::
//    ↑     ↑     ↑           ↑              ↑
//   요청   측정   측정   다음요청시까지_대기   측정간격(차수내)
static const uint32_t PMS_READ_DELAY = 30000;		// 센서 부팅후 대기시간 (30 sec)
static const uint32_t PMS_READ_GAP = 3000;			// 측정간격 (1 sec)

// 전역변수 선언
uint8_t cycles = 0;		// 반복측정 횟수
bool PMS_POWER = false;	// PMS7003센서의 동작상태

// the setup function runs once when you press reset or power the board
void setup() {
	// 시리얼 포트 열기
	DEBUG_OUT.begin(115200);		// 디버깅용
	mySerial.begin(PMS::BAUD_RATE);	// 소프트 시리얼용

	// 패시브모드로 변경 후 센서 대기상태로 설정
	pms.passiveMode();
	pms.sleep();
	DEBUG_OUT.println("반복측정 횟수를 입력하세요.");
}

// the loop function runs over and over again until power down or reset
void loop() {
	// 센서동작여부를 판단에 사용할 타이머 변수
	static uint32_t timerLast = 0;		// 센터부팅시작시간 (값이 유지되도록 정적변수 사용
	static uint32_t timerBefore = 0;	// 직전측정시간
	
	// 시리얼모니터로 값을 입력받아 입력받은 값을 cycles 변수에 할당
	if (DEBUG_OUT.available()) {
		cycles = DEBUG_OUT.parseInt();	//한번에 몇번을 측정할지 입력받기
		DEBUG_OUT.print(cycles);
	}

	// 측정요청이 있으면 센서를 깨우고 깨운 시간을 기억
	if (!PMS_POWER && cycles > 0) {
		DEBUG_OUT.println("Waking up.");
		pms.wakeUp();
		timerLast = millis();
		PMS_POWER = true;
	}

	// 입력받은 cycles 수만큼 측정 
	//   센서가 깨어나고나서 최소대기상태를 지났을 때만 측정간격을 두고 측정 실시
	while (cycles > 0) {
		uint32_t timerNow = millis();
		if (timerNow - timerLast >= PMS_READ_DELAY) {
			if (timerNow - timerBefore >= PMS_READ_GAP) {
				timerBefore = timerNow;
				readData();
				cycles--;
			}
		}
	}

	// 측정이 끝나면 cycles 변수는 0이되었기 때문에 센서를 대기모드로 바꾸고 다음 측정요청을 대기
	if (PMS_POWER && cycles == 0) {
		DEBUG_OUT.println("Going to sleep.");
		DEBUG_OUT.println("반복측정 횟수를 입력하세요.");
		pms.sleep();
		PMS_POWER = false;
	}
}

// PMS7003센서에 측정요청을 하고 데이터를 읽어와서 시리얼 화면에 표시하는 함수
void readData()
{
	PMS::DATA data;

	// Clear buffer (removes potentially old data) before read. Some data could have been also sent before switching to passive mode.
	while (Serial.available()) { Serial.read(); }

	DEBUG_OUT.println("Send read request...");
	pms.requestRead();

	DEBUG_OUT.println("Reading data...");
	if (pms.readUntil(data))
	{
		DEBUG_OUT.println();

		DEBUG_OUT.print("PM 1.0 (ug/m3): ");
		DEBUG_OUT.println(data.PM_AE_UG_1_0);

		DEBUG_OUT.print("PM 2.5 (ug/m3): ");
		DEBUG_OUT.println(data.PM_AE_UG_2_5);

		DEBUG_OUT.print("PM 10.0 (ug/m3): ");
		DEBUG_OUT.println(data.PM_AE_UG_10_0);

		DEBUG_OUT.println();
	}
	else
	{
		DEBUG_OUT.println("No data.");
	}
}

하드웨어 연결

하드웨어 연결은 엄청 간단합니다. PMS7003센서는 총 10개의 핀이 있는데 핀싸이즈가 작아서 직접 연결하는게 쉽지 않습니다. 그래서 그래서 보통 센서팔때 컨넥터를 같이 팔아서 그걸 사서 연결 했습니다. 이번 예제에는 전원과 시리얼 포트만 연결해주면되니 선 4개만 아래 그림처럼 연결해줍니다.

 PMS7003 쪽 아두이노 쪽 
 GND GND 
 VCC 5V 
 RX TX 
 TX RX 

결과

시리얼모니터로 다음과 같이 결과값 확인해 볼수 있습니다.

컴퓨터 USB가 열결된 상태에서 시리얼모니터를 열어주면 먼저 몇번반복해서 측정할지 사용자입력을 대기합니다. 숫자로 횟수를 입력해주면, 그즉시 센서를 대기상태에서 깨우고 센서가 측정상태가 되는 30초가 지나면 입력된 횟수만큼 미세먼지를 1초간격으로 측정하고 값을 모니터로 보여줍니다. 

음... 결과는, 실외 미세먼지상태가 나쁜 날이었는데 공기청정기를 틀고 있어서 깨끗하게 나오네요. 

이상 실습을 마치겠습니다.

 

끝!

PS.

미세먼지센서를 활용한 좀더 업그레이드 된 프로젝트 진행중입니다. 다음글도 관심 부탁드려요. ^^

 

아두이노 휴대용 미세먼지 측정기 만들기 완결편 - 아두이노 나노, PMS7003센서, Nextion LCD, 3D프린팅 패키징까지

배경 지금 이 글을 쓰고 있는 2019년 7월 벌써 1주일이 넘게 미세먼지가 나쁨 이상을 유지하고 있습니다. 한동안 즐기던 파란 하늘이 그립니다. 그래서 빨리 이 프로젝트를 마무리 해야겠다 맘먹게 되었고 드디어..

kwonkyo.tistory.com

 

아두이노 공기질 감시기 만들기 (PMS7003 미세먼지 센서, Nextion LCD를 동시에 Softwareserial 2개로 연결)

아두이노 프로젝트 - 미세먼지 측정기 및 온습도계 만들기 (feat. by multiple Softwareserial of Arduino) 아두이노를 활용한 공기질 감시기(미세먼지 측정기 + 온습도계)를 만들어 봤습니다. 저는 미세먼지에 민..

kwonkyo.tistory.com

 

아두이노 공기질(미세먼지, 온습도) 감시기, 아두이노 나노버전

개요 이전 포스팅에서 아두이노 우노를 사용해서 미세먼지와 온습도를 측정하는 공기질 감시기를 만들어 본적 있었습니다. 아두이노 공기질 감시기 만들기 (PMS7003센서, Nextion LCD를 동시에 Softwareserial 2개..

kwonkyo.tistory.com

 

반응형

댓글