【Raspberry Pi】Tcl/TkとC言語で距離センサーの値を表示するGUIをつくろう 第4回
北本です。
まずはじめに、「【Raspberry Pi】C言語とTcl/Tkを連携」というタイトルで連載してきました一連の投稿ですが、最終回である今回にして「【Raspberry Pi】Tcl/TkとC言語で距離センサーの値を表示するGUIをつくろう」というタイトルに変更させていただきます。C言語にまともに触れているのはほぼ第2回のみで、後半はTcl/Tk側の話題オンリーとなってしまっているのに「C言語とTcl/Tkの連携」と謳うのはタイトル詐欺だなあ……と思った次第です。
では、本題に入ります。
C言語とTcl/Tkを連携させ、周期的にセンサーの測距値の取得および表示をすることを目指していたわけですが、前回はTclにおけるプロシージャや変数について説明しました。今回は周期処理に関する部分などについて述べていくこととします。
以下は、前回のTcl側のコードの再掲です。
gui.tcl
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 | label .valueLabel -text "-" -font {Monospace 24} button .startStopButton -text "START" -font {Monospace 24} -command startStop pack .valueLabel .startStopButton set running "false" proc mainLoop {} { global running if {$running == "true"} { get } after 200 mainLoop } proc startStop {} { global running if {$running == "true"} { set running "false" .startStopButton configure -text "START" } else { set running "true" .startStopButton configure -text "STOP" } } mainLoop |
周期処理を実行するには、afterコマンドが要となります。というより、このafterコマンドさえあればすぐにできます。
12行目に「after 200 mainLoop」とありますが、これは200ミリ秒後にmainLoopコマンド(プロシージャ)を実行してくださいというコマンドです。ちなみに、コマンドを指定せず「after 200」と書けば、ただ単に200ミリ秒間処理を待機します。ここでは、mainLoopプロシージャの中で、afterコマンドを用いてmainLoop自身を再帰的に呼び出すことによって、200ミリ秒間隔で処理を繰り返すことを実現しています。
あと、個人的に躓いた点をひとつ。起動時に最初のmainLoopプロシージャの呼び出しを26行目で行っていますが、初めはmainLoopプロシージャの記述より前(6行目あたり)で行っていたところ上手く動作しませんでした。どうやら、TclではC言語同様、関数(プロシージャ)宣言よりも前に呼び出ししてはいけないようです。つまり、mainLoopの定義より前に、mainLoopを呼び出していたので上手くいかなかったわけです。ただし、2行目のstartStopの呼び出しに関しては、ボタンを押下したタイミングで初めて呼び出されるため、その時には既にstartStopの定義も読み込まれているので問題ありません。
それと、まだTclのif文については説明していませんでした。何らかのプログラミング言語を触ったことがあれば、内容は何となく読み取れると思いますが、書く場合はTcl独特の文法に気を付ける必要があったりします。
例えば、9行目の
1 2 3 | if {$running == "true"} { get } |
を
1 2 3 4 | if {$running == "true"} { get } |
と記述すると上手くいきません。
詳細を説明しようとすると長くなるので割愛しますが、端的に言うと、Tckのifは第1引数に条件を第2引数に条件を満たした時の実行内容を渡すコマンドとなっており、下のコードのように改行が入ると第2引数が存在しないとみなされてしまうためです。これは、プロシージャの定義などの際も同様です。
参考サイト:M.Hiroi’s Home Page Tcl/Tk お気楽 GUI プログラミング入門 リストと制御構造
では、実際に動かしてみた時の動画です。
フォントを大きくしたので、前回の動画よりも大分わかりやすくなったはずです。
前回に挙げた
・STARTボタンを押下すると200ミリ秒周期で測距値を取得してラベルに表示する。
・STARTボタンは1度押下されるとSTOPボタンに変わり、それを押下する周期的な測距値の取得を停止する。
・STOPボタンは1度押下されると、STARTボタンに戻る。
という仕様を満たしているかと思います(処理間隔が200ミリ秒であるかどうかまでは判別困難ですが)。
これにて、全4回にわたる連載は終わりです。今回は、ただ単にセンサーの値を文字列として画面に表示するだけでしたが、今後はセンサーを使ってもっと面白いことができたらいいですね。例えば、測距値に合わせて音が鳴ったりとか。