Arduino MKR WiFi 1010をデータ入力に使う⑨I2C温湿度センサSHTC3
前回の温湿度センサHTS221は、ライブラリが入っていたので、すぐに使えました。Sensirionの温湿度センサSHT3Cは、Sensirionの温湿度センサSHT31などとほぼ同じに使えます。Adafruitのブレークアウト・ボードを入手しました。
SHTC3 | SHT31 | |
---|---|---|
電源電圧[V] | 1.62~3.6 | 2.15~5.5 |
消費電流[uA] | アイドル時45(typ)、測定時430(typ) | アイドル時0.2(typ)、測定時600(typ) |
湿度[%RH] | 確度±2、分解能0.01 | 確度±2、分解能0.01 |
温度[℃] | 確度±0.2(0~90)、分解能0.01 | 確度±0.2(0~60)、分解能0.01 |
外形[mm] | 2×2×0.75 | 2.5×2.5×0.9 |
ボードには、5V->3.3Vのレギュレータと3.3<->5V信号レベル変換回路が入っています。4ピンのコネクタ(I2C)でArduino MKR WiFi 1010と接続します。第4回の気圧センサLPS25HBの接続と同じです。
裏面に印刷してあるように、アドレスは0x70です。
●プログラム-step1
このデバイスは、電源が入ったのちスリープします。プログラムの最初に起こします。
I2CのクロックSCLをLowにしたまま時間を稼ぐクロック・ストレッチを利用できますが、ここでは、配線の距離が短いので使いません。送られるデータを、湿度、温度の順にするコマンドが0x58E0です。
readで6バイト読んできます。最初の2バイトが湿度データで、そのCRCが3バイト目に入っています。次の2バイトが温度で、そのCRCが6バイト目に入っています。
とりあえず、CRCは無視します。データシートに書かれている換算式で、湿度と温度を得ます。
clear all
a = arduino('COM15', 'MKR1010', 'Libraries', 'I2C');
shtc3 = device(a, 'I2CAddress', 0x70);
wakeup = [0x35,0x17];
write(shtc3, wakeup, 'uint8');
Measurement_H = [0x58,0xE0]; % no clockstretch,Humi first read
write(shtc3, Measurement_H, 'uint8');
rdata = read(shtc3, 6, 'uint8')
sleep = [0xB0,0x98];
write(shtc3, sleep, 'uint8');
humi = double(bitshift(uint16(rdata(1)), 8)) + double(rdata(2));
RH = 100 * humi / 65535
tempT = double(bitshift(uint16(rdata(4)), 8)) + double(rdata(5));
temperature = -45 + tempT * 175 / 65535
実行結果です。
●プログラム-step2
CRCの計算をして、測定値と比較します。
CRCの計算は関数にしました。
clear all
a = arduino('COM15', 'MKR1010', 'Libraries', 'I2C');
shtc3 = device(a, 'I2CAddress', 0x70);
wakeup = [0x35,0x17];
write(shtc3, wakeup, 'uint8');
Measurement_H = [0x58,0xE0]; % no clockstretch,Humi first read
write(shtc3, Measurement_H, 'uint8');
rdata = read(shtc3, 6, 'uint8');
sleep = [0xB0,0x98];
write(shtc3, sleep, 'uint8');
humi = double(bitshift(uint16(rdata(1)), 8)) + double(rdata(2));
RH = 100 * humi / 65535;
tempT = double(bitshift(uint16(rdata(4)), 8)) + double(rdata(5));
temperature = -45 + tempT * 175 / 65535;
fprintf(' humidity=%.1fRH readCRC= 0x%s 0x%s <-calcCRC' ...
, RH, dec2hex(rdata(3)), dec2hex(CRC8(humi)) );
fprintf(' temperature=%.2f`C readCRC= 0x%s 0x%s <-calcCRC' ...
, temperature, dec2hex(rdata(6)), dec2hex(CRC8(tempT)) );
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
Polynomial = 0x131;
initialConditions = 0xff00;
% init XOR
data = bitxor(inputData, initialConditions);
Polynomial = uint32(Polynomial);
% '0000000' zero padding input data
data = bitshift(uint32(data),8);
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'));
Polynomial = bitshift(Polynomial, length_data-length_Polynomial);
data = bitxor(data, Polynomial);
end
end
実行結果です。
CRCの計算で、ループを12回まわしていますが、終了条件の判断が甘く、余分にループが回り、まれに、計算を間違えることがあります。
●プログラム-step3
前回と同様にグラフを描きます。
プログラムです。readの前に100msの時間をおいています。Measurementトリガのすぐ後に読み出すとエラーが出る場合がありました。
clear all
a = arduino('COM15', 'MKR1010', 'Libraries', 'I2C');
shtc3 = device(a, 'I2CAddress', 0x70);
h = animatedline('MaximumNumPoints',20, 'Color', 'g', 'LineWidth', 2);
t = animatedline('MaximumNumPoints',20, 'Color', 'r', 'LineWidth', 2);
counter = 1:100;
RH = (counter);
temperature = (counter);
for k = counter
wakeup = [0x35,0x17];
write(shtc3, wakeup, 'uint8');
Measurement_H = [0x58,0xE0]; % no clockstretch,Humi first read
write(shtc3, Measurement_H, 'uint8');
pause(0.1)
rdata = read(shtc3, 6, 'uint8');
humi = double(bitshift(uint16(rdata(1)), 8)) + double(rdata(2));
RH(k) = 100 * humi / 65535;
addpoints(h, counter(k), RH(k));
tempT = double(bitshift(uint16(rdata(4)), 8)) + double(rdata(5));
temperature(k) = -45 + tempT * 175 / 65535;
addpoints(t, counter(k), temperature(k));
drawnow
pause(2);
sleep = [0xB0,0x98];
write(shtc3, sleep, 'uint8');
end