はじめに
ここの所寒いですね。どのくらい寒いのか気になるので温度センサーを使ってみたいと思います。というのは冗談で、しばらく前に購入したものの使用できていなかった温度センサーをようやく時間ができて使うことができたので、そのことを書いてみたいと思います。
2015年1月12日追記:Arduino IDE 1.5以降用の「ライブラリ」としてまとめたものは“Arudino開発環境用の「ライブラリ」を作成してみる – 作成した「ライブラリ」の配布”で配布しています。
使用している「Eaglet(イーグレット)」などについて
- 本記事で使用している以下のものはインテル株式会社のご厚意により“さかきけい”個人に貸し出されたものです。このため私の勤務先等とは一切関係がありません。
- インテル株式会社版「Eaglet(イーグレット)」および「Eaglet用 USB ⇔ シリアル変換ケーブル」
- Intel Edison Kit for Arduino(Intel Edison ModuleとIntel Edison Board for Arduinoのセット)
- 本記事は“さかきけい”が完全に自由意思で書いているもので、インテル株式会社からは何らの要請、制限等は受けていません。
- 使用している以下のものは市販品を“さかきけい”が購入したものです。
- スイッチサイエンス版Eaglet (MFTバージョン)
- 2種類のEagletボードに載せている2つの「Intel Edison Module」
- Intel Galileo Development Board(Intel Galileo Gen 1ボード)
- Intel Galileo Gen 2 Board
- その他、明示していないすべてのパーツ・小物類
Analog Devices ADT7410とは
Analog Devices ADT7410(以下、ADT7410)は、I2C(正確にはI²C、アイ・スクエアド・シー)に対応した温度センサーで、以下の特徴(抜粋)があります:
- 精度
- 典型値で±0.5℃の精度がある。
- 16ビットで0.0078℃、13ビットで0.0625℃の温度分解能がある。
- 簡単な実装
- ユーザーによる温度のキャリブレーションおよび補正を必要としない。
- 線形補正を必要としない。
- 幅広い対応環境
- 対応温度幅:-55℃~+150℃
- 対応電圧:2.7V~5.5V
I2Cのアドレスはデフォルトで0x48
で、チップのA1
およびA0
をそれぞれH(VDD)あるいはL(GND)とすることで、0x49
(LH)、0x4a
(HL)、0x4b
(HH)を選択することができ、最大で1つのI2Cバスに4つのADT7410を接続することができます。
使用するADT7410搭載モジュールについて
今回はこのチップを搭載したモジュールである秋月電子通商の「高精度・高分解能 I2C・16Bit 温度センサモジュール(AE-ADT7410)」を使用します。※1
このチップが持っている割り込み機能は使用できませんが、一般的な用途であれば十分だと思います。アドレスはJ3(A0)およびJ4(A1)をショートさせることで変化させることができます(デフォルトではプルダウンされていて、ジャンパーをショートすることによってHとなります)。
また、必要に応じてJ1およびJ2をショートさせることでSCL/SDAのラインに10kΩのプルアップを付加することができます。
今回は全ジャンパーともショート「なし」で使用します。
テスト環境とテスト方法
今回はこのモジュールをI2CのGroveコネクターを介してテスト対象の機器に接続しました。
テスト対象の機器は以下のとおりです:
- Intel Galileo Development Board(Intel Galileo Gen 1ボード)
- Intel Galileo Gen 2 Board
- Intel Edison Moduleを搭載した以下のボード
- Intel Edison Board for Arduino
- インテル株式会社製試作版Eaglet
- スイッチサイエンス版Eaglet(MFTバージョン)
このうち、動作電圧を切り替えられるものに関しては3.3Vと5Vの両方でテストを行いました。
テスト対象機器との接続にGroveコネクターを使用したのは、Eagletボードが2種類ともGroveコネクターでI2Cを搭載していること、その他のArduino互換のテスト対象に対してもSeeed Studioの「Base Shield V2」を載せることで同様にテストができるため、横並びのテストに適していると考えたためです。
AE-ADT7410との接続は、Groveケーブルの先に4ピン・オスのコネクターを装着し、その4ピン・オスのコネクターの足にスズでメッキされた軟銅線を足としてはんだ付けしてDIPピッチに広げてブレッド・ボードに挿しこみ、このブレッド・ボード上に水平に足を付けたAE-ADT7410を挿し、ジャンパ・ワイヤーで配線することで行います:
このGroveケーブルの挿し先をテスト対象の機器に順次切り替えて動作確認を行います。
Analog Devices ADT7410を駆動するスケッチ
ADT7410から温度を13ビットおよび16ビットで呼び出すスケッチを作成してみました。今回は作りっぱなしというよりはライブラリーとして使用できる一歩手前のものです。ソース・コードを以下に示します:※2
//////////////////////////////////////////////////////////
// Sketch library for ADT7410 (Analog Devices, Inc.)
// Header file.
// Programmed by KEI SAKAKI. https://kei-sakaki.jp/
#ifndef INCLUDED_KEI_SAKAKI_ADT7410_H
#define INCLUDED_KEI_SAKAKI_ADT7410_H
#include <Wire.h>
class ADT7410 {
protected:
int i2c_address;
public:
enum {
DEFAULT_I2C_ADDRESS = 0x48
};
ADT7410(int i2c_address = DEFAULT_I2C_ADDRESS);
virtual ~ADT7410();
virtual int GetTemperatureRaw(bool width16 = false);
virtual float GetTemperature(bool width16 = false);
virtual void SoftwareReset();
virtual void Shutdown();
};
#endif
//////////////////////////////////////////////////////////
// Sketch library for ADT7410 (Analog Devices, Inc.)
// Programmed by KEI SAKAKI. https://kei-sakaki.jp/
// #include <adt7410.h>
ADT7410::ADT7410(int i2c_address) {
this->i2c_address = i2c_address;
SoftwareReset();
}
ADT7410::~ADT7410() {
}
int ADT7410::GetTemperatureRaw(bool width16) {
int raw;
Wire.beginTransmission(i2c_address);
Wire.write(0x03); // 0x03 : Configuration Register
Wire.write(width16 ? 0x80 : 0x00); // bit7 : Resolution : 0 = 13-bit resolution / 1 = 16-bit resolution. (see Data Sheet Rev.A Page 13)
Wire.endTransmission();
Wire.requestFrom(i2c_address, 2);
raw = (Wire.read()) & 0xff;
raw <<= 8;
raw |= (Wire.read()) & 0xff; // high byte order
if(!width16) {
raw >>= 3; // 13-bit mode : bit 0-2 : flags
}
return raw;
}
float ADT7410::GetTemperature(bool width16) {
float temp;
int raw = GetTemperatureRaw(width16);
// (see Data Sheet Rev.A Page 12)
if(width16) {
if(raw & 0x8000) {
raw =- 65536;
}
temp = ((float) raw) / 128.0f;
} else {
if(raw & 0x1000) {
raw =- 8192;
}
temp = ((float) raw) / 16.0f;
}
return temp;
}
void ADT7410::SoftwareReset() {
Wire.beginTransmission(i2c_address);
Wire.write(0x2f); // 0x2f : Software reset
Wire.endTransmission();
delayMicroseconds(200); // ADT7410 need 200 us after reset (see Data Sheet Rev.A Page 19)
}
void ADT7410::Shutdown() {
Wire.beginTransmission(i2c_address);
Wire.write(0x03); // 0x03 : Configuration Register
Wire.write(0x60); // bit5-6 : 00 = Continuous / 01 = One shot / 10 = 1 SPS mode / 11 = Shutdown(Power down) (see Data Sheet Rev.A Page 14)
Wire.endTransmission();
}
//////////////////////////////////////////////////////////
// Sketch library for ADT7410 (Analog Devices, Inc.)
// Test Sketch Source Code.
// Programmed by KEI SAKAKI. https://kei-sakaki.jp/
// #include <adt7410.h>
ADT7410* adt7410;
void setup() {
Serial.begin(115200);
Wire.begin();
adt7410 = new ADT7410();
}
void loop() {
Serial.print("16-bit : ");
Serial.println(adt7410->GetTemperature(true), 4);
Serial.print("13-bit : ");
Serial.println(adt7410->GetTemperature(false), 4);
delay(10000);
}
見ての通り、ライブラリーのヘッダー、ライブラリーの本体、スケッチの3つのファイルを連結した状態のものです。
実行すると「シリアルモニタ」に以下のような感じで温度を16ビットおよび13ビットで読み出して℃に変換した結果を小数点以下4桁を付けて10秒ごとに表示します:
16-bit : 24.1172
13-bit : 24.0625
温度の16ビット読み出しと13ビット読み出しの傾向の差
単純に下位3ビットを読むか読まないかという差になっているようです。このため、13ビットによる読み出しでは16ビット読み出しでは値が入る部分(3ビット分)が実質的に0
評価となるため、相対的に小さな値が出ることが多いようです。
各テスト対象の機器での動作状況
前述のスケッチを使用して各テスト対象の機器で動作させた結果を以下に示します:
ボード/モデル | 動作電圧 | 結果 | 備考 | |
---|---|---|---|---|
Intel Galileo | Gen 1 | 5V | □ | 値がおかしい(8℃くらい高く出る)。 |
3.3V | ○ | |||
Gen 2 | 5V | ○ | ||
3.3V | ○ | |||
Intel Edison | Board for Arduino | 5V | ○ | |
3.3V | ○ | |||
Intel K.K. Eaglet | 3.3V | △ | 「i2c-designware-pci 0000:00:09.1: i2c_dw_handle_tx_abort: lost arbitration」が発生する。 常時13ビットモードでしか動作していない(レジスターの設定に失敗している)模様。 |
|
SSCI Eaglet(MFT Ver.) | 3.3V | ○ |
このように、Intel Galileo Gen 1ボードの5Vおよびインテル株式会社試作版Eagletでは問題が生じましたが、それ以外の環境では正常に動作することが確認できました。
まとめ
このようにI2Cで簡単に扱えるデバイスであっても環境によっては問題が生じることがわかります。先日のメモで使用したI2C接続モーター・ドライバーもそうですが、I2Cは割りと相性が生じやすいようです。
いまはオシロスコープもロジック・アナライザーもなしに試しているだけなので、実際問題として何が起っているのかは不明です。いずれ導入して状況を確認したいと思っています。が、素人な私が必要とする製品はどれなんだろう、ということがよくわからずにカタログを見つつもんもんとしています。とりあえずやってみるという場合にはどの程度の製品があるといいのでしょう…??
実はこの温度センサーは、I2C接続モーター・ドライバーが正常に動作しない際に、問題の切り分けをするためと気分転換をするために購入したものだったりします。だからI2C接続のセンサーなんです。そしてまたまた相性に悩むことになりました。しかし、いろいろと試してみて学習したことも多かったので結果としてよかった感じです。しかも、ひょんなことでこのセンサーを使うことになりました。それについては別のメモとして公開することになるかと思います。
関連記事
- Arudino開発環境用の「ライブラリ」を作成してみる
- Intel Edisonを使って何か作ってみる
- 「Intel Edison Board for Arduino」でLEDの発光を制御
- フリスク(FRISK)を食べながらIntel Edisonをいじろう!
- 「スイッチサイエンス版Eaglet(MFTバージョン)」を使ってみる
- Intel Galileo Gen 2のファースト・インプレッション
- 「Intel Galileo Development Board」でLEDの発光を制御
- はんだ個所にフラックスが過剰についていたり、ピンをまとめる樹脂が焦げているのは、都合により何度かはんだ付けをしたり、逆に取り除いたりを繰り返したためです。このモジュールのピンは今回のように水平につけられるほかに、はんだで見えない部分にある穴に挿しこんで垂直でも装着することができます。
- 何ら動作保証はありません。あくまでもサンプルとして見るだけに留めてください。