おやじに頼まれてた気圧計つくった。
おやじは気圧計を持っているのですが校正されていないアナログ気圧計だったので、校正されている絶対気圧が測れるものが欲しかったらしく、ぼくに製作を依頼してきました。
Digi-Keyにちょうど部品を注文する予定があったのでついでに気圧が測れる半導体センサも注文しました。
freescaleという会社のMPL115A2という気圧センサなのですが、なんと1個199円でした。
スペックをみたところ校正値が内部にプリセットしてあり500~1150hPaの検出範囲を持ち精度は±10hPaでI2Cインタフェースのデジタル出力。
問題なのはLGAパッケージとサイズが小さくて製作するのが難しい点です。本当はリフローはんだとかすべきなのでしょうが、裏面のパッドになんとかポリウレタン線を半田づけして信号線を引き出すことができました。
製作して実際に気圧を表示させたところ973ヘクトパスカルという数値が出ました。
973ヘクトパスカルというと台風並みの低気圧ですが、ぼくの家は高地に位置しているため(といっても標高250m程度)1気圧地点と比べると妥当だそうです。
![とんすけぶろぐ](https://stat.ameba.jp/user_images/20110612/10/tonsuke-usagi/78/0c/j/o0520038011285576899.jpg?caw=800)
スイッチを押すとLCDの右側に気圧(hPa)、左には高度(メートル)を表示します。
10秒経ったらスリープに入り、またスイッチを押すと復帰して上を繰り返します。
ホームセンターに売ってたカードホルダーのケースに組込み裏から白スプレーで塗装しました。
![とんすけぶろぐ](https://stat.ameba.jp/user_images/20110612/10/tonsuke-usagi/ad/d4/j/o0520043911285577432.jpg?caw=800)
右から気圧センサMPL115A2、ATtiny85、P-MOSFETと下は3.3V DC/DCコンバータ(HT7733A)です。
気圧センサはI2Cインターフェースで、LGAパッケージでしたが底面のパッドからポリウレタン線で引き出せました。
LCDはストロベリーリナックスで購入したI2Cタイプの小型液晶です。
同一バス上の2つのデバイスをATtiny85からソフトウェアI2Cで制御してます。
![とんすけぶろぐ](https://stat.ameba.jp/user_images/20110612/10/tonsuke-usagi/15/34/j/o0520049311285576901.jpg?caw=800)
単4電池1本駆動としました。
スリープ時はFETで気圧センサとLCDを電気的にオフする仕組みにしているのでとても消費電力が少ないです。
通常動作時約12mA、スリープ状態で約15μAとなりました。(ほとんどがDC/DCコンバータ HT7733Aの消費電流です。スリープ状態だと電池入れっぱなしで5年程度持つ計算)
気圧データの求め方
気圧データを読み出すのはさほど難しくありませんが、校正値から計算して正しく出力するのは少し面倒です。
hPaの読みは以下の式で求まります。
Pcomp = ao + (b1 + c11*Padc + c12*Tadc) * Padc + (b2 + c22*Tadc) * Tadc
decPcomp = {(65/1023) * Pcomp + 50} * 10
読み出したデータは下のようになりました。
ここからデータシートと照らし合わせて手計算で最終的な気圧データを求めてみます。
Padc(気圧データ アドレス0, 1)
有効ビット数は10ビット。
下位にはゼロがパディングされているので0x5340を6ビット右シフトした値。(1/64倍)
よってPadc = 333
Tadc(温度データ アドレス2, 3)
Padcと同じく有効ビット数は10ビット。
下位にはゼロがパディングされているので0x8080を6ビット右シフトした値。(1/64倍)
よってTadc = 514
a0(係数 アドレス4, 5)
有効ビット数は16。
符号ビット1 整数ビット12 小数ビット3
0x3ACD = 0011 1010 1100 1101
a0 = 11101011001.101 = 1881.625
b1(係数 アドレス6, 7)
有効ビット数は16。
符号ビット1 整数ビット2 小数ビット13
0xBADD = 1011 1010 1101 1101
符号ビットが1なので負数。
2の補数表記なので10進数になおすと、(ビットを反転させて1加える)
1011 1010 1101 1101
↓
0100 0101 0010 0011
b1 = -10.0010100100011 = -2.16052246
b2(係数 アドレス8, 9)
有効ビット数は16。
符号ビット1 整数ビット1 小数ビット14
0xBB79 = 1011 1011 0111 1001
符号ビットが1なので負数。
2の補数表記なので10進数になおすと、(ビットを反転させて1加える)
1011 1011 0111 1001
↓
0100 0100 1000 0111
b2 = -1.00010010000111 = -1.070739746
c12(係数 アドレスa, b)
有効ビット数は14。
符号ビット1 整数ビット0 小数ビット13 小数点ゼロパッド9
0x3328 = 0000 0000 0001 1001 1001 0100 0
c12 = 0.000000000011001100101 = 0.000780582
c11(係数 アドレスc, d)
c11 = 0
c22(係数 アドレスe, f)
c22 = 0
以上のデータからPcompを計算すると、
Pcomp = 1881.625 + (-2.16052246 + 0 * 333 + 0.000780582 * 514) * 333
+ (-1.070739746 + 0 * 514) * 514 ≒ 745
ヘクトパスカル(hPa)の読みになおすと、
decPcomp = {(65/1023) * 745 + 50} * 10 = 973[hPa]
というふうに手計算で求めるのは結構大変ですね(^_^;A
プログラムはアプリケーションノート(http://strawberry-linux.com/pub/AN3785.pdf)からマイコンに組込みました。
アプリケーションノートのプログラム例では浮動小数計算を使用していないので512B SRAMのATtiny85でも十分使えました。
訂正箇所が一カ所あります。プログラムの最後のほうでシフトとキャストの仕方の順番が違ってます。
誤)
// FIXED POINT RESULT WITH ROUNDING:
siPcomp = ((S16)lt3>>13); // goes to no fractional parts since this is an ADC count.
正)
// FIXED POINT RESULT WITH ROUNDING:
siPcomp = (S16)(lt3>>13); // goes to no fractional parts since this is an ADC count.
おやじは気圧計を持っているのですが校正されていないアナログ気圧計だったので、校正されている絶対気圧が測れるものが欲しかったらしく、ぼくに製作を依頼してきました。
Digi-Keyにちょうど部品を注文する予定があったのでついでに気圧が測れる半導体センサも注文しました。
freescaleという会社のMPL115A2という気圧センサなのですが、なんと1個199円でした。
スペックをみたところ校正値が内部にプリセットしてあり500~1150hPaの検出範囲を持ち精度は±10hPaでI2Cインタフェースのデジタル出力。
問題なのはLGAパッケージとサイズが小さくて製作するのが難しい点です。本当はリフローはんだとかすべきなのでしょうが、裏面のパッドになんとかポリウレタン線を半田づけして信号線を引き出すことができました。
製作して実際に気圧を表示させたところ973ヘクトパスカルという数値が出ました。
973ヘクトパスカルというと台風並みの低気圧ですが、ぼくの家は高地に位置しているため(といっても標高250m程度)1気圧地点と比べると妥当だそうです。
![とんすけぶろぐ](https://stat.ameba.jp/user_images/20110612/10/tonsuke-usagi/78/0c/j/o0520038011285576899.jpg?caw=800)
スイッチを押すとLCDの右側に気圧(hPa)、左には高度(メートル)を表示します。
10秒経ったらスリープに入り、またスイッチを押すと復帰して上を繰り返します。
ホームセンターに売ってたカードホルダーのケースに組込み裏から白スプレーで塗装しました。
![とんすけぶろぐ](https://stat.ameba.jp/user_images/20110612/10/tonsuke-usagi/ad/d4/j/o0520043911285577432.jpg?caw=800)
右から気圧センサMPL115A2、ATtiny85、P-MOSFETと下は3.3V DC/DCコンバータ(HT7733A)です。
気圧センサはI2Cインターフェースで、LGAパッケージでしたが底面のパッドからポリウレタン線で引き出せました。
LCDはストロベリーリナックスで購入したI2Cタイプの小型液晶です。
同一バス上の2つのデバイスをATtiny85からソフトウェアI2Cで制御してます。
![とんすけぶろぐ](https://stat.ameba.jp/user_images/20110612/10/tonsuke-usagi/15/34/j/o0520049311285576901.jpg?caw=800)
単4電池1本駆動としました。
スリープ時はFETで気圧センサとLCDを電気的にオフする仕組みにしているのでとても消費電力が少ないです。
通常動作時約12mA、スリープ状態で約15μAとなりました。(ほとんどがDC/DCコンバータ HT7733Aの消費電流です。スリープ状態だと電池入れっぱなしで5年程度持つ計算)
気圧データの求め方
気圧データを読み出すのはさほど難しくありませんが、校正値から計算して正しく出力するのは少し面倒です。
hPaの読みは以下の式で求まります。
Pcomp = ao + (b1 + c11*Padc + c12*Tadc) * Padc + (b2 + c22*Tadc) * Tadc
decPcomp = {(65/1023) * Pcomp + 50} * 10
読み出したデータは下のようになりました。
アドレス | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f |
データ | 53 | 40 | 80 | 80 | 3A | CD | BA | DD | BB | 79 | 33 | 28 | 00 | 00 | 00 | 00 |
ここからデータシートと照らし合わせて手計算で最終的な気圧データを求めてみます。
Padc(気圧データ アドレス0, 1)
有効ビット数は10ビット。
下位にはゼロがパディングされているので0x5340を6ビット右シフトした値。(1/64倍)
よってPadc = 333
Tadc(温度データ アドレス2, 3)
Padcと同じく有効ビット数は10ビット。
下位にはゼロがパディングされているので0x8080を6ビット右シフトした値。(1/64倍)
よってTadc = 514
a0(係数 アドレス4, 5)
有効ビット数は16。
符号ビット1 整数ビット12 小数ビット3
0x3ACD = 0011 1010 1100 1101
a0 = 11101011001.101 = 1881.625
b1(係数 アドレス6, 7)
有効ビット数は16。
符号ビット1 整数ビット2 小数ビット13
0xBADD = 1011 1010 1101 1101
符号ビットが1なので負数。
2の補数表記なので10進数になおすと、(ビットを反転させて1加える)
1011 1010 1101 1101
↓
0100 0101 0010 0011
b1 = -10.0010100100011 = -2.16052246
b2(係数 アドレス8, 9)
有効ビット数は16。
符号ビット1 整数ビット1 小数ビット14
0xBB79 = 1011 1011 0111 1001
符号ビットが1なので負数。
2の補数表記なので10進数になおすと、(ビットを反転させて1加える)
1011 1011 0111 1001
↓
0100 0100 1000 0111
b2 = -1.00010010000111 = -1.070739746
c12(係数 アドレスa, b)
有効ビット数は14。
符号ビット1 整数ビット0 小数ビット13 小数点ゼロパッド9
0x3328 = 0000 0000 0001 1001 1001 0100 0
c12 = 0.000000000011001100101 = 0.000780582
c11(係数 アドレスc, d)
c11 = 0
c22(係数 アドレスe, f)
c22 = 0
以上のデータからPcompを計算すると、
Pcomp = 1881.625 + (-2.16052246 + 0 * 333 + 0.000780582 * 514) * 333
+ (-1.070739746 + 0 * 514) * 514 ≒ 745
ヘクトパスカル(hPa)の読みになおすと、
decPcomp = {(65/1023) * 745 + 50} * 10 = 973[hPa]
というふうに手計算で求めるのは結構大変ですね(^_^;A
プログラムはアプリケーションノート(http://strawberry-linux.com/pub/AN3785.pdf)からマイコンに組込みました。
アプリケーションノートのプログラム例では浮動小数計算を使用していないので512B SRAMのATtiny85でも十分使えました。
訂正箇所が一カ所あります。プログラムの最後のほうでシフトとキャストの仕方の順番が違ってます。
誤)
// FIXED POINT RESULT WITH ROUNDING:
siPcomp = ((S16)lt3>>13); // goes to no fractional parts since this is an ADC count.
正)
// FIXED POINT RESULT WITH ROUNDING:
siPcomp = (S16)(lt3>>13); // goes to no fractional parts since this is an ADC count.