M5StickCで空気圧を測定する

IoT

はじめに

M5StickCとMPX5700GPを組み合わせて、圧力センサーをテストしてみました。M5StickCは小型のIoTデバイス開発ツールです。一方、MPX5700GPは、モノリシックシリコン圧力センサであり、圧力に比例したアナログ出力信号を生成するタイプで、特にゲージ圧を測定するために使用されます。

MPX5700GP(圧力センサー)について

MPX5700GPは、抵抗ブリッジに加わる圧力によるひずみを検出し、それを抵抗値の変化として解釈して圧力を算出するセンサーです。ゲージ圧を測定するタイプであり、データシート上では0から700kPaの範囲での圧力測定が可能です。

1.0kpa = 0.145psi = 0.01bar = 0.0101971621kgf/cm2

ADCの校正

M5StickCに搭載されているESP32のADCは、完全な線形性を持っていないため、SoCごとに異なる特性があります。そのため、ADCの校正が必要になります。

テスト回路を作る

MPX5700GPの場合、PIN1が信号出力(V out)、PIN2が基準(GND)、PIN3が電源(VCC)となっています。センサーの動作電圧範囲が4.75Vから5.25Vなので、M5StickCの5Vを利用します。

センサーからの信号出力は4.7Vですが、M5StickCの入力ピン(G33)は3.3V以下であるため、信号を最大3.3Vに制限するように分圧して調整する必要があります。

データシートに推奨する電源デカップリングと出力フィルタの回路が掲載されていたので、ブレッドボードにそのまま組んでみます。

今回の回路では、電源デカップリング用に0.1μFと0.01μFのコンデンサを、出力フィルタリング用には470㎊のコンデンサを使用しました。これらのコンデンサは、村田製作所のフィルムコンデンサを採用しています。

圧力の計算

センサーの正確な動作を確保するためには、個々のセンサーを個体ごとにキャリブレーションする必要があります。しかし、今回は単なるテストであるため、個体ごとのキャリブレーションは行いません。代わりに、センサーのデータシートに記載されている関数を使用して、センサーから得られるデータを補正します。

$$Vout = Vs × (0.0012858 × P + 0.04)\\ \frac{Vout}{Vs} = 0.0012858 × P + 0.04 \\ \frac{ADC}{4095} = 0.0012858 × P + 0.04 \\ P = \frac { \frac{ADC}{4095} – 0.04 }{0.0012858}$$

Vsはセンサーの動作電圧なので、ADCの最大値4095に置き換えます。また、ADCの校正で得られた回帰式(VADC)は、ADCの値と同等の電圧値を返すため、次の値は等価です。

$$\frac {V_{out}}{5_{V}} = \frac{ADC}{4095} = \frac {V_{ADC}}{3.3_{V}}$$

したがって、データシートの関数は以下のようにまとめられます。

$$P(kPa) = \frac {(\frac{V_{ADC}}{3.3} -0.04)} {0.0012858}$$

準備が整ったので、適当なプログラムを書いてテストしてみます

#include <M5StickC.h>

const int INPUT_PIN = 33;
const int SAMPLE_COUNT = 1000;

double appFormula( double adc );
double calcPressure(double adc);


void setup() {

  M5.begin();
  M5.Lcd.begin();
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setRotation(1);
  M5.Lcd.setTextDatum(4);
  pinMode(INPUT_PIN, ANALOG); 
}

void loop() {
  double data = 0.0;
  double pressure_kpa = 0.0;
  for (int i = 0; i < SAMPLE_COUNT; i++){
    data = data + double(analogRead(INPUT_PIN));
  }
  data = data / SAMPLE_COUNT;
  data = calcPressure(data);

  if(millis() > (5000)){
    M5.Lcd.fillScreen(BLACK);
    M5.Lcd.drawString(String(data) + " : kPa",80,40,4);
  }
  delay(50);
}


double calcPressure(double adc){
  const double voltage = 3.3;
  const double coef_1 = 0.04;
  const double coef_2 = 0.0012858;
  return ((appFormula(adc)/voltage) - coef_1 ) / coef_2;
};


double appFormula( double adc ) {
  double coef_list[] = {
     1.9356393247430315e-002,
		 1.7004612516341605e-003,
		-2.4150612233191874e-006,
		 3.1402623315297472e-009,
		-2.2241794162860271e-012,
		 8.9513305040651527e-016,
		-2.0120219847773836e-019,
		 2.2989933389111859e-023,
		-1.0030578046368812e-027
};
  double multiplier = 1;
  double result = 0;
  for (double coef : coef_list) {
    result += coef * multiplier;
    multiplier *= adc;
  }
  return result;
}
C++


コンプレッサーに接続し、レギュレーターを回すと圧力センサーからの値が変化することを確認できました。

データを突き合わせる

試しに、CKDのPIS-P10K-6Bを使用してM5StickCで取得した値と比較してみました。エアーを両方同時に送るためにチーズを使用し、それぞれの端末から値を取得しました。PIS-P10K-6Bの解像度は0.1毎で、単位はkgf/cm2です。そのため、M5StickCで取得した値の単位であるkPaをkgf/cm2に変換し、両者を突き合わせました。

まとめ

PIS-P10K-6Bで取得した値とM5StickCで取得した値を比較した結果、データの取得はまあまあ良好な結果が得られました。しかし、圧力が高くなるにつれて誤差が広がる傾向が見られました。そのため、実際に使用する場合には適切な補正を行う必要があります

タイトルとURLをコピーしました