ラズベリーパイは基板上に「GPIO」と呼ばれる、ラズベリーパイ上で作成したプログラムから信号の入力・信号の出力が行えるピンが存在します。
信号の入力とは「スイッチのON/OFF」「温度計で室温の計測」といった、ラズベリーパイの外の情報を入力(インプット)してプログラム上で使用することです。
対して、信号の出力とは「LEDを点灯させる」「モータを回す」といった、ラズベリーパイで制御した結果を外に出力(アウトプット)することです。
この記事では、ラズベリーパイのプログラム(Python)で、PWMサイクルのデューティ比を変えることでLEDの明るさを制御する方法について解説します。
LEDの明るさを制御することなく、点灯/消灯を切替えることで制御する方法は以下のページで解説しております。
【ラズパイ電子工作】LEDを点灯させる方法(GPIO使用) 【ラズパイ電子工作】LEDをチカチカ点滅させる方法(while文で無限ループ) 【ラズパイ電子工作】LEDをチカチカ点滅させる方法(for文で回数指定) 【ラズパイ電子工作】スイッチを押している間だけLEDを点灯させる方法(GPIO使用)目次
1. 完成イメージ(LEDの明るさを制御する)
この記事で完成するものは以下のようになります。
(少しわかりずらいですが…)LEDが消灯している状態から徐々に明るくなります。
2. 使用する部品
今回使用する部品は以下の通りです。
『Raspberry Pi 3 Model B+』を使用します。※2020年3月時点で最新はRaspberry Pi 4になります。
LEDや抵抗といった各種部品や(後述する)ジャンパ線などを穴に差し込み、部品間を電気的に接続する板(ボード)です。
電子工作をする上で必須の部品です。
ブレッドボートに差し込み、電子部品の間を電気的に接続します。
↑の写真では両側が「ピン」になっており、ブレッドボートの穴に差し込んで使用します。
日常生活でも馴染みがある方も多いLEDは「Light emitting diode」の略で、発光ダイオードと呼ばれています。
電子工作で頻繁に使用するLEDは極性があり、プラスとマイナスを逆に接続しても光りません。プラス側をアノード(Anode)、マイナス側をカソード(Cathode)とも呼びます。
電子工作をするため、これまで解説した部品の他にもスイッチやセンサなど、色々な部品が必要になってきます。個々で購入するには手間がかかるため、最初はセット品を購入することをおススメします。
私は以下のセット品を購入しました!
また、これからラズベリーパイを購入する場合、ラズベリーパイ本体を含めたセット品を購入することをおススメします。
ラズベリーパイ本体を収めるケースや、OSをインストールするためmicroSDカードなど必要なものを個々に購入する手間を省くことができます。
3. 回路図・配線の様子
ラズベリーパイのプログラム(Python)で、スイッチを用いてサーボモータの角度を制御する回路を解説します。
回路図は以下のようになります。
ラズベリーパイの「GPIO 18番ポート」と赤LEDのプラス側(アノード)を接続します。(オレンジ色のジャンパ線)
LEDのマイナス側(カソード)と抵抗(220Ω)を接続して、抵抗とGNDを接続します。(黒色のジャンパ線)
配線の様子です。こんな感じになりました。
↑では、フラットケーブルでGPIOの全ピンをブレッドボードに接続しています。回路図と実際の配線は異なる部分がありますがご了承ください。
※電気的には「回路図」と同じ意味です。
4. プログラム(Python)
PWMサイクルのデューティ比を変えることでLEDの明るさを制御するプログラム(Python)は以下のようになります。
#必要なモジュールをインポート
import RPi.GPIO as GPIO #GPIO用のモジュールをインポート
import time #時間制御用のモジュールをインポート
import sys #sysモジュールをインポート
#ポート番号の定義
Led_pin = 18 #変数"Led_pin"に18を代入
#GPIOの設定
GPIO.setmode(GPIO.BCM) #GPIOのモードを"GPIO.BCM"に設定
GPIO.setup(Led_pin, GPIO.OUT) #GPIO18を出力モードに設定
#PWMの設定
Led = GPIO.PWM(Led_pin, 50) #GPIO.PWM(ポート番号, 周波数[Hz])
#初期化処理
Led.start(0) #PWM信号0%出力
bright = 0 #変数"bright"に0を代入
#while文で無限ループ
#LEDの明るさをデューティ比で制御
#Led.ChangeDutyCycle(デューティ比)
while True:
try:
Led.ChangeDutyCycle(bright) #PWM信号出力(デューティ比は変数"bright")
time.sleep(0.05) #0.05秒間待つ
bright += 1 #変数"bright"を+1
if bright >= 100: #変数"bright"が100以上であれば以下を実行
bright = 0 #変数"bright"に0を代入
except KeyboardInterrupt: #Ctrl+Cキーが押された
Led.stop() #LED点灯をストップ
GPIO.cleanup() #GPIOをクリーンアップ
sys.exit() #プログラムを終了
極端に言うと、GPIOの18番ポートを用いてPWM出力のデューティ比をwhile文で繰り返し変化させているプログラムです。
#必要なモジュールをインポート
import RPi.GPIO as GPIO #GPIO用のモジュールをインポート
import time #時間制御用のモジュールをインポート
import sys #sysモジュールをインポート
2行目~4行目で、今回必要な「モジュール」を宣言します。
#ポート番号の定義
Led_pin = 18 #変数"Led_pin"に18を代入
変数”Led_pin”に数値を代入します。この数値はGPIOのポート番号として扱い、後からポート番号を変更する場合はこの数値を変更します。
#GPIOの設定
GPIO.setmode(GPIO.BCM) #GPIOのモードを"GPIO.BCM"に設定
GPIO.setup(Led_pin, GPIO.OUT) #GPIO18を出力モードに設定
GPIOの設定を行います。
GPIO.setmode(GPIO.BCM)
は、GPIOをポート番号で扱う方法に設定します。
GPIO.setup(Led_pin, GPIO.OUT)
は、GPIO 18番ポートを出力モードに設定します。
#PWMの設定
Led = GPIO.PWM(Led_pin, 50) #GPIO.PWM(ポート番号, 周波数[Hz])
PWM信号を使用する為の設定を行います。
Led = GPIO.PWM(Led_pin, 50)
は、GPIO 18番ポートを50HzのPWM信号に割り当てます。
#初期化処理
Led.start(0) #PWM信号0%出力
bright = 0 #変数"bright"に0を代入
初期化する処理を行います。
Led.start(0)
は、GPIO 18番ポートのPWM信号のデューティ比を0%に出力します。
#while文で無限ループ
#LEDの明るさをデューティ比で制御
#Led.ChangeDutyCycle(デューティ比)
while True:
try:
Led.ChangeDutyCycle(bright) #PWM信号出力(デューティ比は変数"bright")
time.sleep(0.05) #0.05秒間待つ
bright += 1 #変数"bright"を+1
if bright >= 100: #変数"bright"が100以上であれば以下を実行
bright = 0 #変数"bright"に0を代入
except KeyboardInterrupt: #Ctrl+Cキーが押された
Led.stop() #LED点灯をストップ
GPIO.cleanup() #GPIOをクリーンアップ
sys.exit() #プログラムを終了
「while文」は条件を指定して、その条件が真の時に繰り返し処理を行うものです。
while 条件式:
繰り返し処理を行うコード
↑の「条件式」にTrue
を指定することにより、条件式は常に真となりwhile文は無限に繰り返します。
ただし、このままではプログラム実行中に無限ループから抜け出す方法がありません。そこでwhile文の中にある「try文」と「except文」を使用します。
このtry-except文を用いることにより、while文の処理は以下のようになります。
while True:
try:
繰り返し処理を行うコード
except KeyboardInterrupt: #Ctrl+Cキーが押された
GPIO.cleanup() #GPIOをクリーンアップ
sys.exit() #プログラムを終了
except KeyboardInterrupt:
は、キーボードのCtrl + Cキーが押された時にwhile文の繰り返し処理から抜けて「GPIOのクリーンアップ」と「プログラムの終了」の処理を行います。
Ctrl + Cキーが押されていないとき、try:文の中の処理を繰り返し行います。(以下で解説)
while文の中の「繰り返し処理を行うコード」は以下の通りです。つまり、Ctrl + Cキーが押されるまで以下の処理を繰り返します。
Led.ChangeDutyCycle(bright) #PWM信号出力(デューティ比は変数"bright")
time.sleep(0.05) #0.05秒間待つ
bright += 1 #変数"bright"を+1
if bright >= 100: #変数"bright"が100以上であれば以下を実行
bright = 0 #変数"bright"に0を代入
Led.ChangeDutyCycle(bright)
はGPIO 18番ポートのデューティ比を変数”bright”の値に変更します。
変数”bright”は上記で0を代入してありますので、最初はデューティ比が0となりLEDは消灯します。
time.sleep(0.05)
は、何もせずに0.05秒待ちます。この処理を行うために3行目でtimeモジュールをインポートしています。
bright += 1
は変数”bright”をインクリメント(1ずつ加算)します。この変数をインクリメントすることでデューティ比が上がっていき徐々にLEDが明るくなっていきます。
「if文」を使用して、変数”bright”が100に到達すると0に戻す処理を行います。
if 条件式:
条件式が"真"の時に実行するコード
この「while文」内の処理を無限ループすることでLEDを徐々に明るくする制御をします。
5. おわりに
PWMサイクルのデューティ比を変えることでLEDの明るさを制御する方法を解説しました。
同様にPWMサイクルのデューティ比を制御してサーボモータを動かす方法を以下のページで解説しております。
【ラズパイ電子工作】サーボモータを動かす方法(デューティ比指定)まだまだラズベリーパイ初心者の私ですが、以下の参考書が大変参考にさせて頂いております。
2冊とも初学者にも易しい内容になっており、ゼロからラズベリーパイを始める方にもオススメできる参考書です。