KLab若手エンジニアの これなぁに?

KLab株式会社の若手エンジニアによる技術ブログです。phpやRubyなどの汎用LLやJavaScript/actionScript等のクライアントサイドの内容、MySQL等のデータベース、その他フレームワークまで幅広く面白い情報を発信します。

Hardware

温度測定システム[5] 測定システムに纏わる3つの謎

uchikawa-yです 一応今回が最終回のつもりです。 今回は前回までと趣向を変えてDS2480Bを実際に使うにあたっていろいろぶつかったことや気になったことについて書いていきます。今回は最初に項目をあげておきましょう。
  • DS2480Bのシリアル入出力
  • byte単位のreadコマンド/モードが無い?
  • センサの電源を配線しないでも動いてしまった - 2線使用時の電源の謎 -

DS2480Bのシリアル入出力

なんでデータモードも含めてほとんどのコマンドで1byteの戻り値が帰ってくるのだろう

DS2480Bは1-Wireバスとシリアル(RS-232C TTLレベル)の変換器として動作しますが、シリアル入出力の仕様は以下の通りです。
  • TTLレベル 正/負論理(端子接続で切り替え可能)
  • 9600bps(デフォルト値)~115200bps
  • フロー制御なし
  • 送信バッファなし、受信バッファ1byte

DS2480Bには送信バッファはありませんがシリアル経由でPCなどのホストへ送られたデータはPC側の受信バッファにたまります。このため送られてきたデータは適切に処理するなり読み飛ばす必要があります。そうしておかないと必要なデータをバッファオーバーフローで失ったり、データのずれが起きたりする可能性があります。 ほとんど全てのコマンド、データモードの送信で1byteの戻り値があるのでDS2480Bでは基本的には「1byteの書き込みを行ったら1byte読む」という形に自然になります。最初はこの仕様を奇妙に思ったのですが実はちゃんと意味があった…というお話です。

1-Wireの最大データ転送レートはオーバードライブ(高速)モードで142kbps、標準モードでは実質的16kbps程度です。センサのDS18B20がオーバードライブに対応していないのでここでは標準モードを使用しています。この場合、9600bpsでもシリアル入出力のほうが高速なので、DS2480Bへの送信でデータオーバーフローの可能性があります。受信バッファが1byteしかないのでホスト側では1byteごとにチェックしなければならないわけです。

DS2480Bが受け取った1byte分の処理の完了は、ホスト側のDS2480Bの返す1byteの読み取り完了で検出できる 割合当然といえば当然なのですが、私は一番最初に引っかかってます。「実行例ちゃんと読めよ」ですね。CTS/RTS制御が使える環境でドライバ任せにするプログラムしか書いたことなかったですから…(ぶーぶー)。

データモードの戻り値についてはもう一つ別の大きな意味がありました。 というわけで次の項に続く

DS2480Bにはbyte単位のreadコマンド/モードが無い?

これは…何て言っていいのか、個人的には使うにあたって一番詰まったところだったりしますが… DS18B20は9バイトの読み出し可能なメモリ(Scratchpad)を持っていて、温度測定結果などが収められています。温度測定完了後にこれを読み出したいのですが、データモードでセンサに対してRead Scratchpadコマンドを送って待っていても9バイトのデータを受け取ることはできません。
  • シリアルポートに対してソフトウェア的にreadを行っても対向のポートには「read待ちの状態である」というような情報は伝わらない
  • 1-Wireではマスタ側がReadスロットを開始しないとスレーブ側はデータを送信しない
ということがあって、シリアルポートの向こう側から待っているだけではデータは出てこないのです。1bit単位のreadコマンドはコマンドモードで用意されているのですが、これを繰り返し使うのはいかにも無駄です。 ではどうすればいいのかというと……これも「データシートの実行例読めよ」が結論なのですが。 結論:byte単位でデータを読むにはデータモードでffh(全bit1の1byte)を送信して戻り値を読む。読み出した1バイトがスレーブの送ったデータである。 1-Wireの仕様をちゃんと理解した上で、DS2480Bのデータモード時の戻り値が1-Wireバス上の波形を反映したものである、という内容を考えれば想像つかないものでもないですが、この行間を読むのはちょっと厳しいです(実行例に書かれているので最終的には正解にたどり着けるようになっているとは言えるのかもしれませんが)。 本気でデータシートの本文に書いておいてほしいと思いました。

センサの電源を配線しないでも動いてしまった  - 2線使用時の電源の謎(strong pullupの意味) -

1-Wireは信号線と+電源(Vdd)を時分割して共有する配線も可能で、2線で使用できるようになっています。これはネットワークケーブルや電話線のUTPのうち1ペアが利用可能ならそれを流用した配線もできるようにと考えたものらしいです。 アプリケーションノートにはネットワークケーブルを使う例があげられています。DC等のルール的に問題があるかどうかは別としてラック間配線のためのパッチパネルなどが利用できると楽だったりしませんか? (なお以下の部分には「いくらか」アナログ回路設計の知識が必要な内容が含まれます。まあオームの法則程度なので気楽に読んで下さい) 信号線と+電源を共有するというと特別な方法を使っているような印象を持つかもしれませんが、これは回路的には大したものではなくて概念的にはダイオードとコンデンサを組み合わせた以下のような回路で接続されています。
2線接続の場合の電源


1-Wireの信号線はデータのやり取りを行っているときには短時間0となる場合がありますが、大部分の時間では1(プルアップ抵抗を介して+5Vに接続している状態となっています。
信号線QDが1
QDからダイオード経由で電源が供給される
信号線がQDが0
ダイオードによってQDは切り離され、コンデンサに蓄えられた電荷が(短時間の)電源供給に利用される
もし、1-Wireバス上のスレーブデバイス全体の消費電流が小さい(数μA程度のオーダー)ならばこれはこのまま何もしなくても動作してしまうと考えられます。実際にはそうも行かなくて、DS18B20の場合温度測定を開始したり、設定内容の書き換えを行う場合はデータシート上、最大1mA電流が流れるとあります。 1mA電流が流れるとして、仮にプルアップ抵抗を推奨回路の通り4.7kΩとするとプルアップ抵抗の両端の電圧Vrは、 Vr = I×R = 1×10^(-3)×(4.7×10^3) = 4.7(V) DS18B20のDQの電圧は5-4.7=0.3(V)となり、電源電圧として必要な電圧に達しません。正常に温度測定できないことになります(実際には規格上の電流の最大値まで流れないことも多いようですが)。この問題に対応するため、2線で使う場合はプルアップ抵抗をバイパスできるような回路が必要です。バイパス回路はDS2480Bには内蔵されていてソフトウェアから制御可能になっています。 バイパスした状態をDS2480Bではstrong pullupと呼んでいます。 以下の図はDS2480B経由で1-Wire上にセンサ4個を2線接続して温度変換コマンドを送り、DQ端子の電圧を見たものです。
strong pullupの効果


DS2480Bは単純なプルアップ抵抗を使用しているわけではなく、アクティブプルアップとなっているので多少事情は異なりますが、strong pullupを使用すると電圧の低下が少なくなることがわかります。 ところでDS18B20は電源電圧は最低3Vなのでこの測定結果によればstrong pullupなしでもぎりぎり動作するような気がします。実際に動かしてみると完全に規格外の使い方ですがstrong pullupを行わなくても動作してしまいます。 実は先に2線接続をしてstrong pullupを行わずに測定プログラムを動かしてみたら「あれ?動いちゃった」状態だったので調べてみたのですが、元々動いてもおかしくない状態だったようです。 ただ、調子に乗ってセンサをいくつもつないだりすれば誤動作しやすいでしょう。また、1-Wire上を流れる電流はセンサ全ての合算ですから、全てのセンサで同じタイミングで温度測定を行うと誤動作しやすいということもわかります。

最後に

温度測定システムの紹介ということで5回にわたって書きましたが、なにぶん書き慣れないことなのでどの程度伝わったか不安ではあります。 Perlで書いた測定プログラムは公開してありますし、メーカーのデータシートには十分な情報が含まれていますし、含めるとかなり煩雑になりそうだったので、今回は具体的なコマンド体系・シーケンスについてはあえて書きませんでした。なので具体的なコマンドの解説もあったほうがいい等の感想があったら教えていただけるとありがたいです。 温度センサDS18B20は中々よくできているセンサで使わないのはもったいないと感じています。1-Wireのデバイスは温度センサ以外は品揃えがいまいちなのが残念ですが汎用のA/Dコンバータがあるのでいろいろな場面で選択肢の一つとして考えられるものだと思います。

温度測定システム[4]DS2480BとROMコード(アドレス情報)検索

uchikawa-yです 今回は前回に引き続く形で、DS2480Bを使う場合のメリットの一つ、1-Wireデバイスのアドレス検索(ROMコードの検索)について書きます。 DS2480B(現在は鉛フリーパッケージのDS2480B+に置き換えられています)は5mm角程度の大きさの8pinの表面実装パッケージでとても小さなものですが、中々使いでのあるICです。 なお具体的なコマンドのシーケンスについてはここには書きませんでした。こちらについてはDS2480Bのデータシートを参照してください。

DS2480Bについて

DS2480Bは入出力をRS-232シリアルインターフェース(TTLレベル)で行うように設計された1-Wireバスドライバです。 1-Wireはビット単位のデータ入出力は実時間に強く依存した非同期バスですが、このレベルについてはDS2480Bに完全に任せることができます。電気的特性上の要求から設定可能な部分はありますが、少数のデバイスを数m程度の配線で使う分にはデフォルト値のままで全く問題ありません。 DS2480Bには各種初期設定、ビット単位のデータ送受信を行うコマンドモードと、バイト単位のWriteがそのまま1バイト分の1-WireバスへのWriteとなるデータモードがあります。 1-Wireデバイスに対するコマンド(たとえば温度測定開始、測定データの転送などのコマンド)およびデータの送受信はほとんどバイト単位で行うようになっていますから、初期設定的など一部の処理をコマンドモードで行い、大部分の処理はデータモードを使う形になります。後述する検索アクセラレータや単一bitの読み書きを行う場合はコマンドモードを使います。 詳細な状態遷移図はDS2480Bのデータシート上で公開されていますが、大まかな状態遷移は以下のようになっています。
DS2480の大まかな状態遷移


  • コマンドモード: 各種のコマンドを受け付けるモード
  • データモード: "E3"を除いて受け取った1バイトをそのまま1-Wireに出力するモード
  • チェックモード: データモードからコマンドモードへ遷移する途中の一時的なモードで、"E3"を受け取ると1-Wireに"E3"を送ってデータモードに戻る以外はコマンドモードと同じ
チェックモードはデータモードからコマンドモードへ遷移するためのコマンド"E3"のエスケープ処理上発生する一時的な状態です。"E3"を出力する場合は"E3,E3"と2回続けて同じデータを送ることを表現したものです。 なお、チェックモードから電源offの遷移がありませんが、これは元の詳細の状態遷移図に従いました。

ROMコードのSearch と検索アクセラレータ

1-Wireのデバイス(スレーブデバイス)には工場出荷時に64bitのユニークな「ROMコード」が書き込まれており、デバイスを指定するアドレスとして利用されます。64bitのうち8bitはエラーチェック用のCRCコードなので実質56bitのアドレスになります。また56bitのうち8bitは製品の種別を示すファミリコード(温度センサの場合は28h)として使われています。 ROMコードはソフトウェア的に読み取り可能で、複数のデバイスが一つの1-Wireに接続されていてもROM Searchコマンドを使って全てのスレーブのROMコードを読み出すことができるようになっています。 このコマンドは特殊なコマンドで同時に複数のスレーブデバイスが出力行い1-Wire上では複数のデバイスの出力が合成されます。一般のCMOS回路の出力では通常出力端子同士を接続しては使えませんが、1-Wireではオープンドレイン出力なのでこの形は通常の動作です。以前にも書いたとおり出力動作をしているデバイス全ての出力をAND接続した結果が1-Wireの出力になります。 ROM Searchの詳細についてはMAXIM社の公開している資料を読んでいただきたいのですが、要点は以下のようなものです。

ソフトウェアによるROMコードの検索

DS2480Bを使わない場合1-Wireに用意されているSearch ROMコマンドとソフトウェアによる処理の組み合わせでROMコードの値を取得します。 Search ROMコマンドを使うと初期状態では1-Wire上のスレーブデバイス全てが応答します。スレーブはLSBから順番にROMコードの各ビットの値、値を反転したものを出力していきます。 (0bit目の値),(0bit目の値を反転), (1bit目の値),(1bit目の値の反転)…… 1-Wireでは全ての出力がAND接続されていますから、スレーブの中で一つでも0を出力しているものがあれば結果は0になります。たとえば[n bit目の値]と[n bit目の値を反転]の組み合わせについては以下のことが言えます。

  1. [n bit目の値]と[n bit目の値の反転]の値が異なる値であれば全てのデバイスのROMコードのn bit目は[n bit目の値]と同じである
  2. [n bit目の値]と[n bit目の値の反転]が両方とも0なら0bit目が1のデバイスと0のデバイス両方がある(値の衝突がある)
  3. [n bit目の値]と(n bit目の値の反転)が両方とも1なら、正常な動作をしていない。バス、デバイスの異常、シーケンス中にデバイスが取り外された、等が考えられる
この3種類の状態を表にすると以下のようになります
n bit目の値
0 1
n bit目の値の反転 0 出力には0,1両方ある (2) 全ての出力が1 (1)
1 全ての出力が0 (1) 正常動作ならこの状態にはならない (3)



3つめの状態の場合は中断するなり、最初からやり直しですね。1.の場合はそのまま次のbitについて同じ操作を続行します。2.のデバイスによりどちらもあり、の場合は0か1を選んで検索を続行します。この場合、選ばなかった「枝」に属するデバイスはそのまま動作していると、そこより葉に近いノードでは偽の「衝突」の原因になります。 ホストデバイスは「直前に調べたbitのROMコードの値が0(あるいは1)のデバイスは次にバスリセットを行うまで動作を停止する」という指示を行い、検索の対象とならない枝のデバイスはその後の検索に影響を与えないようにします。 これを64bit目まで繰り返すと最終的には1-Wire上で動作しているデバイスは1つだけになり、64bitの値が1つ決定します。1-Wire上のデバイスのROMコードが1つ求められたことになります。 簡単な例を示しましょう。ROMコードを64bitではなく仮に4bitとして、1-Wire上に0101, 0110, 1001(LSB first表記)のROMコードを持つデバイス3台が存在するとします。

  bit位置
デバイス 0123
0101
B0110
C1001

ここで0bit目から値0の枝を優先して検索を行うと以下のようになります
0bit目
初期状態で全てのデバイスが動作している。 A,B:0 C:1と値が不一致で衝突しているので0側の枝を選択、1の側(1xxx)に属するデバイス(ここではCのみ)を停止させる--(1)
1bit目
デバイスA,Bが動作している。 A,Bの値は1で一致しているので1の枝を選び検索を続行
2bit目
デバイスA,Bが動作している。 A:0, B:1と値が不一致。 0側の枝を選択、1側(011x)に属するデバイス(B)を停止させる--(2)
3bit目
デバイスAが動作している A:1で4bit分全てが確定、これが得られたROMコード(0101:4bit)になる

ROMコード検索木



全ての1-Wire上のデバイスのROMコードを求めるには、各デバイスのROMコードが見つかったら、バックトラックを行い64bitのROMコード全体の木検索を行えばいいことになります。ROMコードの値の衝突が起きていないbitでは一意に値が決まりますので実際に検索しなければならない範囲は64bitの木全体から見れば小さい範囲になります。 これはbit演算主体のプログラムになり、結構面倒ですね。MAXIMはサンプルプログラムも公開していますので興味があったら参照してみてください。

DS2480BによるROMコードの検索

DS2480Bを使う場合は上記のROMコードの検索処理のかなりの部分をハードウェアが半自動で行ってくれます。 DS2480Bの「検索アクセラレータ」をOnにして必要なパラメータを送ると、そのパラメータに適合したデバイスのROMコードが戻り値に返されます。上の4bitの例であればデバイスAのROMコード:0101と値の衝突が発生した位置(0bitと2bitで発生):1010の2つの情報がいきなり得られます。値の衝突が発生した位置のデータは「不一致フラグ」と呼ばれます。 入力で使用するパラメータは「値の衝突があった場合どちらの枝を検索するか」を示すデータです。これはインデックス値と呼ばれ、ROMコードの各bitに対応する64bit分ですがフォーマットの関係で128bit(=16byte)のデータをホストは送ります。条件に合致するデバイスのROMコード(64bit)と検索中に値の衝突が発生したビット位置(=検索木の分岐がある位置)のデータ(64bit)の128bit(=16byte)の情報を返してくれます。 たとえば値の衝突を検出した場合に、全ての場合で'0'の側の枝をたどる検索を行うのであればパラメータ64bit分に全て0をセットして検索を行います。 得られた不一致フラグとROMコードから次の検索を行う場合のインデックス値を作り出し、新しいデバイスが見つからなくなるまで検索を繰り返せば1-Wire上の全てのデバイスのROMコードが得られます。

インデックス値の作成と不一致フラグ

ここではDS2480Bで検索アクセラレータを使う場合でもれなく全てのデバイスを検索するためのインデックス値を決める方法について説明します。初期状態ではインデックス値には全bit0の値を与えることにします。 いくつかの1-Wireデバイスが接続され、正常に動作しているならそのうちの一つのデバイスのROMコードと不一致フラグが得られます。2回目以降の検索では今得られたROMコードと、不一致フラグから「未検索の枝」を見つけてそちらを検索するようにインデックス値で指定してやります。 最初の検索では不一致を検出した場合に0を選ぶように指定していますので不一致を検出し、かつ対応するROMコードのbit位置の値が0のものは「未検索の枝」が残っていることになります。ここでは「未検索の枝」のうちMSBに近い側から1の側の枝を選んで検索するよう指定していきます。 インデックス値のフォーマット、作成方法はデータシートを丹念に読めばわかるようになっていますが、一見わかりにくいところもあるので図示します。
  • 検索アクセラレータの出力  128bit(=16byte)の出力は奇数ビットにROMコード、偶数ビットに不一致フラグとビット毎交互に情報が収められています
  • 検索アクセラレータ出力


  • インデックス値の作成
    1. 前回の検索アクセラレータ出力の最大不一致ビットに対応するROMコードのビットを1にする
    2. インデックス値作成1


    3. 今1.の手順で1にしたROMコードのビットよりMSBに近いビットを全て0にする
    4. インデックス値作成2


    5. 作成した64bitのデータを奇数ビットにして128bitに拡張する。偶数ビットの値は任意でよい
    6. インデックス値作成3


ここで得られた値を次の検索で使うインデックス値として使うと先の検索で見つかったデバイスとは別のデバイスのROMコードが得られます。これをLSBまで行うと全てのデバイスが見つかります。ただし最初の検索で無効にした枝の中に複数のデバイスが含まれる場合もありますので、最初に見つかった「不一致フラグ」の1の数より多くのデバイスが1-Wire上にあることもあります。 インデックス値、ROMコードの出力、不一致フラグのフォーマットはハードウェアの都合が極めて強く出たもののようでソフトウェアを作成する立場からすれば無駄に複雑な構造に見えるかもしれません。ホスト側からはシリアルインターフェースからbyte単位でデータの送受信をしますが、DS2480BはROMコード検索のbit単位処理をシリアル送受信の合間にやっているんですよねぇ…… あくまで印象ですが、DS2480Bは比較的小規模な回路追加で可能なシーケンス処理に絞って実現したように思います。その分いくらかはソフトウェア側にしわ寄せが行っているというような点もあるかもしれません。データシートの記述はもう少しわかりやすいものであれば良かったとは思いますが、実行例などが記載されているのでかなり助けられました。 今回は主に1-WireデバイスのROMコード(1-Wireのアドレス情報)の検索について書きました。 次回は今回書けなかったDS2480Bを使う場合の注意点、そのほかの機能について書くつもりです。

温度測定システム[3] 1-Wireのデータ転送

uchikawa-yです。 前回、前々回に引き続き温度測定システムまわりの話をします。 今回はまあ、ハード屋さんです。 個人的にはオシロスコープはテクトロニクス製のアナログオシロが好きなのですが、たとえ買えたとしても普通の家庭では置き場所に困りますよねぇ。今回使ったオシロスコープはUSBでPCに接続して使うタイプのものでした。 DS18B20, DS2480Bを実際使うにあたってはMAXIM社の提供しているデータシート、アプリケーションノート、サンプルプログラムを見るのが最も確実でしょう。特にデータシートなどに記載の実例、サンプルプログラムを真似するだけでもかなりのことができるはずです。 MAXIM社の製品ページDS18B20 MAXIM社の製品ページDS2480B さて、今回の温度測定システムを作り、使うためにはどういう知識が必要だったのでしょうか?
  • ICのデータシートを読む能力
  • 配線材、コネクタ、配線方法、加工方法などの知識(いわゆる工作についての知識)
あたりは置いておくとして課題と解決方法をまとめると以下のようになります。 意図的にネットワーク階層と対応つきやすいように下位のレイヤから書いてみました。完全にきれいに対応するわけではありませんが、DS2480Bはレイヤ1~レイヤ2あたりを担当してくれるデバイスです。これを使用すれば下回りのかなりの部分は知らなくてもある程度はなんとかなります。
1-Wireの電気的特性 DS2480Bが概ね適切に対応してくれる。DS2480Bを使わないならひたすらデータシートを読む
1-Wireのデータ転送条件(タイミングなど) DS2480Bが概ね適切に対応してくれる。DS2480Bを使わないならひたすらデータシートを読む
1-WireのROM Search(スレーブアドレス検出) DS2480Bが半分ぐらい処理。データシートとサンプルプログラムを熟読する
1-Wireシリアル変換器 DS2480Bの制御方法 DS2480Bのデータシート、実例、サンプルプログラムを読む(コピペも可)
温度センサDS18B20の制御方法 DS18B20のデータシート、実例、サンプルプログラムを読む(コピペも可)
シリアルポートの制御方法 perlのモジュール使って逃げた


ただし、数10mの配線を使ったり、センサを20個以上1つの1-Wireに接続するような物理的に厳しい使い方をする場合は結局ドキュメントを熟読する必要が出てくるように思います。

1-Wireのデータ転送

DS2480Bを使うなら「あまり」気にしなくてもいい部分ですが、1-Wireの話をするのにこれがまったく無いのも片手落ちなので書いておきます。なので今回は以降の部分は興味のない人は読まなくてもかまわない内容です。また、網羅した内容ではないので詳細についてはMAXIM社の資料を参照してください。
  • 信号線が1本の双方向非同期シリアルバス
  • 信号線(DQ)はlowレベル:0V, highレベル:ハイ・インピーダンス。外部1箇所で5kΩ程度のプルアップ抵抗を介して3V~5.5Vに接続する(オープンドレイン出力)。
    • マスタ・スレーブすべてのデバイスの出力がAND接続されたものが最終的な出力DQになるとみなせる
    • DS2480Bを使用する場合、DS2480B内でプログラマブルなアクティブ・プルアップ回路が内蔵されているため外部でプルアップは行わない
  • 半二重通信
  • 転送レート 16kbps(標準モード)
  • 100m程度のバス総延長で使用可能
  • スレーブデバイスは実質56bitのアドレス空間を持つ
  • 各デバイスのアドレスは出荷時に決定され変更不可能
通常、バス接続の場合は各デバイスは3-stateの入出力回路を持ち、バスから切り離す(high='1',low='0',ハイインピーダンス状態)ことができるようにしています。1-Wireの場合はハイ・インピーダンス状態と'0'のみを使い、外部でプルアップしています。この回路は、
  • すべての端子がハイ・インピーダンス状態→出力は'1'
  • 一つでも'0'状態の端子があった場合→出力は'0'
ハイ・インピーダンス状態を'1'とみなせば等価的にAND接続されたとみなせます(ワイヤードAND)。このような回路は電気的に高速なスイッチングに不向きですが1-Wireは低速用途に特化して積極的に利用しています。 各デバイスが'1'を出力している場合、他のデバイスから見たり、出力端子を見ている限りはバスから切り離されている状態と区別がつきません。 1-Wireではデバイスの検出(ROM Searchコマンド)など特殊な場合以外は複数のデバイスが同時に出力を行いません。出力をしないデバイスはすべてDQ端子を'1'にします。 ここでは便宜上、マスタからスレーブへデータを送る場合をWrite, スレーブからマスタへデータを送る場合をReadとして1ビットのデータ転送動作を示します。データ転送スロットは必ずマスタから開始されます。マスタがDQを1→0として1μs以上0を続けるとスロットが開始されます。
Fig.1 Writeタイミング


Writeでは全てのスレーブが出力をおこないませんので各スレーブのDQ端子は'1'の状態のままです。従って1-Wire上の最終的な出力結果はマスタの出力状態を反映したものになります。スロット開始から15μs以内にマスタの出力が確定する必要があり、その後45μs以内のどこかの時点でスレーブデバイスがデータを読み込みます。
Fig.2 Readタイミング


Readでは事情が異なります。スロットの開始はマスタ側から行いますが、マスタは1μs以上'0'を出力した後'1'を出力してバスを明け渡します。スロットの後半では出力デバイスが入れ替わり、出力を行うことになっているスレーブデバイスの出力が1-Wireの出力結果になります。マスタはスロット開始15μs以内にデータを読み込むのでこの間はスレーブはデータを保持する必要があります。 以下は実際の8bitのWrite, Read動作を行ったときの1-Wireの波形です。WriteとReadでは動作の違いから波形が異なることがわかります。
Fig.3 8bit Write動作


Fig.3 8bit Read動作


続く!

次はDS2480Bの主要な機能の一つであるROM Searchアクセラレータ(スレーブデバイスの認識、アドレス取得の支援機能)の説明をしようと思います。これは1-Wireデバイスを使う場合に避けられない話題なので今回書くつもりでしたが、続けて書くとかなり長くなりそうなので分けることにします。ではまた次回で。

温度測定システム[2] 測定ソフト, DS18B20, DS2480B

uchikawa-yです。前回に引き続いて温度測定システムの話をします。 忘れていたのですが温度センサDS18B20のスペック等とDS2480Bの機能について何も書いていなかったですね。構成/回路図には名前だけ出ていました。 今回はMAXIM社のデバイスを使用しています。このMAXIM社はアナログ/アナログ・デジダル混在のICに比較的強いメーカーです。他の会社の互換品をオリジナルより高性能にして出したり、他ではなかなか見られないようなユニークなオリジナル製品を作るメーカーです。 まず簡単に動かす方法を紹介して、後は下のレイヤから書いていきましょうかね。

温度測定システムの利用方法

今回作成した測定システムはホストからはUSBシリアルとして見えます。USBシリアル変換チップにはFDTI社のFT232RLを使用しています。FT232用のUSBシリアルドライバが使える環境であれば他にドライバは必要ありません。Perlで測定プログラムを作成してみました。こちらはgithubで公開しています。 https://github.com/uchikawa-y/temper_1w このプログラムではシリアルポートの操作を簡単に行うためにDevice::SerialPortというPerlモジュールを使用しています。 使い方やインストールの方法は上記のURLに置いてあるドキュメントを参考にしてください。 基本的にはperl 5.xとFT232のドライバがあれば動作するはずです。Debian Linux 5.0, FreeBSD 8.1R, NetBSD 5.1(玄箱HG PowerPC), Windows XP(Cygwin上のperl), Windows7(Cygwin上のperl)では動作実績があります。

温度センサDS18B20と1-Wireシリアル変換DS2480B

DS18B20

温度センサDS18B20の主な仕様は以下のようなものです。詳細についてはMAXIM社よりデータシートやアプリケーションノートなど豊富な資料が公開されています。 MAXIM社の製品ページDS18B20
電源電圧 3.0~5.5V
待機電流 750nA TYP(70℃)
動作電流 1 mA TYP(温度測定, EEPROM書き込み時)
温度測定範囲 -55~+125℃
温度測定誤差 ±0.5℃ MAX(-10~85℃)
±2℃ MAX(-55~+125℃)
分解能 9bit~12bit
入出力 双方向非同期シリアル(1-Wire)
パッケージ TO-92 3pin, SOP(1.27mmピッチ) 8pin, μSOP(0.65mmピッチ) 8pin
±0.5℃ MAX(-10~85℃)というのは一般的な半導体温度センサとしては高精度なほうです。サーバ信頼性のための温度測定目的なら無調整で使用できるでしょう。 温度測定時の消費電流が1mAというのは頭に入れておいたほうがいい値かもしれません。

DS2480B

DS2480Bは1-WireをRS-232Cへ変換するICです。ホスト側からはRS-232C経由で各種のコマンドを送り、1-Wireデバイスを制御することができます。1-Wireはバス内に1つのマスタ、複数のスレーブを持つマスタ・スレーブ型の非同期双方向バスですが、DS2480Bは1-Wireのマスタとして動作します。 MAXIM社の製品ページDS2480B データシートに"Serial to 1-Wire Line Driver"とあり、"Line Driver" と言っているところがDS2480Bの本質とメーカーのスタンスなのでしょう。
  • 通信速度:9600bps (default), 19200bps, 57600bps, 115200bps
  • Search ROM(スレーブデバイスのアドレスサーチ)を半自動で行う検索アクセラレータ機能
  • 1-W端子はドライブ能力の高いアクティブプルアップ
  • 2線接続用にstrong pullupに対応
  • 30m以上の長い1-Wireバスに対応するためのスルーレート制御, タイミング制御機能
  • 1-Wireのオーバードライブ(高速モード)に対応
1-Wireの配線総延長が100m程度となるような重い負荷状態への対応として電気的な部分を設定する項目が多数ありますが、今回は電気的な特性にかかわる部分はほとんどデフォルト設定値のままにしてあります。 ソフトウェア側から考えたDS2480Bを使うメリットのうち大きなものは以下の2点です。
  1. 直接1-Wireのバス制御を行う必要がなくなり、1-Wire上のデバイスをRS-232C上のデバイスとして扱うことができる
  2. 1-Wireデバイス(スレーブデバイス)のアドレスサーチ(ROM Search)の処理の一部を2480Bが半自動で行ってくれる
いずれもソフトウェアの負担を低減してくれます。

DS2480Bを使った本当の理由 (1-Wireを使う方法は他にもあるだろう)

前述1.のメリットがあまりに大きいというのがDS2480Bを使用した理由なのですが、少々説明する必要があります。

Linux の1-Wireドライバ

LinuxではGPIO(汎用の入出力端子)を利用して1-Wireバスのマスタ動作をさせるドライバが存在します。これは一般のPC用ではなく組み込み機器用のドライバです。カーネルの構築をするとmenu configの項目に出てくるので知っている人もいるでしょう。しかし、このドライバを使う場合、動作可能なホスト機器(の入手性にやや問題があります。たとえばFonera+OpenWRTでは利用可能でしたが実質的に2100E以外では満足に動作しないようでした(要改造)。

パラレルポートの双方向データ線を使う

一般のPCでも、たとえばパラレルポートの双方向データ線があればそれを利用して直接1-Wireのマスタ動作をさせることは可能です。こちらも試してはみましたが、一般的なPCのハードウェア+Unix/Linux系のOSでは10数μsのレベルの正確なタイミングを発生させる確実な方法が見当たらなかったため、1-Wireのエラーがかなりの頻度で発生したり、使用するPCの機種、OSなどによりパラメータの調整を行う必要があったりしました。 1-Wireのプロトコルは「DQ線をhighレベルにしてから『○○μs以内に必ず』lowレベルにする」というようなハードリアルタイム処理が必要なものであるのでなかなか厳しいです。こういうのはむしろ「H8などの組み込み用CPUボードとITRON」なら楽勝なんですけどね。

結論

測定用のホスト機種や条件で調整する必要があるというのはなかなか使い勝手が悪いので、それならいっその事ハードウェアに任せてしまえ、というのがDS2480Bを採用するに至った理由です。おかげでUSB-シリアル変換器に使ったFT232RLのドライバさえあればハードウェア/OSを問わず動作する汎用性の高い温度測定器になりました。

続く!

今回は測定ソフトウェアと使ったデバイスの紹介をしました。 1-Wireの動作や制御ソフトを作る場合の留意点、そのほか諸々のことにはまだ触れていませんので次はそのあたりを書いてみたいと考えています。 次もやっぱり低レイヤな話が多めになると思います。

温度測定システム[1] ラック内温度を測定する

別に若手でもなんでもないuchikawa-yです 「DSAS開発者の部屋」の方ではおそらく読んでいただける人の期待するものと違うだろう、ということで比較的フリーダムなこっちの方を占拠することにします。『抵抗は無意味だ!』あ、違うか。次何か大物を出す場合には独立したTopをもらえるといいなぁ。 要するにサーバラックなどの環境を把握するための温度測定システムを作ってやろうという話です。Hardwareのカテゴリを作りました。ここは(当面)私の領域です!

1. なぜサーバラック内の温度を測定するか

サーバの信頼性の観点からサーバラック内の環境を正確に把握するのは案外大事なことです。 DSASブログでも以前ラック内温度が低すぎるためにHDDの動作に問題が発生した件がありました。 データセンタではラック内の温度管理を何らかの方法で行っています。あらかじめ決められた基準でユーザに対してラックを提供しています。しかし実使用においてはサーバの設置状況、冷却の方法などによりラック内の温度分布は変化します。たとえばラックの上部と下部では温度差がある場合があります。 またエアフローを考慮した設置方法と、あまり適切ではない設置方法をとった場合に全体の温度分布に違いが発生する場合もあるようです。 ユーザがラック内の温度分布を必要に応じて測定し、サーバ設置や利用方法などの運用に反映させることができればラックの利用効率を高め、かつ信頼性を確保する指針の一つになるでしょう。

2. サーバラック内温度測定の概要

サーバラック内の温度測定を行うにあたり、測定の大まかな用件を示しておきます。
測定温度範囲 10℃~100℃(サーバ排気温を含む)
センサの設置範囲 ラック(80cm×1m×2m程度)が最大10台程度
湿度範囲 30%~60%程度(結露しない)
測定点数 数点~数10点
一般のオフィスルーム内の温度測定とそれほど変わりませんが、センサの設置範囲は最低2m程度、複数のラックの測定を行う場合は20~40m程度の総延長となることが想定できます。測定装置を複数置いてネットワーク接続をする方法も考えられますが、ここでは測定用の機器を最低限の数でまかなえるようセンサ側の制約を少なくする方向で考えます。 温度分布を知りたいため測定点は最低ラック内数点は必要です。配線が少なくてすむような構成が可能なセンサが望ましいです。

3. センサのインターフェース (1-Wire)

温度センサは温度に対応した電圧や電流のアナログ値で出力するものと、内部的にA/D変換を行いデジタル値で出力するものがあります。
  • アナログ出力
    • 電圧出力
    • 電流出力
  • デジタル出力
    • 1-Wire
    • I2C
    • その他
IC化された温度センサにおいては温度に対応する電圧を出力するタイプが従来一般的でした。しかし電圧出力ではセンサと測定器の間が数m以上となる場合、ノイズの影響や、センサケーブルの電圧降下の影響を受けやすく、高精度の測定は行いにくくなります。電流出力形式のものやデジタル出力のものが適しています。 デジタル出力のタイプではバス型のインターフェースを持ち、複数のセンサを1本のバスインターフェース上で扱うことができるものが販売されています。今回の目的ではこのようなインターフェースを持った温度センサがよいでしょう。

1-Wireバス

MAXIM社の温度センサは1-Wireという名前のリモート測定に適した非同期型シリアルバスインターフェースを採用しています(1-WireはMAXIM社の登録商標です) "1-Wire"という名前のいわれは電源・GNDを除く信号線が1本のみであることから来ています。実使用では2線(Vcc+電源と信号線を時分割で共有)または3線で配線します。1本のバス上に複数のデバイスを接続することが可能で、条件次第でバス長は100m程度、デバイス数最大100程度まで使用可能とされています。電気的な条件の制限を受けるので額面通りには受け取れないのですが、広い範囲に多数のセンサを配置することが可能で、今回の目的には適したインターフェースです。 類似のインターフェースとしてはPC内の温度センサ、ファンの回転数センサなどのインターフェースとして使われているI2Cバスがあります。こちらは1-Wireよりも高速のデータ転送が可能ですが、数m以上の配線長での使用には適していません。たとえば電気的特性として負荷容量は400pF以下となっていますが、平行2線の配線ケーブル自体の容量が50pF/m程度はありますのでこの条件だけで10m程度の配線は難しいということになります。

4. 温度測定システムの試作

実際に作成した測定装置は以下のようになります。センサを並列に接続していくことで測定点を増やすことができます。 実験的にはセンサ8個、ケーブル10mまで動作確認をしています。 これをUSBインターフェース経由でPCなどに接続し、データの収集を行います。
Fig.1 温度測定システム


図2に作成した装置の回路図を示します. 最近のPC(サーバ機を含む)ではシリアルインターフェースは省略されることも多いですがUSBは標準装備です。電源供給も同時に行うことができるため使いやすい形になります。 ここでは秋月電子製のUSB-シリアル変換モジュールを使用し、これ経由でPCに接続しています。
Fig.2 温度測定回路図


測定装置基板


PC接続


l実際の測定結果が図3です。これはオフィスに置いた社内システムのサーバラックで温度測定を行ったものです。5分間隔で温度測定を行った結果をrrdtoolを使ってグラフ化しました。
Fig.3 サーバラック温度測定結果


日によって温度変化の様子に大きな違いがあることがわかりました。たとえば休日にオフィスの空調が止まっていると温度の上昇が大きいことがわかりました。 これによって休日に必要のない機器の電源を止めたり、サーバのあるスペースのエアフローを改善するなどの対策が必要であることがわかりました。 次回は測定に使用したプログラムや1-Wireの簡単な話をしたいと思います。
 KLab若手エンジニアブログのフッター