ディジタル値でK型熱電対の温度が簡単に読み出せる温度センサ・モジュールが入手できたので、Arduinoにつないでみました。モジュールの紹介と簡単な使い方を何回かに分けて説明します。また、複数モジュールの使用例やSDカードI/F併用例も解説します。
このモジュールは2013年2月に発売された書籍「Arduino実験キットで楽ちんマイコン開発」で少し紹介しているのですが、タイミング的にあまり詳細に書けなかったので、その補足もかねてここに掲載します。
●熱電対のディジタル測定モジュール
ここで紹介するのはスイッチサイエンス社から販売されている「K型熱電対温度センサモジュールキット」と言うものです。3.3V用と5V用の2種類が販売されていますが、今回は5Vのものを使います。2013年1月時点での価格は5V用のもので2980円です。熱電対コネクタとピンヘッダのみはんだ付けが必要な半完成品です。
キットにはK型熱電対付が付属しています。モジュール基板に専用コネクタが実装できるため、付属の熱電対が直接接続できます。ピンヘッダを付ければブレッドボードに直接実装できます。基板サイズは約20×34mm(コネクタ突起含まず)と小型です。
ディジタル接続、単電源で氷点下温度が測定できるため、手軽に低温から高温までの温度測定アプリケーションが製作できます。
この温度モジュールはコントローラにマキシム社のMAX31855というディジタル熱電対コンバータを使用しています。製品に取説類は付属していないため、MAX31855のデータシートにより簡単にまとめると次のような特長があります。詳細は同ICのデータシートを参照してください。
- 冷接点補償つき
- 分解能:14ビット(符号付き)、0.25℃
- -200℃~+700℃の温度範囲で±2℃の精度
●インターフェースはSPI
マイコンとのインターフェースはSPI接続なので、Arduinoの他、SPI機能があるマイコンなど、何にでも接続できます。SPIは制御が簡単なので、汎用のI/Oポートを使ってソフトウェアでも簡単に制御できます。
一般的なSPIデバイスと同様、複数の温度モジュールを並列接続してSS信号で切り替えれば、複数ポイントの測定なども可能です。またSDカードI/Fなども併用可能です。ただし、このモジュールはMISO信号をそのまま並列接続できないようなので、それについては後ほど並列接続の項で説明します。
●SPIデータモード
SPIのデータ・フォーマットには、クロック(SCK)が正論理か負論理か、また、入出力タイミングがクロックの立ち上がりエッジが立ち下がりエッジかで4通りの組み合わせ(モード)があります。
MAX31855は正論理クロック、立ち下がりエッジ・サンプリングのモード1で使用します。
なお、SDカードI/FもSPI接続ですが、Arduino標準のSDライブラリを使用する場合はモード0(Arduinoデフォルト)で通信するため、温度モジュールと併用する場合はアクセスの都度データモードの切り替えが必要です。切り替え方法などはSDカード併用のアプリの項で説明します。
●通信フォーマット
下図にSPI通信で温度モジュールから受信するデータのビット・フォーマットを示します。熱電対の温度が14ビット、基準接点の温度が12ビット(ともに符号ビット含む)、それにエラー状態などを示すビットが4ビット、リザーブビットの合計32ビットから構成されています。SPIで8ビットずつ受信する場合は4バイト受信ということになります。 目当ての熱電対温度はビット31~ビット18に格納されています。従って、エラーチェックや補正などが不要な簡易的な用途では先頭の2バイトだけSPIで受信して利用することもできます。
温度値は符号1ビット+数値データ13ビットの合計14ビット構成で、2の補数形式で格納されています。そのうち下位2ビットは小数点以下の数値です。また1ビットの重みは0.25℃となっています。
●温度値の取り出し
2の補数形式の数値は、符号ビットが”1″の負数のときは、全ビットを反転して1を加え、桁上がりを無視すれば数字部分を正数で得られます。今回は14ビットの内、下位2ビットは小数なので、正数化した後に整数部分(符号除く)が11ビット、小数部分2ビットと分けて処理します。 具体的な方法はサンプル・スケッチを参照してください。SPIで受信した先頭2バイトの生データから、符号付き温度値の文字列を求める”getTemp()”という関数を用意してあります。
プログラムの説明は次回行いますが、先にサンプルスケッチだけ掲載しておきます。適当なフォルダへzipファイルを解凍して使ってください。
<サンプルスケッチ ReadTemp.zip>
/* 熱電対コンバータ 温度読み出しサンプル copyright (c) 2013 T.N www.wsnak.com 13/01/14 新規 熱電対センサモジュールSPI MISO (D12) CLK (D13) CS (D9) */ #include <SPI.h> #define SPI_CS_ON digitalWrite(SPI_cs, LOW) // /cs = L #define SPI_CS_OFF digitalWrite(SPI_cs, HIGH) // /cs = H const int SPI_cs = 9; // 熱電対センサモジュール CSポート番号 byte spiDat[4]; char strBuf[16]; // ------------------------- // 初期化 // ------------------------- void setup() { Serial.begin(19200); // シリアルポート初期化 pinMode(SPI_cs, OUTPUT); // センサモジュール cs SPI_CS_OFF; SPI.begin(); SPI.setClockDivider(SPI_CLOCK_DIV4); // SPIクロック分周比 SPI.setBitOrder(MSBFIRST); // 送信ビット順番 SPI.setDataMode(SPI_MODE1); // SPIデータモード切替 } // ------------------------- // メインループ // ------------------------- void loop() { word val; byte i; SPI_CS_ON; for(i = 0; i < 2; i++) { // 2バイトだけ受信 spiDat[i] = SPI.transfer(0); // ダミーデータ送信(1バイト受信) } SPI_CS_OFF; val = ((word)spiDat[0] << 8) | (word)spiDat[1]; getTemp(val, strBuf); Serial.println(strBuf); delay(1000); // 1秒 } // // SPIで読み出したデータを温度値の文字列にシリアル送信する // void getTemp(word spival16, char *str) { word val, vali; byte sign, vals; val = spival16 >> 2; if(val & 0x2000) { // 符号ビットをチェック // 負数(2の補数) val = ~val + 1; // 正数に戻す val &= 0x3FFF; // 数値抽出 sign = true; // 負数マーク } else { // 正数 sign = false; } // 整数部分と小数部分に分ける vali = val >> 2; // 整数部(上位11ビット) vals = (byte)val & 0x03; // 小数部(下位2ビット) vals = vals * 25; // 25=0.25*100 小数部を整数化 // 表示用文字列作成 if(sign) { // 負数 sprintf(str, "-%d.%-2d", vali, vals); } else { // 整数 sprintf(str, "+%d.%-2d", vali, vals); } }
この記事は2013年1~2月頃にCQ出版のブログへ掲載したものを少し修正したものです。
参考文献