MG811 센서 기반 CO2 sensor module을 사용해보자
▶ 이 가이드를 따라하면
- 이산화 탄소 농도 변화를 ppm단위로 알아낼 수 있다.
▶ 먼저 읽으면 좋은 글
- Arduino 일반 : http://bbangpan.tistory.com/1
▶ 부품 설명 및 회로 구성
이산화탄소 농도는 다양한 고가의 센서들이(적외선 방식 등-Infrared CO2 sensor) 존재하나 아두이노에서 사용해볼만한 저렴한 센서를 소개해본다. MG811 CO2 센서로 25$전후로 Aliexpress에서 구매할 수 있다. 요즘 파는 녀석은 이렇게 생겼다. 저 동그랗게 툭 튀어나온 은색의 머리가 MG811 센서이다.
<MG811 CO2 센서를 탑재한 CO2센서 모듈>
이 센서는 30~60초 정도 예열을 통해 센서를 약간 뜨겁게 만들고 이후 화학반응을 통해 CO2의 농도를 AOUT(혹은 Vout)으로 전압으로 출력한다. DOUT이 있는 것들은 뒤에 나사로 조절가능한 조절기(threshold 설정)를 같이 탑재하고 있는데, 특정 전압이하로 내려가면(이산화탄소가 농도가 높을수록 전압이 내려간다) LED가 점등되어 알려주며, Low(혹은 High)를 출력해준다.
또다른 조절기가 달려 있다면, 이산화탄소 농도에 따른 전압 출력의 scale을 조절해주는 조절기이다(아래 사진의 위쪽 조절나사)
<MG811 센서모듈 뒷면. 빨간색은 전압 인가 확인/파란색은 특정 농도 검출 LED이다. 사진 아래쪽 나사를 돌려 정의한다.>
이 녀석의 까다로움은 바로 calibration이다. 대기중의 기본 이산화탄소 농도는 대략 400ppm, 날숨은 10,000ppm이상으로 알려져 있는데, 이 센서의 측정 범위가 10,000ppm까지다. 따라서 이 값을 참조해서 calibration한다. 회로 연결은 Vcc(사진의 VDD)는 5V, GND는 GND에 연결하고 DOUT은 threshold검출하기 위해서 D9에 연결하고 가장 중요한 Aout은 A0에 연결한다. 이 4개 핀 외에 나머지 핀은 사용하지 않는 것으로 알려져있다.
<MG811 센서 모듈/Arduino UNO 연결도, 외부 전원 연결을 추천하기도 하나, UNO단독으로도 잘 작동했다>
이 MG811센서의 output과 CO2 농도와의 관계는 아래와 같다(datasheet : http://sandboxelectronics.com/files/SEN-000007/MG811.pdf )
<출력전압과 CO2농도(ppm)와의 관계/MG811 Datasheet발췌>
대략 400ppm이면 0.32V(320mv)를, 10,000ppm이면 0.26V(265mv)정도 된다는 것을 알 수 있다. 그런데 또 하나의 골치거리는 제공되는 수 많은 소스들의 출력 값이 이 실제 값이 아니라 증폭된 전압 값이라는 점이다. MG811 센서의 출력 전압 영역이 0.2v~0.6v정도 되기 때문에 0~5V수준으로 맞추어 측정하기 위해 대략 8.5배정도 회로 내부에서 증폭한다고 한다. 이 비율은 DC_GAIN이라는 파라메터로 보통 처리한다. (소스코드 참조)
다만, 이 모듈로 정확한 ppm값을 측정하기는 어려워보인다. 먼저 1분정도의 예열시간이 소모되고 이후 온도가 상승할수록 출력전압이 조금씩 상승하는 단점이 있다.(calibration이 어려워진다) 그리고 CO2가 한번 검출되면 다시 동일한 시간동안 복귀하는 시간이 필요하다(대략 30초가 넘게 걸려야 처음 상태로 복귀된다). 따라서 주로 CO2의 갑작스런 증가(날숨) 등을 측정하는 용도로 사용하면 좋아 보인다.
날숨을 뿜으면 전압은 확실하게 급감한다. 그러면 실제 소스를 보면서 최대한 calibration해보자. 참조로 다행히도 대부분의 CO2 센서는 다양한 방식에도 실제 측정 원리는 유사하므로, 결국 출력 전압을 조금만 계산 매핑하면 실제 CO2농도를 구할 수 있게 되어 있다.
▶ 소스 코드 입력 및 구동
http://sandboxelectronics.com/?p=147 소스를 참조하였다. CO2농도와 출력전압과의 관계가 log반비례하므로 계산하는 식은 복잡하지만, 결국에는 출력 전압을 CO2농도로 변환하는 것에는 다름이 없다. 튀는 전압값을 방지하기 위해 일정 횟수 이상 구하여 평균을 내는 점이 특이하다.
-------------------------------------------------------------------------------------------------------------
/*******************Demo for MG-811 Gas Sensor Module V1.1*****************************
Author: Tiequan Shao: tiequan.shao@sandboxelectronics.com
Peng Wei: peng.wei@sandboxelectronics.com
Lisence: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)
Note: This piece of source code is supposed to be used as a demostration ONLY. More
sophisticated calibration is required for industrial field application.
Sandbox Electronics 2012-05-31
Note: Parameters tuned for MG811 adjustable output CO2 sensor module by bbangpan.com
************************************************************************************/
/************************Hardware Related Macros************************************/
#define MG_PIN (0) //define which analog input channel you are going to use – A0 pin
#define BOOL_PIN (9) // D9 – Dout pin
#define DC_GAIN (8.5) //define the DC gain of amplifier
/***********************Software Related Macros************************************/
#define READ_SAMPLE_INTERVAL (50) //define how many samples you are going to take in normal operation
#define READ_SAMPLE_TIMES (5) //define the time interval(in milisecond) between each samples in
//normal operation
/**********************Application Related Macros**********************************/
//These two values differ from sensor to sensor. user should derermine this value.
#define ZERO_POINT_VOLTAGE (0.185) //define the output of the sensor in volts when the concentration of CO2 is 400PPM
#define REACTION_VOLTGAE (0.010) //define the voltage drop of the sensor when move the sensor from air into 1000ppm CO2
/*****************************Globals***********************************************/
float CO2Curve[3] = {2.602,ZERO_POINT_VOLTAGE,(REACTION_VOLTGAE/(2.602-3))};
//two points are taken from the curve.
//with these two points, a line is formed which is
//"approximately equivalent" to the original curve.
//data format:{ x, y, slope}; point1: (lg400, 0.324), point2: (lg4000, 0.280)
//slope = ( reaction voltage ) / (log400 –log1000)
void setup()
{
Serial.begin(9600); //UART setup, baudrate = 9600bps
pinMode(BOOL_PIN, INPUT); //set pin to input
digitalWrite(BOOL_PIN, HIGH); //turn on pullup resistors
Serial.print("MG-811 Demostration\n");
}
void loop()
{
int percentage;
float volts;
volts = MGRead(MG_PIN);
Serial.print( "SEN-00007:" );
Serial.print(volts);
Serial.print( " V / before_amp : " );
Serial.print(volts/DC_GAIN);
Serial.print( " V " );
percentage = MGGetPercentage(volts,CO2Curve);
Serial.print("CO2:");
if (percentage == -1) {
Serial.print( "<400" );
} else {
Serial.print(percentage);
}
Serial.print( "ppm\n" );
if (digitalRead(BOOL_PIN) ){
Serial.print( "=====BOOL is HIGH======" );
} else {
Serial.print( "=====BOOL is LOW======" );
}
Serial.print("\n");
delay(200);
}
/***************************** MGRead *********************************************
Input: mg_pin - analog channel
Output: output of SEN-000007
Remarks: This function reads the output of SEN-000007
************************************************************************************/
float MGRead(int mg_pin)
{
int i;
float v=0;
for (i=0;i<READ_SAMPLE_TIMES;i++) {
v += analogRead(mg_pin);
delay(READ_SAMPLE_INTERVAL);
}
v = (v/READ_SAMPLE_TIMES) *5/1024 ;
return v;
}
/***************************** MQGetPercentage **********************************
Input: volts - SEN-000007 output measured in volts
pcurve - pointer to the curve of the target gas
Output: ppm of the target gas
Remarks: By using the slope and a point of the line. The x(logarithmic value of ppm)
of the line could be derived if y(MG-811 output) is provided. As it is a
logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic
value.
************************************************************************************/
int MGGetPercentage(float volts, float *pcurve)
{
if ((volts/DC_GAIN )>=ZERO_POINT_VOLTAGE) {
return -1;
} else {
return pow(10, ((volts/DC_GAIN)-pcurve[1])/pcurve[2]+pcurve[0]);
}
}
상기 소스를 구동하면, 아래와 같은 값이 나오는데 참조하여 중요 상수를 조절해야 한다.
<Dout의 pin상태(BOOL)와 증폭후 MG811의 전압, 증폭전 전압, 환산 CO2농도가 표시된다>.
먼저 증폭후의 전압과 증폭전의 전압이 출력된다. 이 중에 증폭전의 전압(before_amp)은, 일반 공기중에서의 ZERO_POINT_VOLTAGE를 측정하는데 중요하다. 필자는 대략 0.185V값을 보여서 아래와 같이 소스에 적었다.
#define ZERO_POINT_VOLTAGE (0.185) //define the output of the sensor in volts when the concentration of CO2 is 400PPM
날숨을 측정해 본 결과 대략 0.01V 감소함을 알 수 있었다. 따라서 전압 강하를 0.010V로 명기했다. 실제 전압값이 아닌 전압 강하(차이)값 임을 주의하자.
#define REACTION_VOLTGAE (0.010) //define the voltage drop of the sensor when move the sensor from air into 1000ppm CO2
이렇게 조절 후 날숨을 불어 넣었더니 위와 같은 결과를 얻었다. 증폭전 전압이 0.18V->0.15V로 떨어지면서 10,000ppm이상을 표기하고 있다. 그러나 필자가 구매한 모듈 같은 경우 앞서 밝혔듯이 시간이 지속 흐르면(대략 1시간 이상) 계속 전압이 조금씩 올라가기 때문에 실제 정확한 ppm 측정을 위해서는 더 시행 착오가 필요해 보인다.
참조로 위 출력 결과의 BOOL is HIGH는 특정 threshold를 넘으면 LOW로 변경된다.(조절 나사로 조정)
▶ 구매 가이드
CO2 Sensor 모듈: http://www.aliexpress.com/w/wholesale-CO2-sensor.html?initiative_id=SB_20150713073958&site=glo&SortType=total_tranpro_desc&shipCountry=kr&SearchText=CO2+sensor&CatId=523 (25$~60$)
▶ 강의 키워드
Arduino UNO, MG811 CO2 co2 sensor, gas sensor, 대기 센서
'아두이노 센서' 카테고리의 다른 글
[센서/움직임감지센서] PIR(passive infrared) motion sensor로 움직임을 감지해보자 (0) | 2015.11.10 |
---|---|
[센서/Tachometer] 무언가 반복해서 지나가는 속도를 측정할때는 IR(적외선) 기반 Tachometer를 사용하세요 (0) | 2015.10.26 |
[센서/진동] 가변 진동 센서-디지탈/Adjustable vibration sensor-digital with potentiometer (0) | 2015.08.24 |
[센서/충격] 충격(진동) 감지 센서/Knock sensor/Vibration sensor (0) | 2015.08.17 |
[센서/조도] Lux(룩스)단위로 빛의 밝기를 읽어주는 GY-302센서(BH1750) (1) | 2015.08.12 |
[센서/먼지] 공기의 탁함, 먼지 농도 등을 측정하는 샤프(sharp)의 GP2Y1010AU 센서 (7) | 2015.06.26 |
[센서/무게,하중] 1kg미만의 무게를 측정 가능한 무게 센서(weight sensor) (4) | 2015.06.25 |
[센서/초음파 거리측정] 물체와의 거리를 측정해주는 초음파 센서(ultra sonic sensor) (0) | 2015.06.24 |
[센서/터치] 정전식 터치 센서를 통해 손가락 터치를 감지한다 (0) | 2015.06.22 |
[센서/진동] 약한 진동까지 감지할 수 있는Piezo Disk Vibration Sensor(피에조 디스크 진동 센서) (12) | 2015.06.22 |