아두이노 코딩-31: 아두이노 PM 측정기 샘플 데이터 평균값 계산 및 Low Pass Filtering 기법 적용 II
아두이노 PM 미세먼지 측정기에 디지털 Low Pass Filtering 기법을 적용해도 측정 값의 불규칙성을 제거한 스무드한 표현을 얻어낼 수 없었다. 그렇다고 디지털 Low Pass Filtering 기법에 문제가 있는 것은 아니다.
이 문제에 관해서는 바로 앞에 포스팅한 다음의 블로그 자료를 참조하기 바란다.
아두이노 코딩-30: 아두이노 PM 미세먼지 측정기 Low Pass Filtering 기법 적용 I
https://steemit.com/kr/@codingart/30-pm-low-pass-filtering-i
이러한 문제를 해결하기 위해서 필터링 기법을 적용하기 이전에 샘플링 데이터의 평균값 계산에 의해서 일차적으로 스무싱 작업을 실시한다. 아두이노의 연산 속도를 고려하여 50 개 정도가 좋을 듯하다.
평균 값 계산이 한번 시작되면 각 샘플 데이터를 하나씩 앞 어레이에 옮겨 놓고 최근에 샘플한 데이터를 마지막 어레이에 넣어 다시 평균 값을 계산하는 루틴을 반복한다.
이러한 알고리듬을 적용하면 다소 부드러워진 PM 값 그래프를 볼 수 있다. 이들 평균화된 데이터를 대상으로 디지털 Low Pass Filtering 기법을 적용하도록 한다.
α = 0.7 을 택한여 디지털 필터링 한 결과를 관찰해 보도록 한다.
이 결과는 2018년 5월 5일 오전 미세먼지 일기 예보와 아두이노 PM 미세먼지 측정기로 실측 비교한 결과로서 50개의 샘플링 데이터를 평균한 값들을 대상으로 디지털 Low Pass Filtering 기법을 적용한 결과로서 비교적 잘 맞는듯하며 아두이노 PM 미세먼지 측정기의 실용 가능성을 보여 준다.
※50개 샘플데이타의 평균 값만을 시리얼 플로팅한 결과와 평균 값에 한번 더 디지털 Low Pass Filtering을 한 결과와 비교해 보면 차이가 그다지 크지는 않으나 필터링한 결과의 변동폭이 훨씬 적음을 알 수 있었다.
※※코딩 자체는 간단하지만 이와 같은 실용적인 결과를 얻어냄에 있어서 미세먼지 측정기를 제작한지 1년의 실험 시간이 투자되었슴을 참고하시기 바랍니다.
PM_sensor_i2clcd_avr_01
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F,16,2);
float previous_dustDensity = 0;
float alpha = 0.7;
int measurePin = 0; //Connect dust sensor to Arduino A0 pin
int ledPower = 2; //Connect 3 led driver pins of dust sensor to Arduino D2
int samplingTime = 280;
int deltaTime = 40;
int sleepTime = 9680;
float voMeasured = 0;
float calcVoltage = 0;
float dustDensity = 0;
float average_dustDensity = 0;
float previousDensity = 0.0;
int num = 50; //샘플수
float sum = 0.0;
float D[] = {
0.0, 0.0, 0.0, 0.0, 0.0,0.0, 0.0, 0.0, 0.0,0.0,
0.0, 0.0, 0.0, 0.0, 0.0,0.0, 0.0, 0.0, 0.0,0.0,
0.0, 0.0, 0.0, 0.0, 0.0,0.0, 0.0, 0.0, 0.0,0.0,
0.0, 0.0, 0.0, 0.0, 0.0,0.0, 0.0, 0.0, 0.0,0.0,
0.0, 0.0, 0.0, 0.0, 0.0,0.0, 0.0, 0.0, 0.0,0.0
};
void setup(){
lcd.init();
lcd.backlight();
Serial.begin(9600);
pinMode(ledPower,OUTPUT);// 미세먼지 센서 내부 LED
}
void loop() {
// average_dustDensity = alphaprevious_dustDensity + (1.0-alpha)particleSensing();
D[num-1] = particleSensing();
for ( int i = 0; i<num; i++ ) {
D[i] = D[i+1];
sum = sum + D[i];
}
average_dustDensity = sum/num;
lcd.setCursor(3,0);
// int dnsty = average_dustDensity;
int dnsty = alphapreviousDensity + (1.0-alpha)average_dustDensity;
Serial.println((int)dnsty);
lcd.println(dnsty);
sum = 0.0;
previousDensity = average_dustDensity;
}
float particleSensing() {
digitalWrite(ledPower,LOW); // power on the LED
delayMicroseconds(samplingTime);
voMeasured = analogRead(measurePin);
delayMicroseconds(deltaTime);
digitalWrite(ledPower,HIGH); // turn the LED off
delayMicroseconds(sleepTime);
// 0 - 5V mapped to 0 - 1023 integer values
calcVoltage = voMeasured * (5.0 / 1024.0);
if( calcVoltage > 0.6 ) {
// linear eqn from http://www.howmuchsnow.com/arduino/airquality/
dustDensity =1000.0*( 0.172 * calcVoltage - 0.1);
delay(190);
}
return dustDensity;
}
짱짱맨=날씨인사...
요런느낌이군요...^^ 오늘은 날이 아주좋아요^^
호출 감사합니다.
어린이날 무사히 보내셨군요! 반갑군요!