LチカをWebで制御する


**利用する機材**
① LED１個
② ジャンパー線２本　（オス・メス）
③ 抵抗１個　（1kΩ）
④ ブレッドボード（小）

**ＬＥＤ**
LEDはプラス（アノード：長）とマイナス（カソード：短）が決まってます。
LEDを使うに当たり、Raspberryと直結すると、通常の御遊びのLEDであれば、即焼けるので、抵抗を直列に繋ぐのが一般的ですが、では、最低抵抗値は？
　　LEDの仕様：順電圧 (Vf) ／ 順電流 (If)　の時、 
　　抵抗値(R) ＝（電源電圧 － 順電圧）／ 順電流　　で計算可能です。
　（例）順電圧が2V、順電流が20mA のLED、Raspberryの電源電圧（5v）を利用する場合
 　　Ｒ ＝（5V － 2V）／ 0.02A ＝ 150 Ω
＜勝手な個人見解＞
LEDをAmazon等で買うのは良いのですが、順電圧や順電流の値を忘れ、結局、計算できず…
そんなズボラな私は、とりあえず1kΩで繋いでます。明かりが小さいと思えば、もう少し小さな抵抗値に変更です。
もちろん、何かが壊れたら、悲しみます…　（痛い授業料です）

**ＧＰＩＯ**
Raspberry PI に用意された40本のピンですが、それぞれに役割があり、間違えて使うと本体が壊れる可能性もあるので、注意しましょう。
Raspberry 3や4では、外側が偶数ピン、SDカード側から順に並んでます。
特殊な事が出来るピンがあり（SDAやSCL等）、Ｌチカで使うなら、特殊な記載の無いピンを使いましょう。GND（Ground）は、マイナスを意味します。
私のRaspberry4では、4ピン（5V電源）と6ピン（GND）で冷却用のFANを常時回してます。

**実機実装**
11番ピン（GPIO17）をプラスに使い、9番ピン（GND）をマイナスに使います。
Raspberry本体にジャンパー線のメス、ブレッドボードにオスを刺し、11番と9番の間にＬＥＤと抵抗を直列につなげます。

**前準備**
下記リンク先の手順で、RaspberryにPython-flaskでWeb表示する準備を済ませて下さい。
[安価なWeb開発勉強環境の構築①](https://qiita.com/MasahiroShouya/items/6cd832c6eee0645055c3)

**プログラムの用意**
まずは、普通にＬチカしてみましょう
```diff_python:ltika.py
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT)
try:
  while True:
    GPIO.output(17, 1)
    time.sleep(0.5)
    GPIO.output(17, 0)
    time.sleep(0.5)
except KeyboardInterrupt:
    print("Ctrl+C pressed. Cleaning up...")
    GPIO.cleanup()
```
python3 ltika.py　（プログラム実行）
ＬＥＤがチカチカと点滅したら、普通のＬチカ完成です。
CTRLキー＋Ｃで、プログラムを停止します。

**余談**
source /flask/test1/venv/bin/activate　（仮想環境に切り替えて）
python3 ltika.py　（プログラム実行）
エラー「ModuleNotFoundError: No module named 'RPi'」が表示されます。
これは、仮想環境にGPIOのパッケージが無い為に表示されるエラーです。
対応方法としては、少しコツがあって、、、
sudo apt-get install pip　（コツ＝デフォルトのpipを補填します）
pip install RPi.GPIO　（仮想環境にGPIOのパッケージを用意します）
python3 ltika.py　（プログラム実行）
正常に、ＬＥＤがチカチカと点滅しますよね。　＜ＯＫ＞

**Webの制御画面を用意してみましょう**
```diff_conf:フォルダ構成　（/flask/test1）
├── app
│   ├── templates
│   │   └── main.html
│   ├── gpio_on.py　　　（LEDをONするプログラム）
│   ├── gpio_off.py　　 （LEDをOFFするプログラム）
│   └── __init__.py
└── app.wsgi
```
```diff_python:app.wsgi
import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0, "/flask/test1")
from app import app as application
```
```diff_html:app/templates/main.html
<!DOCTYPE html>
<html lang="ja">
<head><meta charset="UTF-8"></head>
<body>
  <a href="?parm=on">点灯</a><br><br><br>
  <a href="?parm=off">消灯</a>
</body>
</html>
```
```diff_python:app/__init__.py
import subprocess
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
def index():
    if request.args.get('parm') == 'on':
        subprocess.call("sudo python /flask/test1/app/gpio_on.py", shell=True)
    elif request.args.get('parm') == 'off':
        subprocess.call("sudo python /flask/test1/app/gpio_off.py", shell=True)
    else:
        subprocess.call("sudo python /flask/test1/app/gpio_off.py", shell=True)
    return render_template('main.html')
if __name__ == '__main__':
    app.run()
```
```diff_python:app/gpio_on.py
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT)
GPIO.output(17, 1)
```
```diff_python:app/gpio_off.py
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT)
GPIO.cleanup()
```
**処理の説明**
このままRaspberryを再起動して、「http://（RaspberryのIPアドレス）:8080」へアクセスしても、想定通りの処理が行えません。
理由は、Web表示するプロセスが、「app/\_\_init__.py」の「sudo python」を実行する際、権限が足らず実行できない為です。
sudoの制御は管理者権限を有するユーザが実行する必要があります。
この現象の対応の為、apacheとFlaskで実行されているユーザの、「www-data」に対して、「sudo python」を実行する権限を付与します。
sudo visudo　（sudoの実行権限を設定）
```diff_conf
  root    ALL=(ALL:ALL) ALL
+ www-data  ALL=(ALL:ALL) NOPASSWD: /usr/bin/python
``` 
この後、Raspberryを再起動して、「http://（RaspberryのIPアドレス）:8080」へアクセスし、「点灯」「消灯」をクリックしてみましょう。　＜おしまい＞

**注意**
「www-data」に対して、「sudo」の権限を付与していますが、一般的なWeb開発ではセキュリティ問題となる悪手です。
Webプロセスはハッカーに狙われやすい機能であり、強い権限を付与するのはリスクとなるので注意しましょう。