初心者向けの電子工作本、ラズパイのガイド本とかの、最初のレッスンは「LEDを繋げて光らせよう!」ですよね。
私も、本やネットのプログラムを参考に、動画のような動き(物理ボタンで開始停止、ctrl+cで停止)をするプログラムを作りました。
このカテゴリー「Python独学 その1」では、このプログラムを作るときに私が調べたことや、感じたことを記事にしています。
通称 エルチカ
趣味で電気工作をやろうと思い、私みたいにラズパイを買ってしまった方なら、本を見ながらプログラムを打ちこめば、赤色のLEDを一個光らせるのも、数秒おきに点滅させるのも、RGB LEDをPWM制御で色んな色に光らせるのも、物理ボタンで開始したり止めたりするのも、特に難しいものではないと思います。
多分、配線とかのハード的なものよりも、本に書かれているPythonのプログラム記述の中でも、主にループに関する部分が、いろんな本、サイトで微妙に違うのに戸惑うかと思います。
というか、私はそこにモヤモヤを感じながら、LEDを光らせていました。
・for in : の構文でループ 3回とか単純なものは分かる
・while True: の構文でループ 無限ループさせる必要性あるの?
・if name == ‘main’: の構文の意味、必要性が??
・try :
except KeyboardInterrupt: Thonnyで停止させればいいのでは??
・return(0) の意味は??
・sys.exit(main()) の意味は??
初心者向きの本は、「for inで何回か繰り返して終了」のプログラム。
アマゾンの電子工作キットのレッスンPDFには、if name に続く構文がありました。
ネットで押しボタンのチャタリングを調べたときは、sys.exit(main()) という記述あり。
初心者向きのプログラムなら、難しい記述省いて、for in だけで良いと思います。
物理ボタンの入力待ちとかで、無限ループは必要ですが、ボタンを押して必要な処理をしたら、そのまま終了するか、数回繰り返すようなプログラムで良いと思います。
それなのに、 なぜ意味不明な構文、というか定型文みたいな、if name == ‘main’: のような記述があるのか?
本来のプログラムというか、プロが作る実践的なプログラムは、より上の階層のプログラムから呼び出して使うことを想定しているんですよね。
「プログラムの冒頭で import 何々 で宣言して」、色んな制御や結果が出た際に、では「LEDを光らせたいから、LEDを光らすプログラムを実行する」という流れだと思うのです。
なので、初心者にはよく分からない構文が、ネットのプログラムには見られるんですよね。
ということで、それぞれの簡単な説明は、別の記事で書きたいと思います。
無駄に難しいプログラムでエルチカ
冒頭の動画のプログラムです。このカテゴリー「Python独学 その1」は、このプログラムの説明となります。
記事の参考のためというか、私が独学中に遭遇した無限ループやプログラムの基本的?な記述をごちゃ混ぜにしたものですので、実践で役に立つかは不明です。
私と同じように、独学で色んなサイトの情報やプログラムを見たときに、「なんじゃコレは??」と感じた時の手助けになればうれしいです。
このプログラムを見て、特に難しくもないし、常識じゃんと思った方は、たぶん私のサイトとは縁がないかと思いますw
#ラズパイのGPIOを制御するために、Rpi.GPIOライブラリーを読み出し
import RPi.GPIO as GPIO
#時間に関する制御をするために、time関数を読み出し
import time
#問題なくプログラムが終了したと報告するための sys.exit()用
import sys
#使用するLEDのGPIO番号(セットモードはBCM)
LedPin1 = 17
#使用する開始終了ボタンのGPIO番号
endBotann = 26
#開始終了ボタンが押されたら 初期値 1true 押されたら 0false ループ解除用
G_break_loop = True
#初期設定 setup()関数の定義
def setup():
#立ち上がり時のGPIOのエラーメッセージを非表示
GPIO.setwarnings(False)
#GPIOのピン番号指定方法(通常はGPIO番号 BCM)(物理ピン番号での指定は BOARD)
GPIO.setmode(GPIO.BCM)
#使用するGPIOピンを入力(IN)で使用するのか、出力(OUT 3.3v)で使用するのかの設定
#initialは初期の状態 1=GPIO.HIGH=True
#初期設定がHighなのは、LEDのカソード(ー)をGPIOに繋げるため
GPIO.setup(LedPin1,GPIO.OUT,initial=1)
#開始終了ボタンの設定 GPIO内部のプルアップ抵抗を使用 ボタンの先はGND
GPIO.setup(endBotann,GPIO.IN,pull_up_down=GPIO.PUD_UP)
#立ち下がり(GPIO.FALLING)を検出する。bouncetime チャタリング防止用
GPIO.add_event_detect(endBotann,GPIO.FALLING,bouncetime=200)
#イベント発生時のコールバック関数を登録
GPIO.add_event_callback(endBotann,Botann_pressed)
#LED 点灯時間調整
def led_time(ledtime):
for loop_i in range(ledtime):
time.sleep(0.1)
#ボタンが押された時に呼び出されるコールバック関数
#gpio_no: イベントの原因となったGPIOピンの番号
def Botann_pressed(gpio_no):
#メッセージを表示
print('GPIO番号',gpio_no,'に接続のボタンが押されました')
#基幹プログラムのループ解除用
#グローバル関数の呼び出し
global G_break_loop
G_break_loop = False
led_time(1) #気持ちチャタリング防止用
#開始終了ボタンのループリセット
def Botann_reset():
global G_break_loop
G_break_loop = True
#メインプログラム1 main1()関数の定義 LEDの点灯
def main1():
#LED ON 0.5秒点灯
GPIO.output(LedPin1,GPIO.LOW)
led_time(5)
#メインプログラム2 main2()関数の定義 LEDの点灯と消灯
def main2():
#LED ON 0.5秒点灯
GPIO.output(LedPin1,GPIO.LOW)
led_time(5)
#LED OFF 0.5秒消灯
GPIO.output(LedPin1,GPIO.HIGH)
led_time(5)
#エンディングプログラム destroy()関数の定義
def destroy():
#LED OFF
GPIO.output(LedPin1,GPIO.HIGH)
#GPIOの初期化
GPIO.cleanup()
#基幹プログラム main1とmain2をループ [clrl+c] でループ離脱
def main():
try:
setup()
print('ボタンを押してスタート')
while G_break_loop:
main1()
else:
print('点滅開始')
Botann_reset()
while G_break_loop:
main2()
else:
print('点滅終了')
except KeyboardInterrupt:
print('ctrl+c が検出されました')
print('プログラムを終了します')
destroy()
return 0
#importで他のプログラム等から呼び出し時に、実行しないための記述
if __name__ == "__main__":
sys.exit(main())
#return 0 でエラーなく終了したことになる。sys.exit(0)という結果
コメント