Raspberry Pi Zero でLチカ（オンボードLED編）

今回、基板上のLEDを用いるため、ハードウェアの知識がなくとも、Lチカを行うことができます。
(LEDを準備しなくてだいじょぶ！　抵抗とか、わからなくてもだいじょぶ！)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558094/1ac88f33-4bc8-1715-a9f2-cfef46b487e3.gif" width="80%">

なお、少しコマンドの知識と、Pythonの知識が必要です。
ですが、コピペで進行できるようにしています。（viの操作も無いです）
(適宜、ターミナルにコピペしてください)

# すること
- 基板上のLEDの制御
- PythonによるLEDの制御
- PWMとsleepを利用したLEDの制御

# 必要な物　（TOP写真に写っているものだけでOK!）
Raspberry Pi ZERO W (Wがなくとも大丈夫だと思われます)
以上！！　（あとUSBケーブル、端末とか）

# 環境
- Raspberry Pi ZERO W　（他のRPiでは、説明でのGPIO番号が異なる場合があります）
- Raspberry Pi OS　⇒　[Raspberry Pi Imager](https://www.raspberrypi.org/software/) にて焼きこむ
- コマンドのみで操作　（GUI環境でも、CUI環境でも大丈夫です）

# Raspberry Pi の基板上のLEDの詳細
Raspberry Pi ZEROには、基板上にLEDが**1つ**搭載されている
他のRaspberry Piには、**2つ**搭載されている場合が多いが、ここでは言及しません

Raspberry Pi ZERO のLEDは、ACTLED (activity LED)と呼ばれていて、標準では、SDカードの読み書きか何かで、点滅するように設定されています。（多分）
また、Raspberry Pi ZERO のACTLEDは負論理で、Highを出力で消灯、Lowを出力で点灯します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558094/47bdd4e6-e964-1d5c-30db-b763754659cd.png" width="80%">

# 基板上のLEDの制御
コマンドの入力はターミナルに行ってください。
コピペで大丈夫なはずです。エラーが出た場合は、何か問題があります。
## 標準のLED動作の設定の変更
標準(初期状態)では、システムによってLEDが制御されており、GPIOで制御できないため、設定を変更する。

`/sys/class/leds/led0/trigger`に、ACTLED の制御設定が設定されており、**「none」**をファイルに上書きすることで、LEDを消灯できる。

`sh -c "echo テキスト > ファイル"`で、ファイルに1行のテキストを上書きできる。

```sh:LEDの消灯「none」
sudo sh -c " echo none > /sys/class/leds/led0/trigger"
```
このコマンドを入力した時、LEDが消灯したことを確かめてください。

また、`/sys/class/leds/led0/trigger`に、**「heartbeat」**を設定することで、なんちゃってLチカを実行することができます（コマンド実行後、直ちにLEDが点滅し始めるはずです）。

```sh:なんちゃってLチカ「heartbeat」
sudo sh -c " echo heartbeat > /sys/class/leds/led0/trigger"
```
なお、次のコマンドで、`/sys/class/leds/led0/trigger`を開くことができ、内容の閲覧ができます。

```sh:/sys/class/leds/led0/triggerの内容閲覧
cat /sys/class/leds/led0/trigger
```
**次に進むために、`/sys/class/leds/led0/trigger`に「heartbeat」ではなく、「none」を上書きしておいてください。**
noneにすることで、システム以外から正しく制御できるようになります（信号が重複しない）。

## GPIO ポートを制御する
あとは、GPIO ポートを制御するだけです。
ACTLEDのGPIO番号はGPIO47です。

ここで問題なのは、GPIO47は普段シェルコマンドでGPIOの制御に利用しているsysfs では制御できない事です。
なので、Pythonから、「RPi.GPIO」モジュールを利用します。

## PythonによるLEDの制御
Python が実行できるかどうか確認します。

```sh:Pythonバージョン確認
python --version 
```

`Python x.x.x`と表示されればOK、エラーが出た場合、Pythonをインストールする必要がある。

以下にソフトPWMを利用した、Lチカのコードを記載します（**これは直接コンソールにコピペできない**）


```py:エンター押すまでLチカ.py
# モジュール読み込み
import RPi.GPIO as GPIO
# LEDの点滅周期を1Hzに設定
frequency = 1

# GPIO番号で、指定できるように設定
GPIO.setmode(GPIO.BCM)
# GPIO47を出力に設定
GPIO.setup(47, GPIO.OUT)
# GPIO47をソフトPWMで設定
pwm47 = GPIO.PWM(47, frequency)

# PWMをDuty比10で出力(負論理、かつ100がMAX)
pwm47.start(90)

# エンターを押すまで、待機
raw_input('Press return')	

# 終了処理
pwm47.stop()
GPIO.cleanup()
```

以下のコマンドはコンソールにコピーペーストで動作します。(3秒間Lチカ)

```sh:3秒間Lチカ
# Lchika pwm blink test
cat > test.py <<_EOT_
import RPi.GPIO as GPIO
from time import sleep

frequency = 1

# mode set
GPIO.setmode(GPIO.BCM)
# set GPIO47
GPIO.setup(47, GPIO.OUT)
# set pwm
pwm47 = GPIO.PWM(47, frequency)

# PWM Out
pwm47.start(90)

sleep(3)

pwm47.stop()
GPIO.cleanup()

_EOT_
python test.py # 実行コマンド
rm test.py # ファイル削除コマンド 
```

# Raspberry Pi ZERO 起動時に、自動でLチカを行う
Raspberry Pi ZERO 起動時にプログラムを動作させるには、`/etc/rc.local`に実行したいスクリプトの場所を追記することで、起動毎に実行してくれます。

## Lチカのプログラムを`/usr/local/bin/BlinkLED.py`に保存
まず、無限ループするLチカのプログラムを`/usr/local/bin/BlinkLED.py`に保存しておきます。

```sh:無駄にもふわり、またたくLチカ
# Lchika pwm animation test
sudo sh -c "cat > /usr/local/bin/BlinkLED.py" <<_EOT_
import RPi.GPIO as GPIO
from time import sleep

frequency = 100

# mode set
GPIO.setmode(GPIO.BCM)
# set GPIO47
GPIO.setup(47, GPIO.OUT)
# set pwm
pwm47 = GPIO.PWM(47, frequency)

# PWM Out
pwm47.start(100)

# Change PWM Duty
def SetDuty(duty_cycle,sleep_sec):
    if (0<=(100-duty_cycle)) and ((100-duty_cycle) <= 100):
        pwm47.ChangeDutyCycle(100-duty_cycle)
        sleep(sleep_sec)

# animation
def animation():
    SetDuty(20,0.05)
    SetDuty(50,0.05)
    SetDuty(100,0.1)
    SetDuty(90,0.05)
    SetDuty(50,0.05)
    SetDuty(0,0.7)

# main
while True:
    animation()

# not use
pwm47.stop()
GPIO.cleanup()

_EOT_
python /usr/local/bin/BlinkLED.py # 実行コマンド
```
実行すると、LEDがふんわり点滅することが確認できるはずです。
ここで、実行した場合、無限ループするプログラムなので、ターミナルが応答しなくなります。

ターミナルでの実行を終了する場合、**`Ctrl+[C]`**を入力します。

## `/etc/rc.local`にBlinkLED.pyを自動で起動するように追記
今回、Raspberry Pi起動ごとにして欲しい事は、BlinkLED.pyの起動と、`/sys/class/leds/led0/trigger"`を**[none]**に設定することです。

以下のコマンドで`/etc/rc.local`に追記できます。(正確には、文章内終盤の"exit 0"の手前に追記する必要があります)

```sh:rc.localに追記
sudo sed -i "/^exit 0/i\echo none >/sys/class/leds/led0/trigger"  /etc/rc.local
sudo sed -i "/^exit 0/i\python3 /usr/local/bin/BlinkLED.py "  /etc/rc.local
```

最後に再起動します

```sh:再起動
sudo reboot
```
私の場合、再起動コマンド入力後、40秒程度で、LEDがふんわり点滅しだしました。

ここで、40秒程度たっても、LEDがいつも通りな場合、`/etc/rc.local`がうまく動作していません。
消灯する場合、`/sys/class/leds/led0/trigger`は「none」に設定できており、`BlinkLED.py`がうまく動作していません。

# まとめ
おつかれさまでした。
今回、LinuC/lpicの学習の一環で、Raspberry Piをいじり直す機会があり、やってみました。
なので、catやsedなどのコマンドが多く、Linux初心者には、わかりずらいかもしれません。



<br/><br/><br/><br/><br/><br/><br/><br/>