趣味のページ

●雑記のメニューに戻る


■AVR(Arduino)にLM35温度センサをつなげた場合に正しくA/D変換出来ないトラブル(2012年2月15日)

Arduinoの入門書か何かにLM35温度センサの使用例として↓こんな回路が載っていた。

見ての通りLM35とArduino(AVR)を直結してるような、一見何の変哲も無い回路なのだけども
コレが正常に動作しないことがあるという(ある意味)面白い相談を受けたわけだ。

どうだろうか?
温度センサーICをA/Dコンバータに繋げただけ。ホントにただそれだけだ。
どこに問題があるというのか?

最初にお断りしておくけども、この現象(トラブル)は、「必ず起きる」ものではない。というか、
入門書に堂々と載っているくらいの回路だから、大抵の場合では素直にすんなり動作するのだとは思われる。
…いや、良く知らんけどね。
ぶっちゃけ、手元の数個のサンプルで症状を確認しただけなので、再現頻度とかそのあたりは良く判らない。

それでも敢えて、わざわざこうしてメモを書くのは、このトラブルが入門者にとって比較的「たちが悪い」からだ。
例えばごく簡単なコード(Arduinoのスケッチ)では症状が出ない事が多い。
だから入門書の簡単なサンプルコードの通りだと動作する(してしまう)が、
そこに手を加えて何かを始めようとすると、いきなり発症したりする。
なんかもう、普通の入門者ならココロをへし折られそうなシチュエーションである。

というわけで、同じ現象で悩んでいる人がいるかもしれないので、ここにメモを書いておくことにした。

なお、これはArduino(AVRのATmega系)に限らず、似たようなADC(というかS/H部)であれば、
他のチップ、例えばPICとかH8でも起き得るし、問題が起きる相手(センサー)もLM35には限らない。
実際、この手のトラブルが最初に持ち込まれたのは10年くらい前のH8マイコンだった(気がする)。

あまりに殺風景なので。描いてるマンガのラフとかですまぬが。

【現象】
この問題は、以下のような実験方法で確認することが出来るかもしれない(あなたの個体で再現するかどうかは判らない)。
analog4とanalog5にそれぞれ下記の回路図のようにボリュームとLM35を接続する。
  ※別にanalog4とanalog5じゃなくても、他のアナログ入力ピンでもよい。
  ※ボリュームの抵抗値は、これは適当に分圧さえ出来れば良いので、10kΩ〜1kΩくらいならOK。

実験回路

そしてanalog4とanalog5をそれぞれA/D変換して値をシリアルポートで送信し、ArduinoIDEのシリアルモニターで受信する。
以下、何の変哲も無いコード(Arduinoスケッチ)だし、別にキッチリこの通りである必要も無い。

void setup(){
Serial.begin(9600);
}
void loop(){
int a4,a5;
a4=analogRead(4);
a5=analogRead(5);
//a4とa5の値をシリアルポートで出力
Serial.print(" analog4=");
Serial.print(a4,DEC);
Serial.print(" analog5=");
Serial.println(a5,DEC);
delay(500);
}

これを実行すればパラパラとデータが送られてくるはずだ。

で。

この状態でボリュームを0V→5Vへと動かせば、当然ながらanalog4の値も0→1023へと変化する。
シリアルモニターで受信するとこんな感じだ。

 analog4の値が0→1023へと上昇

しかしよく見ると、なぜかanalog5(LM35)の値が変動してしまっている。
このケースでは、なんか中央付近(ボリューム真ん中?)あたりで5カウントほど下がっている。
1LSB=5mVなので25mVくらい。
温度に換算すると(LM35は10mV/℃なので)2.5℃相当。結構な誤差なのだが、
条件によってはもっと大きな誤差が出る時もあるし、そうでない時もあるし、
また必ずしも真ん中が凹むわけでもない。

あと、ボリュームの位置によってはLM35の値が不安定になったりする場合もあるかもしれない。

 ボリュームを操作していないのにanalog5がふらつく

いずれにしても、LM35の電圧を正常に読み取れていない。
なぜこんな単純な回路で、こんな現象が起きるのか?
一見ありふれたつまらない日常も、よく見ると不思議でいっぱいだ!
  ※現場に行くと、あふれんばかりの不思議だらけで、目を覆いたくなるぜ!

【推測される原因】
単にArduinoを動かしたいだけの人(電気に興味が全く無い人)とかは、ここはスキップして対策のみ読んでくれ。

さて。
↓これがAVRのA/DコンバーターのS/H部の等価回路。見ての通りADCnから入力されたアナログ電圧をCS/Hで保持している。
 S/H部回路図。 AVRデータシートから引用
A/D変換の際(正確にはサンプル時)には、図中のスイッチがONとなり、CS/Hへの充電(または放電)が瞬間的に行われるわけだが、
そのチャージ電流は、当然ながらアナログ入力ピン(図中ADCn)から供給されることになる。
逆に言えば、アナログ入力ピンへ接続する信号(今回はLM35)には、その充電電流を供給できるだけのドライブ能力が要求される。
具体的には「インピーダンスは10kΩ以下にしてね」とAVRのデータシートには(一つの目安として)書いてある。

で、そのLM35のドライブ能力であるが、以下は推測も入り込むので注意
まずはLM35の等価回路だが、
 National SemiconductorLM35データシートより引用
ここで出力段に注目してみる。
簡略化して描くとこんな感じだね↓。
 LM35の出力段を簡略化
ここで、「流れだし」についてはトランジスタが強力にドライブしてくれるので、出力インピーダンスはほぼゼロだ。
なので、AVRのホールドキャパシタCS/Hの充電は余裕でOKだと思われる。
逆にCS/Hの「放電」はと言うと、これは上図「吸い込み」方向の電流となるのだが、
見ての通り、これは抵抗Rに頼ることになる。だからRが充分に小さければ(インピーダンスが低ければ)良いわけだけど、残念ながらそうなってない。
(というか、そもそもこのR(データシートでのR2)はドライブ用ではなくで、OPアンプA2へ負帰還をかけるためだろうね)
で、このRの実際の値はと言うと、手持ちの個体を見た感じの勝手な推測だけども、どうも50kΩくらいじゃないかと思うのだが、いずれにしても
LM35の出力インピーダンスを無条件に「低い」と考えてはマズそうだ(少なくとも吸い込み用には設計されていないだろう)。


しかし、だ。


LM35のデータシートを見ると、こんな事が書いてある。
 National SemiconductorLM35データシートより引用
…あれ?
誇らしげに「出力インピーダンスが低いですぜ」と書かれているじゃないか。

実はこのデータシートの「特長」の項目というのは、ぶっちゃっけ気を引くためのセールストーク的な意味合いが強いので、
まぁさすがにウソは書かれてはいないけども、「ある条件では」とか「そのようなオプションも特注で承ります(が、高価だよ)」とか、
なかなか結構油断できないトコロなのだ。
ある意味難易度が高くて読解力が要求される(笑)項目。
なので、「実際の所どうなの?」というのは「電気的特性」を読むことになる。
こちらは細々と条件とか言い訳とか書いてあって、わりと地に足が付いた感じのする話だ。

            くどいようだけどもNational SemiconductorLM35データシートより引用
LM35と一口に言っても結構バリエーションが豊富で、無印、C、D、A、CA等があり、さらにパッケージのバリエーションまであるわけで、
我々がお店で買ってくるのは大抵Dタイプ(LM35D)なのだけども、ククク、ヤツは我々LM35四天王の中でも一番の小物というか安物。
そのLM35の特性のなかで注目すべきは「Load Regulation」の項目で、Typical値で±0.5mV/mAとなっているが、これは
すごく大雑把に言えば、出力インピーダンス0.5Ω相当。
先の「特長」で謳っていたほどでは無いが、まぁ十分すぎるほど低い。何の問題も無い。

…が。

赤で囲った部分を見てみると、「0≦I≦1mA」などという但し書きがある。
これは「出力電流(I)が0〜1mAの範囲という条件に限る」と言う意味なので、それ以外、
つまりゼロ以下(=マイナス)に関してはノーコメントということだ。

ちなみに出力電流は「流れだしをプラス」で表現するので、マイナスは吸い込み方向を意味するので、
要するに「吸い込み側のインピーダンスに関して、データシートには何のコメントも約束も無い」という事になるわけだ。
明記されていないと言う事は、実際のインピーダンスは、高いかもしれないし、低いかもしれないし、良く判らないわけだが、
少なくても「LM35の出力インピーダンスは充分に低いので、ADCに直結OK」と言えるだけの根拠は見当たらなさそうだ。

そんなわけでデータシートを眺めてきたわけだけども、
等価回路からも電気的特性からも、「吸い込み側のインピーダンス、高いんじゃね?」と思えてならないわけだな。
というか、「低いと書かれていない」「メーカーが保証していない」のであれば、とりあえず自力で現物をチェックしてみよう。
もしLM35が手元にあるのなら↓こんな感じに「吸い込み方向」に負荷をかけて、出力電圧がどうなるか実験してみると良いかも。
 
この「100kΩ」というのは負荷としては極めて軽いわけで、
これがLM35ではなくて、例えばOPアンプのボルテージフォロアとかであれば、こんな100kΩの負荷ごときでは、それこそビクともしない。
その「軽い負荷」がLM35にどの程度の影響を及ぼすか、実測してみるわけだ。
もしこれで出力電圧が変動するようならば、そこから大雑把に出力インピーダンスを求められるわけだけど、
実際うちにあったLM35では、先にも書いたけども出力インピーダンスは50kΩ程度だったわけだよ、かなりでかいのよ。
もちろん、あなたの持っているLM35がどうなのかは判らないから、それは自分で測ってくれ。

さて、仮にドライブ能力が不足してるとどうなるか?
まずは先にも書いた通り、CS/Hへの充放電がスローになる。当然だね。
もう一点、ドライブ能力不足状態では、A2(等価回路図中のOPアンプね)のイマジナリ・ショートが破綻する。
その場合にA2は一瞬「気を失った」状態となるかもなので(たぶん妙なオーバーシュートとかが起きる)、
そうするとCS/Hへの充放電がさらに遅延することになる。
いずれにしても、ドライブ能力が不足するとA/D変換に深刻な影響を及ぼす可能性がある

…って、未確認なんだけどね、実は。
間違ってたらごめんね。ま、雑記のヨタ記事だからね。
つかオシロ欲しいなぁ。
※なお、この現象はA/D変換した値がふらついたりするなど「ノイズっぽい」挙動ではあるのだけども、しかしこれはノイズでは無い。
なので、一般的なノイズ対策は効かない。
例えば、AVRのデータシートの「Analog Noise Canceling Techniques」に従っても改善しない。
安直に「ノイズが乗っている」と判断してしまうダメ回路屋も多いので注意。

※LM35とよく似た温度センサーICでLM60とか61という製品が存在するが、等価回路を見る限り出力段はLM35と類似してるので、
(実際、吸い込みが弱いので)原則として同様な注意が必要と考えた方がよさげ。
■しかしながら話はここでは終わらない。


いきなり話が飛んで申し訳ないのだけども、
この手のADCは、常に過去を引きずって生きている。
具体的に言うと、直前のA/D変換でチャージされた CS/Hの電圧(電荷)は、結構いつまでもそのまま残っている。

例えば先の実験回路(ボリュームとLM35のヤツね)からLM35を外して(つまりanalog5を「空きピン」にして)
そのままコードを実行してみるとわかりやすい。
何も繋がっていないはずのanalog5は、analog4に近い値を返すし、ボリュームを動かせば連動する。
つまり直前の変換結果に引きずられている。

CS/Hにチャージされた電圧(電荷)が、A/D変換完了後にどういう運命をたどるかというと、
次の変換に備えて適切に処分されるなんて事は全く無くて、単純に放置されている(たぶん)。
放置された電荷はそのままCS/Hでヒマしてる事になる。行くところも無くてぶらぶらしてる。
だから、ここで空きピンに対してA/D変換を実行すると、当然CS/Hには全く充放電が行われないから(そりゃあ相手が空きピンだからな)、
それはつまり前回の、残留してヒマしてる電荷をもう一度A/D変換することになる。
だから直前のA/D変換とほぼ同じような値を得ることになる。

つまりADCは常に過去を引きずっている。
そして、そんな過去からキレイに完全に解放してあげるには、充分に強力なドライブ能力でCS/Hを完璧に上書きする必要があるというわけだ。
タイヘンだな、LM35氏。

…が、実はそうタイヘンでもない場合もある(笑)。

例えばADCが直前に5VをA/D変換したとすれば、CS/Hにはその産業廃棄物的な5Vがチャージされたままだ。
ここで気温25℃のLM35は0.25Vを出力しようとするわけだけど、
それはつまり5VフルチャージなCS/Hを、ほぼスッカラカンな0.25Vまで放電する、と言う意味だから
これはLM35にとってはキツイ条件じゃないかと思われる。というか、かなりやばい。

が、逆に言えば、前回のA/D変換が5Vじゃなくて0.25V近辺ならば、
つまりCS/Hに既に0.25V近辺がチャージされていれば、
これならLM35は充電も放電もほとんど必要無いから、ドライブはぐっと楽になる。

そんなわけで、
直前にどんな電圧をA/D変換したかにより、このLM35のトラブルの発生確率は左右される。

【対策】
対策をいくつか試してみた。

1.抵抗をぶら下げる。

 Rを追加する

LM35の弱点である「吸い込み側」を適当な抵抗で補助してやると、それなりに改善する模様。
例えば10kΩくらいをぶら下げて実験してみると、割と安定動作っぽくはなる。
一方、抵抗値が極端に小さいとLM35自身の発熱で測定温度に誤差が生じるので、下限は1kΩくらいか。
ただ、無駄な電流が流れるので電池動作とかには向かない方法ではある。

2.コンデンサをぶら下げる

 Cをぶら下げる。発振止めの抵抗も必要。

AVR内S/HのCが14pFならば、その1000倍(≒10bit分解能)以上の容量、例えば0.1uFとかをぶら下げておけば良いはず。
ただし、そのままCをぶら下げるとLM35が発振するかもなので、発振防止に抵抗が必要。
また、AVRの保護用として念のために保護抵抗(10kΩ)を入れているが、まぁ、こっちは無くても大丈夫かもしんない。
この方式だと消費電流は増えずに済むし、そもそも確実な効果が期待できる。
なお、一見するとRCによる「ノイズフィルタ」に見えるかもだけども、もちろん全然違う。

3.A/Dを空読み。
1回のチャージで足りないのなら、何度か繰り返せば良い。たとえば以下のコードのように。

a5=AnalogRead(5); //空読み。 a5の値は捨てる
a5=AnalogRead(5); //本番

一昨年あたりのHS15湿度計ネタの時に採った方法がコレ。
ただし、結果を推測しづらいので(保証出来ないので)よほどでなければ使いたくない方法。

4.ボルテージフォロアを入れる。
まぁ当たり前すぎるけども、コレがホントに正攻法なんだろうなぁ。回路は略。

   * * *

さて、これまでの話の通りであるならば、
この問題は原理的に以下の条件では表面化(発症)しない。

 ・アナログ入力ピンに繋げているのはLM35が1つだけ。
 ・かつ、比較的短い周期でA/D変換を繰り返す

仮に気温が25℃であれば、LM35の出力電圧は0.25Vなので、
ADCはこの0.25Vだけを繰り返しA/D変換することになる。
結果、CS/Hは常時「0.25Vチャージ済み」状態となる。

で、先にも書いた通り、「0.25Vチャージ済み」のCS/Hに対して0.25Vをサンプル動作しても充放電の電流は流れないので
今回のような問題は起きず正常動作に見える(表面化しない)ことになる。

もう気がついたかもしれないが、
つまり、よく入門書で見かける「LM35を一つだけ繋いで温度を表示させる」ような簡単なサンプルが
コレに該当するわけだ。
なので、ホントは問題を抱えているにもかかわらず正常に動作したように見えてしまっている個体もあるかもしれない。
そしてその場合、読者がそこから次のステップを踏み出した瞬間に(例えば別のセンサを追加したとか)
原因不明のトラブルに見舞われる。
というか、実際そんな経緯で相談を受けたのが今回のネタの発端。

【まとめ】
・LM35とArduino等を直結した場合、正しくA/D変換できないケースがあるかもしれない
・ただし、その場合でも「Arduino入門書にあるような簡単なサンプル」では一見正常に動作してしまう。
・「LM35以外をADCにぶら下げたら途端に挙動不審となる」場合は、この不具合を疑った方が良いかもしれない
・「かもしれない」という記述の通り、発生頻度は正直良く判らない。ごめんね。

  *  *  *

そんなわけで、結構事情は複雑なのだ。
もう一度、そもそもの「回路図」を見てみる。

当初「センサーとADCを繋げただけの簡単な回路」に見えたのは、それは錯覚だ。
どちらのデバイスにも、内部には泥臭い回路とか固有の事情が詰まっているわけで、
この図は、単にそれらを省略して描いているにすぎない。
そして省略されたのが「必要な回路情報」だったりすると、良く判らない現象が起きてしまう。
その意味で、この図は実質的にデバイス同士の事務的な結線図に過ぎず、
電子回路を表現した回路図などでは無い。

最近はホントにIC化・ユニット化が進んでしまったおかげで、↑こんな回路図がとても多くなっているが、
このような回路図を前にした場合、我々は二つの選択肢を意識すべきじゃないかと思う。
事務屋になるのか、回路屋になるのか。
どちらを選ぶべきという事ではなく、選択肢が在ることを意識したほうがよいと言う話かと思う。

  *  *  *


…と、ここまで書いておいて何だけども、今回は決定的証拠が無いわけさ。
ホントならLM35の出力をオシロスコープで観測して、A/D変換の瞬間に揺さぶられる現場が押さえられればいいんだけど
いかんせんオシロ持ってないので、推測の域でしかないというか状況証拠だけっていうか、
そんな感じに終始してて申し訳ない

なんかもうね、いい歳した回路屋がね、
嫁さんが居ないのはともかくオシロも持ってないってのはどうよ?などと
ちょっと考えてしまった。

…いや、考えてしまったというか、
正直欲しいわけですよ、便利とか必要とか、そういう理由付け以前に。オシロ。
ガキの頃からの憧れだからね。
なんか一番安いヤツが秋月で3万くらいとかですよ、
このまえうっかり買っちゃったPS3と同じじゃないか、
つか、なにゲーム機なんて買っちゃってるのさ俺。

…いや、一度くらいはゲーム機ってモノを買ってみたいなー…って思って。
そんなわけで、「初めてのゲーム機はPS3でした〜」などという、まるで平成生まれ世代状態の俺様でございます。

しかし、毎年一回くらいは、この「オシロ欲しい病」にかかるわけで、
そんでもってウダウダと1〜2週間くらい悩んで、しかしその後は快方へ向かうみたいな。
ああ、マジで発病と回復を毎年繰り返してるな、これ。
まるでインフルエンザ的イベントなのだけども、
そして今まで耐えてきたのだけども、
素直に買っちまえば解決じゃね?
この先、毎年楽じゃね?

…ということに(ようやく)気がついたらしい。

オチも無く終わる。