LEDがホタルみたいに光ったらいいな。

# LEDを点滅させてみる。

## 1. はじめに

### 記事の目的と概要

この記事では、電子工作の基本を学びながら、LED点灯を題材にして電圧と閉回路に流れる電流について理解を深めていきます。今回はアナログピンを使って蛍のようにゆっくりと明るくなり、ゆっくりと消える仕掛けを勉強してみます。

### 必要な部品とツール

- LED（発光ダイオード）
- 抵抗（220Ω 推奨）
- ジャンパーワイヤー
- ブレッドボード
- Arduinoボード（Uno 推奨）
- USBケーブル
- パソコン（Arduino IDEがインストールされていること）

---

## 2. 基本の電圧と電流

さて、さっそく回路を組み始めましょう。と、その前に。。。
LED点滅のサンプルはいつも220Ωの抵抗をつけます。これはなぜなんでしょう。まずはその点を考えます。

### 電圧とは何か

一般的な電圧の解説は以下の通りです。

```
電圧は電気回路における電位差を意味し、電荷を移動させる力のことです。
単位はボルト（V）で表され、2点間の電圧が大きいほど電流が流れやすくなります。
```

ここで、電位差ってなんなんでしょうね。電子のような見えない世界の話はイメージしにくいので、電位差＝「高さ」だと考えてみます。

ここで大切なお約束です。

**電気回路は一周回るときに、スタート地点と同じ「高さ」にいなくてはならない。**このルールを守らないと、回路は動作しないというか壊れたりします。まずはこのルールを頭に入れておきましょう。

### 電池と豆電球

皆さんがおそらく小学4年生で学習した豆電球と電池の回路も実はこのお約束を厳密に守っています。

![1-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837176/c35ad07b-c11c-355a-7716-0d78f000f60c.png)


こんな感じですよね。電池があって豆電球とつなぐ。この時、電池の＋極から-極に向かってこの図では反時計回りに電気が流れるとならっと思います。ではなぜ電気は流れるのでしょうか？電池に電気がたまっているから？それはちょっと違いますね。

　**電池には電気はたまっていない。**

ことに注意しましょう。じゃぁ電池は何をするんでしょうか。電位差＝つまり高さを生み出しているのです。いわば電池は-と+の間の上り階段のようなものです。回路が動作するためにはこの上った「高さ」の分だけ一周している間に降りなくてはいけません。

電池の稼ぐ高さは1.5v です。一周する間に1.5v降りない限りこの回路は動作しません。使える場所は、豆電球だけです。つまりこのまめ電球で1.5v分「降りている」と考えます。

![1-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837176/74063354-da49-a9fd-4b49-0e88a4a52b77.png)

### 発光ダイオードの場合

さて、みなさんの利用している発光ダイオードですが、データシートで重要な部分を抜粋してみます。

| 主な仕様       |                      |
| -------------- | -------------------- |
| 順電圧         | 2V                   |
| 順電流max.     | 20mA                 |
| 逆電圧         | 5V                   |

ポイントは順電圧です。これはこの発行ダイオードを正しく動作する方向に設置した場合、2Vの電圧をさげるという意味です。(順電圧降下)。Arduinoの場合、GND(=地面)とGDPのPINの間では5Vの電位差（高さが）が生まれます。さてこの回路は動作するでしょうか？

![1-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837176/f7637216-418f-c8bd-4211-f5b724f74017.png)

動作しない。。だけではなく、発光ダイオードが壊れます。なぜなら、5V上がった高さを使う箇所が発光ダイオードの2Vしかないので、残り3Vもここで**無理やり降りようとするのです**。当然順方向電圧が2Vの素子で5Vも降下したら、普通に壊れます。安全に使うためには3Vを使い切るための下り階段として、抵抗を入れる必要があります。抵抗を入れることで、発光ダイオードの順降下電圧2V、抵抗で残りの3Vと段階を踏んでおろすことができるため、発光ダイオードを破損させることはありません。

![1-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837176/4bddac87-a374-f410-a3f1-1f057d6c6be5.png)

では、使い切れば安全に動作するのか？というと必ずしもそうではありません。先ほど見たデータシートを再度確認します。

| 主な仕様       |                      |
| -------------- | -------------------- |
| 順電圧         | 2V                   |
| 順電流max.     | 20mA                 |
| 逆電圧         | 5V                   |

今度は順電流maxに注目です。20mAとあります。ダイオードに流れる電流が20mA以下となるように抵抗値を設定しろということです。

### 抵抗とオームの法則

抵抗は電流の流れに対する妨げの度合いを示します。抵抗値が高いほど電気は流れにくくなります。つまり同じ電圧降下で流れる電流が少なくなるということです。単位はオーム（Ω）で、オームの法則により次のように表されます。

``` math
V = I \times R 
```
ここで、Vは電圧、Iは電流、Rは抵抗です。この法則を理解することで、回路の設計やトラブルシューティングが容易になります。

なお、この式は展開することで自由に電流(I)、電圧(V)、抵抗(R)を求めることができます。

``` math
\begin{align} 
  I = \frac{V}{R} \\
  R = \frac{V}{I} \\
\end{align}
```

さて、このダイオードは30mA以下に電流を抑えなければいけなかったのでしたね。簡単な不等式です。

``` math
\begin{align}
 I < 20 mA = 20 \times 10^{-3} A\\
 　I = \frac{V}{R} であるから \\
 \frac{V}{R} < 20 \times 10^{-3}\\
 V = 3vなので\\
 \frac{3}{R} < 20 \times 10^{-3} \\
 3 < 20 \times 10^{-3}  \times R\\
 \frac{3}{20  \times 10^{-3}} < R\\
 \frac{0.15}{10^{-3}} < R\\
 0.15 \times 10^{3} < R\\
 R > 0.15 kΩ　\\
\end{align}
```
0.15kΩつまり150Ω以上であれば20mA以上の電流は流れないことになります。そこで、余裕をもって220Ωの抵抗値を採用します。

参考まで220Ωを選択した場合の電流値は

``` math
I = \frac{V}{R} = \frac{3}{220} = 0.013(13mA)
```
となり、予定通り20mA以下となります。

---

## 3. LED点灯の基本実験

### LEDの仕組みと特性
さて、抵抗値の選択も終わったのでいよいよ回路を作っていきます。
LED（発光ダイオード）は、電気エネルギーを光に変える半導体素子です。順方向電圧を加えることで発光し、逆方向電圧では電流を流さない特性があります。LEDには電圧を印加する向き（アノードとカソード）が重要で、誤った接続では発光しません。

### アナログピンを使った簡単な回路

今回はアナログピンを使ってLEDを制御します。以下の図のように、LEDのアノード（長い足）を抵抗を介してArduinoのアナログピンに接続し、カソード（短い足）をGNDに接続します。

``` 回路
[Arduino]
Analog Pin 9 ------> [220Ω Resistor] ------> [Anode] LED [Cathode] ------> GND
```


### 回路図と説明

1. ブレッドボードにLEDと抵抗を配置します。
2. LEDのアノード側に抵抗を接続し、抵抗のもう一方をアナログピン（ここではPin 9）に接続します。
3. LEDのカソード側をGNDに接続します。


---

## 4. アナログ制御への導入

### アナログ制御の基本概念

アナログ制御では、連続的な値を使ってデバイスの動作を制御します。PWM（パルス幅変調）は、Arduinoでアナログ制御を実現するための主要な手法です。PWMでは、高速でのオンオフの切り替えを行うことで、平均的な電圧を調整し、アナログ出力を実現します。

### PWM（パルス幅変調）とは

PWMは、一定の周波数でオンとオフを切り替えることで、デバイスに供給される平均電力を制御します。デューティサイクル（オンの時間の割合）を変えることで、例えばLEDの明るさを調整することができます。

### アナログピンを使ったLED制御

Arduinoの `analogWrite` 関数は、PWMを使ってアナログ出力を模倣します。前の章で示したコード例では、この `analogWrite` 関数を使ってLEDの明るさを調整しています。

---

## 5. ArduinoでLEDを制御する

### Arduinoの基本説明

Arduinoは、電子工作やプロトタイピングに広く使われるオープンソースのマイクロコントローラーボードです。プログラミングはArduino IDEを使用し、C++に基づいた簡単なコードを書いてボードにアップロードすることで、様々なセンサーやアクチュエーターを制御することができます。

### 回路の接続方法

前の章で説明した回路を使用します。以下の手順で接続します：

1. ブレッドボードにLEDと抵抗を配置します。
2. LEDのアノード側に220Ωの抵抗を接続し、抵抗のもう一方をArduinoのアナログピン（ここではPin 9）に接続します。
3. LEDのカソード側をGNDに接続します。

### アナログピンを使ったコード例

次に、Arduinoを使ってLEDを制御するためのコードを書きます。ここでは、アナログピンを使ってLEDの明るさを調整する例を示します。

``` cpp
int ledPin = 9; // LEDが接続されているピン番号

void setup() {
  pinMode(ledPin, OUTPUT); // LEDピンを出力モードに設定
}

void loop() {
  analogWrite(ledPin, 50); // LEDの明るさを50に設定
  delay(2000); // 2秒間待つ
  analogWrite(ledPin, 150); // LEDの明るさを150に設定
  delay(2000); // 2秒間待つ
  analogWrite(ledPin, 255); // LEDの明るさを255に設定
  delay(2000); // 2秒間待つ
}
```

このコードでは、 analogWrite 関数を使用してLEDの明るさを50、150、255に設定し、それぞれ2秒間ずつ点灯させます。

電圧と明るさの関係
analogWrite 関数の引数は0から255の範囲で指定します。この範囲はPWM（パルス幅変調）のデューティサイクルを表しており、LEDに供給される平均電圧に比例します。

- `analogWrite(ledPin, 150)`：デューティサイクルは約60%（150/255）。LEDの明るさは中程度になります。
- `analogWrite(ledPin, 255)`：デューティサイクルは100%（255/255）。LEDの明るさは最大になります。

このように、 `analogWrite` の値を変更することで、LEDに供給される平均電圧が変わり、それに比例してLEDの明るさも変わります。

### 実験結果の観察

Arduinoにコードをアップロードし、LEDが異なる明るさで点灯する様子を観察します。これにより、PWM制御を通じて電圧と明るさが比例関係にあることが確認できます。

---

## 6. 周期関数を用いたアナログ制御

### 周期関数の利用

今回はホタルの光を目指したいのです。蛍の光って独特ですよね。ゆっくりジワーッと明るくなって、ジワーッと暗くなるそんな光です。それを一定周期で繰り返す。そんな感じですよね。

これをなんとか表したい。それもお手軽に!!

せっかくアナログピンがあるんです例えば10ミリ秒事に明るさが1ずつ増える関数を考えてみます。もちろん最大値が255ですから255で折り返します。コードで書くとこんな感じです。

```
int brightness = 0;
int increment = 1;

void setup() {
  pinMode(9, OUTPUT);
}

void loop() {
  analogWrite(9, brightness);
  brightness += increment;
  if (brightness <= 0 || brightness >= 255) {
    increment = -increment;
  }
  delay(10);
}

```

実行するとわかるのですが、じわーっと感がいまいちでこれが蛍か？と言われるとすこし微妙です。グラフを見てみるとわかるのですが、

![WS000000.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837176/eac52590-0adb-ddf4-2a58-8018c0124839.jpeg)

こんな感じに、ギザギザしちゃってるんですよね。

他の関数を探しましょう。関数の条件はこんな感じです。

- 0 ～ 255の間を繰り返す。
- 増→減、減→増の切り替えが滑らかに行われる。

あら。ちょうどいいのがありますね。三角関数です。今回は正弦波=$\sin\theta$。を使います。グラフを見てみましょう

![WS000001.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837176/72620f52-d4bd-11dc-191f-3b9cf0d6cf37.jpeg)

お。なんだかなめらかです。でもよく見てください。値が -1～1ですね。おしい。0～255じゃない。これじゃな使えない。。とあきらめるのは早いです。使えないなら、使えるようにしていきましょう。

#### 大きく(スケール)する
グラフの形を変えずにおお聞きするために何をするか。そう。掛け算です。今回は元の形が-1～1と最大値と最小値の「幅」が2の関数なので、この幅を255にするために127.5を掛けます。$127.5\sin\theta$そうすると-127.5～127.5の幅が255の関数が出来上がるわけです。グラフにするとこんな感じです。

![WS000002.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837176/2a4d8ad7-2a44-2bfd-787b-32a35277900c.jpeg)

やった。これで使える。。わけではありません。よく見てください。幅は255になりましたが、0より下の数が使われています。破線の部分です。実際に回路で実行するとこの部分はLEDが消えてしまうので一寸おかしな動きになります。どうにかしてグラフ全部を上にあげていきたいのです。

#### グラフをy軸方向に移動する。

これは簡単ですね。すべての点が上に移動すればいいのです。-127.5を0に 0を127.5に127.5を255にしてあげればいいのです。全ての点に127.5を足せばいい。$127.5\sin\theta+127.5$ですね。ちょっと結合して$127.5(\sin\theta+1)$です。グラフを見てみましょう。

![WS000003.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837176/438bcfb6-7a0d-6adb-246d-64a6d1e99ac1.jpeg)

やりました。無事、0～225の範囲で増減する正弦波を得ることができました。

このように、直接は使えない関数を自分の都合に合わせて拡大縮小、移動することを「スケールする」といいます。かっこいいので覚えておきましょう。

### コード例と解説

さっそく、コードにおとしましょう。以下のコードは、サイン波を使ってLEDの明るさを滑らかに変化させる例です。ラジアンがどうとかめんどくさいこと書いてありますがそこは無視しましょう。

```cpp
#include <math.h>

int ledPin = 9; // LEDが接続されているピン番号

void setup() {
  pinMode(ledPin, OUTPUT); // LEDピンを出力モードに設定
}

void loop() {
  for (int i = 0; i < 360; i++) {
    float rad = radians(i); // 度をラジアンに変換
    int brightness = (sin(rad) + 1) * 127.5; // サイン波で明るさを計算
    analogWrite(ledPin, brightness); // LEDの明るさを設定
    delay(15); // 少し待つ
  }
}
```
このコードでは、 math.h ライブラリを使ってサイン波を生成し、その値に基づいてLEDの明るさを調整します。 radians 関数を使って度をラジアンに変換し、 sin 関数を使ってサイン波の値を計算します。計算された値を0から255の範囲にスケーリングし、 analogWrite 関数でLEDの明るさを設定します。

### 実験結果の観察と考察
実際にコードをアップロードし、LEDの明るさが滑らかに変化する様子を観察します。これにより、アナログ制御と周期関数の組み合わせが理解できます。

## 7. まとめと応用

### 実験結果の総括
この記事では、LED点灯を題材にして電圧と電流の基本を学び、アナログピンを使ったLED制御を実践しました。基本的なオンオフ制御から始め、最終的には周期関数を用いた滑らかな明るさの変化を実現しました。

### 応用例と今後の発展
今回学んだアナログ制御の技術は、他の電子工作プロジェクトにも応用できます。例えば、モーターの速度制御や音量調整など、多くの応用が考えられます。今後は、さらに複雑な制御やセンサーとの組み合わせを試してみることをお勧めします。

### 参考資料と追加リソース
Arduino公式サイト：https://www.arduino.cc/