強い光を検知してLEDを点灯させる回路を組んでみよう

ある日突然、**ア!!!!! レーザーポインターに反応してLEDが光る回路を工作したい!!!!!**という思いが脳内に生まれたため、作ってみることにしました。

# 必要なもの
使用した道具はAmazonで揃えました。
[エレクトロニクス をはじめよ スターターキット ビデオとPDF教材 電子工作実践](https://www.amazon.co.jp/gp/product/B016LSOFGE/)

# 参考記事
[第5回 光センサーでArduinoへの入力を試してみる！](https://deviceplus.jp/hobby/entry_005/)

# やったこと
## 動作確認する
まずは回路を組みます。
上記記事と同じ構造になるように差し込みました。
抵抗は大きめのモノを使った方がいいかもしれません。
![PhotoPictureResizer_190703_102259910_crop_2419x3225-604x805.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336249/51ef97be-8bc9-da94-9a41-509c375a5ae8.jpeg)
次に付属のUSBケーブルでPCと接続。（上記写真では既に接続しています）

ここでデバイスマネージャーからシリアルポートを確認。
![55e356f30d3b091b2cd51410ceb4abf7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336249/68f26a36-7d21-4c8b-0638-fcd19df1d260.png)
私の環境では**COM10**として認識されていることがわかりました。

これだけでは動かないので、プログラム（スケッチと呼ばれる）を書きこんでいきます。
[Arduino IDE](https://www.arduino.cc/en/Main/Software)をダウンロードして起動。
`ツール→シリアルポート`から、先ほど確認したシリアルポート番号を選択します。
![8f6d812c3b565fe7fd7534d0faf3674e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336249/d8696675-264d-3f72-5ae0-ed8f0acf8a70.png)
ついでに、`ツール→ボード`から使っているボードの種類も指定しておいたほうが良さげです。
私の使ったボードは`COM10(Arduino/Genuino Uno)`と表示されていたので、同じものを選びました。

あとは`ファイル→新規ファイル`でスケッチを新規作成し、上記記事のサンプルコードをコピー。
IDE左上の`✅`（検証）ボタンでコンパイルを実行し、エラーが無いか確認した上で、`⇒`（マイコンボードに書き込む）ボタンを押せば書き込みが完了します。
ちなみに、スケッチはフォルダ単位で管理されます。

ボードへの書き込み状況はIDE左下のステータス表示で確認しましょう。
![9590eeb2af3a17972e2d38c160924fd4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336249/bfe9b178-6f1e-7af3-5c57-c82e762cc901.png)
私は一度、`ツール→ボード`の指定をデフォルトのまま適当にやっていたらエラーが出てしまいました。
同じ轍を踏んでしまった方でも、エラーメッセージに`指定されたボードが見つかりません`と出てくれたので、すぐに気づけると思います。

書き込みが完了したあとは、何もしなくても自動的にプログラムが動き始めます。
ソースコードにも`loop`の表示がある通り、一定の動作を無限ループしているイメージですね。

実際に動作している映像がこちらになります。
![ledtest.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336249/6926e91d-9365-e241-e23d-69bf9bd9eb23.gif)
センサーが光を感知したタイミングでLEDの光も強くなっていることが確認できると思います。

## 光の強さを読み取る
ここまでの内容ではあくまでも、当たっている光の強さに応じてLEDの光の強さが変わるという動作しかできていません。
ここから、本来の目的である**一定以上の強さの光が当たったときだけLEDを点灯させる**動作を実装していきましょう。

まずはその前段階として、間接的に光の強さを取得できるようにします。

ここで使用している光センサー（硫化カドミウムCdSを利用したフォトレジスタ）は、光が当たれば当たるほど抵抗値が低くなるという性質を持ちます。
ということは、**抵抗値をArduino側で読み取って、一定の値以下になったときだけLEDを光らせる**というプログラムを書けば実現できそうです。

抵抗値を読み取る方法も上記記事のものを参考にします。
記事通りに回路を組んでスケッチを書き込んで実行してみましょう。
読み取った抵抗値の出力先を表示するために、実行後はIDEの`ツール→シリアルモニタ`の起動を忘れずに。
実際にテストしてみた様子が以下の動画になります。
![ledtest2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336249/7f3f1999-16e6-d98e-57f1-d9eb295eb673.gif)
光を当てた時だけ、画面上の数値が小さくなっているのが確認できるでしょうか。
本当はもっと局所的で強い光を照射できる、レーザーポインターのようなものを使いたかったのですが、手元に無かったため適当なライトで代用しました。

使用したソースコードは記事の物と同じですが、下記の通り。

```
int val=0;
void setup() {
  Serial.begin(9800); //モニターに出力するための設定
}
void loop() {
  //ANALOG INの０番ピンからデータを受け付ける
  val=analogRead(0);
  Serial.println(val/4); //入力された値をモニターに出力
  delay(100);
}
```

ソースコード解説の詳しいところは上記記事に譲ります。
要点は以下の通り。

- アナログ入力値を読むには`setup()`で`Serila.begin(9800)`を実行しておく
- 入力値を読みたいタイミングで`analogRead(ピン番号)`を実行すれば取得できる
- **入力値は1024段階で表現**される（0から1023）

入力値の表現方法の仕様上、実際の抵抗値（単位がオームの値）を表示できるわけではないという点には注意が必要ですね。
モニターへの出力時に`val/4`としているのは、この後LEDに電力供給するときに関係してきます。

## 一定以上の光に反応させる
これで抵抗値がわかる＝光の強さがわかるようになりました。
あとは抵抗値が一定以下の場合だけLEDに電気を流すような回路とプログラムを実装すれば完成です。

まずは回路を組みます。と言っても上記記事のままです。
以下二つの回路に分けて考えると理解しやすいでしょう。

1. LEDに電力を供給する回路
2. センサーから光の強さを検出する回路

上記記事で紹介されている回路はまさしく上半分が1番、下半分が2番の回路に相当します。
私は2番部分の回路を記事通りに組んだら上手く動作しなかった（抵抗値がほとんど変わらなくなってしまった）ので、2番部分の回路については先ほどの「光の強さを読み取る」の部分で利用した回路をそのまま流用することにしました。

実際の回路の写真は次のようになりました。と言っても写真だと電子的な特徴は確認しづらいかと思います……すみません。
![IMG_20190703_140207-756x567.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336249/ab2806d4-cfa8-4852-bd45-a37bccefa3d3.jpeg)

次はソースコード。一定以上の強い光を当てた時だけ、という条件分岐を実装します。
今回の場合は先ほどの入力結果から「抵抗値（`val/4`）が100未満のときにLEDを点灯させる」ようにしてみましょう。
ソースコードは次のようにしました。

```
int val=0;
void setup() {
  Serial.begin(9800); //モニターに出力するための設定
}
void loop() {
  val=analogRead(0); //ANALOG INの０番ピンからデータを受け付ける
  Serial.println(val/4); //入力された値をモニターに出力
  if (val/4 < 100) {
    analogWrite(3,val/4); //DIGITAL PWMの3番ピンからval/4の強さで出力する
  } else {
    analogWrite(3,0);
  }
  
  delay(100);
}
```

ここでようやく`val/4`と**入力値を4で割った理由**が明らかになります。
と言っても論理は単純です。単にアナログ入力が1024段階の整数で表される仕様になっているのに対し、**デジタル出力は256段階の整数で指定する必要がある**という仕様によるものなんですね。
だから、入力値に連動する仕組みを実現するだけなら、4で割って256段階の値に変換してしまうのが簡単という都合でした。

それから、光が当たっていないときは消灯する必要もあります。
こちらは`else`文の中で電力の出力を0とすることで実現しました。

実際に動作させている様子は以下の動画で確認できます。
![ledtest3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336249/1e3e823d-f388-e81c-8d25-429e54825fc6.gif)
LEDが光っていることを分かりやすくするため、回路に仕切りを置いて撮影しました。

# 感想
特に専門的な工具も部品も必要なく、スターターキット的な物の一部だけで簡単に組めたのが驚きでした。
回路について物理的な知識は高校以来抜け落ちてしまってめちゃ勉強不足なのですが、なんとか手探りでもやれますね！