注釈
こんにちは、SunFounderのRaspberry Pi & Arduino & ESP32愛好家コミュニティへようこそ!Facebook上でRaspberry Pi、Arduino、ESP32についてもっと深く掘り下げ、他の愛好家と交流しましょう。
参加する理由は?
エキスパートサポート:コミュニティやチームの助けを借りて、販売後の問題や技術的な課題を解決します。
学び&共有:ヒントやチュートリアルを交換してスキルを向上させましょう。
独占的なプレビュー:新製品の発表や先行プレビューに早期アクセスしましょう。
特別割引:最新製品の独占割引をお楽しみください。
祭りのプロモーションとギフト:ギフトや祝日のプロモーションに参加しましょう。
👉 私たちと一緒に探索し、創造する準備はできていますか?[ここ]をクリックして今すぐ参加しましょう!
4.1.17 ゲーム – 数字当て¶
はじめに¶
数字当ては、楽しいパーティゲームです。あなたと友人は、数字(0〜99)をRaspberry Piに入力し、それがモールスコードとして表示されるようにします。数字を入力するたびに範囲が狭くなり、誰かが正しく答えるとそのプレイヤーが負けて罰されます。例えば、プレイヤーが見ることができない運の数字が51の場合、プレイヤー①が50を入力すると、数字の範囲のヒントが50〜99に変わります。プレイヤー②が70を入力すると、数字の範囲は50〜70となります。プレイヤー③が51を入力すると、このプレイヤーが不運なものとなります。このプロジェクトでは、数字を入力するためのキーパッドと結果を出力するためのLCDを使用します。
必要な部品¶
このプロジェクトでは、以下のコンポーネントが必要です。
キット全体を購入することは非常に便利です。リンクは以下のとおりです:
名前 |
このキットのアイテム |
リンク |
---|---|---|
Raphael Kit |
337 |
以下のリンクから別々に購入することもできます。
コンポーネントの紹介 |
購入リンク |
---|---|
- |
|
回路図¶
T-Board Name |
physical |
wiringPi |
BCM |
GPIO18 |
Pin 12 |
1 |
18 |
GPIO23 |
Pin 16 |
4 |
23 |
GPIO24 |
Pin 18 |
5 |
24 |
GPIO25 |
Pin 22 |
6 |
25 |
SPIMOSI |
Pin 19 |
12 |
10 |
GPIO22 |
Pin 15 |
3 |
22 |
GPIO27 |
Pin 13 |
2 |
27 |
GPIO17 |
Pin 11 |
0 |
17 |
SDA1 |
Pin 3 |
SDA1(8) |
SDA1(2) |
SCL1 |
Pin 5 |
SCL1(9) |
SDA1(3) |
実験の手順¶
ステップ1: 回路を組み立てます。
ステップ2: I2Cを設定します( I2C設定 を参照してください。)
ステップ3: ディレクトリを変更します。
cd ~/raphael-kit/python/
ステップ4: 実行します。
sudo python3 4.1.17_GAME_GuessNumber.py
プログラムが実行された後、LCDに初期ページが表示されます:
Welcome!
Press A to go!
‘A’を押すと、ゲームが開始され、ゲームページがLCDに表示されます。
Enter number:
0 ‹point‹ 99
ゲームが始まると、ランダムな数値「 point 」が生成されますが、LCDには表示されません。あなたのタスクはそれを推測することです。入力した数字は、最終計算が完了するまでの第一行の末尾に表示されます。(「D」を押して比較を開始し、入力数が 10 より大きい場合、自動的な比較が開始されます。)
「point」の数字範囲は2行目に表示されます。そして、あなたはその範囲内の数字を入力する必要があります。数字を入力すると、範囲が狭まります。もしあなたが運よく、または不運にもラッキーナンバーを手に入れた場合、"当たり!"と表示されます。
注釈
FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1'
というエラーが出た場合は、 I2C設定 を参照してI2Cを有効にする必要があります。ModuleNotFoundError: No module named 'smbus2'
エラーが発生した場合は、sudo pip3 install smbus2
を実行してください。エラー
OSError: [Errno 121] Remote I/O error
が表示された場合、モジュールが間違って配線されているか、モジュールが壊れている可能性があります。コードと配線が正しく、LCDがまだ内容を表示しない場合、背面の可変抵抗を回してコントラストを上げることができます。
コード
注釈
下のコードを 変更/リセット/コピー/実行/停止 することができます。しかし、それを行う前に、ソースコードのパス(例: raphael-kit/python
)に移動する必要があります。コードを変更した後、それを直接実行して効果を確認することができます。
#!/usr/bin/env python3
import RPi.GPIO as GPIO
import time
import LCD1602
import random
##################### HERE IS THE KEYPAD LIBRARY TRANSPLANTED FROM Arduino ############
#class Key:Define some of the properties of Key
class Keypad():
def __init__(self, rowsPins, colsPins, keys):
self.rowsPins = rowsPins
self.colsPins = colsPins
self.keys = keys
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(self.rowsPins, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(self.colsPins, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
def read(self):
pressed_keys = []
for i, row in enumerate(self.rowsPins):
GPIO.output(row, GPIO.HIGH)
for j, col in enumerate(self.colsPins):
index = i * len(self.colsPins) + j
if (GPIO.input(col) == 1):
pressed_keys.append(self.keys[index])
GPIO.output(row, GPIO.LOW)
return pressed_keys
################ EXAMPLE CODE START HERE ################
count = 0
pointValue = 0
upper=99
lower=0
def setup():
global keypad, last_key_pressed,keys
rowsPins = [18,23,24,25]
colsPins = [10,22,27,17]
keys = ["1","2","3","A",
"4","5","6","B",
"7","8","9","C",
"*","0","#","D"]
keypad = Keypad(rowsPins, colsPins, keys)
last_key_pressed = []
LCD1602.init(0x27, 1) # init(slave address, background light)
LCD1602.clear()
LCD1602.write(0, 0, 'Welcome!')
LCD1602.write(0, 1, 'Press A to Start!')
def init_new_value():
global pointValue,upper,count,lower
pointValue = random.randint(0,99)
upper = 99
lower = 0
count = 0
print('point is %d' %(pointValue))
def detect_point():
global count,upper,lower
if count > pointValue:
if count < upper:
upper = count
elif count < pointValue:
if count > lower:
lower = count
elif count == pointValue:
count = 0
return 1
count = 0
return 0
def lcd_show_input(result):
LCD1602.clear()
if result == 1:
LCD1602.write(0,1,'You have got it!')
time.sleep(5)
init_new_value()
lcd_show_input(0)
return
LCD1602.write(0,0,'Enter number:')
LCD1602.write(13,0,str(count))
LCD1602.write(0,1,str(lower))
LCD1602.write(3,1,' < Point < ')
LCD1602.write(13,1,str(upper))
def loop():
global keypad, last_key_pressed,count
while(True):
result = 0
pressed_keys = keypad.read()
if len(pressed_keys) != 0 and last_key_pressed != pressed_keys:
if pressed_keys == ["A"]:
init_new_value()
lcd_show_input(0)
elif pressed_keys == ["D"]:
result = detect_point()
lcd_show_input(result)
elif pressed_keys[0] in keys:
if pressed_keys[0] in list(["A","B","C","D","#","*"]):
continue
count = count * 10
count += int(pressed_keys[0])
if count >= 10:
result = detect_point()
lcd_show_input(result)
print(pressed_keys)
last_key_pressed = pressed_keys
time.sleep(0.1)
# Define a destroy function for clean up everything after the script finished
def destroy():
# Release resource
GPIO.cleanup()
LCD1602.clear()
if __name__ == '__main__': # Program start from here
try:
setup()
while True:
loop()
except KeyboardInterrupt: # When 'Ctrl+C' is pressed, the program destroy() will be executed.
destroy()
コードの説明
コードの冒頭部分には、 keypad と I2C LCD1602 の機能関数があります。詳細については、 1.1.7 I2C LCD1602 および 2.1.8 キーパッド で学ぶことができます。
以下に、私たちが知る必要がある内容を示します:
def init_new_value():
global pointValue,upper,count,lower
pointValue = random.randint(0,99)
upper = 99
lower = 0
count = 0
print('point is %d' %(pointValue))
この関数はランダムな数値「 point 」を生成し、pointの範囲のヒントをリセットします。
def detect_point():
global count,upper,lower
if count > pointValue:
if count < upper:
upper = count
elif count < pointValue:
if count > lower:
lower = count
elif count == pointValue:
count = 0
return 1
count = 0
return 0
detect_point()
は、入力された数値 (count) と生成された “point” を比較します。比較の結果、2つの値が異なる場合、 count は upper と lower に値を割り当て、‘0’を返します。逆に、2つの値が同じである場合、‘1’を返します。
def lcd_show_input(result):
LCD1602.clear()
if result == 1:
LCD1602.write(0,1,'You have got it!')
time.sleep(5)
init_new_value()
lcd_show_input(0)
return
LCD1602.write(0,0,'Enter number:')
LCD1602.write(13,0,str(count))
LCD1602.write(0,1,str(lower))
LCD1602.write(3,1,' < Point < ')
LCD1602.write(13,1,str(upper))
この関数はゲームページの表示のためのものです。
str(count)
: write()
はデータタイプとして string のみをサポートしているため、 number を string に変換するために str()
が必要です。
def loop():
global keypad, last_key_pressed,count
while(True):
result = 0
pressed_keys = keypad.read()
if len(pressed_keys) != 0 and last_key_pressed != pressed_keys:
if pressed_keys == ["A"]:
init_new_value()
lcd_show_input(0)
elif pressed_keys == ["D"]:
result = detect_point()
lcd_show_input(result)
elif pressed_keys[0] in keys:
if pressed_keys[0] in list(["A","B","C","D","#","*"]):
continue
count = count * 10
count += int(pressed_keys[0])
if count >= 10:
result = detect_point()
lcd_show_input(result)
print(pressed_keys)
last_key_pressed = pressed_keys
time.sleep(0.1)
main()
はプログラムの全体のプロセスを含んでおり、以下のように表示されます:
I2C LCD1602 と Keypad を初期化します。
ボタンが押されたかどうかを判定し、ボタンの読み取りを取得します。
ボタン‘A’が押された場合、ランダムな数字 0-99 が表示され、ゲームが開始されます。
ボタン‘D’が押されたと検出された場合、プログラムは結果の判定に入ります。
ボタン 0-9 が押された場合、 count の値が変更されます。 count が 10 より大きい場合、判定が開始されます。
ゲームの変更とその値は LCD1602 に表示されます。