温湿度センサSHT31とLCD、BLEを搭載したボードが、デバイス・メーカ自身センシリオンから販売されています。Digi-KeyやMouserで購入できますが、送料を考慮し、マルツで入手しました。【SHT31-SMART-GADGET】Sensirion 温度 / 湿度センサ(3,140円)BLEモジュールには技適のマークが印刷されています。
データシートは同社のダウンロードセンターから入手できます。UUIDの構成は、GitHubにありました。
起動
ボード上にはCR2032電池があって、絶縁シートが挟まれているので抜きます。動き出します。タクト・スイッチをクリックすると表示が変わります。ダブルクリックすると、BLEが動き出しました。Bluetoothのアイコンが点滅している状態はアドバタイジングをしているようです。
見つける
clear
scan = blelist("Timeout", 20);
でscanします。10秒だと見つけられませんでした。
SHT31_address = "Smart Humigadget"
b = ble(SHT31_address);
bb = b.Characteristics;
scanの値を見ます。1個しかないのでnameでアクセスします。複数同時に使うならaddressでアクセスします。
bbの値を見ます。GitHubにあるUUIDの図と同じ情報が見れます。
読み出す温湿度データのサービスとキャラクトリスティックは次の四つのUUIDです。
SHT31_Humi_ServiceUUID = "00001234-B38D-4985-720E-0F993A68EE41" ;
SHT31_Temp_ServiceUUID = "00002234-B38D-4985-720E-0F993A68EE41" ;
bb18_CharacteristicUUID = "00001235-B38D-4985-720E-0F993A68EE41" ;
bb19_CharacteristicUUID = "00002235-B38D-4985-720E-0F993A68EE41" ;
温度と湿度を読み出す
データシートのロギングのところに値はfloat32と書かれています。固定小数点形式の4バイトです。matlabの関数を探すとhex2numが使えそうでしたが、だめでした。倍精度だけを対象としています。そこで、単精度用処理関数を作りました。
読み出したデータは10進なので2進に変更し、1バイト=8桁の文字列にします。リトルエンディアンなので、逆順で結合して32ビットの文字列を作ります。次の図は、単精度浮動小数点IEEE 754-2008のフォーマットです。
最上位ビットは符号です。次は指数です。22ビットから0ビットが仮数ですが、暗黙のビットが最上位にあるので、実際は24ビットです。
関数はhex2numSという名前にしました。matlabは、それまでシフトJISでしたが、2020バージョンからUTF-8になったそうです。コメントを日本語で書いても文字化けの心配はありません。
function shortF = hex2numS(decimal4)
data11 = num2str( dec2bin( decimal4(1),8 ));
data12 = num2str( dec2bin( decimal4(2),8 ));
data13 = num2str( dec2bin( decimal4(3),8 ));
data14 = num2str( dec2bin( decimal4(4),8 ));
data111 = strcat(data14,data13,data12,data11);
f = (-1)^str2num(data111(1)); % 符号
sisuu = data111(2:1:9);
kasuu = ("1"+data111(10:1:end));
k = bin2dec(kasuu)/(2^23) ; % 仮数
s = 2 ^ (bin2dec(sisuu) -127) ; % 指数
shortF = f * k * s;
end
参考資料;単精度浮動小数点数
IEEE単精度実数形式から10進数への変換
Pythonで浮動小数点数floatと16進数表現の文字列を相互に変換
Floating Point to Hex Converter
グラフを描く
全体のプログラム
clear
scan = blelist("Timeout", 20);
SHT31_address = "Smart Humigadget"
b = ble(SHT31_address);
% bb = b.Characteristics;
SHT31_Humi_ServiceUUID = "00001234-B38D-4985-720E-0F993A68EE41" ;
SHT31_Temp_ServiceUUID = "00002234-B38D-4985-720E-0F993A68EE41" ;
bb18_CharacteristicUUID = "00001235-B38D-4985-720E-0F993A68EE41" ;
bb19_CharacteristicUUID = "00002235-B38D-4985-720E-0F993A68EE41" ;
temperature = [];
humidity = [];
count = 20;
c18 = characteristic(b, SHT31_Humi_ServiceUUID, bb18_CharacteristicUUID);
c19 = characteristic(b, SHT31_Temp_ServiceUUID, bb19_CharacteristicUUID);
for i = 1:count
humidity(i) = hex2numS(read(c18));
temperature(i) = hex2numS(read(c19));
pause(1)
end
figure
x=[1:count];
yyaxis left
plot(x, temperature,'-o')
ylabel('Temp[C]')
yyaxis right
plot(x, humidity, '-x')
ylabel('Humi[RH]')
title('SHT31 temperature & humidity')
xlabel('x')
grid on
function shortF = hex2numS(decimal4)
data11 = num2str( dec2bin( decimal4(1),8 ));
data12 = num2str( dec2bin( decimal4(2),8 ));
data13 = num2str( dec2bin( decimal4(3),8 ));
data14 = num2str( dec2bin( decimal4(4),8 ));
data111 = strcat(data14,data13,data12,data11);
f = (-1)^str2num(data111(1)); % 符号
sisuu = data111(2:1:9);
kasuu = ("1"+data111(10:1:end));
k = bin2dec(kasuu)/(2^23) ; % 仮数
s = 2 ^ (bin2dec(sisuu) -127) ; % 指数
shortF = f * k * s;
end
20回の測定をしています。