前回までの状況はこちら。
前回作成したサンプルソースコードを元に、スイッチ処理をモジュール化します。
やり方としては、スイッチの押下検出をスレッドで動かしてメインスレッドで取り出す、という方式が良いと思います。
GPIOのエッジ検出で割り込み処理する、という方法もありますが、このスイッチモジュールの仕様上、それは難しそうです。
import RPi.GPIO as GPIO
import time
import threading
X_p = 0
Y_p = 0
Z_p = 0
A_p = 0
B_p = 0
C_p = 0
D_p = 0
Non = ""
Key = Non
thread = None
Loop = True
def PinsInit(x, y, z, a, b, c, d):
省略
def Start():
thread = threading.Thread(target=threadProcess)
thread.start()
def Stop():
global Loop
Loop = False
def GetKey():
global Key
ret = Key
Key = Non
return ret
def threadProcess():
global Key
col = 1
swState = [0] * 12
while Loop:
if col == 1:
GPIO.output(X_p, GPIO.LOW)
GPIO.output(Y_p, GPIO.HIGH)
GPIO.output(Z_p, GPIO.HIGH)
elif col == 2:
GPIO.output(X_p, GPIO.HIGH)
GPIO.output(Y_p, GPIO.LOW)
GPIO.output(Z_p, GPIO.HIGH)
else:
GPIO.output(X_p, GPIO.HIGH)
GPIO.output(Y_p, GPIO.HIGH)
GPIO.output(Z_p, GPIO.LOW)
# 1押下
if swState[1] == 0 and col == 1 and GPIO.input(D_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(D_p) == 0:
Key = "1"
swState[1] = 1
# 1押下戻し
elif swState[1] == 1 and col == 1 and GPIO.input(D_p) == 1:
Key = Non
swState[1] = 0
# 2押下
if swState[2] == 0 and col == 2 and GPIO.input(D_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(D_p) == 0:
Key = "2"
swState[2] = 1
# 2押下戻し
elif swState[2] == 1 and col == 2 and GPIO.input(D_p) == 1:
Key = Non
swState[2] = 0
# 3押下
if swState[3] == 0 and col == 3 and GPIO.input(D_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(D_p) == 0:
Key = "3"
swState[3] = 1
# 3押下戻し
elif swState[3] == 1 and col == 3 and GPIO.input(D_p) == 1:
Key = Non
swState[3] = 0
# 4押下
if swState[4] == 0 and col == 1 and GPIO.input(C_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(C_p) == 0:
Key = "4"
swState[4] = 1
# 4押下戻し
elif swState[4] == 1 and col == 1 and GPIO.input(C_p) == 1:
Key = Non
swState[4] = 0
# 5押下
if swState[5] == 0 and col == 2 and GPIO.input(C_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(C_p) == 0:
Key = "5"
swState[5] = 1
# 5押下戻し
elif swState[5] == 1 and col == 2 and GPIO.input(C_p) == 1:
Key = Non
swState[5] = 0
# 6押下
if swState[6] == 0 and col == 3 and GPIO.input(C_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(C_p) == 0:
Key = "6"
swState[6] = 1
# 6押下戻し
elif swState[6] == 1 and col == 3 and GPIO.input(C_p) == 1:
Key = Non
swState[6] = 0
# 7押下
if swState[7] == 0 and col == 1 and GPIO.input(B_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(B_p) == 0:
Key = "7"
swState[7] = 1
# 7押下戻し
elif swState[7] == 1 and col == 1 and GPIO.input(B_p) == 1:
Key = Non
swState[7] = 0
# 8押下
if swState[8] == 0 and col == 2 and GPIO.input(B_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(B_p) == 0:
Key = "8"
swState[8] = 1
# 8押下戻し
elif swState[8] == 1 and col == 2 and GPIO.input(B_p) == 1:
Key = Non
swState[8] = 0
# 9押下
if swState[9] == 0 and col == 3 and GPIO.input(B_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(B_p) == 0:
Key = "9"
swState[9] = 1
# 9押下戻し
elif swState[9] == 1 and col == 3 and GPIO.input(B_p) == 1:
Key = Non
swState[9] = 0
# *押下
if swState[10] == 0 and col == 1 and GPIO.input(A_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(A_p) == 0:
Key = "*"
swState[10] = 1
# *押下戻し
elif swState[10] == 1 and col == 1 and GPIO.input(A_p) == 1:
Key = Non
swState[10] = 0
# 0押下
if swState[0] == 0 and col == 2 and GPIO.input(A_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(A_p) == 0:
Key = "0"
swState[0] = 1
# 0押下戻し
elif swState[0] == 1 and col == 2 and GPIO.input(A_p) == 1:
Key = Non
swState[0] = 0
# #押下
if swState[11] == 0 and col == 3 and GPIO.input(A_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(A_p) == 0:
Key = "#"
swState[11] = 1
# #押下戻し
elif swState[11] == 1 and col == 3 and GPIO.input(A_p) == 1:
Key = Non
swState[11] = 0
col += 1
if col > 3:
col = 1
time.sleep(0.005)
Start()でthreadProcess()をバックグラウンドで実行、Stop()でLoop=Falseになるまで実行します。
スイッチを押すと、その値がKeyに入るので、それをGetKey()で取り出します。
変数でワンクッション置いているのは、ボタン押しっぱなしで複数回キー入力を検出するのを防ぐためです。
def __main__():
GPIO.setmode(GPIO.BCM)
SW.PinsInit(21, 22, 23, 24, 25, 26, 27)
SW.Start()
try:
while True:
key = SW.GetKey()
if key != "":
print(key)
time.sleep(0.1)
except KeyboardInterrupt:
SW.Stop()
GPIO.cleanup()
__main__()
ここまで出来れば、他モジュールと組み合わせることも出来そうです。