MPL115A1をMicroPythonで動かしてみた

# 秋月の気圧センサ：MPL115A1　

[秋月電子で売ってるSPIインターフェースの気圧センサ：MPL115A1](https://akizukidenshi.com/catalog/g/gI-06078/)を[MicroPython](https://micropython.org)で動かすコードを書いたので，そのメモ． 

例によってMicroPythonの実行プラットフォームには[MIMXRT1050-EVKB](https://www.nxp.com/design/development-boards/i-mx-evaluation-and-development-boards/i-mx-rt1050-evaluation-kit:MIMXRT1050-EVK)を使っている（あとで[ラズピコ](https://www.raspberrypi.com/products/raspberry-pi-pico/)にも対応したので，それも追記した）．SPIインスタンスの宣言部を変更すれば他のマイコン基板でも動作するはず． 

# 最初のコード 

最初に書いたコードは[こちら](https://gist.github.com/teddokano/f818574be715d03355dde5725eff0d35)． 
とりあえずデータを読んできて，必要な計算を行い，結果を表示する．計算は[データシート](https://www.nxp.com/docs/en/data-sheet/MPL115A1.pdf)の8.2節に記載の通り．

コードを書いて実験したら値が安定しない．秋月の説明書を見たら，pin2のCAPピンに1uFのコンデンサをつけろと書いてある．[データシート](https://www.nxp.com/docs/en/data-sheet/MPL115A1.pdf)を見ると「1uFのセラミック・コンデンサ」と書いてある．きっとこれが無いせいなんだろう．次に会社に行く時のついでに秋葉原で買ってこようと考えて，しばらく放置していた． 

やっとコンデンサを調達して，再度動かしてみる．値はそれなりに安定してるのだけど妙に低い．で，コードをよーく見てみると，[30行目](https://gist.github.com/teddokano/f818574be715d03355dde5725eff0d35#file-simple_mpl115a1s-py-L30)の代入の変数の順番が逆だった (^^; 変更したら，それっぽいものになった． 
Pythonは関数から複数の値を返すことができて便利だけど，こういうワナがあるのね．

```python 
p_adc, t_adc = pressure_temp( data ) # 訂正したコード
```

コンデンサはモジュールの基板に直付けしたので，この写真のような感じになってる．よーくみると，モジュールの2番3番ピンの間に，青い部品が載ってるのがわかる． 
（このモジュールは8ピンの小さいモジュール．マイコン基板のArduinoシールド・ソケットに接続するために，ブレッドボードを搭載したシールド基板をアダプタとして使っている．）
![mpl115a1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288603/5c3629a2-6402-016d-5ffa-a375865091fe.jpeg)

# 書き直したコード 

その後，上記のコードをもう少し使いやすいように描き直したのが[こちら](https://gist.github.com/teddokano/e1baaa01c05db6e7c5076ab738cace3c/24b204642f13d38d8a2af75c4547ed035618ad27)．デバイスをクラス化して再利用しやすくしてみた．これを使って気圧を読むだけなら，こんな感じで書くことができる．

さらに自分で使いやすいように変更した最終的なコードは[こちら](https://gist.github.com/teddokano/e1baaa01c05db6e7c5076ab738cace3c)．ローカルファイルにログを，あとで処理しやすいように日時のフォーマットなどを変更した．


```python
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ピン制御を追加した．

```python
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から直接，現在時間を得ることができるので下のようなコードが使える．  
```python
# MIMXRT1050-EVKB
rtc	= RTC()
print( rtc.now() )
```
しかしラズピコのRTCには`RTC.now()`メソッドが用意されておらず，代わりに同等であるはずの`RTC.datetime()`を呼んでみても，現在時間は返ってこない． 
これはどうしたものかと[調べてみた](https://blog.goo.ne.jp/jh7ubc/e/645e80166ed8543059efea0e9c228949)ら... RTCのインスタンスにアクセスするのではなくて`utime.localtime()`で得ることができるらしい．ていうか，そもそもこうするものだったのか.. (^^;

# ローカル・ファイルにログを残す

当初は日時データはPython内のタプル表現のままにしていたのだけど，データを処理しやすい形で出すようにした． 
それから同じ文字列を基板上のローカル・ファイルとして保存もするようにしておいた．
```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分毎に起きてデータを取っていたみたいだ．
![measured_data_20230603.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288603/ef61dbc3-9013-5889-a0e4-0f04f0a6d39c.png)
この日の正午の天気図はこんな感じ．
![SPAS_COLOR_202306030300.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288603/ec9dbf75-c9ff-971d-ed56-7337f127b66f.png)
https://www.data.jma.go.jp/fcd/yoho/wxchart/quickdaily.html?show=20230603

グラフにするには，表示されたデータをコピペしたり，ローカルに保存されたデータを拾ってきて表計算ゾフとなどで処理すればグラフが得られる．

上記のグラフ作成には[gnuplot](http://www.gnuplot.info)を使った．
以下のファイルを保存しておいて，`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
```