気圧センサー(MPL115A2)で大気圧と標高を測定して見ます

〔LPS25H:I2C〕   〔PICの動かせ方入門に戻る〕


実験中にMPL115A1センサーを壊してしまいました、
だからぁPICでMPL115A1(SPI)接続の記事はMPL115A1センサーを再度手に入れたら再実験後記事にしたいと思います。

なのでぇ、MPL115A1でSPI接続の話はこちらのArduinoでの記事を参考にして置いて下さい。
この頁ではPIC16F1938とI2C接続のMPL115A2センサーを使い、大気圧と高度の計算をさせこれを表示させて見ます。

なぜぇ、PIC16F1938なのぉ?
それはねぇ、プログラミングでのfloat (浮動小数点型) の計算や、float 数値を文字列に変換するのに
sprintf 関数を使っているせいでプログラム容量が約7.8K程有るからなのさぁ。
だからぁプログラム容量が8K以上のPICを使用して下さい、手持ちからPIC16F1938(16K)にしました。
ちなみに、標高の計算を利用しない、sprintfを使わない(整数で表示)なら4KでもOKですけどね。

センサーモジュールはこちらを秋月電子で購入していますが、 *5)
データシートはこちらを見て下さい、レビジョン(Rev 8, 06/2012)が新しいです。
新しいデータシートは校正係数のC11とC22は使用しない様に変更されています。
おそらく今までもこの係数を読み出しても0で意味がなかったのではと思えます。

また、PICでI2Cの基本概要等はこちらを参考にして下さい。
尚、ArduinoでMPL115A2(I2C)の記事はこちらを参照下さい。

《 配線図 》

ピンの構成図(PIC) ピンの構成図(MPL115A2)

PICの今回使用するピン番号は20番(VDD)と8/19番(VSS)
を電源に配線します。
I2C関連ピンは14番(SCL)と15番(SDA)です。

また、表示用として別途作成のLCDモニターに28番(RB7)から出力しています。

配線図  左図のMPL115A2は左下がピン1番です。

 I2C用プルアップ抵抗はデータシートに
 47KΩと書いて有ったのでそれを使いました。

 MPL115A2モジュールの電源ラインには
 パスコン付きです。

 NCピンについて
 使用しないピンです。

 SHDNピンについて
 通常はVDDに接続します、GNDに接続するとスリープ状態に移行し1uAの消費電流になる様です。

 RSTピンについて
 通常はVDDに接続します、GNDに接続するとI2C接続ピンがハイ・インピーダンスになりI2C通信が
 出来なくなります。

注意
2013年3月現在、センサーモジュールが新型になっていますが、ここでは旧モジュールでの記述です。
新型は、電源通電用LEDが追加になっただけで端子配列は変わりません。 *1)

《ダウンロードプログラムについて》

↓ここからサンプルプログラムソースファイルをダウンロードして下さい。
MPL115A2.lzh(Ver2.00 2014/02/02) *3)
MPL115A2.lzh ライブラリとMPLAB X用に変更 *4)

プログラムソースをダウンロードしたら、MPLAB Xにてプロジェクトを作成します。
以下のファイルをプロジェクトディレクトリにコピーしてプロジェクトに取込んで下さい。
次にコンパイルPIC書き込みを実行して下さい。 *4)
MPLAB(R) XC8 C Compiler Version 1.32コンパイラを使用しています。

ダウンロードファイルを解凍すると下記の様なファイル構成です。
Pressure.c・・・・・・・・・ 本体のプログラムソースファイル *4)
skMPL115A2.c・・・・・ MPL115A2ライブラリ関数ソースファイル
skMPL115A2.h・・・・・ MPL115A2ライブラリ用インクルードファイル
skI2Clib.c・・・・・・・・・・ I2C通信を行う関数ソースファイル *4)
skI2Clib.h・・・・・・・・・・ I2C通信を行う関数のインクルードファイル *4)

このプログラムにはデバッグモニタープログラム「skMonitorLCD.c」「skMonitorLCD.h」が必要です。
デバッグLCDモニターについてはこちらを参照して下さい。
「skMonitorLCD.c」は送信データをTimer2のタイミングで送る様に変更しました、
その為にPressure.cプログラムを変更しています。
 *3)

また、LCDモニターの出力はRB7から行っているので「skMonitorLCD.h」を下記の様に変更します。
#define _XTAL_FREQ 8000000  // 使用するPIC等により動作周波数値を設定する
#define MONITOR_PIN RB7      // モニタ出力するピンの番号を設定する

Pressure.c

センサーからデータを読込んで大気圧と標高(高度)の計算と表示を行うメインの本体プログラムです。

表示結果  実行すればこの様に表示されると思います。
 この表示データは、圧力・温度のA/D変換値の生データを
 20回読み込んで単純平均化したデータで計算させた内容です。
 また、計算した高度に+80m補正を加えた内容で表示されています。

この表示は上1行目が大気圧値で、下2行目が高度値が表示されています。

  H_CORRECTについて
  #define H_CORRECT   80                // 自宅でのセンサと実際の高度差補正値(My自宅の標高は100m)
  これはセンサー値から計算した高度値(ICAO標準大気)と実際の高度値(実測する場所)に誤差が
  有る為の補正値用データです。
  まず、自宅でセンサー値から計算した高度値を表示させます。(H_CORRECT=0で計算させる)
  次に調べた自宅の高度と表示させた高度値の差をH_CORRECTにm値で変更して下さい。
  この操作は天気が穏やかな日が良いでしょう。(我が家では80mの差が有りました)
  尚、自宅の標高を調べるには、こちらの国土地理院のWeb地図で分かります。

  高度補正操作についてはArduinoとMPL115A1のこちらの記事を参照下さい。

skMPL115A2.h

MPL115A2にアクセスする為のライブラリ用のインクルードファイルです。
"skMPL115A2.c"を利用する場合に
#include "skMPL115A2.h" をプログラムの先頭で記述して下さい。

I2Cスレーブアドレスについて  *2)

アドレス設定  アドレスは7ビットで表します、左図の1〜7ビットです。
 0ビット目はR/Wでこれはスレーブに対する読書き指示ビットです。
 R/W=0 : 書き込み要求です(スレーブは受信モード)
 R/W=1 : 読み込み要求です(スレーブは送信モード)

今回のMPL115A2アドレスは、7ビット"1100000"(0x60)です。("1100000"+R/W)
データシートには、
R/W=0 : "1100000"+"0"で0xc0
R/W=1 : "1100000"+"1"で0xc1
と8ビットで記載されています注意しましょう。
よってここでは
#define SENSOR_ADRS 0x60 // MPL115A2のI2Cアドレス
となっています。

skMPL115A2.c

このライブラリはMPL115A2にアクセスを行う為の関数集です。
この関数集自体は他のPICでも使用出来ます。

MPL115A2にアクセスを行う関数の使い方を説明します。

 ans = CoefficientRead( )
  メモリーマップから係数を読み出す処理
  校正係数が工場出荷時にセンサー内部のメモリマップに保存されています、大気圧を計算する時に
  利用するのでこれを読み出して置く必要が有ります、立ち上げ時に1回読み出せばOKです。
  係数はa0,b1,b2,c12の4つです。
  古いデータシートではc11,c22も使用していたのですが新しいレビジョンでは使いません。
   ans :戻り値、 0=正常 1=I2C通信異常(相手からACKが返ってこない)

  ※ このセンサーから読み出した"係数"につては、(私の記事は怪しい!)
    セッピーナさんの"PICでI2C - MPL115A2の大気圧計算法"を読んで下さい、詳しいです。 *6)

 ans = PressureRead( )
  メモリーマップから圧力と温度のA/D変換値データを読み出す処理
  読み出したデータはそれぞれ Press 、Temp の変数に格納されます。
  注意として、ここで読み出す温度データ(Temp)は実際の温度として利用するには無理っぽいです。
  なので、温度を測定したい人は別に温度センサーを用意しましょう。(温度センサーの話はこちら)
   ans :戻り値、 0=正常 1=I2C通信異常(相手からACKが返ってこない)

 ans = PressureAVE(count)
  圧力・温度のA/D変換値を平均化させ気圧値を計算する処理
  PressureRead( )関数から読み込むデータはばらつきが有るので数回読み込んで平均を行い
  大気圧値を計算(PressureCalc)させます。
  平均処理は単純平均化で行っていますが本当は移動平均の方が良いと思えます。
   count : A/D変換値を平均の為に何回読み込むか指定する。(今回は20回を指定)
   ans  :大気圧値を hPa (float)で返す。

 ans = PressureCalc( )
  気圧値(hPa)を計算する処理
  読み出した係数と圧力・温度のA/D変換値データから大気圧を計算します。
   ans :大気圧値を hPa (float)で返します。

  圧力・温度のA/D変換値のデータと校正係数データから大気圧を計算させるにはめんどくて複雑な
  処理をさせないとだめですがこの頁ではその説明は省きます、興味が有る人はデータシートや他の
  サイト様を参考にして下さい。

 ans = AltitudeCalc(float pressure,int Difference)
  大気圧のデータから高度(標高)を計算します。
  ICAO(国際民間航空機関)標準大気での計算になります
  (平均海水面での気圧が1013.25hPa、気温が15℃、対流圏の約11km以下での条件となります)
  なので実際は場所や季節や天気状態等でICAO標準大気と誤差が出るので補正が必要でしょう。
   pressure :計算した大気圧値を hPa でセットします。
   Difference:標高の差を指定します。(上のH_CORRECTについてを参照下さい)
   ans     :高度値を m (float)で返します。

skI2Clib.h

I2C通信の関数ライブラリ用インクルードファイルです。
"skI2Clib.c"を利用する場合に
#include "skI2Clib.h" をプログラムの先頭で記述しないとだめです。

デフォルトではMSSP1を使う様になりますが、PICによってはMSSP2が有ります。
MSSP2側を使う場合は、"#define I2C_MSSP2_USE"を記述して下さい。 *4)

skI2Clib.c

このライブラリはデバイス(RTC/EEPROM等)とI2C接続を行う為の関数集です。
この関数集は12F1822/16F182x/16F193x/18F25K22系で利用可能です、
又、SSP1/SSP2何方でもOKです、今回の変更で統合しました。 *4)

I2C通信の関数ライブラリの使い方を説明します。

 InitI2C_Master(speed) *4)
  I2C通信のマスターモードで初期化を行う処理です。
  I2C通信用の速度クロック周波数は100KHzでの設定です、
  この速度はFOSC(PICのCPU周波数)8MHzの場合で初期化されています。
  FOSCを変えた場合はこちらを参考にSSPADDレジスタを変えて下さい。
   speed  :I2Cの通信速度を指定します。(0=100KHz 1=400KHz)

  尚、MPL115A2はI2C通信用の速度クロック周波数400KHzにも対応しています。
  又、通信速度を400KHzにしても、実際は250KHz程しか速度は出ません。 *4)

 ans = I2C_Start(adrs,rw)
  スレーブにスタートコンディションを発行する処理です。
   adrs  :スレーブのアドレスを指定します
   rw     :スレーブに対する動作の指定をします
        0 = スレーブに書込みなさい要求  1 = スレーブに送信しなさい要求
   ans   :0 = 正常 1 = 異常(相手からACKが返ってこない)

 ans = I2C_rStart(adrs,rw)
  スレーブにリピート・スタートコンディションを発行する処理です。
   adrs  :スレーブのアドレスを指定します
   rw     :スレーブに対する動作の指定をします
        0 = スレーブに書込みなさい要求  1 = スレーブに送信しなさい要求
   ans   :0 = 正常 1 = 異常(相手からACKが返ってこない)

 I2C_Stop()
  スレーブにストップコンディションを発行する処理です。

 ans = I2C_Send(dt)
  スレーブにデータを1バイト送信する処理です。
   dt     :送信するデータを指定します
   ans   :0 = 正常 1 = 異常(相手からACKが返ってこない又はNOACKを返した)
  例)slave_adrsへの2バイト送信
     ans = I2C_Start(slave_adrs,RW_0);  // スタートコンディションを発行する
     if (ans == 0) {
          I2C_Send(dt) ;                // 1バイト目を送信する
          I2C_Send(dt) ;                // 2バイト目を送信する
     } else 異常 ;
     I2C_Stop() ;                       // ストップコンディションを発行する
 c = I2C_Receive(ack)
  スレーブからデータを1バイト受信する処理です。
   ack    :スレーブからデータを受信した後に返答するデータを指定します
        0 = ACKをスレーブに返す 1 = NOACKをスレーブに返す(受信データが最後なら1)
   c       :受信した1バイトのデータを返す
  例)slave_adrsから2バイト受信する
     ans = I2C_Start(slave_adrs,RW_1) ;  // スタートコンディションを発行する
     if (ans == 0) {
          dt1 = I2C_Receive(ACK) ;       // 1バイト目を受信する
          dt2 = I2C_Receive(NOACK) ;     // 2バイト目を受信する
     } else 異常 ;
     I2C_Stop() ;                        // ストップコンディションを発行する
 InterI2C()
  I2C関連の割り込み処理です。
  今回は割込み発生したらフラグをクリアしているだけです。
  メインプログラム(例"Pressure.c")の割込み処理で必ず呼びます。
  例)
     void interrupt InterFunction( void )
     {
          // I2C関連の割り込み処理
          InterI2C() ;
     }

《その他》

実験風景
 左写真は実験時の物です。
 左写真と上の配線図ではMPL115A2
 センサーが上下逆になっています注意。

 モニターの1行目表示で下の1ドットが
 欠けていますが気にしないで下さいね。

 ん〜ん、なんとなくもう一歩
 デンプシィロールがぁ、じゃ〜なっくてぇ
 精度が欲しい様なぁ、
 そんな感じがぁしますぅ、みたいなぁ
 お天気予報を行うにはこのセンサーでも
 OKでしょうが?、たぶん、きっとぉ、
 高度計を作るならこちらのセンサーが
 高分解能で性能が良くて、温度センサー
 出力も有ります、
 ただちょっとぉ、お値段お高いですがね。
 (まぁその内購入出来たら実験ですかね)

 お天気予報の実験はその内にでも
 行うと言う事でぇ.....
 (データ取るのがメンドそうなのでぇ..)
 お天気予報はこちらo-Familyさんを参考にして下さい。





記事一部追記(*6) 2018/03/20
リンク切れ見直し(*5) 2017/01/11
ライブラリとMPLAB X用に変更(*4) 2015/10/26
"skMonitorLCD.c"変更により"Pressure.c"のプログラム変更(*3) 2014/02/02
追記(*2) 2013/08/25
追記(*1) 2013/03/30


【きむ茶工房ガレージハウス】
Copyright (C) 2006-2017 Shigehiro Kimura All Rights Reserved.