LoginSignup
6
7

More than 5 years have passed since last update.

二酸化炭素センサー MH-Z19 のPWM入力プログラムを割り込み処理で実現

Last updated at Posted at 2017-10-12

二酸化炭素センサー MH-Z19 のPWM入力でデータを取得したくて
Arduino用のサンプルプログラムを使ってみたのですが、
このプログラムPWMのパルス長の計測をメイン処理の中でやっていたので、
このままでは他のセンサーとの併用が難しいので、
データ取得部分を割り込み処理に変更してみました。

割り込みには「MsTimer2」ライブラリを使用しています。
またデータのフィルタリングの処理も追加しています。

公開されていた元のプログラム

mh-z19.ino
#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));
    }
  }
}

割り込み処理に変更したプログラム

mh-z19_int.ino
/*
  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)に変換
      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);
}

これで loop()内に他のセンサーの取り込みプログラムが書けます。
なおデジタルフィルタリング処理に関しては
センサの入力などに使うディジタルフィルタ
こちらのページの解説が分かりやすいです。

割り込みによるCO2でーた取得確認中の様子

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7