Arduino MKR WiFi 1010をデータ入力に使う⑫SPI白金測温抵抗体+MAX31865

 I2Cバスの転送は、デフォルト100kHzなので、比較的低速なデバイスに向いています。少し高速な通信が必要なセンサや表示器にはSPIバスが使われます。matlabでは用意されている関数はdeviceとwriteReadの二つだけで。deviceは最初の設定に使うものなので、読み書きはwriteReadの一つだけです。

 SPIは8ビット単位でデータがやり取りされます。読み書き時にはクロックが必須ですが、独自に用意されません。マスタが、データを送るときに自動的に発生します。また、マスタがデータをスレーブから受け取るときにも、マスタがクロックを発生しなければなりません。したがって、マスタは意味のないデータを送信します。ダミーデータと呼ばれることがあります。

温度デバイスMAX31865

 MAX31865は、白金測温抵抗体(RTD)専用の抵抗-ディジタル・コンバータです。

  • 抵抗値 PT100(100Ω)〜PT1000(1kΩ)
  • 接続  2、3、4線式のいずれにも対応
  • インターフェース SPI(ChipSelect、SCL、MISO、MOSI)

 ブレークアウト・ボードとPT100のセンサはアマゾンで入手しました。ボードはAdafruit製とよく似ています。

  HiLetgo PT100 MAX31865 Arduino用RTD温度熱電対センサーアンプモジュール

  uxcell PT100 RTD温度センサープローブ 3線ケーブル熱電対 ステンレス鋼 200cm(6.56ft)、2Bグレード

  Adafruit MAX31865 RTD PT100 or PT1000 Amplifier

SPI(Serial Peripheral Interface)の信号

  • ChipSelect CSと訳されることが多い。 Chip Enable(CE)、Slave Select(SS)と呼ばれることもある。1対nの接続のときは、スレーブごとマスタには独立したCSポートを用意する。
  • SCL Serial CLockはSCLKもしくはSCKと略されることも多い。1対nの接続のとき、スレーブ・デバイスは、この信号を共有する。
  • MOSI(Master Out Slave In)には、スレーブ・デバイスの入力をつなぐ。SDI、Din、SIという信号名が多い。スレーブ・デバイスにMOSIがある場合は、MOSIをつなぐ。1対nの接続のとき、スレーブ・デバイスは、この信号を共有する。
  • MISO(Master In Slave Out)には、スレーブ・デバイスの出力をつなぐ。SDO、Dout、SOという信号名が多い。スレーブ・デバイスにMISOがある場合は、MISOをつなぐ。1対nの接続のとき、スレーブ・デバイスは、この信号を共有する。

ボードの結線

 センサが白金抵抗なので、MAX31865との間を導線でつなぎます。白金の抵抗は100Ωと低いので、2本の導線の抵抗値の差が、温度の誤差に表れやすいです。導線の影響をキャンセルできるのが4線もしくは3線接続です。ここでは3線接続を利用します。

  • 2ピンのターミナルを連結して、ボードに挿し込んではんだ付けする
  • 8ピンのピンヘッダをはんだ付けする
  • シルク印刷「2/3Wire」のショート部分をはんだを盛ってショートする
  • シルク印刷「2 4 3」 ショート部分のはんだ吸い取り線ではんだを取り去る。2-4間がプリント版の銅配線でショートされているので、ナイフで削り取る。4と3をはんだを盛ってショートする
  • F+とRTD+にPT100の赤色のケーブルをそれぞれ接続する
  • F-にPT100の赤色でないケーブルを接続する
  • ピンヘッダVinをArduino MKR WiFi 1010のVccに、GND同士をつなぐ
  • ピンヘッダCLKをArduino MKR WiFi 1010のSCK(9)につなぐ
  • ピンヘッダSDOをArduino MKR WiFi 1010のMISO(10)につなぐ
  • ピンヘッダSDIをArduino MKR WiFi 1010のMOSI(8)につなぐ
  • ピンヘッダCSをArduino MKR WiFi 1010の(7)につなぐ

プログラム

 初期化部分です。モードは1です。MAX31865はモード1と3をサポートしています。SPIインターフェースの8割以上はモード0です。

 モードは、次の表の内容になっています。Clock Polarityは正論理(0)か負論理(1)のどちらのクロックを使うか、Clock Phaseは立ち上がりエッジ(0)か立ち下がりエッジ(1)でデータ確定かを決めます。

SPI Mode Clock Polarity Clock Phase
0 0 0
1 0 1
2 1 0
3 1 1

clear all
a = arduino('COM15', 'MKR1010', 'Libraries', 'SPI')
MAX31865 = device(a, 'SPIChipSelectPin', 'D7', 'SPIMode', 1, 'BitRate', 100000, 'BitOrder', 'msbfirst')

 データ転送速度は、数百kHzから数MHzまで変化させてもデータが化けるなどの問題はなさそうでした。MSBfirstはもっとも一般的です。

 実際のやり取りで、チップ・セレクトCS信号は、負論理です。Arduino IDEなどでは、プログラムで転送の始まる前にLowにし、終わったらHighに戻すようにします。matlabでは自動です。

データリード

 関数はwriteRead()しかありません。初期化時にインスタンスMAX31865を作りました。基本形は、

writeRead(MAX31865, [ 8ビット(一つもしくは複数)])

 最初はConfigurationレジスタの定義です。8ビットのレジスタです。

D7;VBIAS
 1 = ON
 0 = OFF
D6;Conversion mode
 1 = Auto
 0 = Normally off
D5;1-shot
 1 = 1-shot
 (auto-clear)
D4;3-wire
 1 = 3-wire RTD
 0 = 2-wire or 4-wire
D3-D2;Fault Detection
 Cycle Control
D1;Fault Status Clear
 1 = Clear
 (auto-clear)
D0;50/60Hz filter select
 1 = 50Hz
 0 = 60Hz

 VBIASはON、3-wireを使います。Fault Status Clearはクリヤします。ACハム・ノイズ除去のノッチ・フィルタは、関東なので50Hzにします。

 Configurationレジスタの書き込みアドレスは0x80です。

 そのあと、Fault Statusレジスタを読み出していますが、電源ON直後は0です。特に意味はありません。

 0x55はダミーです。


Configuration_REGISTER_W = 0x80;
set_config = 0b11010011;  % 3wire autoconvertion 50Hzfilter
writeRead(MAX31865, [Configuration_REGISTER_W set_config])
pause(0.01);
Fault_Status_R = 0x07;
Fault_Status = writeRead(MAX31865, [Fault_Status_R 0x55])

 読み出すレジスタは上位8ビットRTD MSBsが0x01で、下位8ビットRTD LSBs が0x02です。連続しているので、0x01から2バイト読み出します。最後のLSBはFaultフラグになっているので、右に1シフトさせます。プログラムでは2で割っています。


RTDnominal = 100.0;
refResistor = 430.0;

for i= 1:10
    pause(0.1)
    RTD_Resistance_MSB = 0x01;
    dataH = writeRead(MAX31865, [RTD_Resistance_MSB 0x55 0x55]);
    RTD = bitshift(dataH(2), 8) + dataH(3);
    RTD = RTD / 2;
    Rrtd = RTD * refResistor / 32768;
    r = Rrtd;
    temp = -1.6030e-13 * r^6 + 2.0936e-10 * r^5 - 3.6239e-8 * r^4 ...
      - 4.2504e-6 * r^3 + 2.5646e-3 * r^2 + 2.2233 * r - 2.4204e2

    pause(0.5)

end

RTD Dataレジスタ値から温度への変換

 読み出したADCコード(RTD)から抵抗値Rrtdを計算します。Rrefは、PT100と直列に入っている抵抗の値です。ボード上には431と書かれていたので、430Ωです。

  Rrtd = (ADCコード x Rref) / 2^15

 抵抗値と温度の関係を示すグラフは適度な直線性を備えて
いますが、ある程度の曲率は存在し、Callendar-Van Dusenの式によって表されます。

  R(T) = R0 (1 + aT + bT^2 + c (T - 100)T^3)

  ( T = 温度(℃)、R(T) = Tにおける抵抗値、R0 = (T = 0℃)における抵抗値 )

 R(T)は前記のRrtdです。求めたい値はTですが、式を変形していっても解けないように思えます。

  RTD測定システム設計の基礎

に、エクセルでグラフを描き、零下という条件で、

t = -1.6030e-13 × r^6 + 2.0936e-10 × r^5 -3.6239e-8 × r^4 -4.2504e-6 × r^3 + 2.5646e-3 × r^2 + 2.2233 × r -2.4204e2

が導き出されているので使います。室温もこの近似式で使えるように思います。高温には適用できないかもしれないです。

 実行結果です。

前へ

Arduino MKR WiFi 1010をデータ入力に使う<番外編2>ShiftRegister

次へ

Arduino MKR WiFi 1010をデータ入力に使う⑬I2C 9軸IMU LSM9DS1