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

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

by lovey25 2019. 7. 23.
반응형

2020-03-16 update log: 결선도 수정(아두이노 나노에서 5V외부입력 사용시 5V단자를 사용해야 함, Vin단자는 7V이상 전원 사용)
2020-12-16 update log: 미세먼지 측정기 케이스 3D프린팅 모델 추가


배경

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

간단히 개요를 말씀드리겠습니다.

아두이노 나노를 컨트롤러로 사용하고 미세먼지 센서는 PMS 7003, 그리고 데이터를 화면으로 표시하기 위해서 Nextion LCD를 사용하였습니다. 단순한 미세먼지 측정기에는 너무 고급사양이긴 하지만 나중에 차차 기능을 추가할 때를 대비해서 고~급 디스플레이 사용했습니다. 그리고 휴대용이기 때문에 리튬이온 배터리를 사용하기 위해서 배터리 및 충전/승압 회로 추가하여 전체 시스템을 구성하였습니다. 

본론으로 들어가기 전에 아두이노에 아직 익숙하지 않으신 분들은 이전 포스팅 한번 보고오시면 도움이 될 수 있으니 참고해 주세요. (아두이노 공기질(미세먼지, 온습도) 감시기, 아두이노 나노버전)

Hardware

준비물

  • 아두이노 나노
  • 미세먼지 센서 (PMS7003)
  • Nextion LCD (NX3224T024)
  • 리튬폴리머 배터리 (MP 602540 550mAh)
  • 충전 모듈 (TP4065)
  • 승압 모듈 (MT3608)
  • 3D 프린터로 출력한 케이스
  • 헤더소켓 2x5 (1.2mm) 
  • SOP14 1.27 -> 2.54mm 변환기판 
  • On/Off 스위치
  • 전원 케이블 및 점퍼 케이블
  • M3 볼트 4개

(※ DHT22 센서는 위 사진에는 같이 찍혀있는데 이번에는 포함하지 않았습니다.)

결선도

온습도 센서(DHT22)도 집어넣으려고 계획했었으나 사용할 데가 생겨서 일단 생략하고 진행했습니다. 위 그림에서 맨 오른쪽에 있는 하얀색 부품이 DHT22입니다. 참고하세요.

케이스

3D 프린터로 패키징을 위한 케이스를 제작했습니다. 상당 시간을 공들여서 만들었는데 프린터 자체의 오차도 있고 제가 사용한 모델들이 실제 부품들과 차이도 있어서 최종 품질은 예상보다 좀 떨어졌습니다. 필요한 치수를 다시 측정해서 수정하면 되긴 하지만 이게 또 은근 노가다 작업이라서 일단 프로토타입이니 이정도로 만족하려 합니다.

조립 시뮬레이션 중입니다. ㅎ

노가다 장면 잠시 감상하시겠습니다. ㅎ

조립

결선도에 따라서 하나하나 납땜해서 부품들을 연결해 줍니다. 모듈화 된 부품을 사용하였기 때문에 따로 빵판에서 회로를 구성할 필요 없이 단자들을 결선도에 따라서 납땜해서 연결하였습니다.

그중에 PMS7003 센서의 납땜이 좀 까다로운 부분이었는데요. 센서의 인터페이스가 10핀짜리 소켓으로 되어 있고 핀 간격이 1.75mm로 아주 작아서 5x2 헤더소켓에 점프 케이블을 바로 납땜해서 쓸려고 했는데 너무 작아서 땜질도 어렵고 헤더소켓의 다리도 너무 얇다 보니 쉽게 부러져서 아래 그림처럼 변환보드를 써서 헤더소켓을 붙이고 변환보드에서 라인들을 납땜해주었습니다. 

우여곡절을 거쳐서 모든 부품의 연결을 마쳤습니다. 아래는 부품들을 하나씩 케이스에 조립하는 사진입니다.

배터리와 충/방전 모듈을 가장 바닥에 위치시켰고. 그위에 미세먼지 센서와 아두이노 나노를 자리 잡도록 케이스를 설계했습니다. 그리고 승압모듈은 케이스 옆에 남는 공간에 그냥 욱여넣어서 별도로 고정은 되지 않는 구조입니다. 마지막으로 Nextion LCD를 올려서 뚜껑 케이스를 덥고 4 모서리를 볼트로 고정하도록 만들었습니다. 

이 사진은 조립이 완성된 사진입니다. 그런데 보시다시피 제작 오차가 커서 케이스가 완전히 닫히지 못하고 틈이 생겼습니다. 케이스를 다시 출력해야 하는데 귀찮아서 당분간은 그냥 이대로 쓰렵니다. ㅎ

위쪽 사진에서 모이는 2개의 구멍은 미세먼지센서의 공기 흡입구와 토출구입니다. 그리고 아래쪽 사진에는 구멍이 어려 개 뚫려있는 데 사용하는 건 3개입니다. 미니 USB 포트는 아래쪽이 충/방전 모듈이라서 충전용 포트이고 위쪽이 아두이노라서 디버깅용입니다. 그 아래 조그마한 스위치는 전원을 켜고 끄는 용도입니다. 처음에 미세먼지 측정기를 구상할 때 스위치 부분은 미쳐 생각하지 못해서 나중에 급조된 부분입니다. 충방전 모듈에서 승압모듈로 가는 전원선에 설치했고 스위치는 케이스 안쪽에 글루건으로 고정했습니다. 젤 왼쪽에 있는 구멍 하나는 스위치용 구멍으로 뚫었다가 고정이 힘들어서 아래로 옮기는 바람에 남아있게 되었습니다. 그리고 맨 아래 우측에 있는 길쭉한 구멍들은 온습도 센서가 위치할 부분이라서 바람구멍으로 뚫어놓은 곳입니다. 

사용전압 조정

부품들은 단자와 단자가 1:1로 직관적인 연결로 이루어지기 때문에 손쉽게 따라 할 수 있는데 승압 모듈은 캘리브레이션을 위해서 손을 좀 봐줘야 합니다. 원래 조립하기 전에 미리 세팅을 했어야 하는데 전 조립 다하고 나중에 센서가 제대로 작동을 하지 않아서 뒤늦게 확인했던 부분입니다. 

미세먼지 측정기에 사용되는 주요 부품인 미세먼지 센서와 LCD가 모두 5V로 동작합니다 그래서 거기에 맞도록 전원 공급을 해주어야 하는데요. 저는 전원으로 인터넷으로 쉽게 구할 수 있는 리튬폴리머 전지를 선택했습니다. 하지만 리튬폴리머 전지는 출력 전압이 3.7V이기 때문에 승압이 필요했고 가변형 스탭업 모듈을 구매했습니다. 구매했을 당시 세팅대로는 3V가량이 출력되었는데 가변저항을 조절해서 5V 이상이 나오도록 조정을 해주어야 했습니다.  

왼쪽 사진에서 드라이버로 돌리고 있는 부분이 승압모듈의 가변저항입니다. 저 나사를 돌리면 출력 전압이 조절이 됩니다. 우측 사진에 출력이 5.38V 나오는 게 보이시죠? 그런데 생각보다 많이 돌려줘야 해서 고장 난 게 아닌가 쫄았었습니다. 이런 류의 모듈을 만져본 적이 없어서 이게 정상인지 아닌지는 모르겠지만 3V대에서 5V대까지 올리는데 10바퀴 이상 돌려 준거 같습니다.

Software

HMI

Nextion LCD의 HMI는 단순하게 미세먼지 센서에서 보내주는 3가지 먼지농도 수치와 시간의 흐름별 그래프를 볼 수 있도록 아래 그림과 같이 구성하였습니다.

Nextion에 대해서 별도로 다룬 포스팅이 있기 때문에 이번에는 상세한 내용은 생략합니다. (Nextion LCD 사용기, Arduino SoftwareSerial로 연결해서 온습도(DHT22) 측정 및 LED 컨트롤)

Firmware

아두이노 코드입니다. 코드에 대한 설명은 주석으로 대신합니다.

/*
 Name:		AEWT.ino
 Created:	2019-07-07
 Author:	KWONKYO	
  미세먼지 측정기 용 펌웨어 입니다.
  아두이노 Nano의 소프트웨어시리얼 2개를 동시사용하여
  Nextion디스플레이 및 PMS7003센서와 통신하고 하드웨어시리얼 포트는 디버깅용으로 사용합니다.
*/

#include <SoftwareSerial.h>		// 소프트웨어시리얼 사용을 위한 헤더
#include <Nextion.h>			// Nextion LCD용 라이브러리
#include <PMS.h>				// PMS센서용 라이브러리
#include <string.h>				// stoi 함수용

// PMS7003센서 통신용 소프트웨어시리얼
#define PMS_TX 3								// Tx: D3
#define PMS_RX 4								// Rx: D4
SoftwareSerial SerialForPMS(PMS_RX, PMS_TX);	// 소프트웨어시리얼포트 지정
PMS pms(SerialForPMS);							// PMS센서통신포트로 지정

PMS::DATA data;

// Nextion 통신용 소프트웨어시리얼
#define NEX_TX 7								// Tx: D7
#define NEX_RX 6								// Rx: D6
SoftwareSerial SerialForNex(NEX_RX, NEX_TX);	// 스프트웨어시리얼포트 지정

// Nextion 화면개체 선언 - (page id = 0, component id = 1, component name = "b0") 
/// page0
NexText tPM1_0 = NexText(1, 2, "tPM1_0");
NexText tPM2_5 = NexText(1, 3, "tPM2_5");
NexText tPM10_0 = NexText(1, 4, "tPM10_0");
NexWaveform sPMS = NexWaveform(1, 1, "sPMS");

// 미세먼지 농도를 측정하고 Nextion에 표시하기위한 함수
void UpdatePMS() {
	Serial.println("update PMS");
	// 변수 선언
	uint16_t number[3] = { 0 };
	char temp[10] = { 0 };

	SerialForPMS.listen();							// PMS센서가 연결된 시리얼포트 활성화
	while (SerialForPMS.available()) { SerialForPMS.read(); }	// 버퍼에 남아있을 어떤 데이터를 미리 삭제
	pms.requestRead();			// PMS센서에 측정요청신호 보내기

	// 미세먼지 측정이 되었을 경우 측정값을 Nextion에 표시
	if (pms.readUntil(data))				// 측정값이 저장된 버퍼 읽어오기
	{
		Serial.println("reding PMS start");
		number[0] = data.PM_AE_UG_1_0;		// PM 1.0 (ug/m3)값 읽어서 변수에 저장
		utoa(number[0], temp, 10);			// 정수를 텍스트로 변환
		Serial.println(temp);
		tPM1_0.setText(temp);				// Nextion에 표시
		number[1] = data.PM_AE_UG_2_5;		// PM 2.5 (ug/m3)값 읽어서 변수에 저장
		utoa(number[1], temp, 10);
		tPM2_5.setText(temp);
		number[2] = data.PM_AE_UG_10_0;		// PM 10.0 (ug/m3)값 읽어서 변수에 저장
		utoa(number[2], temp, 10);
		tPM10_0.setText(temp);
		for (int i = 0; i < 3; i++) {				// waveform 0~2ch 차례대로 data전달
			if (number[i] < 151)
				sPMS.addValue(i, (uint8_t)(number[i] * 1.13));	// 그래프 범위: 0~150ug/m3으로 스케일링
		}
		Serial.println("reding PMS finish");
	}
}

void setup() {
	// 장비 초기화
	/// Nextion 초기화
	nexInit();			// 경우에따라 NexConfig.h의 설정값 수정필요 (Nextion용 BaudRate는 9600)
	/// PMS센서 초기화
	pms.passiveMode();	// 센서측정주기와 아두이노 수신주기가 동기되지 않을 수 있기 때문에 수동모드 사용
	pms.wakeUp();

	// 시리얼 포트 열기
	Serial.begin(9600);		// 디버깅용
	SerialForPMS.begin(PMS::BAUD_RATE);	// PMS센서 소프트웨어시리얼 열기	
}

void loop() {
	nexLoop(nex_event_list);		// Nextion에서 발생하는 이벤트를 전달
	static uint32_t started = 0;	// 타이머용 변수 선언 및 초기화
	if (millis() - started >= 2000)	// 2초간격으로 측정
	{
		Serial.println("Go into Microbe mode");
		UpdatePMS();				// 미세먼지관련 함수 호출
		started = millis();			// 타이머기준 리셋
	}
}

마무리

최종적으로 완성된 미세먼지 측정기의 모습니다.

상단 케이스의 화면 위치도 조금 조정을 해야 할 것 같고, 케이스도 빈틈이 없도록 수정해야 하고, 필요 없는 구멍은 없애야 하고...  완성은 했는데 손봐야 할 곳이 한두 군데가 아니네요. ㅎ

완성된 휴대용 미세먼지 측정기

센서의 성능에 대해서는 이미 전에도 확인을 했었고 검증했었던 회로 구성과 아두이노 코드를 그대로 준용하였기 때문에 이번에 따로 언급하지는 않겠습니다. 아래는 예전에 찍어둔 사진인데, 외부에서 미세먼지농도를 측정해보면 PM10 농도는 거의 유사하게 나오고 PM 2.5 이하는 편차가 조금 더 크게 나오는 걸 알 수 있습니다. 

위에서 기술한 미세먼지 측정기의 이전버전 이라서 내용과 화면구성이 약간다릅니다.

이번에 달라진 부분은 전원으로 리튬폴리머 배터리를 이용했다는 부분인데, 제가 선택한 550mAh 배터리로 완전 방전까지 시간이 얼마나 걸리는지는 확인해 보지 않았는데, 그냥 필요할때마가 꺼내서 농도 확인하고 하는 용도로는 일주일도 문제없었습니다. 소비전류를 적확하게 계산해보지 않고 허용되는 공간에 들어갈 수 있는 최대용량의 베터리로 선택을 했었기 때문에 어쩌면 오버스펙일지도 모르겠습니다.

다 해놓고 보면 별거 아닌데 워낙 모르는 것도 많아서 이것저것 찾아봐야 하고 그리고 시간이 잘 나지 않아서 짬나는 대로 하다 보니 질질 늘어져서 의도치 않게 시리즈 포스팅이 되어버린 휴대용 미세먼지 만들기가 드디어 마무리되었습니다.

앞으로 더 개선하고 싶은 부분은 일정 시간이 지나면 전원이 저절로 꺼지고 화면을 터치하면 다시 켜지는 부분이라던가 Nextion LCD 화면 밝기 조정하기라던가 등 해보고 싶은 것들이 더 있는데 언제쯤 해볼 수 있을지 모르겠네요 ㅎ 빨리 시간이 많이 나서 조만간 추가 포스팅을 올릴 수 있었으면 좋겠습니다.

음... 그냥 마무리 하긴 아쉬워서 미세먼지를 측정하면서 다니다가 알게 된 재미있는 사실 한 가지 공유합니다.

아래 사진은 차 안에서 미세먼지를 측정했던 결과입니다. 이날은 외부 미세먼지농도가 PM10 기준으로 약 30~50um/m3 정도로 약간 나쁨의 상태였습니다. 지상에 차량을 주차해두었다가 차를 타면서 미세먼지를 측정하기 시작했고 약 10여분이 지난 후에 아래 사진을 찍었습니다. 상단의 그래프를 보시면 미세먼지 농도가 약 50 정도에서부터 시작해서 시간이 지날수록 점차 내려가는 것을 보실 수 있습니다. (그래프의 좌측이 시간의 흐름상 최근입니다.) 차량의 공조는 에어컨을 켜고 외기를 차단한 상태입니다. 시간이 지날수록 공기가 깨끗해지고 있는 것을 보여주고 있는데요 사진을 찍는 순간은 미세먼지 수치가 4입니다. 거의 없다는 거죠.제 차는 테슬라처럼 특수한 필터가 들어가는 것도 아니고 심지어 중간중간 외기가 유입이 되기도 했었는데 차량 에어컨 필터만으로도 공기청정기 효과가 충분히 있었다는 걸 알 수 있었습니다. 신기하죠?! ^0^

요즘 차량용 공기청정기 많이 팔고 있죠? 그리고 LG에서는 휴대용 공기청정기를 티브이 광고까지 하고 있던데 이 결과를 보면 과연 차 안에서 공기청정기를 따로 사용할 필요가 있는가 하는 생각이 드네요. 나중에 겨울이 되면 히터를 사용하는 상황에서도 공기정화 효과가 있는지 확인해 봐야겠네요.

 

끝!

 

PS.

댓글 요청이 있어서 미세먼지측정기 케이스로 사용한 모델파일 추가합니다.

미세먼지측정기케이스.zip
0.13MB

반응형

댓글