google-site-verification: google3bd66dd162ef54c7.html

気圧センサLPS25Hを使った高度計の試作

 以前買っておいたLPS25Hという気圧センサを動かしてみました。1年前くらいの気圧センサの定番はLPS331というセンサーで、雑誌やブログなどで製作記事をよく見かけました。私もLPS331を使った気圧計や高度計をあれこれ作りましたが、残念ながらディスコンになってしまったようです。今回取り組むLPS25HはたぶんLPS331の後継機種いう位置付けだと思います。

 せっかく動かしてみるなら以前と同じことをやっても面白くありません。そこで今回はSPIインターフェイスで動かし、グラフィック液晶に表示をさせることにしました。最終的にはカラーグラフィック液晶に飛行機のアナログ高度計みたいな画像を表示させたいのですが、まずは手持ちの小さなモノクロ液晶で試すことにしました。

 なお、LPS25Hはそのままでは扱い難いので秋月のLPS25H使用 気圧センサーモジュールDip化キット(AE-LPS25H)を使いました。

▼試作中
LPS25H動作テスト中
 左は最近作ったFSTN液晶シールドで、その下にはArduino UNOがあります。

▼回路図
LPS25H高度計の回路図
 2N7000は5V→3.3Vのレベル変換に使っています。抵抗で分圧する手もありますが、クロックが速くなると抵抗値をかなり下げないと波形のなまりが大きくなります。また特定の値の抵抗を使うことになるので、その値だけストックが減ってしまって後で困るかも知れません。その点、この回路なら抵抗の値は数kΩ程度の値ならどうでもいいし、2N7000は抵抗の値段とあまり変わりません。ということで最近はこのレベル変換回路を愛用しています。
 なお、ブレッドボードで使った回路ではFSTN液晶シールドのレベル変換回路を使っているのでこの回路図通りにはなっていません。

 ちなみに、3.3V/8MHzで動くArduino UNOを持っていれば毎回こんな面倒なことしなくてもいいわけで、そろそる作っちゃった方が良さそうです。

▼表示
FSTN液晶
 グラフィック液晶なので文字サイズやフォントの指定が出来ます。上の大きな文字が高度。その下のPxの値は気圧センサーの値。一番下のPoは海面気圧で気象庁のサイトなどから現在の値を入手して入力します。なお、この値はアナログポートに接続した可変抵抗を使って入力します。また括弧内の値は高度計規正値(QNH)なので飛行場のATISを聞いてセットすることも可能です。

▼SPIクロックとデーター波形
SPIのクロックとデータ波形
 上がクロック、下がデーターで、指定通り、CPUクロック(16MHz)の1/4の4Mhzになっています。クロックの立ち上がりでデーターを読んでいる感じです。

 プログラムのループにはdelay(100)を入れているので100ms+αの周期で処理が廻っているはず。ということでオシロで確認したところ、何とループを1回廻る速度は約200ms。つまり+αの部分が100msもかかっていることが判明しました。どうも液晶の表示に結構な時間が必要みたいです。

 テストに使ったスケッチは以下のような内容になっています。なお環境はArduino IDE 1.6.1を使っています。

・センサーと液晶はSPIで動かす
・グラフィック液晶の制御はu8glibを使う
・LPS25Hはワンショットモードで動かしFIFOを使ったアベレージングをかける。

 作ってみるとフォントがメモリを大食いするようで、簡単なスケッチなのにサイズが27kバイトにもなっています。これではカラーグラフィック液晶に本物そっくりなアナログ高度計を表示させるのは難しいかも知れません。
/*
気圧センサ LPS25Hの動作テスト
センサーをSPIモードで動かし、結果をSPIの液晶に表示
液晶はaitendoのFSTN液晶、モノクロ、128x64、SPI(UC1701)
スケッチサイズ26.938バイト,
2015/3/23 ラジオペンチ、http://radiopench.blog96.fc2.com/
 */

#include <U8glib.h>
#include <SPI.h>
#include <Wire.h>

float p0, hpa, qnh, elev;
float Pdiff = -3.6;                       // 気圧補正値

U8GLIB_MINI12864 u8g(10, 9);              // u8glibをハードウエアSPIで動かす,(UC1701)

void setup(void) {
  pinMode(A0, INPUT);                     // 海面気圧入力ポート
  pinMode(8, OUTPUT);                     // 気圧センサーのCS
  digitalWrite(8, HIGH);

  SPI.begin() ;                           // SPI開始
  SPI.setBitOrder(MSBFIRST) ;             // ビットオーダー
  SPI.setClockDivider(SPI_CLOCK_DIV4) ;   // SPI CLK倍率設定(16MHz/4)
  SPI.setDataMode(SPI_MODE3) ;            // クロックとデータ定義

  u8g.setContrast(175);                   // 液晶のコントラスト設定
  LPS25H_setup();                         // LPS25Hに測定条件設定
}

void loop(void) {
  hpa = LPS25H_mesure();                 // 気圧測定
  p0 = getP0();                          // 気圧補整値読取り
  elev = 153.8 * (15 + 273.2) * (1 - pow(hpa / p0, 0.1902)); // 標高計算

  u8g.firstPage();                       // display loop開始
  do {
    lcdDisp();
  }
  while ( u8g.nextPage() );
  delay(100);
}

void LPS25H_setup() {            // 気圧センサ測定条件設定
  LPS25H_write(0x10, 0x05);      // アベレージング回数=気圧32回、温度16回
  LPS25H_write(0x20, 0x84);      // PD=1, OneShot Mode, BDU=1
  LPS25H_write(0x2E, 0xDF);      // FIFO移動平均モード、サンプル数=32
  LPS25H_write(0x21, 0x40);      // FIFO=Enable
}

float LPS25H_mesure() {        // 気圧の読み出し
  float p;
  unsigned long val, data;
  LPS25H_write(0x21, LPS25H_read(0x21) | 0x01);  // 変換スタートビットを立て
  while ((LPS25H_read(0x21) & 0x01) == true) {   // 変換完了まで待つ
  }

  val = LPS25H_read(0x28);    // read XL
  data = LPS25H_read(0x29);   // read L
  data = data << 8;
  val = val | data;
  data = LPS25H_read(0x2A);   // read H
  data = data << 16;
  val = val | data;
  p = val / 4096.0;           // 換算係数を掛けてhpaを計算
  p = p + Pdiff;              // センサ誤差補正
  return p;
}

void LPS25H_write(byte adr, byte data) {
  digitalWrite(8, LOW);       // LPS25H CS ON
  SPI.transfer(adr);
  SPI.transfer(data);
  digitalWrite(8, HIGH);      //  LPS25H CS off
}

byte LPS25H_read(byte adr) {
  byte ret;
  adr = adr | 0x80;          // 最上位ビット=1でWrite
  digitalWrite(8, LOW);      // LPS25H CS ON
  SPI.transfer(adr);
  ret = SPI.transfer(0);
  digitalWrite(8, HIGH);     //  LPS25H CS off
  return ret;
}

float getP0() {                                   // 海面気圧設定
  float p0;
  int data;
  unsigned long p100;
  data = analogRead(A0);                          // A0ピンの電圧を読む
  p100 = map(data, 0, 1023, 98000, 104000);       // 980~1040hPaにスケーリング
  p0 = p100 / 100.0;                              // 海面気圧値に換算
  qnh = p0 * 0.029536;                            // QNH換算値も算出
  return p0;
}

void lcdDisp() {                                  // 液晶表示
  u8g.setFont(u8g_font_helvB24);                  // 大きい文字で
  u8g.setPrintPos(20, 30); u8g.print(elev, 1);    // 標高表示
  u8g.setFont(u8g_font_unifont); u8g.print("m");  //

  u8g.setPrintPos(0, 48); u8g.print("Px=");
  u8g.print(hpa, 2); u8g.print("hPa");            // 気圧測定値

  u8g.setPrintPos(0, 63); u8g.print("Po=");
  u8g.print(p0, 1); u8g.print("(");               // 海面気圧 hPa
  u8g.print(qnh, 2); u8g.print(")");              // 海面気圧 QNH
}
 気圧計と液晶モジュールでSPIのモードが違っていると修正が難しくなった可能性がありますが、運よくそんなことしないでも動きました。

 このまま箱に入れて外に持ち出してちょっと使ってみると、文字が大きいので読みやすくて結構使える感じです。カラー液晶にすると消費電流が大きくなっちゃって使いにくくなる可能性もあります。そこで、これはこのままコンパクトな物に仕上げてしまうのもいいような気がしてきました。

 考えてるより手を動かせ、ってことですね。
関連記事

コメントの投稿

管理者にだけ表示を許可する

カレンダー
09 | 2017/10 | 11
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 - - - -
プロフィール

ラジオペンチ

Author:ラジオペンチ
電子工作を中心としたブログです。たまに近所(東京都稲城市)の話題など。60過ぎて視力や器用さの衰えを感じつつ日々挑戦!
コメントを入れる時にメールアドレスの記入は不要です。なお、非公開コメントは受け付けていません。

記事が気に入ったらクリックを!
最新記事
カテゴリ
最新コメント
リンク
FC2カウンター
検索フォーム
月別アーカイブ
RSSリンクの表示
QRコード
QRコード