アナログ入力の解説

# はじめに
ここでは、Arduino UNOで **<font color=green>アナログ入力</font>** の実験をします。

目次へ戻るには [ここ](https://qiita.com/hsgucci/items/085680123f758c8c3eb4#%E5%AE%9F%E9%A8%93%E6%89%8B%E9%A0%86) をクリック

※本ページは実験のテキストです。

# アナログ入力

[デジタル入力の解説](https://qiita.com/hsgucci/items/4baf40a9855cee8e769a) では、**<font color=red>デジタル入力</font>** の機能を説明しました。
特定のピンに接続されたスイッチのON(5V)/OFF(0V)状態を読み込み、シリアル通信でＰＣへ送信しました。

今回は、**<font color=green>アナログ入力</font>** です。
デジタル入力では、ONかOFF、5Vか0Vという二値しかありませんでしたが、
アナログ入力ではその中間の電圧、すなわち3.3Vとか1.06Vなどの値を受け取ることができます。

具体的には、下図のように、
![aios_board.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/43a41909-2612-92c8-d6db-3608a8abc111.png)
可変抵抗をブレッドボートに配置し、
 「**可変抵抗の状態をシリアル通信でパソコンに送信する**」
というプログラムをテストします。
また、次回の **<font color=purple>アナログ出力</font>** で使うためのLEDも配置します。

実際の作業としては
•【ハードウェアの作業】ブレッドボードに電子部品を配置し、適切に配線する
•【ソフトウェアの作業】配線した状態に合わせて、プログラムを作成する

の２つの作業を行います。

# ブレッドボートに部品を並べる

必要な部品を写真に示します。
![aios_parts.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/e14736a5-4568-b5b4-aa26-f249457411d0.png)

- 可変抵抗（スターターキットのものは10kΩ）
- LED（何色でもよい）
- 抵抗(220Ω)　赤赤茶 （[抵抗早見表](http://part.freelab.jp/s_regi_list.html)）
- ジャンパ線（適当に）

が必要です。

---
それでは、下の画像を参考に、ブレッドボードに配線してください。
![aios_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/ec5f5059-291d-bef6-edd9-33ac58496721.png)


回路図としては以下のようになっています。
![aios_sch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/1825bd07-02e9-04fc-72c5-b8cfaa6526d1.png)

参考までに、筆者が配線した写真を示します。
![aios_board.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/43a41909-2612-92c8-d6db-3608a8abc111.png)


今回も、配線作業で注意すべき点をいくつか挙げておきます。

## LEDの向きに注意
ダイオードは、アノード(A)からカソード(K)へしか電流が流れません。逆流はできません。
したがって、LEDの向きを間違えると、電流が流れないので点灯しません。
LED(Light Emitting Diode)は足の長いほうがアノードなので、注意しましょう。
![aios_led.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/c73b70b4-b78b-16cf-e8dd-c3779cfc11e7.png)


## 可変抵抗は真ん中が大事
可変抵抗の足は、二等辺三角形を作っています。
このとき、底辺にあたる部分が抵抗の両端、頂点が可変部になります。
![aios_vr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/eaf3ece6-acc8-ccf9-36e3-4fe9b1cb8b55.png)
底辺の両端に+5VとGND(0V)を接続し、頂点をアナログ入力ピンに繋ぐことで、0～5Vの電圧を計測できるのです。
接続を間違えると、予期せぬ動作をしてしまう（綺麗に値が変化しないなど）ので注意しましょう。


# サンプルスケッチを読み込む
では次に、ソフトウェア側の作業を行います。

**可変抵抗の状態を読んでシリアルで送信するプログラム**は、Arduino IDEの開発環境に予め用意されています。

それでは、サンプルプログラムを開きましょう。
[**ファイル**]-[**スケッチ例**]-[**03.Analog**]-[**AnalogInOutSerial**]を開きます。
![aios_sketch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/100226d4-e8cb-4c2f-1234-f42ed7bce21b.png)

これまでは、[01.Basics]を使ってきましたが、今回は[03.Analog]です。
スケッチ例の名前も、「AnalogIn（アナログで入力）して、OutSerial（シリアルで出力）」と、何をやっているか明確ですね。

# コンパイルと、プログラムの書き込み
それでは、[Lチカのプログラムをコンパイルし、書き込んだ](https://qiita.com/drafts/b6fdd726395c327444d1/edit#%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB)時と同様に、
コンパイルと、マイコンへの書き込みを行ってください。

# 実行結果
[シリアル通信をしてみよう](https://qiita.com/hsgucci/items/eee5894e3651d0a8cb75#%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%AB%E3%83%A2%E3%83%8B%E3%82%BF%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9) の時と同様に、シリアルモニタを開きましょう。

プログラムが実行されると、下図の様に、メッセージが連続して表示されます。
![aios_result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/2e659c01-2579-380c-53da-a0045fe23fa8.png)

`sensor = `というのが可変抵抗の値、
`output = `というのがLEDへ出力している値です。

これが確認できれば成功です。

<font color=red>**数値が安定せず、色々な値が混じっている**</font>
という場合は、可変抵抗の配線にミスがあると思われます。

---
では、可変抵抗のツマミを右や左へ回してみましょう。
`sensor =`　の値が変化することが分かります。
限界まで回すと、最小値の0か最大値の1023に振り切ります。
![aios_limit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/fe265b6a-1cb7-34cb-3aa6-a5184b3a2b4c.png)


# スケッチの解説
実際のプログラムは英語で書かれているので、日本語に訳したものを下記に示します。

```cpp:AnalogInOutSerial.ino
/*
  アナログ入力, アナログ出力, シリアル出力

  アナログ入力ピンの値を読み込み、その結果を0～255の範囲に変換します。
  0～255の値は出力ピンのPWM(パルス幅変調)値として使います。
  また、シリアルモニターにも結果をプリントします。

  回路:
  - アナログ入力ピン0に、ポテンショメータ(可変抵抗）
    ポテンショメータの中央のピンをアナログ入力ピンに接続する
    ポテンショメータの側面のピン達は、+5V と GND に接続する
  - LED はデジタル出力ピン9と、GNDに接続する（もちろん電流制限抵抗が必要）
*/

// これらの固定値は変更してはいけません。使用するピンに名前を与えています。
const int analogInPin = A0;  // ポテンショメータに接続するアナログ入力ピン
const int analogOutPin = 9; // LEDに接続するアナログ出力ピン

int sensorValue = 0;        // ポテンショメータから読み取った値
int outputValue = 0;        // アナログ出力でＰＷＭ出力する値

void setup() {
  // シリアル通信を初期化する。ボーレートは9600bps
  Serial.begin(9600);
}

void loop() {
  // アナログ入力の値を読む
  sensorValue = analogRead(analogInPin);
  // アナログ入力の0～1024の値を、アナログ出力の使用範囲0～255に変換する
  outputValue = map(sensorValue, 0, 1023, 0, 255);
  // アナログ出力値を変更する
  analogWrite(analogOutPin, outputValue);

  // シリアルモニターに結果をプリントする
  Serial.print("sensor = ");
  Serial.print(sensorValue);
  Serial.print("\t output = ");
  Serial.println(outputValue);

  // アナログ->デジタル変換のために2ミリ秒のウェイトが必要
  delay(2);
}
```

---
それでは、それぞれの関数を見ていきましょう。
次回の **<font color=purple>アナログ出力</font>** で解説する部分は割愛しています。
今回は **<font color=green>アナログ入力</font>** だけ。

まずはグローバル変数とsetup関数です。

```cpp:グローバル変数とsetup関数
// これらの固定値は変更してはいけません。使用するピンに名前を与えています。
const int analogInPin = A0;  // ポテンショメータに接続するアナログ入力ピン

int sensorValue = 0;        // ポテンショメータから読み取った値

void setup() {
  // シリアル通信を初期化する。ボーレートは9600bps
  Serial.begin(9600);
}
```

アナログ入力に使うピン`A0`に、int型の固定値(const)`analogInPin`という名前を付けています。
可変抵抗から読み取った値は、int型の変数`sensorValue`に格納します。

次に、setup関数の内部では、
`Serial.begin`関数で、シリアル通信を9600bpsで初期化しています。
デジタル入出力の際には、`pinMode`関数によるピンの初期化がありましたが、
**アナログ入出力では何も書く必要がない**、というのが特徴ですね。

アナログ入力のピンは、デジタル入出力とは反対側にあります。
![aios_pinout.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/b7731c0b-be1d-a8e6-5332-5c7846054ef5.png)
デジタル入出力は0～13という名前が付いていますが、
アナログ入力はA0～A5というように、アナログを表す`A`が付いていますね。
アナログ出力に関しては次回説明します。

---
次はloop関数を見ていきます。

```cpp:loop関数
void loop() {
  // アナログ入力の値を読む
  sensorValue = analogRead(analogInPin);

  // シリアルモニターに結果をプリントする
  Serial.print("sensor = ");
  Serial.print(sensorValue);
  Serial.print("\t output = ");
  Serial.println(outputValue);

  // アナログ->デジタル変換のために2ミリ秒のウェイトが必要
  delay(2);
}
```
`analogRead`関数は、アナログ入力モ専用のピンの値を読み取る命令です。
解説：[analogRead解説](http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=2113)

`analogRead`関数が返す値は、5Vのとき1023、0Vのとき0です。
なのでint型の変数`sensorValue`には、0～1023の値が入ります。


次は、`Serial.print`関数および`Serial.println`関数で、文字列や変数値を表示しています。
Ｃ言語のプログラミング経験者であれば、

```cpp
printf( "sensor = %d\t output = %d\n", sensorValue, outputValue );
```
と書く方が理解しやすいと思います。
しかし、Arduinoには、`Serial.printf`という関数はないので、
文字列だけを表示する`Serial.print`と、変数の中身を表示する`Serial.print`を別々に書かなければなりません。

最後に、`delay`関数を使って2ミリ秒のウェイトを入れています。
analogReadで使うアナログ->デジタル変換機能は、瞬時に値を読み取れるものではなく、
コンデンサ等に一旦蓄えた後に、比較計算を行う装置を経由するので、変換時間がかかるのです。



# まとめ

アナログ入力では、

- analogRead でピンの状態を読む
- analogReadで取れる値は0～1023
- アナログ入力はA0～A5という、それ専用のピンがある。
- アナログ入力には変換時間が必要なので、数ミリ秒の待ち時間を入れる

という事が分かったと思います。


 [目次](https://qiita.com/hsgucci/items/085680123f758c8c3eb4#%E5%AE%9F%E9%A8%93%E6%89%8B%E9%A0%86) へ戻って次の作業を行ってください。