温度、湿度、気圧、などいろいろな物理情報を得るにはセンサを使います。多くの事象はゆっくり変化するので、データの転送は急ぎません。センサICの多くはI2CもしくはSPIです。I2Cと言っても、メーカによってレジスタなどの構成が異なり、簡単にデータを読み出せないこともあります。
気圧センサは、その昔、10個近い補正データを生で出力してきたので、受け取るデータの項目も多く、演算も簡単に処理できませんでした(5ドル!ラズパイ・ゼロ(Raspberry pi Zero)でIoT (40) 気圧センサ2 SPI MPL115A1)。
ボッシュのBME280(SpresenseでLチカから始める (24) Wireライブラリ 温度気圧BMP280)などは、補正データも少なくなり、扱いやすくなりました。ここで使用するSTマイクロのLPS25は、24ビット・データを読み出したら、4096で割るだけで、hPaの気圧データが得られます。
気圧センサLPS25HBの特徴
ICは手はんだしずらい形状なので、秋月電子通商からブレークアウト・ボードを入手しました。

- 動作電圧 3.3V(デバイスは1.7~3.6 V)
- 消費電流 約2mA(LED分を含む。ハイレゾ、1Hz測定間隔時25uA)
- 測定範囲 260~1260hPa
- 確度 ±0.1hPa(25℃)、±1hPa(0~80℃)
- インターフェース SPI、I2C。I2C用プルアップ抵抗は実装、デフォルトは切り離し
ボードのAE-LPS25HB取扱説明書から、CS(5ピン)を VDD に接続してI2Cを利用します。SA0(4 ピン)をVddにつなぎ、スレーブ・アドレスを0x5dにします。
マイコンはMKRZero
matlabのアドオンMATLAB Support Package for Arduino Hardware(無償で使える)は、Matalbを起動しているときに、ArduinoをUSBケーブルで挿したら検出され、メッセージの通りにインストールします。
情報は、アドオンマネージャの管理を立ち上げ、MATLAB Support Package for Arduino Hardwareのドキュメンテーションをクリックします。
Examplesのタブが見えています。Functionsのタブに、利用できる関数一覧があります。
MKRZeroは、Cortex-M0(アトメルSAMD21)を搭載した幅の狭いMKRシリーズの一つで、無線の機能がありません。Arduino UNOより価格は安いです。メモリも比較的多いので、利用上のストレスは少ないです。
R2019bからサポートされています。Wi-FiやBLEが使えるモデルはありますが、現時点で、無線はサポートされていないようです。BLEは、別途BLEボードをシリアル(UART)でつなぐ方法のようです。
現在コスト・パフォーマンスがよいので利用が多いESP32ボードもサポートされていないようです。
配線とプログラミングのスタート
先ほどのドキュメンテーションのExamplesから「I2C Devices — Examples」を選べばいいのですが、SPIを選んでしまいました。そのまま進めます。それぞれのExamplesの右下のOpen Live Scriptをクリックすると、ライブエディタが開きます。
AE-LPS25HBボードの裏側で、I2C信号のプルアップ抵抗を有効にするため、J1、J2のランドをはんだをもってショートします。AE-LPS25HBボードの1ピンVDDをMKRZeroのVCCへ、8ピンGNDはGNDへ、2ピンSCLはSCLへ、3ピンSDAはSDAへつなぎます。合計4本です。
初期設定部分です。
clear all
a = arduino('COM10', 'MKRZero', 'Libraries', 'I2C');
LPS25 = device(a, 'I2CAddress', 0x5d, 'BitRate', 400000); % 4pin-Vcc
最近まで、パラメータは10進で渡す記述だったのですが、今は16進が直接書けます。
最初に、スリープしているので、0x20レジスタに0x90を書き込みます。
単純に気圧pressは、0x28レジスタから3バイトを読みますが、うまく読めません。GitHubにあるいろいろなソースを読むと、0x28 | 0x80で正しく読めるようです。
温度tempのデータは読み出した後の計算方法の説明が見当たりません。秋月の補足説明の計算式を利用しました。しかし、相当変な温度データを読み出します。
気圧から高度altitudeを求めていますが、基準となる海面の気圧、温度が大幅に変化することから、実用化は、もっと工夫しないといけないです。温度は急には変わりませんし、測定前に高度をリセットすれば、絶対的な高さの変化は求まります。分解能は24ビットなので、階段の段差も測定できるかもしれません。
countsは測定回数です。
data=のところは間違っています。グラフはこのままでは正しく描画できません。後で修正します。
data=[];
counts = 100;
writeRegister(LPS25, 0x20, 0x90, 'uint8')
pause(0.5);
for i=1:counts
PRESS_OUT = bitor(0x28, 0x80);
write(LPS25, PRESS_OUT, 'uint8')
RegisterData = read(LPS25, 3, 'uint8');
% fprintf('\nread data is %d \n', RegisterData);
press = (double(bitshift(RegisterData(3), 16)) + double(bitshift(RegisterData(2), 8)) + double(RegisterData(1))) / 4096;
% fprintf('\nLPS25HB %.3f hPa ', press);
TEMP_OUT = 0x2b;
write(LPS25, TEMP_OUT, 'uint8')
RegisterDatat = read(LPS25, 2, 'uint8');
%fprintf(' read data is %d \n', RegisterDatat);
temp = (double(bitshift(RegisterDatat(2), 8)) + double(RegisterDatat(1)))/480 + 42.5;
%fprintf(' %.1f C ', temp);
altitude = ((power((1013.25 / press), (1 / 5.257)) - 1) * (temp + 273.15)) / 0.0065;
%fprintf(' %.3f m\n', altitude);
fprintf('\nLPS25HB %.3fhPa %.3fm %.1f C ', press, altitude, temp);
data = altitude;
pause(0.1);
end
グラフです。工夫してください。
x = linspace(1, counts, counts);
plot(x, data, '-o')
終了処理です。
clear a