こちらの記事でも使っていましたが、Sensirionの温湿度センサSHT31をラズパイにつないで温度と湿度をもってきます。
I2Cインターフェースは10~20cm以内で使うものだと認識していましたが、写真のように、長めのケーブルが付いた製品が、アマゾンで入手できます。農業用などとコマーシャル・トークが書かれていますが、このデバイスは、雷に打たれ強いとは思われません。筐体に入れた製品が屋外で使う製品はたくさん市販されています。ケーブルを延長して利用するやり方には不安が残ります。
SHT31のおもなスペック
- 電源電圧;2.4~5.5V
- インターフェース;I2C(最大データ転送速度1MHz)
- 温度;-40~+125℃(確度±0.2℃)、分解能0.015℃
- 相対湿度;0~100%(0~90℃時)、分解能0.01%
- データ・ビット長;16ビット
- スレーブ・アドレス;ADDRピンをプルアップで0x45、GNDへつなぐと0x44
アマゾンから入手しました。
防塵土壌デジタル温度湿度センサーステンレス鋼プラスチックハウジングI2C出力FS400-SHT3X高精度低消費(SHT31)
接続
ケーブルの先はオスだったので、切り取り、メスのジャンパ・ケーブルを取り付けました。
SHT31ケーブル | ラズパイ |
---|---|
赤色 | 3.3V 1番ピン |
黒色 | GND 9番ピン |
青色 | SDA 3番ピン |
黄色 | SCL 5番ピン |
CRCデータも送られてくる
設定用のコマンドを送るときには必要ありませんが、読み出したデータにはCRCのチェックサムがついています。無視してもかまいません。
matlabには、CRCを計算する新旧二つの関数がありますが、うまく使えませんでした。なので、XORによる手計算を模してプログラムを作りました。処理速度は気にしていません。
SHT31のデータシートによれば、初期値0xff、CRC-8の多項式はX^8+X^5+X^4+1、反射入力はfalse、反射出力はfalseなので、MSBfirstのデータです。最終XORは0x00なので、何もしません。この条件でプログラムを作りました。
動作確認は、http://www.sunshine2k.de/coding/javascript/crc/crc_js.html で行いました。次の画面は、データシートに載っている0xBEEFを入れて、CRCデータ0x92を算出した様子です。
まずスレーブ・アドレスを知る
clear all
rpi = raspi('192.168.111.114', 'pi', 'raspberry'); % host name raspberrypi-uMchsTIvew
for i = 1:length(rpi.AvailableI2CBuses)
scanI2CBus(rpi, rpi.AvailableI2CBuses{i})
end
0x44でした。
sht31D = i2cdev(rpi, 'i2c-1', '0x44');
データシートの「表9 周期的連続測定コマンド」に書かれている設定コマンドを送ります。送るデータによっては、期待しないデータが送られてくる場合があります。ここでは、
- 測定頻度[mps] (測定回数/秒)が4:0x23
- 繰返し精度レベル 高い:0x34
Ctrl_OUT = [0x23,0x34];
write(sht31D, Ctrl_OUT, 'uint8');
pause(0.5);
本体です
10回繰り返しました。
for i = 1:10
Ctrl_OUT = [0xe0, 0];
write(sht31D, Ctrl_OUT, 'uint8');
rdata = readRegister(sht31D, 0, 6); % 0=dummy
tempT = double(bitshift(uint16(rdata(1)), 8)) + double(rdata(2));
temperature = -45 + tempT * 175 / 65535;
humi = double(bitshift(uint16(rdata(4)), 8)) + double(rdata(5));
RH = 100 * humi / 65535;
fprintf(' temperature=%.2f`C readCRC= 0x%s 0x%s <-calcCRC', temperature, dec2hex(rdata(3)), dec2hex(CRC8(tempT)) );
fprintf(' humidity=%.1fRH readCRC= 0x%s 0x%s <-calcCRC', RH, dec2hex(rdata(6)), dec2hex(CRC8(humi)) );
pause(1);
end
CRC関数です
function [data] = CRC8(inputData)
% CRC-8 Dallas/Maxim/AnalogDevices
% x^8+X^5+X^4+1. X=2, Polynomial=0x131=[1 0 0 1 1 0 0 0 1]
% 初期化(InitialConditions)=0xff 反射入力(ReflectInputBytes)=false
% 反射出力(ReflectChecksums)=false 最終XOR(FinalXOR)=0x00
%
%inputData = 0xBEEF
Polynomial = 0x131;
initialConditions = 0xff00;
% init XOR
data = bitxor(inputData, initialConditions);
% fprintf('Get the xor of data and initialConditions %0s',dec2bin(data));
Polynomial = uint32(Polynomial);
% fprintf('CRC-8 Polynomial is %0s',dec2bin(Polynomial));
% '0000000' zero padding input data
data = bitshift(uint32(data),8);
% fprintf('zero padding(8) -> 24bit data %0s',dec2bin(data));
for i = 1:12
length_data = length(de2bi(data, 'left-msb'));
if length_data < 9 % 8ビット
break
end
length_Polynomial = length(de2bi(Polynomial, 'left-msb'));
% fprintf('zero padding input data %0s',dec2bin(data));
Polynomial = bitshift(Polynomial, length_data-length_Polynomial);
data = bitxor(data, Polynomial);
% fprintf('zero padding Polynomial %0s', dec2bin(Polynomial));
% fprintf('xor %0s 0x%x', dec2bin(data),data);
end
% fprintf('input=0x%x CRC=0x%x', inputData, data);
end
実行例です。不一致だったら、再度読み込むという使いかただと思います。
CRC 参考にしたところ
CRC(Cyclic Redundancy Check)の初期値とかシフト方向とか出力とか
Cyclic Redundancy Check(CRC)を理解する
CRC8 ATMの計算方法
2.CRC(巡回冗長検査・巡回冗長符号)
CRC(巡回冗長検査)で適正なデータ通信を実現