アナログ電圧出力のICは、温度や加速度といった物理量を電圧に変換して出力します。 Arduinoにはアナログ電圧入力がありますから、簡単に使うことが出来ます。
アナログ電圧入力ピンに入力できる電圧の範囲は 0[V]からArdunoの電源の電圧までです。5[V]で動作している Arduino Uno では5[V]まで、3.3[V]で動作している場合には3.3[V]までです。 この範囲を超える電圧(負の電圧を含む)を変換回路などなしに 直接入力することは出来ません。
特殊なIC以外は、ICの電源が Arduino の電源と同じでよいなら気にしなくても良いでしょう。
センサICの電源電圧がArduinoの電源電圧と同じなら特に考える必要はありません。 Arduinoの電源が5[V]で、センサICの電源電圧が3.3[V]のときには、Arduinoの3.3[V]ピンが使えるかもしれません。 ただし、センサICが必要とする電流が大きかったり、精密な電圧が必要なときには 別途用意する必要があるかもしれません。
センサICによっては、Arduinoに直接つなぐと、思った精度が出ない場合があります。 ICの出力インピーダンス(抵抗のようなもの)が 1[kΩ]以下なら問題は出にくいと 思いますが、それを超えると誤差が増える原因になります。 その場合には、抵抗やコンデンサ、あるいはオペアンプといった部品で回路を作る 必要があるかもしれません。
アナログ電圧を入力できるピンは 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 |
ナショナルセミコンダクタの温度センサ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 も忘れないでください。これで整数と区別をします。 少し計算が遅くなりますが、簡便な方法です。
ここまでをまとめると次のようになります。