気圧センサを使ってみた
RaspberryPi/pigpioでMPL115A1

2021年4月30日

どもです。
前回は、DHT11をRaspberryPi/pigpioで使用、温度を測定してみました。
今回は、同じ環境(RaspberryPi/pigpio)で大気圧センサーであるPL115A1を使用してみます。

1.開発環境

本エントリの内容の開発環境を、下表に記載します。

開発環境
PC本体 OS Windows10 Pro
バージョン:1903
CPU Intel Core i7-8700
メモリ 16GB
Eclipse Version 2019-06
4.12.0
Build id 20190614-1200
RaspberryPi
クロスコンパイラ
raspberry-gcc8.3.0
RaspberryPi ライブラリ pigpio
バージョン:71

2.配線

まず、ブレッドボード上の配線です。
配線図は、下記の通りです。
MPL115A1_raspi
MPL115A1との通信方法は、SPI通信になります。
なので、RaspberryPiもそのためのピンをしています。

3.使い方

MPL115A1では、大気圧を直接取得できません。
大気圧を取得するためには、必要な係数と値を取得して計算します。
ここでは、係数と値の取得方法について書いていきます。

3.1.MPL115A1との通信

MPL115A1からの値は、SPI通信で取得します。
このとき、通信方法としては「半二重」になります。
一応コードを示しておきます。

void SendAndRecvCommand(
	const unsigned int spiHandle,
	const uint8_t command,
	uint8_t* readData)
{
	spiWrite(spiHandle, (char*)(&command), 1);
	spiRead(spiHandle, (char*)(readData), 1);
}
			

上記spiWrite()で送信しているcommandの値はメンドクサイここで書くと量が多くなってしまうので、MPL115A1のデータシートを参照して下さい。

3.2.係数の取得

大気圧を取得するために必要な係数は、a0、b1、b2、およびc12の3つがあります。
データシートによれば、各係数のフォーマットは、
a0→S12.3
b1→S2.13
b2→S1.14
となっています。
全て16bitの値です。
c12ついては、少し異なっています。
即ち、取得データのうち13bitがデータになり、その値は小数点第10位以下の値になります。
また13bitの範囲は、16bitの内の下記の範囲になります。
MPL115A1_bit_order
データシートに明記はされていませんが、最上位MSBの最上位ビットを符号ビットとしています。
係数の取得と変換のコードは、下記の通りです。

/**
 * Convert buffer data, data type is uint8_t, into float.
 *
 * @param[in]   buffer  Pointer to buffer conataining the uint8_t data.
 * @param   msbIndex    Index of buffer of MSB byte.
 * @param   lsbIndex    Index of buffer of LSB byte.
 * @param   floatLsb    LSB of float value.
 * @param   mask        Bit array to mask buffer. Default value is 0xFFFF.
 */
float Buff2Float(
		uint8_t* buffer,
		int msbIndex, int lsbIndex,
		float floatLsb,
		uint16_t mask = 0xFFFF)
{
	float converted = 0.0;

	uint16_t rawData = ((uint16_t)(buffer[msbIndex] << 8) + (uint16_t)(buffer[lsbIndex]));
	rawData &= mask;
	converted = (float)((int16_t)rawData * floatLsb);

	return converted;
}

/**
 * Read coefficient value..
 *
 * @param   spiHandle   SPI handle.
 */
void ReadCoefficient(const unsigned int spiHandle) {

	StartSequence();
	for (int buffIndex = 0; buffIndex < MPL115A1_DATA_INDEX_COEFF_MAX; buffIndex++) {
		SendAndRecvCommand(spiHandle, READ_COEFF_SEQ_COMMAND[buffIndex], &coefficientBuff[buffIndex]);
	}
	SendExtraCommand(spiHandle);
	StopSequence();

	//Setup coefficient from receive data.
	MPL_115A1_a0 = Buff2Float(
			coefficientBuff,
			MPL115A1_DATA_INDEX_COEFF_A0_MSB, MPL115A1_DATA_INDEX_COEFF_A0_LSB,
			MPL115A1_COEFF_A0_LSB);
	MPL_115A1_b1 = Buff2Float(
			coefficientBuff,
			MPL115A1_DATA_INDEX_COEFF_B1_MSB, MPL115A1_DATA_INDEX_COEFF_B1_LSB,
			MPL115A1_COEFF_B1_LSB);
	MPL_115A1_b2 = Buff2Float(
			coefficientBuff,
			MPL115A1_DATA_INDEX_COEFF_B2_MSB, MPL115A1_DATA_INDEX_COEFF_B2_LSB,
			MPL115A1_COEFF_B2_LSB);
	uint16_t rawData_c12 =
			((uint16_t)(coefficientBuff[MPL115A1_DATA_INDEX_COEFF_C12_MSB] << 8) +             (uint16_t)(coefficientBuff[MPL115A1_DATA_INDEX_COEFF_C12_LSB]));     rawData_c12 >>= 2;
	rawData_c12 &= 0x3FFF;
	MPL_115A1_c12 = (float)((int16_t)rawData_c12 * MPL115A1_COEFF_C12_LSB);
}

3.3.値の取得

大気圧を算出するために参照する値は、大気圧の値と温度の値になっています。
それぞれの値のサイズは、10bitです。
受信した2バイトのデータのうち、上位10bitの値を使用します。
実際に値を取得、抜き出す実装は下記になります。

/**
 * Read pressure and temperature value.
 */
void ReadTempAndPress(const unsigned int spiHandle) {
	StartSequence();
	for (int buffIndex = 0; buffIndex < MPL115A1_DATA_INDEX_MAX; buffIndex++) {
		SendAndRecvCommand(spiHandle,
				READ_PRESS_TEMP_SEQ_COMMAND[buffIndex],
				(uint8_t*)(&dataBuff[buffIndex]));
	}
	SendExtraCommand(spiHandle);
	StopSequence();

	//Get Padc and Tadc value by buffer.
	{
		uint16_t rawData_padc =
				(((uint16_t)dataBuff[MPL115A1_DATA_INDEX_PRESS_MSB]) << 8) +                 dataBuff[MPL115A1_DATA_INDEX_PRESS_LSB];         rawData_padc >>= 6;
		MPL_115A1_padc = (float)((int16_t)rawData_padc);
	}
	{
		uint16_t rawData_tadc =
				(((uint16_t)dataBuff[MPL115A1_DATA_INDEX_TEMP_MSB]) << 8) +                 dataBuff[MPL115A1_DATA_INDEX_TEMP_LSB];         rawData_tadc >>= 6;
		MPL_115A1_tadc = (float)((int16_t)rawData_tadc);
	}
}

3.4.大気圧の計算

これまで取得した値を使用して、大気圧を算出します。
算出は、下記の順番で実施します。

  1. 圧力補正を算出
  2. 大気圧を算出

それぞれの値は、下記の計算式で算出します。

圧力補正

image009


image011

この計算の実装は、下記になります。

/**
 * Get pressure by reading data from the sensor.
 *
 * @return  Pressure specified by kPa.
 */
float GetPress() {
	float MPL_115A1_press_comp =
			MPL_115A1_a0 +
			(MPL_115A1_b1 + MPL_115A1_c12 * MPL_115A1_tadc) * MPL_115A1_padc +
			MPL_115A1_b2 * MPL_115A1_tadc;
	MPL_115A1_press = (MPL_115A1_press_comp * ((115.0 - 50.0) / 1023.0)) + 50.0;

	return MPL_115A1_press;
}

この関数の戻り値が、kPa単位の大気圧になります。

4.まとめ

今回は、MPL115A1からRaspberryPiで大気圧を取得する方法について記載しました。
このセンサー、データシートには明記されていませんが、実は気温も取得できるようです。
今回のエントリでは省略していますが、分かったら教えてください。

ではっ!

ex.公開しています

今回のエントリで作成したコードや資料は、GitHubで公開しています。
本エントリに記載したコードは、必要な個所のみとなっています。
全てのコードは、上記リンクから参照してください。