強弱をつけてLEDを点滅させる
こんにちは。
大分期間が空いてしまいましたが、LEDをただ光らせるのではなく明るくしたり、暗くしたり、強弱をつけて点滅させる方法について解説していきます。
詳細は下記URLを参照してください↓
http://osoyoo.com/2017/06/26/pi3-breathing-led/
PWMとは?
強弱をつけて点滅させるためには「PWM (Pulse Width Modulation)」という信号を使う必要があります。ご存知の通り、GPIOから出力される信号はデジタル信号なので0か1です。そのため、普通に考えればLEDの明るさを調整するなんてできるはずがありません。しかし、LEDは半導体なので電圧が加わってから明るくなるまでに多少のラグがあります(扇風機の電源を入れると最初ハネはゆっくり回って徐々に回転を上げていくあの現象をイメージして下さい)。この性質をうまく活用して、電圧を加える時間を調整することでLEDの明るさを調整します。「PWM」について詳しく知りたい場合は下記URLを参照してください↓
https://toshiba.semicon-storage.com/jp/design-support/e-learning/brushless_motor/chap3/1274512.html
LEDの配線
PWMに関する説明はここまでとして、まずLEDの配線を行います。以下配線図と実際の配線の様子です。今回はGPIO18のピンを使用します。前回も申し上げましたが、LEDの向きに気をつけて下さい。
プログラムのダウンロード
配線が終わったら、osoyooからプログラムをダウンロードします。コマンドラインを立ち上げて下記のコマンドを入力します。
sudo wget http://osoyoo.com/driver/pi3_start_learning_kit_lesson_6/breathing_led.py
ダウンロードしたプログラムの内容は下記の通りです。
import RPi.GPIO as GPIO
import time
#set BCM_GPIO 18(GPIO1) as LED pin
LEDPIN = 18
#print message at the begining ---custom function
def print_message():
print ('|**********************************|')
print ('| Breath LED |')
print ('| ---------------------------- |')
print ('| LED Connect to GPIO1 |')
print ('| ---------------------------- |')
print ('| |')
print ('| OSOYOO|')
print ('|**********************************|\n')
print ('Program is running...')
print ('Please press Ctrl+C to end the program...')
pass
#setup function for some setup---custom function
def setup():
global p
GPIO.setwarnings(False)
#set the gpio modes to BCM numbering
GPIO.setmode(GPIO.BCM)
#set all LedPin's mode to output,and initial level to HIGH(3.3V)
GPIO.setup(LEDPIN,GPIO.OUT,initial=GPIO.LOW)
#set LEDPIN as PWM output,and frequency=100Hz
p = GPIO.PWM(LEDPIN,100)
#set p begin with ualue 0
p.start(0)
pass
#main function
def main():
#print info
print_message()
while True:
print("|****************************|")
print("| Increase duty cycle |")
print("|****************************|")
#increase duty cycle from 0 to 100
for dc in range(0,101,4):
#chang duty cycle to dc
p.ChangeDutyCycle(dc)
time.sleep(0.1)
pass
print("|****************************|")
print("| Decrease duty cycle |")
print("|****************************|")
#decrease duty cycle from 100 to 0
for dc in range(100,-1,-4):
#change duty cycle to dc
p.ChangeDutyCycle(dc)
time.sleep(0.1)
pass
pass
pass
#define a destroy function for clean up everything after the script finished
def destroy():
#stop p
p.stop()
#turn off led
GPIO.output(LEDPIN,GPIO.LOW)
#release resource
GPIO.cleanup()
pass
# if run this script directly ,do:
if __name__ == '__main__':
setup()
try:
main()
#when 'Ctrl+C' is pressed,child program destroy() will be executed.
except KeyboardInterrupt:
destroy()
pass
pass
コードの解説
前回解説した「LEDを点滅させる」場合と異なるのは赤文字と青文字で示したコードです。そこだけ解説していきます。
※なお、
PythonでLEDを点滅させる ~その2~ - ひまひま電子工作
で解説済みのコードの解説は割愛します。
①setup関数
この関数でPWMの設定を行っています。
global p
↑変数の前にglobalを入れることで、関数の外でも変数を使えるようにします。実際、ここでのpという変数はmain関数でもdestroy関数でも使われています。
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(LEDPIN,GPIO.OUT,initial=GPIO.LOW)
p = GPIO.PWM(LEDPIN,100)
↑GPIO.PWM(ピン番号,100)とすることで指定したPINでPWMが使用できるようになります。今回はLEDPIN=18なのでGPIO18のピンでPWMを使うということです。ちなみに100はPWMの周波数を100Hzにするという意味です。
p.start(0)
↑pの最初の出力を0にします。
pass
②main関数
LEDを徐々に明るくしてその後徐々に暗くする動作を実行します。
print_message()
while True:
print("|****************************|")
print("| Increase duty cycle |")
print("|****************************|")
for dc in range(0,101,4):
#chang duty cycle to dc
p.ChangeDutyCycle(dc)
time.sleep(0.1)
pass
↑ChangeDutyCycleでsetup関数で定義したpにPWM信号を出力します。for dc in range(0,101,4)となっており、すなわち0から最大出力の101までを4のステップで上げていくことになります。101を変更すれば最大時の明るさを変更できますし、4を変更すれば最大の明るさになるまでのスピードを変更することができます。
print("|****************************|")
print("| Decrease duty cycle |")
print("|****************************|")
for dc in range(100,-1,-4):
#change duty cycle to dc
p.ChangeDutyCycle(dc)
time.sleep(0.1)
pass
↑今度はfor dc in range(100,-1,-4)となっており、明るい状態から徐々に暗くしていく、というコードです。
pass
pass
プログラムの実行
ではプログラムを実行します。コマンドラインで下記コマンドを入力することで実行可能です。
sudo python breathing_led.py
実行後の動作の様子は下記の通りです。
ちなみに複数のGPIOピンを使うとPWMでこんなこともできます。
以上になります。PWMを活用することで電子工作はより楽しいものになるはずです。ぜひ活用してください。
PythonでLEDを点滅させる ~その2~
今回は、ひとつ前の記事「PythonでLEDを点滅させる ~その1~」で触れなかったプログラムの内容について解説します。少し長くなりますがお付き合い頂けたら幸いです。
さて、前回はコマンドラインで以下のコマンドとURLを入力してLED点滅用のプログラムをダウンロードしたと思います。
wget http://osoyoo.com/driver/pi3_start_learning_kit_lesson_4/pythontest.py
プログラム名は「pythontest.py」です。ダウンロードしたプログラムのコードはnanoエディタというテキストエディタ上で起動することにより見たり編集したりすることができます。起動には以下のコマンドを入力します。
sudo nano pythontest.py
プログラムの中身は以下の通りです。
import PRi.GPIO as GPIO
import time
# set GPIO 0 as LED pin
LEDPIN=17
def print_message():
print ('|*********************************|')
print ('| blink LED |')
print ('| ------------------------- |')
print ('| LED connect to GPIO |')
print ('| |')
print ('| LED will blink at 500ms |')
print ('| ------------------------- |')
print ('| |')
print ('| OSOYOO |')
print ('********************************** ')
print ('Program is running...')
print ('Please press Ctrl+C to end the program...')
def setup():
GPIO.setwarnings(False)
#set the gpio modes to BCM numbering
GPIO.setmode(GPIO.BCM)
#set LedPin's mode to output,and initial level to LOW(0V)
GPIO.setup(LEDPIN,GPIO.OUT,initial=GPIO.LOW)
#main function
def main():
#print info
print_message()
while True:
GPIO.output(LEDPIN,GPIO.HIGH)
print('...LED ON ')
time.sleep(0.5)
GPIO.output(LEDPIN,GPIO.LOW)
print('LED OFF... ')
time.sleep(0.5)
pass
pass
#define a destroy function for clean up everything after the script finished
def destroy():
#turn off LED
GPIO.output(LEDPIN,GPIO.LOW)
#release resource
GPIO.cleanup()
#if run this script directly ,do:
if __name__== '__main__':
setup()
try:
main()
#when 'Ctrl+C' is pressed, child program destroy() will be excused.
except KeyboardInterrupt:
destroy()
なにやら長くて難しく感じてしまいますが、順番に解説していきますのでご辛抱ください。まずこのプログラムは大きく分けて、①赤色のコード:必要なライブラリのインポート、②紫色のコード:使用するGPIOピンの指定、③緑色のコード:LED点滅に使用する関数の定義、④茶色のコード:関数の実行(LEDの点滅)、の4つのパートに分かれています。以下、各パートごとに解説していきます。
①必要なライブラリのインポート
LEDを点滅させるためには、RaspberryPiからGPIOピンを介してLEDへ信号を出力したり、出力する時間を制御したりする必要があります(例えば1秒間信号を出力してLEDを光らせた後、1秒間出力を止める。これを繰り返せば1秒おきにLEDは点滅する)。そのため、今回はGPIOピンの制御に使用する「PRI.GPIO」と時間の制御に使用する「time」の2つのライブラリをインポートします。
インポートは、
import ライブラリ名(今回の場合、RPI.GPIOやtimeのこと)
で実施します。ちなみに、
import ライブラリ名 as ○○
と入力するとライブラリ名を○○に置き換えることができ、ライブラリ名が長い場合は後々コードを書く作業が楽になります。今回は、PRI.GPIOをGPIOという名前に置き換えています。
PRI.GPIOとtimeは電子工作において必須のライブラリと言えます。プログラムを作成する際はコードの冒頭に必ずimport PRI.GPIOとimport timeを書いておきましょう。
②使用するGPIOピンの指定
ここはLEDPINという変数を定義しているだけです。今回の場合、GPIO17から信号を
出力するので17を指定します。
③ LED点滅に使用する関数の定義
ここがLEDを点滅させるのに一番大事なパートになります。プログラムでは同じ動作を何度も繰り返すことがよくあるので、繰り返し行う動作をひとつの関数として定義してしまいます。これによって、いちいち同じコードを書き直さなくても関数名を指定するだけで済みます。関数は以下のように定義します。
def 関数名():
関数の内容
ダウンロードしたプログラムでは、【1】print_message、【2】setup、【3】main、【4】destroy、の4つの関数が定義されています。このうち【1】はただコマンドラインに文字を表示するだけのプログラムなのでLEDの動作とは関係ありません。よってここでの解説は省略します。
【2】setup
GPIOでLEDを制御するための前準備にあたる関数です。最初にimport PRI.GPIO as GPIOと置き換えたので、コードに記されたGPIOはPRI.GPIOライブラリのことを指します。GPIO.○○と書くことでPRI.GPIOライブラリの関数を利用できます。
GPIO.setwarnings(False)
↑ 書かなくても問題ないです。setwarnings(False)とすることでGPIOピンの値がデフォルト値じゃないときに表示される警告を無視することができます。警告はGPIOピンを使った別のプログラムが並行で動作しているときなどに表示されます。
GPIO.setmode(GPIO.BCM)
↑ GPIOピンの番号を定義します。setmode(GPIO.BCM)ならBCMで番号指定。setmode(GPIO.BOARD)ならピンの並び順で番号指定。詳しく知りたい方は、「PythonでLEDを点滅させる ~その1~」か下記サイトを参考にしてみてください。
http://mamerium.com/raspberry-pi-rpi-gpio-basic/
GPIO.setup(LEDPIN,GPIO.OUT,initial=GPIO.LOW)
↑ setup(ピン番号,GPIO.OUT,initial=GPIO.LOW)は「指定したピンを,出力端子として使用します,初期値は0です」という意味になります。今回はLEDPIN=17と定義しているので、「GPIO17のピンからLEDへ出力します。最初は出力しません」という意味になります。
【3】main
LEDを点滅させる関数です。ここのプログラムに変更を加えることでLEDを点滅させるタイミングなども変えることができます。
print_message()
↑ 【1】のprint_message関数です。説明は省きます。
while True:
↑ While True:構文を使うとエラーが発生しない限り、コロン以降の字下げされたコードをひたすら繰り返します。以下は字下げされたコードです。
GPIO.output(LEDPIN,GPIO.HIGH)
print('...LED ON ')
time.sleep(0.5)
GPIO.output(LEDPIN,GPIO.LOW)
print('LED OFF... ')
time.sleep(0.5)
pass
↑ GPIO.output(LEDPIN,GPIO.HIGH)でGPIO17のピンの出力を1にする→print('...LED ON ')でコマンドラインに「...LED ON」と表示する( は改行を意味します)→time.sleep(0.5)で上記の状態を0.5秒間キープする
その後、GPIO.output(LEDPIN,GPIO.LOW)GPIO17のピンの出力を0にする→print('LED OFF... ')でコマンドラインに「...LED OFF」と表示する)→time.sleep(0.5)で上記の状態を0.5秒間キープする
passは字下げされたコード部分で例外が発生したときに何もしないという意味です。これによりエラーによるプログラムの停止を避けることができます。
【4】destroy
LED点滅プログラムを停止するための関数です。プログラムでWhile true:を使っているので、この関数がないとひたすらLEDは点滅し続けます。
GPIO.output(LEDPIN,GPIO.LOW)
GPIO.cleanup()
↑ GPIO17からの出力を0にし、GPIO.cleanup()でピンの設定を初期化します。cleanupを最後に行わないとsetup関数で設定した情報が残るため、別のプログラムを実行したときに誤作動を引き起こす可能性があります。
④関数の実行(LEDの点滅)
最後に関数の実行です。ここでは③で定義した各関数を呼び出すことでLEDを点滅させます。
if __name__== '__main__':
↑ if○○:は○○の条件がTrueである場合のみに、コロン以降の字下げされた部分のコードを実行するという構文です。__name__== '__main__'は今回扱ったプログラムをコマンドライン上で実行した場合のみTrueとなることを意味します。逆に、import python test.pyのように他のプログラムでモジュールとして呼び出した場合、Falseになりif構文に含まれたコードは実行されないということです。ここは私も今一つ理解できていませんが、詳しく知りたい方は以下のURLが参考になるかもしれません。
https://qiita.com/taigamikami/items/2713856b9f3c3b90f6fd
http://programming-study.com/technology/python-if-main/
setup()
try:
main()
except KeyboardInterrupt:
destroy()
↑ setup関数→main関数→例外が発生した場合はdestroy関数、という内容のコードです。ここで、try:とexcept エラー名:はセットで使われる構文で、tryの中で発生したエラーがexceptで指定したエラーと一致する場合はexceptの中のプログラムを実行するというものになります。そして、KeyboardInterruptはctrl+cを検出する関数です。よってここのコードは「try内のmainを実行するが、コマンドラインでctrl+cが入力された場合はdestroyを実行する」という意味で、もっとわかりやすく言うと「ctrl+cが入力されたらLEDの点滅を終了する」ということになります。
プログラムの内容の解説は以上になります。次回は、より複雑な信号をLEDに出力する方法について解説していきたいと思います。
PythonでLEDを点滅させる ~その1~
前準備が完了したら、ここから電子工作に取り掛かります。
まずはLEDを点滅させるという非常にシンプルなものを作成します。
osoyooの「Raspberry Pi Starter Kit V1」を教材に進めていきます。詳細を知りたい方は下記ページにアクセスしてください↓
http://osoyoo.com/2017/10/09/raspberry-pi-starter-kit-v1-introduction/
ページにアクセスして下にスクロールすると様々な電子工作が紹介されています。ここではその中のLesson4に沿って解説していきます。
Lesson4では以下の流れで解説しています。
①RPi.GPIOライブラリがインストールされているかの確認
②IDLE(Development and Learning Environment)ツールの紹介
③LEDの配線方法
④IDLEを使ったプログラムの編集・実行
⓹コマンドライン(Terminal)を使ったプログラムの編集・実行
ここで、IDLEはRaspberry Piに最初からインストールされているPython用のツールで、コードの管理やデバグ(プログラムの不具合の発見と修正)をする上で大変便利です。ただ、osoyooのその他のLessonの内容を見ると、コマンドラインを使って解説を進めているのでここでは使用しません。よって、
① → ③ → ⓹
の順番で解説を進めていきます。
【RPi.GPIOライブラリがインストールされているか確認】
ひとつ前の記事で、C言語を使って電子工作をする場合は素子を制御するためにWiringPiというソフトウェアをインストールする必要がある、と述べました。RPi.GPIOはそのPython版と言えます。幸いなことに、2015-05-27以降にリリースされたRaspberry PiのOSであればこのRPi.GPIOのライブラリが既にインストールされています。まずはインストールが完了しているか、コマンドラインで確認しましょう。コマンドラインはトップ画面の左上のアイコンを左クリックすることで立ち上がります。
コマンドラインが立ち上がったら下記を入力します。
import RPi.GPIO
上記入力後、エラーが発生しなければPRi.GPIOは問題なくインストールされています。さらにバージョンを確認したい場合は下記を入力します。
RPi.GPIO.VERSION
以上でPRi.GPIOの確認は終了です。
【LEDの配線方法】
次はPython本体へのLEDの配線方法についてです。各素子はGPIOピンに配線していきます。GPIOはGeneral Purpose Input/Outputの略とのことで、言わばコンピュータが外部の電子機器とデジタル信号のやりとりをするための出入り口のようなものみたいです、、、。いまいち私も理解が及んでいませんが、とにかくコンピュータごとに出入り口となるピンの数と各ピンの名前が決まっていて、名前を指定することによってそのピンから信号を出力したり、信号を入力したりすることができます。私の説明よりも下記のサイトを参考にしたほうがいいかもしれません。
~参考URL~
http://denshikousaku.net/raspberry-pi-gpio-layout
Raspberry PiのGPIOは40ピンで構成されており、各ピンの名称は下の写真の通りです。例えば上から数えて12番目のピンの名前はGPIO18です。
補足を加えると、写真に書かれた番号はBCMというネーミングシステムで管理されているそうで、PythonはこのBCMに対応しています。C言語はWiringPiに対応しているので、使用する言語によってGPIOの各ピンの名前も変わることに注意してください。各ピンの対応関係は下記コードをコマンドラインで入力することで確認できるので、興味がある方は試してください。
gpio readall
ところで「こんなピンがたくさんあったら目的のピンを見つけるのも大変だし間違えそう!!」と思うかもしれませんが、安心してください。「Raspberry Pi Starter Kit V1」にはRaspberry Pi専用の拡張ボードが付属しており、この拡張ボードを使用すればひとめでピンの位置がわかります。
だいぶ前置きが長くなりましたが、LEDの配線に移ります。
簡易的な回路図は下記のとおりです。B17はRaspberry Piの11番目のピン、すなわち「GPIO 17」です。ここからデジタル信号が出力され、LEDが光ります。LEDは十分に電圧がかかった状態だと電気抵抗が0に近づくため、B17とGND(接地)が直接つながったような状態になり危険です(最悪Raspberry Piが壊れます)。なので、必ず200Ωの抵抗を入れましょう。また、LEDは一方向にしか電流が流れないのでB17に+側が繋がっていることも確認しましょう(足の長いほうが+側です)。
配線した様子は以下のとおりです。
以上で配線は完了です。
【コマンドライン(Terminal)を使ったプログラムの編集・実行】
ここからが最後のステップです。Pythonでプログラムを作成し、LEDを点滅させます。親切なことに、osoyooでは各LessonごとにPythonのコードを配布しています。下記コードをコマンドラインで入力することによりコードのダウンロードが可能です。
wget http://osoyoo.com/driver/pi3_start_learning_kit_lesson_4/pythontest.py
補足を加えると、wgetはwebからファイルをダウンロードするときに使われるコマンドで、後ろにURLを付け加えて使用します。
ダウンロードが完了したら、下記コマンドを入力してダウンロードしたコードを実行しましょう。
sudo python ./pythontest.py
sudoは管理者としてコマンドを実行するときに頭に付けます。pythonのコマンドラインでのプログラム実行は「python ファイル名.py」と入力します。
配線に問題がなく、プログラムが不具合なく動いていれば下の動画のようにLEDが点滅するはずです。
Raspberry PiにLEDを配線してPythonでLEDを点滅させるとこまでを解説しました。基本的に他のLessonもここで紹介したような手順で進むので簡単だと思います。しかし、一方でプログラムを作成する作業がまったくなかったので、「自分の手でLEDを点滅させた!」という実感もいまいち湧かなかったと思います。次回は、osoyooからダウンロードしたコードを読み解きながらPythonによるGPIOの制御について理解を深めていきたいと思います。
p.s.
毎年、恐竜博物館のすぐ近くで行われるというラリー選手権に行ってきました。今年はなんとTOYOTA現社長のモリゾウこと豊田章男さんも参加されていました。冬も行われるみたいでまた見に行きたいです(向かう途中の雪道で事故らなければいいですが)。
電子工作の前準備
こんにちは。
このブログではosoyooの「Raspberry Pi Starter Kit V1」という初心者向けのキットを使用して電子工作を進めていきます。詳細を知りたい方は下記URLにアクセスして下さい。
http://osoyoo.com/ja/2017/10/09/raspberry-pi-starter-kit-v1-introduction/
キットはAmazonで2780円で購入しました。価格のわりにLED、ブザー、温度センサー、リレー回路など、ひと通りの部品が揃っていてお得です。人の侵入を検知してスマホに知らせる、みたいなデバイスも作れちゃいます。
まずはRaspberry Pi本体の準備です。
動作環境の構築やOSのダウンロード等は下記サイトがわかり易かったので参考にして下さい。この後プログラミング言語のインストールやコードのダウンロードが必要になるのでネットワークの設定も忘れずに行いましょう。
http://techblog.clara.jp/2016/04/raspberry-pi-3-model-b_install_and_ssh_connect/
Pythonで電子工作を行う場合はこれで前準備完了になりますが、もしC言語で電子工作したいという方は、「WiringPi」をインストールします。これはRaspberry PiからC言語でセンサーやモーターやLEDなどを制御するために必要なソフトウェアです。厳密にはGPIO(General Purpose Input/Output)を扱うためのソフトウェアらしいのですが、GPIOについてまだ理解不足なので別の機会に話ができたらと思います、、、。
まずはWiringPiがRaspberry Piにインストールされているかターミナル(Terminal)でコマンド入力して確認しましょう。
ターミナルはホーム画面の左上のアイコンをクリックすることで起動できます。
起動したら下記のコマンドを入力します。
gpio -v
コマンドを入力してエンターを押し、gpioのバージョンが表示されたら既にインストールされています。「No such file or directory」と表示されたらWiringPiをインストールしましょう。
WiringPiはターミナルで以下のコマンドを入力することでインストールします。
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install git-core
git clone git://git.drogon.net/wiringPi
cd ~/wiringPi
./build
以上で前準備は完了です。次回から実際に電子工作を始めていきます。
p.s.
福井といえば恐竜博物館、福井市街地から車で約1時間です。毎月第三日曜日は無料開放されます。野外恐竜博物館(別料金)は化石発掘体験もできて大人でも熱中できます。
【初稿】~時間を持て余した会社員が電子工作をゼロから始める〜
福井に出向して早1ヶ月。
関東に住んでた頃は友達も近くに住んでいたので土日は東京出て遊んだり旅行に行ったりスポーツやったりして過ごしてた訳なんですが、、、そう、、、今は暇なんです。
福井は料理も上手いし自然豊かだし温泉もあるし、、、だけど遊ぶ友達がいない。
ひまひまひまひま、、、と思い続けてた自分の目に留まったのは1年ほど前に興味本位で秋葉のショップで購入した「Raspberry Pi 3」でした。
、、、これだ!
電子工作には興味あるけどやったことないしプログラミングはド素人だし。という理由で今まで手をつけずにいたんですが、暇を持て余した自分にもう迷いはありませんでした。
というわけで初めまして。普段はメーカーで開発職をしているものです。
このブログでは自分が最近趣味として始めた電子工作について、そのソースコードや製作の様子などを公開していく予定です。事前に断っておきますが、私は電子工作のプロでもプログラミングのプロでもないので見苦しい内容が多々含まれると思います。ご了承ください。
また、電子工作は基本的にOSOYOOの「Raspberry Pi Starter Kit」という初心者向けのキットを参考にしています。興味のある方は下記URLを参照して下さい(英語です)。
http://osoyoo.com/ja/2017/10/09/raspberry-pi-starter-kit-v1-introduction/
現時点では初心者で電子工作のことは右も左もわかりませんがブログを更新していく中で徐々に勉強させて頂きたいと思います!どうぞよろしくお願いします!
p.s. 福井の東尋坊。行ったことある方はご存知だと思いますが普通に危ないです。
↑自分の足↑