秋月の気圧センサ:MPL115A1
秋月電子で売ってるSPIインターフェースの気圧センサ:MPL115A1をMicroPythonで動かすコードを書いたので,そのメモ.
例によってMicroPythonの実行プラットフォームにはMIMXRT1050-EVKBを使っている(あとでラズピコにも対応したので,それも追記した).SPIインスタンスの宣言部を変更すれば他のマイコン基板でも動作するはず.
最初のコード
最初に書いたコードはこちら.
とりあえずデータを読んできて,必要な計算を行い,結果を表示する.計算はデータシートの8.2節に記載の通り.
コードを書いて実験したら値が安定しない.秋月の説明書を見たら,pin2のCAPピンに1uFのコンデンサをつけろと書いてある.データシートを見ると「1uFのセラミック・コンデンサ」と書いてある.きっとこれが無いせいなんだろう.次に会社に行く時のついでに秋葉原で買ってこようと考えて,しばらく放置していた.
やっとコンデンサを調達して,再度動かしてみる.値はそれなりに安定してるのだけど妙に低い.で,コードをよーく見てみると,30行目の代入の変数の順番が逆だった (^^; 変更したら,それっぽいものになった.
Pythonは関数から複数の値を返すことができて便利だけど,こういうワナがあるのね.
p_adc, t_adc = pressure_temp( data ) # 訂正したコード
コンデンサはモジュールの基板に直付けしたので,この写真のような感じになってる.よーくみると,モジュールの2番3番ピンの間に,青い部品が載ってるのがわかる.
(このモジュールは8ピンの小さいモジュール.マイコン基板のArduinoシールド・ソケットに接続するために,ブレッドボードを搭載したシールド基板をアダプタとして使っている.)
書き直したコード
その後,上記のコードをもう少し使いやすいように描き直したのがこちら.デバイスをクラス化して再利用しやすくしてみた.これを使って気圧を読むだけなら,こんな感じで書くことができる.
さらに自分で使いやすいように変更した最終的なコードはこちら.ローカルファイルにログを,あとで処理しやすいように日時のフォーマットなどを変更した.
spi = SPI( 0, 1000 * 1000, cs = 0 )
sensor = MPL115A1( spi )
pressure = sensor.pressure()
print( pressure )
しかし.. 測定結果を見てみるとノイズが多いみたい.データを繰り返し読んで,それを平均化してみる.ちょっと多過ぎるかもしれないけど,とりあえず1000回読んで,それの平均を表示するようにしてある.そうするとなんとかそれっぽい感じになった.
MPL115A1では一回の気圧測定を行うため,まず測定開始コマンドの後に3ms待ってからデータを読み出すようにしなければならない.なので1000回の測定結果を平均して1つの値を得るようにすると,それを得るために「3ms * 1000」の待ち時間に加えて,読み出しと計算の時間がかかることになる.
まぁ通常の気圧変化はそんなに急に起こるものでは無いから,これでもOKかな?
これに加えて,変化を記録するために日時情報も一緒に表示するようにした.RTCから得た情報を同じ行に書き出す.書き出すフォーマットはCSV.
ラズピコでも動かしてみる
MIMXRT1050-EVKBで動作したので,ラズピコでも動作を確認してみた.SPIインターフェースをラズピコのpin14~pin17(GPIOの10~13:それぞれSCLK,MOSI,MISO,CS)で使うようにして接続.
次のようなコードも追加して,MCU基板を自動認識してSPIを切り替えるようにした.
またMPL115A1クラスにも手を加えて,ラズピコの場合はChipSelectピン制御を追加した.
import os
...
if "MIMXRT" in os.uname().machine:
spi = SPI( 0, SPI_FREQ, cs = 0 )
sensor = MPL115A1( spi, None )
elif "Raspberry Pi Pico" in os.uname().machine:
spi = SPI( 1, SPI_FREQ, sck = Pin( 10 ), mosi = Pin( 11 ), miso = Pin( 12 ) )
sensor = MPL115A1( spi, Pin( 13, Pin.OUT ) )
さらにここに落とし穴があった.
MIMXRT1050-EVKBならRTCから直接,現在時間を得ることができるので下のようなコードが使える.
# MIMXRT1050-EVKB
rtc = RTC()
print( rtc.now() )
しかしラズピコのRTCにはRTC.now()
メソッドが用意されておらず,代わりに同等であるはずのRTC.datetime()
を呼んでみても,現在時間は返ってこない.
これはどうしたものかと調べてみたら... RTCのインスタンスにアクセスするのではなくてutime.localtime()
で得ることができるらしい.ていうか,そもそもこうするものだったのか.. (^^;
ローカル・ファイルにログを残す
当初は日時データはPython内のタプル表現のままにしていたのだけど,データを処理しやすい形で出すようにした.
それから同じ文字列を基板上のローカル・ファイルとして保存もするようにしておいた.
dt = localtime()
p_str = "{:04d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}, {}".format( dt[ 0 ], dt[ 1 ], dt[ 2 ], dt[ 3 ], dt[ 4 ], dt[ 5 ], p / DEPTH * 10 )
print( p_str )
with open( "data.csv", "a" ) as f:
print( p_str, file = f )
グラフ
このコードで実際に取得してみたグラフがこれ.
測定した場所は埼玉県北部.標高は約100mある.この2023年6月3日は太平洋を台風2号が進んでいて,午前中は大雨.昼からはカラッと晴れて北寄りの強風.次の日の午後までの気圧の変化を取ってみた.いい感じに取れたっぽい.普段使ってるGarminの腕時計の気圧変化グラフもだいたいこんな感じになってたし.
ちなみにデータを取ったのはMIMXRT1050-EVKBの基板で,このときはまだラズピコ対応やローカル・ファイル保存に対応してなかったので,表示したデータをコピペして処理した.コンピュータが寝てる状態の時は,その上で動いているアプリケーションは15分毎に起きてデータを取っていたみたいだ.
この日の正午の天気図はこんな感じ.
https://www.data.jma.go.jp/fcd/yoho/wxchart/quickdaily.html?show=20230603
グラフにするには,表示されたデータをコピペしたり,ローカルに保存されたデータを拾ってきて表計算ゾフとなどで処理すればグラフが得られる.
上記のグラフ作成にはgnuplotを使った.
以下のファイルを保存しておいて,gnuplot <ファイル名>
のように実行させるとtest_png.png
という名の画像ファイルができる.それがさっきのグラフ.
set datafile separator ","
set xdata time
set timefmt "%Y-%m-%d %H:%M:%S"
#set format x "%y-%m-%d %H:%M:%S"
set xlabel "date&time"
set ylabel "Atmospheric pressure [hPa]"
set terminal png
set output 'test_png.png'
plot 'data.csv' using 1:2 w l