matlabでラズパイにつないだ温湿度センサSHT31からデータをもってくる

　[こちらの記事](https://qiita.com/jamjam/items/d67d06edbca8c03acccb)でも使っていましたが、Sensirionの温湿度センサSHT31をラズパイにつないで温度と湿度をもってきます。
　I2Cインターフェースは10～20cm以内で使うものだと認識していましたが、写真のように、長めのケーブルが付いた製品が、アマゾンで入手できます。農業用などとコマーシャル・トークが書かれていますが、このデバイスは、雷に打たれ強いとは思われません。筐体に入れた製品が屋外で使う製品はたくさん市販されています。ケーブルを延長して利用するやり方には不安が残ります。
![IMG_4827.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/e89ccebd-c89c-8a18-a0c8-0abf48b5ddff.png)

###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)](https://www.amazon.co.jp/gp/product/B07WPJC2RW/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1)

###接続
　ケーブルの先はオスだったので、切り取り、メスのジャンパ・ケーブルを取り付けました。

| 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を算出した様子です。
![スクリーンショット 2020-10-31 15.27.34aa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/8dd58396-b035-c95e-d58f-1cd7c6ef5e47.png)

###まずスレーブ・アドレスを知る

```matlab
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でした。

```matlab
sht31D = i2cdev(rpi, 'i2c-1', '0x44');
```

　データシートの「表9 周期的連続測定コマンド」に書かれている設定コマンドを送ります。送るデータによっては、期待しないデータが送られてくる場合があります。ここでは、

- 測定頻度[mps] （測定回数/秒）が4：0x23
- 繰返し精度レベル　高い：0x34

```matlab
Ctrl_OUT = [0x23,0x34]; 
write(sht31D, Ctrl_OUT, 'uint8');
pause(0.5);
```

###本体です
　10回繰り返しました。

```matlab
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関数です

```matlab
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
```

　実行例です。不一致だったら、再度読み込むという使いかただと思います。
![スクリーンショット 2020-10-31 16.33.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/ed4c308c-ef60-8125-4984-796370752308.png)




###CRC　参考にしたところ
>[CRC（Cyclic Redundancy Check）の初期値とかシフト方向とか出力とか](https://taekwongineer.hatenablog.jp/entry/2020/03/25/233948)
>[Cyclic Redundancy Check(CRC)を理解する](https://qiita.com/tobira-code/items/dbcffc41f54201130b6c)
>[CRC8 ATMの計算方法](https://okwave.jp/qa/q8815769.html)
>[2.CRC(巡回冗長検査・巡回冗長符号)](http://zeropaso.gozaru.jp/snetw1gai2.html)
>[CRC（巡回冗長検査）で適正なデータ通信を実現](https://www.analog.com/jp/analog-dialogue/articles/cyclic-redundancy-and-correct-data-communications.html)