デジタル入力の解説

# はじめに
ここでは、Arduino UNOで **<font color=red>デジタル入力</font>** の実験をします。

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

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

# デジタル入力

[Lチカ(デジタル出力)の解説](https://qiita.com/hsgucci/items/8ae1fc4bb542893d130b) では、 **<font color=blue>デジタル出力</font>** の機能を説明しました。
Arduinoの特定のピンを5VにしたりGNDにしたりすることで、LEDを点灯/消灯できました。

今回は、 **<font color=red>デジタル入力</font>** です。
入力なので、スイッチ等の人間の操作をマイコンで受け取ることになります。

具体的には、下図のように、
![drs_all.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/40d4722a-c284-7af0-c8e0-e08d68bdf5ad.png)



スイッチをブレッドボートに配置し、
「**スイッチの状態をシリアル通信でパソコンに送信する**」
というプログラムを作成します。

実際の作業としては

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

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


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

必要な部品を写真に示します。
![drs_parts.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/7f501e42-1c2c-ea52-bc52-ddccb32d1c9b.png)

- プッシュスイッチ(タクトスイッチ)
- 抵抗(10kΩ)　茶黒橙 （[抵抗早見表](http://part.freelab.jp/s_regi_list.html)）
- ジャンパ線(何本か)

が必要です。

この実験で準備している「[Arduinoスターターキット](https://www.switch-science.com/catalog/2628/)」では、
赤と黒の長いジャンパ線が用意されているので、これを電源のプラス(5V)とマイナス(GND)に使うと良いでしょう。

それでは、下の画像を参考に、ブレッドボードに配線してください。
![drs_board.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/3d590ba5-2ac1-3e03-257e-52a83d63616d.png)

回路図としては以下のようになっています。
![button_sch2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/1eaf18d8-693c-bbd4-13f0-e6955ca3c4e2.png)


参考までに、筆者が配線した写真を示します。
![drs_all.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/40d4722a-c284-7af0-c8e0-e08d68bdf5ad.png)

ポイントは、「**<font color=blue>プルダウン抵抗</font>**」です。

ある端子を、普段使わないときは常時OFF側にしたい、入力値としてはゼロにしておきたい場合、
「**GND(0ボルト)側に落とすために抵抗を入れるテクニック**」が「プルダウン」です。
下側(ダウン)に引っ張る(プルする)、です。
「プルダウンするための抵抗」を略して「プルダウン抵抗」と呼んでいます。

また、「**<font color=blue>プルアップ抵抗</font>**」もあります。
プルダウンとは逆に、常時ON(常に1)にしておくために使うテクニックです。

<font color=red>**プルダウン抵抗やプルアップ抵抗と言う名前の特別な抵抗が売っているわけではない**</font>ことに注意してください(^^;
プルダウン/プルアップに使う抵抗は、普通のカーボン抵抗や金属皮膜抵抗です。
電子部品屋さんで「プルダウン抵抗ください」なんて言わないように注意です！
初心者丸出しで超恥ずかしいですよ。（電気街で何度かそういうシーンを見たことがあります）


今回、ブレッドボードで配線作業をする際に注意すべき点をいくつか挙げておきます。

## スイッチの向きに注意
プッシュスイッチを使う際、**スイッチの向き**に注意してください。
下図の左の様に、プッシュスイッチの左右の足は内部的に導通しています。
４本の足がすべて独立しているわけではありません。
![drs_switch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/62e09084-7483-211f-d59f-6f2f6a1e69a3.png)
裏側を見て、スイッチが入っている方向をしっかり確認する必要があります。

もしスイッチの縦と横の向きを間違えると、おかしな動作をしてしまいます。
![drs_switch_miss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/3acacf99-ee8d-b060-ae3b-0cc7cb389a0b.png)

## 実物や写真の真似をしない
ブレッドボードを組む時に絶対にやってはいけないことは、

**<font color=red>「知り合いの作った実物や、ネットにある写真と全く同じ配置にしようとしてはいけない」</font>**

です。

思考停止して「全く同じ場所に挿せばいいや」「全く同じ色のケーブルを使えば長さも同じだ」などと考えて真似をすると、
**実際には１列ズレていたり、全然違う場所に挿さっていたりして、動作しない/ショートする**
というトラブルが非常に多いです。

本実験はあくまで「入門」なので、この様な参考イメージを載せていますが、
![drs_board.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/3d590ba5-2ac1-3e03-257e-52a83d63616d.png)
本来は回路図だけをみてブレッドボードを組めるようになっておくことが重要です。

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

**スイッチの状態をシリアルで送信するプログラム**は、Arduino IDEの開発環境に予め用意されています。
用意されているサンプルプログラムは、メニューバー[ファイル]の中に「**スケッチ例**」としてまとめられています。

それでは、サンプルプログラムを開きましょう。
[**ファイル**]-[**スケッチ例**]-[**01.Basics**]-[**DigitalReadSerial**]を開きます。
![digitalreadserial.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/a7d48c63-c0b8-bd9f-35ec-c74db62ed60f.png)

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

<font color=red>COMポートは認識しているけどプログラムの書き込みが出来ない</font>、という場合は、
ブレッドボード上の配線で+5VとGNDが繋がってしまった「**<font color=red>ショート状態</font>**」にあるかもしれません。

Arduinoの電源ランプを確認しましょう（下図）

このLEDが消灯している場合、どこかでショートしているので、そもそもマイコンが動いていません。
このまま放置すると、マイコンが壊れてしまう、またはパソコンのUSBポートが壊れてしまう可能性があります。
**すぐにUSBケーブルを外して電源供給を断ってください！**
電源がなければ安全です。その後、ゆっくり原因を探しましょう。

# 実行結果
[シリアル通信をしてみよう](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) の時と同様に、シリアルモニタを開きましょう。

プログラムが実行されると、下図の様に、画面上にはひたすら`0`という文字が表示されます。
![drs_result2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/b7661919-2aa5-095d-0aae-dfe8d2df34ab.png)

そしてスイッチを押すと`1`に変わります。
スイッチを離せば`0`に戻ります。

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

- 1と0がグチャグチャに交じっている
- ずっと0のまま
- 最初から1が表示される

という場合は、ブレッドボードの配線にミスがあると思われます。
それぞれの対処例を以下に解説します。

### 1と0がグチャグチャに交じっている

２番ピンがスイッチの足に繋がっていない、あるいは、10kΩのプルダウン抵抗がきちんと接続されていない、ことが予想されます。
デジタル入力ピンはプルダウン抵抗に繋がっていないと、値が安定せず0と1を行ったり来たりしてしまいます。

- Arduinoの２番ピンはスイッチに繋がっているか
- プルダウン抵抗の片方の足が+5Vと繋がっているか
- プルダウン抵抗の反対側の足がスイッチと繋がっているか

を確認しましょう。

### ずっと0が表示され続ける

プルダウン抵抗は２番ピンへとちゃんと接続されている様ですが、スイッチが機能していないと思われます。

- スイッチの反対側の足がGNDと繋がっているか

を確認しましょう


### 最初から1が表示される

スイッチの向きが間違ってるかもしれません。プッシュスイッチの４本足は横方向には導通しています。

- スイッチの向きを確認する。押したときに繋がる向きで設置する。

を確認しましょう。



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

```cpp:DigitalReadSerial.ino
/*
  DigitalReadSerial

  ピン2のデジタル入力を読み込み、シリアルモニターへ結果をプリントする

  このプログラム例はパブリックドメインです

  http://www.arduino.cc/en/Tutorial/DigitalReadSerial
*/

// デジタルピン2に接続されているプッシュボタンに変数名を与える
int pushButton = 2;

// セットアップ関数はリセットボタンが押されると１回だけ実行される
void setup() {
  // シリアル通信を初期化する。ボーレートは9600bps(ビット/秒)
  Serial.begin(9600);
  // プッシュボタンのピンを入力モードに設定する
  pinMode(pushButton, INPUT);
}

// ループ関数は繰り返し呼び出される（永久ループ）
void loop() {
  // 入力ピンの状態を読み取る
  int buttonState = digitalRead(pushButton);
  // 入力ピンの状態をシリアルでprintする
  Serial.println(buttonState);
  delay(1);        // 読み取り関数の安定のために、ディレイを入れる
}
```

---
それでは、それぞれの関数を見ていきましょう。
まずはグローバル変数とsetup関数です。

```cpp:グローバル変数とsetup関数
// デジタルピン2に接続されているプッシュボタンに変数名を与える
int pushButton = 2;

// セットアップ関数はリセットボタンが押されると１回だけ実行される
void setup() {
  // シリアル通信を初期化する。ボーレートは9600bps(ビット/秒)
  Serial.begin(9600);
  // プッシュボタンのピンを入力モードに設定する
  pinMode(pushButton, INPUT);
}
```

まず、int型のグローバル変数`pushButton`を定義し、中身を2とすることで、
「プッシュボタンはデジタル入出力ピンの2番に接続するよ」と表現しています。

次に、setup関数の内部では、
`Serial.begin`関数で、シリアル通信を9600bpsで初期化しています。

`pinMode`関数ではpushButton(=2番ピン)をINPUT(入力)に設定しています。
解説：[pinMode解説](http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=2014)

図で赤く囲われているデジタル入出力ピンの「2番を入力ポートとして使う」という事です。
![digitalport.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/51e4130c-e2cb-b9b7-065e-4f8a601b9c1d.png)

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

```cpp:loop関数
// ループ関数は繰り返し呼び出される（永久ループ）
void loop() {
  // 入力ピンの状態を読み取る
  int buttonState = digitalRead(pushButton);
  // 入力ピンの状態をシリアルでprintする
  Serial.println(buttonState);
  delay(1);        // 読み取り関数の安定のために、ディレイを入れる
}
```
`digitalRead`関数は、入力モードに設定したピンが、 **<font color="red">HIGH</font>** の電圧(5V)か **<font color="blue">LOW</font>** の電圧(GND=0V)なのかを判定する命令です。
解説：[digitalRead解説](http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=2075)

`digitalRead`関数が返す値は、5Vのとき1、0Vのとき0です。
すなわち、int型の変数`buttonState`には、1か0の値が入ります。
「`state`ステート」という「状態」を表す単語はプログラミングでよく使います。
皆さんに馴染み深いのは、RPGで使う「`status`ステータス」ではないでしょうか？
`status`は`state`の複数形の様な意味合いを持っています。
つまり「ちから」や「すばやさ」といった１つ１つの項目は`state`で、
それらを全部まとめて一覧で見るから`status`というメニューがあるのです。


次に、`Serial.println`関数で、取得した`buttonState`を送信しています。
関数の末尾に`ln`が付いているので、1か0を表示した後に改行してくれます。
もし`ln`が無いと、`0000000001111111000000111...`と横に表示され続けます。


# まとめ

デジタル入力では、

•pinMode で`INPUT`を指定
•digitalRead で端子の状態を読む

という作業をする事が分かったと思います。


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