ラズベリーパイのGPIO応答速度を測定(Python & GUI編)
ラズペリーパイのGPIO応答速度測定をGUIプログラムでやってみたいと思います。
最初はC言語でやってみようとしたのですがあまりうまくいかないので、おとなしくPythonでやることにしました。
PythonでGUIアプリを作るにはtkinterを使えばいいようです。そしてそのtkinterはPython3では標準でインストールされているようです。
いくつかのブログなどを参考に以下のようなコードでGUIアプリを作りました。
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
root = Tk() root.title('GUI GPIO') root.geometry('250x50') frame1 = ttk.Frame(root, padding=10) label1 = ttk.Label(frame1, text='LED On/Off ') on_off = True button1 = ttk.Button( frame1, text='Off', command = button_clicked) frame1.pack() label1.pack(side=LEFT) button1.pack(side=LEFT) root.mainloop() |
これをラズベリーパイのXWindow上で実行するとGUIアプリが起動します。
ボタンをクリックするとボタンが”On”表示になり、もう1回クリックすると”Off”表示に戻ります。
ここにラズベリーパイのGPIO応答速度を測定(Python編)で使用したRPi.GPIOパッケージを使ってボタンをクリックするとGPIO出力に反映される様にします。今回はそのGPIO出力をGPIO27に割り当てました。
ラズベリーパイのGPIO応答速度を測定(Python編)ではGPIO18(swIn)にはNucleo側からスイッチ信号が入力されていましたが今回はGUIアプリボタンに連動したGPIO27(buttonOut)出力から入力されます。その信号をそのままGPIO17(ledOut)に出力するところはラズベリーパイのGPIO応答速度を測定(Python編)と同じです。
つまるところ配線は以下のようになります。
Nucleo F411 | Raspberry Pi | |
GUIアプリのボタンクリック | ||
↓ | ||
PA0(RPiIn / インプットキャプチャー Timer2 Channel1) | ← | GPIO27(buttonOut) |
↓ | ||
GPIO18(swIn) | ||
↓(ラズベリーパイ Pythonプログラムで折り返し) | ||
PA1(RpiIn / インプットキャプチャー Timer2 Channel2) | ← | GPIO17(ledOut) |
(絵のLEDはOn/Off動作確認用です)
ラズベリーパイのGPIO応答速度を測定(Python編)ではGPIO18(swIn)信号をポーリングでモニターしていてGPIO17(ledOut)に出力していましたが、tkinterを使ったGUIアプリでは上記のPythonコードのmainloop()でどこかのループに飛びイベント待ちになっているのでGPIOもエッジイベントを登録してコールバック関数でGPIO17(ledOut)をHigh/Lowするようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
def swIn_edge_event_callback(swIn): global led_out if led_out == False: led_out = True GPIO.output(ledOut, True) else: led_out = False GPIO.output(ledOut, False) GPIO.add_event_detect(swIn, GPIO.BOTH) GPIO.add_event_callback(swIn, swIn_edge_event_callback) def button_clicked(): global button_on if button_on == False: button1.config( text='On' ) button_on = True GPIO.output(buttonOut, True) else: button1.config( text='Off' ) button_on = False GPIO.output(buttonOut, False) |
すなわちGUIアプリのボタンクリックでGPIO27(buttonOut)出力もHigh/Lowさせて、GPIO18(swIn)入力のエッジイベントのコールバック関数(swIn_edge_event_callback)でGPIO17(ledOut)出力をHigh/Lowさせています。
Nucleo側のファームウェアはラズベリーパイのGPIO応答速度を測定(Python編)と同じものでいいのですがバラツキが大きいので標準偏差も計算するようにしました。
結果は以下のとおりです。
レスポンス時間は約412usとCLI版と比べて50倍くらい遅くなっています。
標準偏差は約75usなので結構大きいですね。3σが75usx3=225usなので412us±225usの範囲に95%の値が入ることになります(バラツキが正規分布なら)。
Nucleoのファームウェアはここにあります。
またラズベリーパイ側Pythonプログラム全体は以下のとおりです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
from tkinter import * from tkinter import ttk import RPi.GPIO as GPIO ledOut = 17 swIn = 18 buttonOut = 27 GPIO.setmode(GPIO.BCM) GPIO.setup(ledOut, GPIO.OUT) GPIO.setup(swIn, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(buttonOut, GPIO.OUT) GPIO.output(buttonOut, False) GPIO.output(ledOut, False) button_on = False led_out = False def swIn_edge_event_callback(swIn): global led_out |
終わり