LEDの明るさを調整する2つの方法【PWM調光とアナログ調光】
LEDの明るさを調整する方法には、
- PWM調光
- アナログ調光
の2つがあります。
今回はPWM調光とアナログ調光の違いと、それぞれのやり方を説明していきます。
アナログ調光
先にイメージしやすいアナログ調光について説明していきます。
アナログ調光とは、LEDに流す電流を連続的に変えることで明るさを調整する方法です。
LEDは電流を多く流すほど明るくなります。
アナログ調光の実験回路
アナログ調光の一番簡単な方法は、抵抗値を変えて流す電流を変化させる方法です。
このような回路でLEDに流す電流を調整します。
1kΩの抵抗は最大電流を決めるためのものです。
可変抵抗器は0Ω~10kΩまで変化します。
今回使ったLEDのVF(順方向電圧)は約2Vなので、可変抵抗器の抵抗が10kΩなら、LEDに流れる電流:IFは
IF = (5V – 2V)/11kΩ = 0.273mA
可変抵抗器の抵抗が0Ωなら、
IF = (5V – 2V)/1kΩ = 3mA
となります。
アナログ調光の実験結果
可変抵抗器のツマミを回して抵抗値を10kΩ⇒0Ωへ徐々に変化させていくと、このようにLEDの明るさが変化します。
ボリュームを使ってアナログ調光をやってみた。 pic.twitter.com/LaeyoQOSRw
— りょうのすけ (@ryo_analog) July 17, 2022
PWM調光とは
PWMはPulse Width Modulationの略で、パルスの幅を変化させることで制御する方式です。
PWM調光とは、LEDを高速でオン・オフさせて明るさを調整する方法です。
目で追えないほど速くオン・オフを切り替えるので、残像現象でずっと点灯しているように見えます。
オンする時間(パルス幅)が長いほど明るくなり、短いと暗くなります。
オンの期間とオフの期間の比率をDUTY(デューティ)といい、単位は%です。
オン期間とオフ期間が同じならDUTYは50%、全期間でオンなら100%となります。
ラズパイでLEDの明るさを制御する
それでは、ラズパイを使って実際にLEDをPWM調光してみましょう。
PWM調光の回路図
回路図はこのようにしました。
ラズパイ4Bの場合、PWMに対応しているGPIOポートは次の4つです。
- PWM Channel0:GPIO 12、GPIO 18
- PWM Channel1:GPIO 13、GPIO 19
今回はGPIO18を使います。
GPIO18がHi(3.3V)を出力するとLEDがオンし、GPIO18がLo(0V)だとLEDがオフします。
HiとLoの期間の比率を変えることでLEDの明るさを変えます。
220Ωは電流制限抵抗で、GPIO18がHiの時に流れる電流を決めています。
LEDに流れる電流:IFは、
IF = (3.3V – 2V) / 220Ω = 5.9mA
となります。
Pythonコード
指定したDUTYで光らせるコードです。
import RPi.GPIO as GPIO #GPIO用のモジュール
import time #時間制御用のモジュール
LedPin = 12 #GPIO18を使用
global p
GPIO.setmode(GPIO.BOARD) # GPIOを物理ピン番号で指定
GPIO.setup(LedPin, GPIO.OUT) # LedPinを出力モードに設定
GPIO.output(LedPin, GPIO.LOW) # LedPinの出力をLoにする
p = GPIO.PWM(LedPin, 500) # PWM周波数を500Hzに設定
p.start(0) # DUTYの初期値を0に設定
p.ChangeDutyCycle(80) # DUTYを80%に変更
time.sleep(5) # 5秒間待つ
GPIO.output(LedPin, GPIO.LOW) # LedPinの出力をLoにする
p.stop() # PWM停止
GPIO.cleanup()
GPIO18から500HzのPWM波形を出力します。
「ChangeDutyCycle」でDUTYを指定します。
DUTYが80%の時の結果
DUTYが20%の時の結果
オシロスコープの波形はGPIO18の出力をモニタしています。
DUTYの違いによってLEDの明るさが変化していることが分かります。
明るさを徐々に変化させる
PWMのDUTYを徐々に変化させることで、明るさを徐々に変化させることができます。
コードは次の通りです。
import RPi.GPIO as GPIO #GPIO用のモジュール
import time #時間制御用のモジュール
LedPin = 12 #GPIO18を使用
def setup():
global p
GPIO.setmode(GPIO.BOARD) # GPIOを物理ピン番号で指定
GPIO.setup(LedPin, GPIO.OUT) # LedPinを出力モードに設定
GPIO.output(LedPin, GPIO.LOW) # LedPinの出力をLoにする
p = GPIO.PWM(LedPin, 500) # PWM周波数を500Hzに設定
p.start(0) # DUTYの初期値を0%に設定
def loop():
while True: # 無限ループ
for dc in range(0, 101, 1): # dc(Duty Cycle)を0%から100%まで1%ずつ大きくする
p.ChangeDutyCycle(dc) # DUTYをdcの値に変更する
time.sleep(0.02) # 20ms間待つ
time.sleep(1) # 1s間待つ
for dc in range(100, -1, -1): # dc(Duty Cycle)を100%から0%まで1%ずつ小さくする
p.ChangeDutyCycle(dc) # DUTYをdcの値に変更する
time.sleep(0.02) # 20ms間待つ
time.sleep(1) # 1s間待つ
def destroy():
GPIO.output(LedPin, GPIO.LOW) # LedPinの出力をLoにする
p.stop() # PWM停止
GPIO.cleanup()
if __name__ == '__main__': # プログラムが実行された時
print ('Program is starting ... ')
setup()
try:
loop()
except KeyboardInterrupt: # ctrl-cでプログラム終了
destroy()
DUTYを1%ずつ、20msごとに変化させています。
このコードを実行した結果はこのようになります(少し早送りしているので、実際はもっとゆっくり変化します)
PWM調光とPWM波形 pic.twitter.com/GQgWbf5CSb
— りょうのすけ (@ryo_analog) 2022年7月17日