M5Stackで電子工作ができるようになりたくて、練習中。
一定間隔でセンサ値をデータベース(Spreadsheet)に送るような仕組みを作ることを目的に、タイマー周りの機能を調べている。
サンプルスケッチ「TFT_Clock_Digital」について読解しながら、どういうスケッチの構造になっているのかを学んでいる。
(このスケッチは、Arduino IDEのメニューから、「ファイル」>「スケッチ例」>「M5Stack」>「Advanced」>「Display」>「TFT_Clock_Digital」から開くことができる。)
前回は、グローバルで定義されている変数を一部見てみた。
今回は、loop()
関数の中身を見ていって、スケッチの構造を理解したいと思う。
loop()関数の構造
loop関数は、このような構造になっている。
- 前回表示から1秒経っているかどうかをtargetTimeで判断
- 前回表示から1秒経っていれば、表示するための時hh・分mm・秒ssを再計算する
- 計算された時hh・分mm・秒ssでM5Stack画面の表示をアップデートする
それぞれのパートに分けてみていく。
(1)1秒の経過を判断
まず、1つ目のパート。
void loop() { // (1) 前回表示から1秒経っているかどうかをtargetTimeで判断 if (targetTime < millis()) { targetTime = millis() + 1000; // 省略 } }
loop()
関数が起動した時点で、targetTime
変数には「前回画面表示をアップデートした時点での時刻 + 1秒」の値が入っている。
(コンパイル時からの起動時間をmills()
関数でミリ秒として取得して、それに1000ミリ秒(=1秒)を加算した値が入っている。)
そのtargetTime
変数と現時点のmills()
を比べて、前回から1秒が経過しているかどうかをif文で判断している。
1秒経っていれば、再びtrgetTime
に1000ミリ秒(=1秒)を加算して、次の処理に移る。
(2) 表示のための時・分・秒を再計算
次に、if文の中身で実行される2つ目のパート。
void loop() { if (targetTime < millis()) { // 省略 // (2) 前回表示から1秒経っていれば、表示するための時hh・分mm・秒ssを再計算する ss++; // Advance second if (ss == 60) { // Check for roll-over ss = 0; // Reset seconds to zero omm = mm; // Save last minute time for display update mm++; // Advance minute if (mm > 59) { // Check for roll-over mm = 0; hh++; // Advance hour if (hh > 23) { // Check for 24hr roll-over (could roll-over on 13) hh = 0; // 0 for 24 hour clock, set to 1 for 12 hour clock } } } // 省略 }
ここでは、表示するための時hh・分mm・秒ssを再計算している。
まず秒の表示ss
に1秒足して、60になったら値を0にして繰り上げる。
同じように分の表示mm
も60で値を0にして繰り上げ、時の表示hh
も24になると0に戻るというロジック。
ちなみに12時間表示にする場合は、このhh > 23
の条件式をhh > 11
として、次の行をhh = 1
と書き換えてやればよさそうだ。
(3) 画面をアップデートする
最後にディスプレイに表示するパート。
void loop() { // 省略 // (3)計算された時hh・分mm・秒ssでM5Stack画面の表示をアップデートする int xpos = 0; int ypos = 85; // Top left corner ot clock text, about half way down int ysecs = ypos + 24; if (omm != mm) { // Redraw hours and minutes time every minute omm = mm; // Draw hours and minutes if (hh < 10) xpos += M5.Lcd.drawChar('0', xpos, ypos, 8); // Add hours leading zero for 24 hr clock xpos += M5.Lcd.drawNumber(hh, xpos, ypos, 8); // Draw hours xcolon = xpos; // Save colon coord for later to flash on/off later xpos += M5.Lcd.drawChar(':', xpos, ypos - 8, 8); if (mm < 10) xpos += M5.Lcd.drawChar('0', xpos, ypos, 8); // Add minutes leading zero xpos += M5.Lcd.drawNumber(mm, xpos, ypos, 8); // Draw minutes xsecs = xpos; // Sae seconds 'x' position for later display updates } if (oss != ss) { // Redraw seconds time every second oss = ss; xpos = xsecs; if (ss % 2) { // Flash the colons on/off M5.Lcd.setTextColor(0x39C4, TFT_BLACK); // Set colour to grey to dim colon M5.Lcd.drawChar(':', xcolon, ypos - 8, 8); // Hour:minute colon xpos += M5.Lcd.drawChar(':', xsecs, ysecs, 6); // Seconds colon M5.Lcd.setTextColor(TFT_YELLOW, TFT_BLACK); // Set colour back to yellow } else { M5.Lcd.drawChar(':', xcolon, ypos - 8, 8); // Hour:minute colon xpos += M5.Lcd.drawChar(':', xsecs, ysecs, 6); // Seconds colon } //Draw seconds if (ss < 10) xpos += M5.Lcd.drawChar('0', xpos, ysecs, 6); // Add leading zero M5.Lcd.drawNumber(ss, xpos, ysecs, 6); // Draw seconds } } }
ちょっと長いのでポイントだけ。
- 時
hh
・分mm
・秒ss
の数値が1桁の時は、頭を0埋めして表示 - 変数
omm
は前回のアップデート時の分の数値が入っていて、もし今回のmm
と異なっていたら、分の表示をアップデートする処理を記述している。 - 変数
oss
も同様で、前回のアップデート時の秒の数値が入っている。 - 秒
ss
と連動してコロンの色が点滅。奇数の時にグレー、偶数の時に黄色で表示。
今回のまとめ
今回は、loop()
関数の構造を見てきた。
細かいところは端折ったけど、こ子まででサンプルスケッチ「TFT_Clock_Digital」で何が行われているのかは一通り読解できたかなと思う。