PICでI2C - MPL115A2の大気圧計算法
今回は「大気圧センサーモジュールMPL115A2の使い方」というのを書こうと思ったのですが、
「きむ茶工房ガレージハウス - 気圧センサーで大気圧と標高を測定して見ます(MPL115A1)(MPL115A2)」
がありました。
もう至れり尽くせりなので私が書くことは何もないのですが、大気圧の計算法のことだけ自分のメモの意味もあってちょっと書いておきます。
-----
記事は一生懸命書きましたがじつはこの大気圧センサーモジュールはあんまりお勧めしません。あんまり精度も分解能もよくないのです。秋月のこの製品のページには
・分解能:0.15kPa
・精度:±1kPa
とあります。
実際この記事の最後にある例
Tadc 0x6300=396 にたいして気圧1004.7hPa
だと
Tadc 0x6340=397 にたいして気圧1003.3hPa
ということで分解能は1.4hPaとちょっとさびしいです。
気圧の計算式を見るとわかるように分解能はほぼb1に依存し、Tadcによって少し変化します。厳密には
(b1 + c12*tADC) * (65.0)/1023 * 10.0
(の符号を変えたもの)が分解能ということになります。
-----
と書いたのですが、分解能はともかく精度はそんなに悪くはないようです。
「意外に正確そうなI2C大気圧センサーMPL115A2の測定値」
(2014.09.19)
-----
これもちっちゃいのはいやなのでDIP化したものを秋月で購入しました。ペラペラの資料がついているのですが、これをいくら読んでも大気圧の計算方法がわかりません。大気圧の計算式はあるのですが、それに使う係数がよくわかりません。つまりI2Cで読み込んだ2バイトのデータをどうやって係数に変換するかというところです。
これは秋月の資料にはないわけでMPL115A2の製造元のFreescale Semiconductorの資料
「MPL115A: 50 to 115kPa, Absolute Digital Pressure Sensor」
この資料は翻訳された方がいらっしゃいます。
「MPL115A2 小型のI Cデジタル気圧計 - Ne」
を見る必要があります。I2Cでのデータの取得方法もこれに詳しく書いてあります。
もっともこれを見てもまだよくわかりません。熟読するとどうやら係数が2進数で収められているけれど小数点の位置が係数によって違う、ということみたいです。それぞれの係数の格納パターンは次のような表になっていました。
a0 | b1 | b2 | c12 | Padc | Tadc | |
Total Bits | 16 | 16 | 16 | 14 | 10 | 10 |
Sign Bits | 1 | 1 | 1 | 1 | 0 | 0 |
Integer Bits | 12 | 2 | 1 | 0 | 10 | 10 |
Fractional Bits | 3 | 13 | 14 | 13 | 0 | 0 |
dec pt zero pad | 0 | 0 | 0 | 9 | 0 | 0 |
“Total Bits”が16というのは2byteということですが、14とか10というのは左詰めなので注意が必要です。
例えばa0の場合sign bits(複数?)+integer bitsで13bitとありますから3bit右にずらせば小数点が右端にきます。シフトすれば小数部分がなくなりますので2^3つまり8で割ればいいわけです。
c12が複雑で上のようにして変換したあとさらにdec pt zero pad の9bit右にずらす必要があります。
結論としてこうすればいいことになります。
まず浮動小数点に変換します。
C = (2byteを整数にしたもの) / 2 ^ ( 16 - sign bits - Integer bits)
Sign Bitsが立っているときは符号を変えます。2の補数と書いてありますので
C = C - 2 ^ ( integer bits + 1 )
を計算します。
C12に関してはさらに
C = C / 2 ^ (dec pt zero pad)
とすることが必要です。
Cで書くとこんな感じです(上のきむ茶工房ガレージハウスさんのプログラムをベースにさせていただきました)
h = I2C_Receive(ACK) ;
l = I2C_Receive(ACK) ;
a0 = ((h << 8) + l) / 8.0;
if( h & 0x80 ) a0 -= 8192.0;
h = I2C_Receive(ACK) ;
l = I2C_Receive(ACK) ;
b1 = ((h << 8) + l) / 8192.0;
if( h & 0x80 ) b1 -= 8.0;
h = I2C_Receive(ACK) ;
l = I2C_Receive(ACK) ;
b2 = ((h << 8) + l) / 16384.0;
if( h & 0x80 ) b2 -= 4.0;
h = I2C_Receive(ACK) ;
l = I2C_Receive(NOACK) ;
c12 = ((h << 8) + l) / 32768.0;
if( h & 0x80 ) c12 -= 2.0;
c12 /= 512.0;
あとはPadc,Tadcから秋月の資料にもある式で気圧を求めます。
pADC=((ip[0]<<8)+ip[1])/64.0;
tADC=((ip[2]<<8)+ip[3])/64.0;
pcomp = a0 + (b1 + c12*tADC )*pADC + b2*tADC;
pressure = (pcomp * (115.0-50.0)/1023.0+50.0)*10.0;
ちなみに私のMPL115A2はこんな係数になっていました。
a0 0x41B4 2102.5
b1 0xB046 -2.491455078
b2 0xC155 -0.979187012
c12 0x3798 0.000848
そして
Padc 0x6300 396
Tadc 0x7D00 500
から
pcomp = 794.3
pressure = 1004.7
が得られました。
赤い矢印で示したところがMPL115の計算用の係数です。
センサーから取得したデータは加工してLCDに表示していますが、PCに送るときはセンサーから取得したナマのデータです。こうしておくとあとで計算式が間違っているのに気がついたときすぐに計算し直すことができます。
なおログの1行目から5行目までは白金薄膜抵抗やサーミスタから温度を計算するときに使った係数です。これをソースの更新履歴と見比べるといつ作った(修正した)ソースを実行していたかがわかります。
------
関連
「I2C大気圧センサーLPS331の驚くべき分解能」
「I2C大気圧温度センサーLPS331 - 海面更正気圧を気象庁とくらべてみた」
「I2C大気圧センサーLPS331の分解能はほんとうに高いのか?(温度編)」
「I2Cデバイス・アドレス一覧」
「I2Cのソース - PIC12F1822/16F1705/16F1938/18F26K22 - LCD(ACM1602)を例にして」
「PICで平方根 - 白金薄膜抵抗で温度を測る」
「PICでI2C - ADコンバーター・MCP3425の使い方」
「PICでI2C - 1 (温度計を作る)」
「PICでI2C - 液晶(LCD)ディスプレイ(ACM1602N1-FLW-FBW)に表示する」
「PICでI2C - LCD(液晶)ディスプレイによる違い」
「サーミスタによる温度測定の精度」
「サーミスタ温度計の精度を調べる - 1」
「PICで作るお手軽サーミスタ温度計」
「炭素皮膜抵抗の温度係数を測定する話」
「ミニ恒温槽の作成に向けて - 1」
「ミニ恒温槽の作成に向けて - 魔法瓶の活用」
参考
「きむ茶工房ガレージハウス - PICの動かせ方入門はこちら - 16F1938覚書」
「きむ茶工房ガレージハウス - I2C通信の実験」
「きむ茶工房ガレージハウス - 気圧センサーで大気圧と標高を測定して見ます(MPL115A1)(MPL115A2)」
以上は予習として拝見していたのですが、とても参考になります。他にも勉強になる記事が多いです。
私の記事を読んでI2Cのセンサーを使って温度計とか気圧計とかそういうものを作りたくなった方も実際に作られるときはこちらを読まれた方がいいと思います。
« PICで作るお手軽サーミスタ温度計 (1) | トップページ | 同じアドレスのI2Cデバイスを使う »
「趣味の電子工作」カテゴリの記事
- PICで作る100MHz周波数カウンタ検証用XOR(エクスクルーシブオア)逓倍器(2016.03.08)
- 150MHz(~200MHz?)周波数カウンター用プリスケーラー(1/4分周器)(2016.03.06)
- 測温抵抗体(Pt100、白金薄膜温度センサー)の抵抗値を温度に変換する(平方根を使わない)計算式(2016.03.01)
- GPS/JJY(標準電波)を基準周波数源とするためのPLLの詳細(2016.02.27)
- GPS受信モジュール1PPS対決 - GE-612T vs GM-5157A(2016.02.21)
この記事へのコメントは終了しました。
コメント