Arduinoでアナログ入力

Arduino

今回は Arduino のアナログ入力について実験します。

アナログ入力の実験

Arduino のアナログ入力端子

Arduino にはアナログ入力機能があります。たとえば Arduino UNO には6つのアナログ入力端子( A0 ~ A5 )を備えています。

デジタル入力端子では端子の電位を HIGH/LOW(閾値より高いか低いか)の二段階で読み取ることができ、これによりスイッチのオン/オフなどを判断することができました。

これに対してアナログ入力端子では、端子の電位が 0 V なのか、2.5 V なのか、3.3 V なのか、5 V なのか…など『どのくらいの電位』なのかをデジタル数値化する機能を備えています。

Arduino UNO のアナログ入力端子では、電位が GND と等しい( 0 V )のときに読取値が 0、電位が電源と等しい( 5 V )のときに読取値が 1023 となるように、1024段階(10bit)に数値化して読み取ることができます。5 V の範囲を1024段階なので、分解能(=入力電位にどれだけ差があれば違う値として読み取れるか)は約 4.9 mV ということになります。

このように、電位などのアナログ値をデジタル数値化することを A/D変換(Analog/Digital変換)、A/D変換を行う装置のことを A/Dコンバータ(Analog/Digital Converter、ADC と略すこともある)といいます。

Arduino UNO 以外では、4096段階(12bit)の A/D コンバータを搭載している機種もあります。その場合、電源が 5 V なら分解能は約 1.2 mv 、電源が 3.3 V なら分解能は約 0.8 mV となります。

なお Arduino のドキュメントには、1回のアナログ値の読み取り(A/D変換)には 100 μs かかる、と記載されています。人間の感覚では 100 μs は一瞬ですが、デジタル入力 の読み取り( digitalRead() 関数の実行)が 4 μs 程度なのに較べると数十倍も時間がかかる処理です。

抵抗器による分圧

今回は、抵抗器によって 0 ~ 5 V の範囲の任意の電圧を作り出し、それを Arduino のアナログ入力で読み取る実験を行います。まずは抵抗器によって任意の電圧を作り出す方法について考えてみましょう。

まず、このような回路を用意します。2つの抵抗 \(R_1\) 、 \(R_2\) を直列に接続し、起電力 \(V\) の電源に接続します。電源の負極は GND に接続し、ここを電位 0 V とします。回路を流れる電流を \(i\) とすると、オームの法則より

\[V_1=i\cdot R_1\\V_2=i\cdot R_2\]

よって、

\[V_1:V_2=R_1:R_2\]

となります。このように、抵抗器によって電位差が分割されることを分圧といいます。このとき、各定稿の端子間電位差の比は抵抗値の比と等しくなります。

また、キルヒホッフの法則より、

\[V_1+V_2=V\]

です。A、B、C点の電位をそれぞれ \(V_A\) 、 \(V_B\) 、 \(V_C\) とすると、 \(V_A=0\) 、 \(V_C=V\) より、 \(V_B\) は

\[V_B=V_A+V_1=\frac{R_1}{R_1+R_2}\cdot V\]

となります。

この性質を利用して、\(R_1\) と \(R_2\) の比をいろいろ変化させれば、\(V_B\) の値を 0 ~ \(V\) の範囲で自由に帰ることができます。

可変抵抗器

可変抵抗器とは、抵抗値を変化させることのできる抵抗器です。

基本構造

可変抵抗器の構造は簡単です。一本の細長い抵抗体の上を、摺動子(稼働する電極)が抵抗体に接触しつつ滑り動くようになっています。こうすると、端子1~3間の抵抗体を、摺動子(端子2)の位置で2つの抵抗に分割したように扱うことができます。

抵抗体の太さ・厚みが一定だとすると抵抗値は抵抗体の長さに比例するので、摺動子が抵抗体の長さを分割するのと同じ比で抵抗値を分割することになります。

つまり、たとえば抵抗体全体の抵抗値が 10 kΩ だとすると、

摺動子が抵抗体を 1:9 に分割する位置なら 1 kΩ と 9 kΩ
摺動子が抵抗体を 5:5 に分割する位置なら 5 kΩ と 5 kΩ
摺動子が抵抗体を 8:2 に分割する位置なら 8 kΩ と 2 kΩ

の、2つの抵抗を直列に接続したのと同じ回路になります。このように、可変抵抗器は端子2の位置で分割される抵抗を 0:10 ~ 10:0 に連続的に変化させることができるのです。

入手の容易な可変抵抗器としては、このように抵抗体を円型にして軸を回転させることで摺動子を移動させるタイプのものが多いです。オーディオ機器の音量調節用などに広く利用されていて、秋月電子通商などで1個数十円程度で入手できます。

写真のものは『 B10kΩ 』と記されています。『 10 kΩ』は抵抗体全体の抵抗値が 10 kΩ であることを表し、『 B 』は摺動子の回転角と抵抗値の分割比の関係を表しています。

カーブ

実は可変抵抗器は、抵抗体の抵抗率が一定でないものも製品化されています。摺動子の位置と抵抗比(抵抗体全体の抵抗値に対する端子1-2間の抵抗値)が比例の関係にあるものを『Bカーブ』といいます。今回の実験の場合は、摺動子の位置と抵抗比(端子1-2間の分圧も抵抗比に比例します)が直線的なBカーブが判り易いと思います。

他に『Aカーブ』『Cカーブ』があり、それぞれ摺動子の地位と抵抗比の関係は下図のようになっています。

Aカーブは対数の逆数の曲線になっています。オーディオ機器の音量の制御にはAカーブのものがよく使われます。これは、人間の音量の感じ方が対数的、つまり『音量が大きいほど音量の変化を感じにくくなる』ため、その分『音量が大きいほど音量の変化が大きくなる』ようにした方がボリュームつまみの回転と音量の関係が比例しているように感じられるためです。

Cカーブは摺動子の位置と抵抗比が対数的な関係になっています。オーディオ機器の音質やエフェクタではこちらのカーブの抵抗器が使われています。

可変抵抗器の回路記号

可変抵抗器の回路記号は2種類あります。

可変抵抗器の3つの端子をすべて使用する場合には、通常の抵抗器の記号に摺動子を表す矢印が接触しているような記号(上図の左)を使用します。

端子を2つだけ使用して単一の『抵抗値が変化する抵抗器』として使用する場合は、通常の抵抗器に斜めに矢印がかかっているような記号(上図の右)を使用します。

製作

使用部品

部品名数量備考
ブレッドボード1小さなものでOK
可変抵抗
( 10 kΩ、Bカーブ)
1抵抗値は多少違っていてもOK
『基板取付用』のものがブレッドボードに直接挿せて便利です。
ジャンパ線
(オス-オス)
3赤×1本、黒×1本、緑×1本がオススメ

回路

今回の回路は以下の通りです。

Arduino の A0 端子を 10 kΩ 可変抵抗の端子2(摺動子)に、端子1を GND に、端子3を 5 V に接続します。今回は入力端子の電流制限抵抗は省略しています。

配線

配線は以下の通りです。

1. ブレッドボードに基板取付用可変抵抗器を挿しこみます。

2. 可変抵抗器の左側の足(端子1)と同じ列の穴Arduino の GND 端子 を黒のジャンパ線で接続します。

3. 可変抵抗器の右側の足(端子3)と同じ列の穴Arduino の 5 V 端子 を赤のジャンパ線で接続します。

4. 可変抵抗器の中央の足(端子2)と同じ列の穴Arduino の A0 端子 を緑のジャンパ線で接続します。

プログラム

PC で Arduino IDE を起動し、新規スケッチを作成して、以下の通りに入力します。

C++
#define ANALOG_PIN 0

void setup() {
  Serial.begin(9600);
}

void loop() {
  int value;
  value = analogRead(ANALOG_PIN);
  Serial.println(value);
  delay(200);
}

プログラムの解説

#defineで定数定義
C++
#define ANALOG_PIN 0

例によってアナログ入力に使う端子番号を定数 ANALOG_PIN として定義しています。プログラム中で関数の引数などに数値を直接指定するのではなく、このように(何の値なのかわかるような名前をつけた)定数として定義することは、プログラムの可読性やメンテナンス性を向上させます。

アナログ入力端子はデジタル出力/PWM 出力/デジタル入力端子とは独立した端子番号が与えられています。たとえば Arduino UNO には6つのアナログ入力端子があり、端子番号として 0 ~ 5 が指定可能です。

setup()関数
C++
void setup() {
  Serial.begin(9600);
}

今回はアナログ端子で読み取った結果をPCのシリアルモニタで見られるようにしたいので、setup()関数では Serial.begin(9600); でシリアル通信の初期設定を行っています。

アナログ入力端子は入力専用端子なので、デジタル出力/PWM 出力/デジタル入力端子のようにpinMode() 関数でモード(入力端子または出力端子のどちらとして使用するか)を設定する必要がありません。

analogRead() でアナログ入力端子の電位を読み取る
C++
void loop() {
  int value;
  value = analogRead(ANALOG_PIN);
  Serial.println(value);
  delay(200);
}

loop() 関数の前半では、ANALOG_PIN 番のアナログ入力端子の入力値を読み取ります。読み取った値は変数 value に格納します。

アナログ入力端子の電位を読み取るには、analogRead() 関数を使用します。
書式は以下の通りです。

int analogRead(int pin)

引数:

名前意味
pinint入力値を読み取るアナログ入力端子番号

返却値:

意味
int入力値を 0 ~ 1023 で返却(10bit A/Dコンバータ搭載の機種、Arduino UNO はこちら)
入力値を 0 ~ 4095 で返却(12bit A/Dコンバータ搭載の機種)
Serial.println() はモニタ用
C++
void loop() {
  int value;
  value = analogRead(ANALOG_PIN);
  Serial.println(value);
  delay(200);
}

analogRead() 関数で読み取り、value に格納された値は、Serial.println() 関数でシリアル通信によってPCに送られます。送られた値は Arduino IDE のシリアルモニタ等で読み取ることができます。

delay()は時間待ち
C++
void loop() {
  int value;
  value = analogRead(ANALOG_PIN);
  Serial.println(value);
  delay(200);
}

loop() 関数内の最後で、は delay(200); で1回の読み取りにつき 200 ms のウェイトを入れています。あまり高速で処理を繰り返しても仕方ないのでこのようにしています。ウェイトの長さは完全に好みの問題なので、もっと数値が大きかったり小さかったりしてもかまいません。

コンパイル&実行

では、USB ケーブルを Arduino に接続し、スケッチをコンパイル&実行してみましょう。

可変抵抗器の軸(動画では回転角度が判り易いようにツマミをつけています)を回すと、その回転角度に応じてシリアルモニタに表示されているアナログ端子の読取値が 0 ~ 1023 の範囲で変化するのが判るでしょう。

まとめ

  • Arduino UNO には6つのアナログ入力専用端子があり、0 ~ 5 V の電位を読み取れる
  • アナログ端子の入力値(電位)を読み取るには、analogRead() 関数を使う
  • 電位は 0(0 V)~1023(5 V)の 1024段階の数値で表される

コメント

タイトルとURLをコピーしました