raspberry piでフルカラーLEDを扱う

# はじめに

秋月にパーツを買いに行ったのですが、営業時間に間にあいませんでした。（18:30閉店は早すぎ！！）
仕方なくマルツに行ったら、ジャンクでフルカラーLEDが50個800円で売っていたので面白そうなので購入しました。

多分これ
https://www.marutsu.co.jp/pc/i/838245/
![image.png](https://qiita-image-store.s3.amazonaws.com/0/38676/8f12904f-864b-ed1e-4c4c-a094ddca03bd.png)

---

あとで調べたら、フルカラーLEDでマイコン内蔵のものもありました。
1個40円なので、ジャンクの2.5倍高いですが、こちらのほうがいろいろ遊べる気がします。

http://akizukidenshi.com/catalog/g/gI-08412/

まあ、IC内蔵よりも直接制御したほうが基本が身に付くと思って頑張りましょう。

---

# 前提条件

以下の条件を満たすものとします。

+ raspberry pi 3
+ Raspbianインストール済み
+ jupyter notebookで行う
+ フルカラーLED
+ ブレッドボード
+ 抵抗３つ
+ オスメスジャンパーワイヤー4本

jupyter notebookは以下のコマンドでインストールできます。

```sh
pip3 install jupyter
```
---

# 通電確認（Lピカ）

まずは、ちゃんと光るかどうか確認しましょう。

ラズベリーパイのピンは以下のようになっています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38676/ca817c17-e6f3-5634-ef1c-4cc6ca312186.png)

先ほどの一番長い足がアノードコモンです。
3.3Vの1番ピンに接続します。
他のピンが赤と青と緑なので、GNDの6番ピンに接続します。

抵抗を入れないと壊れてしまうので、今回は220の抵抗をいれます。

赤
![image.png](https://qiita-image-store.s3.amazonaws.com/0/38676/a3ac827d-ec25-5d65-7bbd-ccf9ec2331a7.png)

青
![image.png](https://qiita-image-store.s3.amazonaws.com/0/38676/763a1fe8-9c4d-5524-be0e-bd3513ad46af.png)

緑
![image.png](https://qiita-image-store.s3.amazonaws.com/0/38676/120b3c3a-043e-495d-4276-c633a858c3d0.png)

どのピンが何色なのか覚えておきましょう。

---

# ラズパイからGPIOで制御

LEDを点灯する場合、通常GPIOからアノードにつなげて、GNDにカソードをつなげます。
しかし、このLEDはアノードコモンのため、各色を制御しようとするとうまくいきません。

なので、今回は逆にアノードに3.3Vをつなげて、他の足は各GPIOにつなげましょう。

この場合、GPIOがOFFの時に、0Vになるため、電気がながれてLEDが点灯します。
GPIOがONの時は、3.3Vになるため、電気が流れずLEDが消灯します。
この接続方法を、吸い込み電流といいます。
通常の接続は吐き出し電流といいます。

以下のように接続します。

1pinとLEDのアノードコモン
11pinと抵抗を挟んでLEDの赤カソード
12pinと抵抗を挟んでLEDの青カソード
13pinと抵抗を挟んでLEDの緑カソード

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38676/55dfbe39-b783-feeb-aedd-bba121e736cf.png)



接続できたら、以下のプログラムを実行します。

```python3
import RPi.GPIO as GPIO
import time

赤PIN = 11
青PIN = 12
緑PIN = 13

GPIO.setmode(GPIO.BOARD)
GPIO.setup(赤PIN,GPIO.OUT)
GPIO.setup(青PIN,GPIO.OUT)
GPIO.setup(緑PIN,GPIO.OUT)

GPIO.output(赤PIN,True)
GPIO.output(青PIN,True)
GPIO.output(緑PIN,True)
```

これで準備完了です。

新しいセルで以下を実行すると、緑に点灯します。

```python3
GPIO.output(緑PIN,False)
```

引数を変更していろいろ色を変えてみてください。

---

# 明るさの制御

このままだとON/OFFしかできないため、少し暗くしたいと思います。
ハード的には抵抗を変えれば電流量が変わるため、明るさが変わるのですが、残念なことにラズベリーパイのGPIOはデジタルでON/OFFしかできません。
そのため、パルス幅変調（パルスはばへんちょう、英語: pulse width modulation、PWM）という技術を利用します。

簡単に言うと、高速にON/OFFを繰り返すことにより擬似的にON/OFFの中間を表すということです。

以下のコードを実行してみてください。

```python
for i in range(1000000):
    GPIO.output(緑PIN,False)
    GPIO.output(緑PIN,True)
```

少し暗く緑に点灯したと思います。
これがPWMになります。

このままだと、指定が難しため以下の関数を定義します。

```python3
def duty_switch(duty_fn, exec_fn):
    p = 0.0
    def fn(*args, **kargs):
        nonlocal p
        p += duty_fn()
        if p > 1:
            p -= 1
            exec_fn(True)
        else:
            exec_fn(False)
    return fn

def led_fn(pin):
    pre = None
    def fn(f):
        nonlocal pre
        if pre != f:
            GPIO.output(pin, not f)
        pre = f
    return fn
```

duty_switchは引数に、周期の増分を返す関数と周期に応じてTrue/Falseで動作する関数を指定すると、実行する毎に周期の増分に応じて、第２引数の関数にTrue/Falseを指定して呼び出す関数を返します。

led_fnは指定されたピン番号をTrueだと点灯、Falseだと消灯する関数を返します。

それぞれを利用して各ピン毎に周期を指定できるような関数を作成します。

```python3
def duty_get(color):
    return lambda : duty[color]

def full_color():
    r = duty_switch(duty_get('red'), led_fn(赤PIN))
    b = duty_switch(duty_get('blue'), led_fn(青PIN))
    g = duty_switch(duty_get('green'), led_fn(緑PIN))
    def fn(*a):
        r()
        g()
        b()
    return fn

fc = full_color()
```

関数ができたら、周期を設定して実行してみましょう。

```python3
duty = dict(red=0.1,blue=0.1,green=0.1)
for i in range(100000):
    fc()
```

dutyの値をいろいろ変更して試してみてください。

## 割り込みを使った明るさの制御

ループで明るさを制御するのは何となくカッコ悪いですよね。
なので、LinuxのOSの割り込みを利用して制御してみましょう。

```python
import signal
import time

# 割り込みが発生した時に実行する関数を指定
signal.signal(signal.SIGALRM, fc)
# 割り込みの開始時間と繰り返し時間を指定（単位秒）
signal.setitimer(signal.ITIMER_REAL, 0.001, 0.001) 

time.sleep(5)

# 後片付け
signal.setitimer(signal.ITIMER_REAL, 0, 0)
GPIO.output(赤PIN,True)
GPIO.output(青PIN,True)
GPIO.output(緑PIN,True)
```

今度はtime.sleepを利用しているため、指定した時間点灯します。

---
# 終わりに

今回はPWM制御をコードを書いて行いましたが、実はラズベリーパイにはハードウェアPWMもついています。しかし２チャンネルしか対応していませんので、今回のケースでは利用できません。

pigpioライブラリを利用すると、ソフトウェアPWMが使えるようになるそうです。
そちらでもチャレンジしてみたいと思います。

あとは、firebaseを使って、インターネット連動させたいですね。

---

# 参考

フルカラーLEDを使ったみた(ハード制御編)
http://vasco-blog.com/blog/2018/01/09/use-fullcolorled/
フルカラーLEDを使ってみた(ソフト制御編)
http://vasco-blog.com/blog/2018/02/06/use-fullcolorled-gpio/
Raspberry Pi3でpigpioライブラリを使ってLチカする
https://qiita.com/yuuri23/items/597fd1a40c63627e59c2