大学は理系の学部だったと言っても、生物系で数学と物理をあまり触れてこなかった私がRaspberry Piに挑戦し始めた。

オームの法則といった定義自体は簡単だけれども、実際に計算しながら回路を組むのが難しいといった壁がたくさんある。


そんな中で、新たに現れた壁として、パルス幅変調(Pulse Width Modulation:PWM)がある。

PWMはモータの制御で重要になるため、施設栽培を理解するためには避ける事ができない重要な内容となっている。

環境制御を学ぶ為にMicro:bitでサーボモータを学ぶ


難しい式は一旦置いといて、実際に使ってみることにする。

パルス幅変調 - Wikipedia




まずはPWMを理解する上で必要最低限のところに触れてみる。

PWMは一旦置いといて、回路に電気を流すことだけを考える。


回路に電気を流す際に重要に成るのが、

電気が流れる状態のHIGHと電気が流れない状態のLOWがある。

※上向きの矢印がHIGH、下向きの矢印がLOW


上記の内容をわかりやすくするようにLチカという練習をしてみる。

LチカはLEDで点灯と消灯を一定の間隔で繰り返す事を指し、HIGHの時に点灯し、LOWの時の消灯する。


※赤い線が+極で、黒い線がー極


LEDの+(アノード)には、65Ω(オーム)以上の抵抗を介してGPIOの4ピンと繋げる。

LEDのー(カソード)には、GPIOのGNDと繋げる。


上の回路図でGPIO4とLEDの間に配置した抵抗が65Ω以上であることのメモを残しておく。

今回使用する5mm赤色LEDはIfが0.020A(20mA)でVfが2Vとする。


LEDは指定の電圧よりも大きな力を与えると壊れてしまうため、抵抗をかまして電圧を下げる必要がある。


Raspberry Pi側のGPIO4の電圧は3.3Vであり、3.3 - 2.0 = 1.3V分の電圧を抵抗で下げる必要がある。

ここでオームの法則であるV = IRを持ち出す。

オームの法則 - Wikipedia


Vは電圧(単位:V)、Iは電流(単位:A)でR(単位:オーム)は抵抗であり、今までの値を代入すると R = 1.3 / 0.02 = 65Ωとなる。

手持ちの抵抗で一番小さいのが470Ωだったので、今回は470Ωを配置する。




続いて、Raspberry Pi側でコードを作成する。

作成したコードは下記の通り。

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)

try:
    while True:
        GPIO.output(4, GPIO.HIGH)
        time.sleep(1)
        GPIO.output(4, GPIO.LOW)
        time.sleep(1)
except KeyboardInterrupt:
    #端末で実行した時に端末から送信されたSIGINT(ctrl + c)を受信した際の挙動を追加
    pass

GPIO.output(4, GPIO.LOW)
GPIO.cleanup()

上記のコードを実行してみたところ、



意図通りのLチカになった。




これからパルス幅変調(PWM)について試す事にする。

PWMで重要になるのは、周期T、パルス幅 τ (タウと読む)とTと τ から導き出されるデューティ比(D)が重要となる。

パルス幅 τ は周期TにおけるHIGHの期間になっている。


周期TはHz(周波数)で指定し、1秒間に何周期あるかを表す。

例えば、50Hzであれば、1秒間に50周期あることになるので、周期Tは0.02秒(20ms)になる。


パルス幅 τ は1msのような数値で指定する。

デューティ比はD = τ / Tで導くので、50Hzでパルス幅が1msの場合、1 / 20 = 0.05(5%)となる。


LEDでPWMを利用してみると、LEDが徐々に明るくなるといった操作が可能となる。




PWMでLEDを制御するために


GPIOを4から12(PWM0)に変更し、下記のコードを作成してみた。

Raspberry Pi Document - Raspberry Pi OS#gpio-and-the-40-pin-header


import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)

pin = 12
GPIO.setup(pin, GPIO.OUT)

# 周波数を60Hzに指定
led = GPIO.PWM(pin, 60)
led.start(0)

# デューティ比を0.1ずつ増やす(実際のコードでは%で指定)
duty = 10
while True:
    led.ChangeDutyCycle(duty)
    duty += 10
    if duty >= 100:
        break
    time.sleep(1)

led.stop()
GPIO.cleanup()

早速このコードを試してみると、


意図通り、LEDが徐々に明るくなった。


追記

Lチカで行ったHIGHはPWMではデューティ比が1(100%)の状態のこと

デューティ比が低い時のLEDの暗さは、実際には暗くはなく、人の目では見えない程の速さで明かりが付ききる前に消灯を行うということを繰り返している状態であるらしい。