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

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

by lovey25 2019. 4. 5.

2020-03-16 update log: 회로구성 수정(아두이노 나노에서는 5V외부전원을 사용할때 Vin포트(7V이상 사용)가 아닌 5V포트를 사용해야함)


개요

이전 포스팅에서 아두이노 우노를 사용해서 미세먼지와 온습도를 측정하는 공기질 감시기를 만들어 본적 있었습니다.

아두이노 공기질 감시기 만들기 (PMS7003센서, Nextion LCD를 동시에 Softwareserial 2개 사용)

 

아두이노 공기질 감시기 만들기 (PMS7003센서, Nextion LCD를 동시에 Softwareserial 2개 사용)

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

kwonkyo.tistory.com

 포인트는 UART 통신을 이용하는 두개의 장치를 동시에 사용하기위해서 소프트웨어시리얼을 사용하는 것이었는데 하드웨어시리얼은 업로드나 디버깅용으로 남겨두기위해서 둘다 소프트웨어시리얼을 사용하는것이 었습니다.

최종적으로는 사이즈를 줄여서 패키징을 하고 휴대용으로 만들어 보려고 하는데, 아두이노 우노는 싸이즈가 너무 커서 아두이노 나노를 사용하는 것으로 결정했습니다. 짝퉁 아두이노 나노는 가격도 싸서 괜찮을 거 같더라구요.

 

그래서 이번에는 지난번 프로젝트에서 컨트롤러만 아두이노 나노를 사용해서 역시 소프트웨어 시리얼로 잘 작동을 하는지 확인해봤습니다.

준비물 

  • 아두이노 나노
  • PMS7003센서
  • DHT22센서
  • Nextion 디스플레이
  • 전원용 USB컨넥터
  • 빵판
  • 점프케이블

회로구성(연결도)

Nextion GUI

Nextion 디스플레이는 이전 프로젝트와 GUI가 완전히 동일하기 때문에 별도로 손대지 않았습니다.

아두이노 코딩(펌웨어)

아두이노 코드역시 우노버전과 동일합니다. 다만 컴파일 및 업로드시에 Visual Studio에서 설정만 약간 다르기 때문에 그 부분만 추가로 언급하겠습니다.

/*
 Name:		PMS_Monitor_wt_Nextion.ino
 Created:	2019-04-05 오후 10:34:36
 Author:	kwonkyo.tistory.com
  PMS7003 센서를 사용한 미세먼지 측정기 펌웨어입니다.
  측정된 농도값은 Nextion LCD에 표시되도록 하고,
  PMS센서와 Nextion은 모두 소프트웨어시리얼로 연결합니다.
*/

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

// DHT22 센서 초기화
#define DHTPIN 2			// DHT센서값을 받을 디지털핀
#define DHTTYPE DHT22		// 사용할 센서타입을 DHT22 로 지정
DHT dht(DHTPIN, DHTTYPE);	// 센서 객체 생성

// 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") 
/// 미세먼지 농도를 표시할 텍스트와 그래프
NexText tPM1_0 = NexText(0, 3, "tPM1_0");
NexText tPM2_5 = NexText(0, 4, "tPM2_5");
NexText tPM10_0 = NexText(0, 5, "tPM10_0");
NexWaveform sPMS = NexWaveform(0, 1, "sPMS");
/// 온습도를 표시할 텍스트와 그래프
NexText tHumi = NexText(0, 6, "tHumi");
NexText tTemp = NexText(0, 7, "tTemp");
NexWaveform sDHT = NexWaveform(0, 2, "sDHT");

// 미세먼지 농도를 측정하고 Nextion에 표시하기위한 함수
void UpdatePMS() {
	// 변수 선언
	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 PMS1");
		number[0] = data.PM_AE_UG_1_0;		// PM 1.0 (ug/m3)값 읽어서 변수에 저장
		utoa(number[0], temp, 10);			// 정수를 텍스트로 변환
		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);
		Serial.println("reding PMS2");
		for (int i = 0; i < 3; i++) {				// waveform 0~2ch 차례대로 data전달
			sPMS.addValue(i, (int)(number[i] / 3));	// 그래프 범위: 0~300ug/m3으로 스케일링하고 그래프는 300까지만 표시
		}
		Serial.println("reding PMS3");
	}
}

// 온습도를 측정하고 Nextion에 표시하기위한 함수
void UpdateDHT() {
	float h = dht.readHumidity();		// 습도값 요청
	float t = dht.readTemperature();	// 온도값 요청

	SerialForNex.listen();				// Nextion이 연결된 시리얼 포트 활성화

	// 온도나 습도의 측정에 문제가 있으면 즉시 함수종료
	if (isnan(h) || isnan(t)) {
		return;
	}

	static char humidityTemp[6];		// 변수선언
	dtostrf(h, 5, 1, humidityTemp);		// 습도값 텍스트로 변환
	tHumi.setText(humidityTemp);		// Nextion에 습도 표시

	static char temperatureTemp[6];		// 변수선언
	dtostrf(t, 5, 1, temperatureTemp);	// 온도값 텍스트로 변환
	tTemp.setText(temperatureTemp);		// Nextion에 온도 표시

	// waveform 그래프 그리기
	sDHT.addValue(0, (int)h);				// 습도 그래프 범위: 0~100% 스케일링없음
	sDHT.addValue(1, (int)(t*3.3 - 32));		// 온도 그래프 범위: 10~40degC 스케일링
}

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

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

void loop() {
	static uint32_t started = 0;	// 타이머용 변수 선언 및 초기화

	if (millis() - started >= 2000)	// 2초간격으로 측정
	{
		started = millis();			// 타이머기준 리셋
		UpdateDHT();				// 온습도관련 함수 호출
		UpdatePMS();				// 미세먼지관련 함수 호출
	}
}

Visual Studio에서 위의 코드를 사용해서 프로젝트를 만들어주고 컴파일대상 보드만 다음과 같이 변경해서 업로드 해 줍니다.

선택할 수 있는 옵션에서는 아두이노 나노가 두가지가 있는제 전 CH340칩을 사용하는 짝퉁 아두이노 보드인데 "(Old Bootloader)"라는 꼬리가 붙어있는 보드를 선택해야 정상적으로 업로드가 되었습니다.

결과

당연한 얘기겠지만 문제없이 잘 동작을 하네요. ^^

이제 저것들을 묶어서 어떻게 작게 만들지를 생각해 봐야겠네요.

 

끝!

 

728x90

댓글2

  • 나그네 2019.06.14 21:50

    배우면서 만들겟다는 마음으로 부품먼저 주문하고보니 참 깜깜하네요. 여기저기 도움될만한 내용을 다 수소문했는데, 여기 내용이 제일 알차고 좋아요.
    여기구성한 부품이랑 똑같은데, 디스플레이가 저는 LCD2004 IIC/I2C 이거네요.
    코드를 어떻게 해야하는지 한참 멀엇지만 좋은내용 잘보구 갑니다.
    답글