[Arduinoのすすめ][ArduinoConf][ArduinoMonitor][iArduino]

ArduinoでセンサIC(アナログ電圧出力)を使う(詳しい話)

アナログ電圧出力のICは、温度や加速度といった物理量を電圧に変換して出力します。 Arduinoにはアナログ電圧入力がありますから、簡単に使うことが出来ます。

アナログ電圧入力を使う

アナログ電圧入力ピンの入力電圧範囲

アナログ電圧入力ピンに入力できる電圧の範囲は 0[V]からArdunoの電源の電圧までです。5[V]で動作している Arduino Uno では5[V]まで、3.3[V]で動作している場合には3.3[V]までです。 この範囲を超える電圧(負の電圧を含む)を変換回路などなしに 直接入力することは出来ません。

特殊なIC以外は、ICの電源が Arduino の電源と同じでよいなら気にしなくても良いでしょう。

センサICの電源

センサICの電源電圧がArduinoの電源電圧と同じなら特に考える必要はありません。 Arduinoの電源が5[V]で、センサICの電源電圧が3.3[V]のときには、Arduinoの3.3[V]ピンが使えるかもしれません。 ただし、センサICが必要とする電流が大きかったり、精密な電圧が必要なときには 別途用意する必要があるかもしれません。

直接接続できないセンサICもあるかも

センサICによっては、Arduinoに直接つなぐと、思った精度が出ない場合があります。 ICの出力インピーダンス(抵抗のようなもの)が 1[kΩ]以下なら問題は出にくいと 思いますが、それを超えると誤差が増える原因になります。 その場合には、抵抗やコンデンサ、あるいはオペアンプといった部品で回路を作る 必要があるかもしれません。

analogRead関数

アナログ電圧を入力できるピンは A0 から A5 です(Arudino Unoの場合)。 analogRead関数を使って値を読みます。たとえば

        a = analogRead(A0);
とすると読んだ値が a に代入されます。
        if (analogRead(A0)>100) {
                digitalWrite(LED, HIGH);
        } else {
                digitalWrite(LED, LOW);
        }
といった使い方も出来ます。 値は入力の電圧に比例していて、0[V]のとき0で、AREFの電圧(マイコンの電源電圧と同じで使うことが多い)のとき1023になります。たとえば、マイコンの電源電圧とAREFが5[V]のときに、ピンの電圧が2.5[V]なら、
2.5[V]÷5[V]×1024 = 512
になります。もう少し正確に書くと 5[V]/1024 = 0.0049[V] = 4.9[mV] の単位で、1ずつ変わります。つまり
入力電圧analogRead関数の値
0[V]以上0.0049[V]未満 0
0.0049[V]以上0.0098[V]未満1
0.0098[V]以上0.0146[V]未満2
0.0146[V]以上0.0195[V]未満3
4.9902[V]以上4.9951[V]未満1022
4.9951[V]以上 1023
となります。入力の電圧が少し違ってもanalogRead関数の値は同じになります。

電圧の換算

ナショナルセミコンダクタの温度センサLM35を使う場合を考えてみます。 LM35は10.0[mV/℃](=0.0100[V/℃])で温度を電圧に変換して出力するICです。25℃なら、

0.0100[V/℃]×25[℃]=250[mV]=0.25[V]
を出力します。これをArduinoのA0ピンに直接つなぎanalogRead関数で値を読むと
0.25[V]÷5[V]×1024 = 51 {=analogRead(A0)}
となります。これから温度の10倍に換算すること(25℃のときに250)を考えます。
(0.0100[V/℃]×T[℃])÷5[V]×1024 = 51 = analogRead(A0)
ですから
T = analgoRead(A0)×5÷1024÷0.0100
  = analgoRead(A0)×5×100÷1024
で温度[℃]は求められ、温度の10倍は
10T = analgoRead(A0)×5×1000÷1024
    = analgoRead(A0)×5000÷1024
で求められます。計算してみると
51×5000/1024 = 249
となります。250にはなりませんね。前後も計算してみます。
50×5000/1024 = 244
51×5000/1024 = 249
52×5000/1024 = 253
となりました。どういうことか分かりますね。温度の最小の刻みが約0.5℃になっているので、 換算したときには刻みの小さい方の値になっているのです。 また、Arduinoの電源電圧は5[V]や3.3[V]ちょうどではありません。 電源電圧が変わると値も変わることにも注意します。

計算の注意

Arduinoで計算が -32768〜32767 の整数の範囲を超えたり、小数点以下を計算するには、 注意が必要です。

50×5000/1024 = 244
は正しく計算されないかもしれません。それは、途中の計算が
50×5000 = 250000
と32767を超えているからです(コンパイラが賢いなら気にしなくてよい)。では、
50/1024×5000
としたらどうでしょうか。
50/1024 = 0
となってしまうかもしれません。

こういった場合の、1つの解決策は途中の計算で、計算範囲を超えたり、割り算で小数点以下がでないようにすることです。また、if文などで判定するときには、analogRead関数の値を温度など物理量に 換算し直するのではなく、物理量をanalgoRead関数の値に換算します。たとえば25[℃] より高いか、低いかを判定するのに、あらかじめ計算した51をつかいます。

もう1つの簡単な解決策は float 型を使うことです。

float a = analogRead(A0);
と宣言、代入し、
a = a * 5000.0 / 1024.0;
と計算します。数値の後ろの .0 も忘れないでください。これで整数と区別をします。 少し計算が遅くなりますが、簡便な方法です。

まとめ

ここまでをまとめると次のようになります。


Arduinoのすすめ
Copyright (c) 2013, Noriaki Mitsunaga