二酸化炭素センサー MH-Z19 のPWM入力でデータを取得したくて
Arduino用のサンプルプログラムを使ってみたのですが、
このプログラムPWMのパルス長の計測をメイン処理の中でやっていたので、
このままでは他のセンサーとの併用が難しいので、データ取得部分を割り込み処理に変更してみました。
割り込みには「MsTimer2」ライブラリを使用しています。
またデータのフィルタリングテストの処理も追加しています。
公開されていた元のプログラム
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #define pwmPin A0 #define LedPin 13 int prevVal = LOW; long th, tl, h, l, ppm; void setup() { Serial.begin(9600); pinMode(pwmPin, INPUT); pinMode(LedPin, OUTPUT); } void loop() { long tt = millis(); int myVal = digitalRead(pwmPin); if (myVal == HIGH) { digitalWrite(LedPin, HIGH); if (myVal != prevVal) { h = tt; tl = h - l; prevVal = myVal; } } else { digitalWrite(LedPin, LOW); if (myVal != prevVal) { l = tt; th = l - h; prevVal = myVal; ppm = 5000 * (th - 2) / (th + tl - 4); Serial.println("PPM = " + String(ppm)); } } } |
割り込みによる処理に変更したプログラム
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | /* MH-Z19 Intelligent Infrared CO2 Module MsTimer2 is a small and very easy to use library to interface Timer2 with humans. It's called MsTimer2 because it "hardcodes" a resolution of 1 millisecond on timer2 For Details see: http://www.arduino.cc/playground/Main/MsTimer2 2017/08/20 NextStep/Kaz Ueno */ #include <MsTimer2.h> /* Switch on LED on and off each half second */ #define LedPin 13 /* LED to pin 13 */ #define pwmPin A0 /* CO2 data input to pin A0 */ boolean prevVal = LOW; uint32_t CO2_data = 0L; uint8_t data_count = 0L; uint32_t th, tl, h, l, ppm, ppm_now; uint32_t ppm_befor = 0L; uint32_t tt = 0L; void flash() { uint8_t myVal = digitalRead(pwmPin); tt++ ; if (myVal == HIGH) { digitalWrite(LedPin, HIGH); if (myVal != prevVal) { tl = tt ; prevVal = myVal; tt =0L; } } else { digitalWrite(LedPin, LOW); if (myVal != prevVal) { th = tt; prevVal = myVal; ppm = 5000 * (th - 2) / (th + tl - 4); ppm_now = ppm_befor * 0.8 + ppm * 0.2 ; ppm_befor = ppm_now; data_count++ ; CO2_data += ppm_now; tt = 0L; } } } void setup() { Serial.begin(9600); pinMode(pwmPin, INPUT); pinMode(LedPin, OUTPUT); MsTimer2::set(1, flash); // 1ms毎に割り込みを発生させる MsTimer2::start(); delay(5000); } void loop() { uint32_t CO2_data_ave; CO2_data_ave = CO2_data / data_count; Serial.println("PPM = " + String(CO2_data_ave) +"," + String(ppm_now) +"," + String(ppm)); CO2_data = 0L; data_count = 0L; delay(5000); } |