埼玉工業大学 工学部 情報システム学科
卒 業 研 究 論 文
題 目
M5Stack によるタイマーの製作
研究室名 : 鯨井研究室
指導教員名 : 鯨井 政祐
卒業研究報告者
学籍番号 1803009 氏名 阿部 栞佑
指導教員認印
学 科 検 印
目次
第
1
章 緒論1
1.1
製作の背景と目的. . . . 2
1.2
製作の概要. . . . 2
1.3
本論文の構成. . . . 3
第
2
章 要素技術4 2.1
緒論. . . . 5
2.2
タイマー. . . . 5
2.3 Arduino . . . . 6
2.4 M5Stack . . . . 8
第
3
章M5Stack
を用いたタイマー10 3.1
緒論. . . . 11
3.2
製作するタイマーの仕様. . . . 11
3.3
実装. . . . 12
3.3.1 Arduino IDE
の導入. . . . 12
3.3.2 M5Display
クラスによる経過時間の表示. . . . 19
3.3.3 Button
クラスによる状態遷移. . . . 25
3.3.4
ベル音の再生. . . . 29
3.3.5
マルチタスク機能の実装. . . . 34
3.4
動作確認. . . . 36
3.5
考察. . . . 43
3.6
ソースコード. . . . 44
第
4
章 結論47 4.1
まとめ. . . . 48
4.2
今後の課題. . . . 48
謝 辞
49
参 考 文 献
50
第 1 章
緒論
本研究室では過去に,シングルボードコンピュータ制御により実際に卓上ベルを 叩くことで,正確性と大音量を兼ね備えた,卒業研究発表会で使用することを想定 した自動プレゼンテーションタイマーが開発された
[1]
。しかし,これらの提案で は,タイマー装置とPC
の両方を持ち歩かなくてはならない欠点があった。そこで 本製作では,M5Stack
のみを使い,同等の機能を実現することを目的とする。1.2 製作の概要
本製作では,
M5Stack
のみを使い卒業研究発表会で使用することを想定したプ レゼンテーションタイマーを製作した。開発環境として,
M5Stack
と互換性があり,開発が容易であるという点から,Arduino IDE 1.8.13
でArduino
言語を用いて実装した。M5Stack
では,M5Stack
ライブラリを使用することにより,同機固有の機能が使用できるようになる。ここでは同ライブラリに用意された関数を用いて,「
mm:ss
」 形式で経過時間表示を実装した。卒業研究発表会では発表時間は限られているた め,時は表示せず分と秒のみ表示すれば良いので,その分フォントを大きくして見 やすい表示とした。M5Stack
にはボタンが3
つあるため,これらを計時のスタート,ストップ,リセット機能にそれぞれ割り当てることにした。ただし,既存のタイマーアプリ等で は計時中でもストップ状態を経ずに直接リセット状態に入れるようになっているこ とが多い。これを考慮して,本製作では上記各ボタンの押下で状態遷移を行うよう に実装した。
ベル音を鳴らす通知機能としては,ベル音の
mp3
ファイルをmicroSD
カードか ら再生する方式とした。計時時間が5
分,7
分,10
分経過するごとに1
回,2
回,3
回とベル音が再生される。ただし同ライブラリの再生機能は再生中にブロックす る仕様なので,その間液晶の表示更新が停止してしまうという問題がある。このため,
ESP32
のマルチタスク機能を使い,音の再生をメインの処理から分離することでこれを解決した。
これら各機能の実装の後,動作確認を行った。結果として,液晶画面には「
mm:ss
」 形式で経過時間が表示されることを確認し,各ボタンの機能,ベル音についても仕 様通りに動作したことを確認した。1.3 本論文の構成
本論文は
M5Stack
のみを用いて,卒業研究発表会で使用することを想定したプレゼンテーションタイマーの製作についてまとめたものである。本文構成は以下の 通りである。
•
第1
章 緒論本製作の背景や目的を述べ,本論文の意義について述べる。
•
第2
章 要素技術本製作で使用した技術の概要について述べる。
•
第3
章M5Stack
を用いたタイマー本製作で提案するシステムの仕様,実装手法,操作方法,動作確認,考察な どについて述べる。
•
第4
章 結論本製作のまとめと今後の課題について述べる。
第 2 章
要素技術
2.1 緒論
本章では,製作に用いたタイマー,
Arduino
,M5Stack
について説明する。2.2 タイマー
タイマーとは,図
2.1
のように経過時間を知らせる仕組みや装置である。本製作 において製作するタイマーは,計測開始時からの経過時間を数えあげていくカウン トアップ式のタイマーである。指定した時間を経過するごとに音声ファイルが再生 される。*1図
2.1:
タイマーの例*1画像は
Web
サイト[11]
より引用した。2.3 Arduino
Arduino
とは,シングルボードコンピュータであり,図2.2
のArduino Uno
は その一種である。図2.3
の統合開発環境であるArduino IDE
により,C
言語を ベースに開発されたArduino
言語を用いて開発が可能である。また,Arduino
言 語を用いたプログラムによって容易にセンサやアクチュエータのプログラムを制御 が可能である。本製作では,Arduino
と互換性を持つM5Stack
と開発環境としてArduino IDE
を用いて開発を行っている。図
2.2: Arduino Uno
図
2.3: Arduino IDE
2.4 M5Stack
図
2.4
のM5Stack
は,シングルボードコンピュータの一種である。液晶画面,ボタン,スピーカ,
microSD
スロットなどを備えているため,追加部品無しである 程度の装置を作れるという特長がある。開発言語はArduino
と互換性があり,開 発もしやすい。CPU
に図2.5
のESP32
を採用しているため,同チップ用のライブ ラリも使用できる。図2.6
のようにType-C USB
でPC
と接続することで開発し たプログラムを書き込むことが可能である。図
2.4: M5Stack
図
2.5: ESP32
図
2.6: Type-C USB
の接続第 3 章
M5Stack を用いたタイマー
3.1 緒論
本章では,本製作のタイマーの仕様,製作,動作確認について説明する。
3.2 製作するタイマーの仕様
本製作のタイマーは,卒業研究発表会で使用する事を目的としている。その ため,
•
液晶画面に「mm:ss
」形式で経過時間が表示される。• 3
つのボタンにスタート,ストップ,リセット機能を実装する。• 5
分,7
分,10
分経過するごとにそれぞれ1
回,2
回,3
回とベル音が鳴る。以上の機能を持つタイマーを
M5Stack
のみを使い実現する。3.3 実装
3.3.1 Arduino IDE の導入
M5Stack
で開発を行うために,Arduino
統合開発環境(IDE)
のインストール及び設定構築を行った。本製作では,
Arduino IDE 1.8.13
を使用した。以下にイン ストール手順を示す。•
図3.1
のArduino
公式サイトのダウンロードページからArduino IDE 1.8.13
のインストーラ(Windows Win 7 and newer)
を選択する。→arduino- 1.8.13-windows.exe
をダウンロードした。•
インストーラを実行→図3.2
のようにライセンス契約の画面が表示されるため,「
I Agree
」を選択して同意した。→図3.3
のようにオプションを選択する画面が表示されるので,チェックボックスは初期値のままで「
Next >
」を 選択した。→図3.4
のようにインストールするフォルダを選択する画面が表 示されるので,インストール先を選択して「Install
」で開始した。→インス トール完了後,Arduino IDE
を起動した。図
3.1: Arduino IDE
ダウンロードページ図
3.2:
ライセンス契約図
3.3:
オプション選択図
3.4:
インストール先の選択次に,
M5Stack
とPC
を繋ぐためにはUSB
シリアルドライバの導入が必要であ る。従って以下に導入の過程を示す。•
図3.5
のM5Stack
公式サイトのArduino IDE Development
からWindows
用のUSB
ドライバ(CP210x_VCP_Windows.zip)
をダウンロードした。•
ファイル展開後,図3.6
の64bit
用のインストーラ(CP210xVCPInstaller_x64_v6.7.0.0.exe)
を選択→USB
シリアルドライバをインストールした。•
インストール完了後,M5Stack
とPC
を繋ぎ,図3.7
のようにWindows
の 設定から「デバイス」選択し,インストールされたドライバが表示されてい るか確認した。図
3.5:
ドライバのダウンロードページ図
3.6: 64bit
用のインストーラ図
3.7:
インストールされたドライバArduino IDE
はボードマネージャを選択することで,使用するボードにコード を書き込む事が可能になる。ダウンロード直後のArduino IDE
にはM5Stack
に付属する
ESP32
の情報が登録されていないため,Arduino IDE
にボードマネージャを追加して
ESP32
を認識可能にした。以下に手順を示す。• Arduino IDE
を起動し、図3.8
の「ファイル」→「環境設定」→「行番号を表示する」にチェックを入れる→「追加のボードマネージャの
URL
」→図3.9
のように「http://dl.espressif.com/dl/package_esp32_index.json
」を入力 した。• Arduino IDE
の「ツール」→「ボード:Arduino/Genuino UNO
」→「ボー ドマネージャ」を選択した。→検索窓に「esp32
」を入力する。→図3.10
の「
esp32 by Espressif System
」を選択し最新バージョン(
バージョン1.0.6)
をインストールした。•
インストール後,「ツール」→図3.11
のようにパラメータを指定した。図
3.8:
環境設定図
3.9:
追加のボードマネージャのURL
図
3.10: esp32 by Espressif System
のインストール図
3.11:
パラメータの指定3.3.2 M5Display クラスによる経過時間の表示
M5Stack
では,M5Stack
ライブラリを使用することにより,M5Stack
固有の機 能が使用できるようになる。以下に導入の手順を示す。•
図3.12
のようにArduino IDE
の「ツール」→「ライブラリを管理」を選択しライブラリマネージャを起動した。
•
検索窓に「m5stack
」を入力する。→図3.13
の「M5Stack by M5Stack
」を 選択し最新バージョン(
バージョン0.31)
をインストールした。図
3.12:
ライブラリマネージャ図
3.13: M5Stack
ライブラリのインストール過時間を「
mm:ss
」形式で表示するプログラムを実装した。以下に,経過時間を表 示するプログラムの内容を示す。また,このタイマーは卒業研究発表会で使用する ことを想定しており,発表時間は限られているため,「時」は表示せず「分」と「秒」のみを表示すれば良いので,その分フォントを大きくして見やすい表示とした。
リスト
3.1
のように,まず,液晶画面の背景色を定める関数M5.Lcd.fillScreen()
を用いて背景色を黒に設定した。また,テキストの文字サイズを定める関数M5.Lcd.setTextSize()
やテキストの色を定める関数M5.Lcd.setTextColor()
を用い てテキストの初期値を設定した。しかし,上記の操作のみでは経過時間を描画することはできないため,「分」,
「:」,「秒」を表示するプログラムが必要になる。リスト
3.2
に「分」,「秒」,「:」を表示する操作をそれぞれ示す。
本製作では,「
mm:ss
」形式表示のタイマーを実装する。そのため,仮に「1
分2
秒」の場合には「01:02
」と表示する必要がある。まず,「分」,「秒」については関数
M5.Lcd.drawChar()
を用いて一の位の値が10
よ り小さい場合に「09
」のように十の位に「0
」を表示し,関数M5.Lcd.drawNumber()
を用いて,「分」,「秒」の値を表示するようにした。「:」についても表示は同様に 関数M5.Lcd.drawChar()
を用い,関数M5.Lcd.setTextColor()
によって2
秒に一度 テキストの色を変更することで,図3.14
,図3.15
のように「:」が点滅して見え るようにした。ここで表示されるテキストは液晶画面の中央から離れて位置しているため,
図
3.16
のようにテキストの表示座標を液晶画面の中央に位置するように設定を 行った。以上より,M5Display
クラスを使用することにより,「mm:ss
」形式表示を 実装した。リスト
3.1:
背景とテキストの設定1 void setup(void) {
2
3 M5.begin(); //M5Stackオ ブ ジ ェ ク ト を 初 期 化
4 M5.Lcd.fillScreen(TFT_BLACK); //背 景 色 設 定
5 M5.Lcd.setTextSize(1); //テ キ ス ト の サ イ ズ 設 定
6 M5.Lcd.setTextColor(TFT_YELLOW, TFT_BLACK); //テ キ ス ト の 色 設 定
リスト
3.2:
「分」,「秒」,「:」の表示1 if (omm != mm) { // 毎 分 再 描 画 す る
2 omm = mm;
3
4 if (mm < 10) xpos += M5.Lcd.drawChar(’0’, xpos, ypos, 8); //10分 よ り 前 の と き 「09」 と 前 に 「0」 を 表 示 す る
5 xpos += M5.Lcd.drawNumber(mm, xpos, ypos, 8); // 「 分 」 を 表 示 す る
6 xsecs = xpos; // 更 新 の た め 秒 のx座 標 を 指 定 す る
7 }
8
9 if (oss != ss) { //毎 秒 再 描 画 す る
10 oss = ss;
11 xpos = xsecs;
12
13 if (ss % 2) { // 2秒 に1回 「 : 」 を 点 滅
14 M5.Lcd.setTextColor(0x39C4, TFT_BLACK); // 「 : 」 の 色 設 定
15 xpos += M5.Lcd.drawChar(’:’, xsecs, ysecs, 8); // 分 と 秒 の 間 に 「 : 」 を 表 示 す る
16 M5.Lcd.setTextColor(TFT_YELLOW, TFT_BLACK); // 「 : 」 の 色 設 定
17 }
18 else {
19 xpos += M5.Lcd.drawChar(’:’, xsecs, ysecs, 8); // 分 と 秒 の 間 に 「 : 」 を 表 示 す る
20 }
21
22 if (ss < 10) xpos += M5.Lcd.drawChar(’0’, xpos, ysecs, 8); // 10秒 よ り 前 の と き 「09」
と 前 に 「0」 を 表 示 す る
23 M5.Lcd.drawNumber(ss, xpos, ysecs, 8); // 「 秒 」 を 表 示 す る
24 }
図
3.14:
「:
」の点滅(1)
図
3.15:
「:
」の点滅(2)
図
3.16:
変更後の経過時間の表示次に,タイマーの計時機能について以下に示す。計時機能はリスト
3.3
のよう に,初期値「00:00
」から1
秒ごとに経過時間の「秒」の値を増加させていき,図3.17
図3.18
のように60
秒経過するごとに「分」の値を代入して増加,「秒」の値を0
に する操作を繰り返すことで実装した。また,図3.19
のように,本製作のタイマーは「
mm:ss
」形式表示の最大値として「99:59
」まで計時可能である。リスト
3.3:
計時機能の実装1 if (targetTime < millis() && measuring) { //1秒 ご と に 更 新
2 targetTime = millis() + 1000;
3
4 if (ss == 59 && mm == 99) { // 99:59で カ ウ ン ト 停 止
5 measuring = false;
6 }
7 else {
8 ss = ss + 1; //「 秒 」 の 値 を1増 加 さ せ る
9
10 if (ss == 60) { // 60秒 を 超 え る と き 「 分 」 の 値 を1増 加 さ せ る
11 ss = 0;
12 omm = mm;
13 mm++;
14 }
15 }
16 }
図
3.17:
「分」の値の増加1
図
3.18:
「分」の値の増加2
図
3.19:
最大値「99:59
」3.3.3 Button クラスによる状態遷移
M5Stack
には,図3.20
のようにボタンが3
つ付属している。本製作は,卒業研究発表会で使用することを想定しているため,
1
人10
分の発表時間ごとにタイ マーをリセットする必要がある。従って,スタート,ストップ,リセットの機能を3
つのボタンにそれぞれ割り当てることにした。ただし,既存のタイマーアプリ等 では計時中でもストップ状態を経ずに直接リセット状態にはいれるようになってい ることが多い。これを考慮して,本製作では,上記各ボタンの押下で図3.21
の状 態遷移図のように状態遷移を行うように実装した。本項では,
M5Stack
ライブラリのボタンの状態管理用クラスであるButton
クラ スを使用することにより,3
つのボタンに操作を割り当てるプログラムを実装し た。以下に,ボタンの押下で状態遷移するプログラムの内容を示す。初めに,計時状態と停止状態をリスト
3.4
の変数measuring
を定めtrue
とfalse
で判別できるようにした。次に左ボタンにスタート機能,中央ボタンにストップ機能を割り当て実装した。
リスト
3.5
の関数M5.BtnA.wasReleased()
,M5.BtnB.wasReleased()
を使用するこ とで,図3.22
と図3.23
のようにそれぞれ指定したボタンが押されたときに計時状 態が切り替わるようにした。右ボタンについても関数
M5.BtnC.wasReleased()
を使用しリスト3.6
のボタンが 押されたとき,図3.24
のように初期状態である「00:00
」で停止状態に遷移する操 作を実装した。本項で使用した関数は厳密にはボタンが離されたかどうかを判別するものであ るが,仮に関数
M5.BtnA.wasPressed()
のように押されたかどうかを判別する場合,押し続けたときにも条件を満たしてしまい不具合が起こる場合がある。そのため,
本製作では,ボタンが離されたかどうかを判別する関数を使用した。
図
3.20: 3
つのボタン計時状態 停止状態
初期状態
右ボタンを押す
(リセット)
右ボタンを押す
(リセット)
左ボタンを押す
(計測開始)
左ボタンを押す
(計測開始)
中央ボタンを押す
(停止)
図
3.21:
各ボタン押下による状態遷移図リスト
3.4:
状態を判別する変数1 //時 間 計 測 切 り 替 え の 変 数(プ ロ グ ラ ム 開 始 時00:00で 停 止 状 態)
2 boolean measuring = false;
リスト
3.5:
左ボタン中央ボタンの割り当て1 M5.update(); //M5Stackの 更 新
2 if (M5.BtnA.wasReleased()) { //停 止 状 態 か ら カ ウ ン ト 中 状 態 に 遷 移
3 measuring = true;
4 delay(1);
5 }
6
7 if (M5.BtnB.wasReleased()) { //あ る 時 間 で 停 止 状 態 に 遷 移
8 measuring = false;
9 delay(1);
10 }
図
3.22:
左ボタン押下の反応リスト
3.6:
右ボタンの割り当て1 if (M5.BtnC.wasReleased()) { //00:00で 停 止 状 態 に 遷 移
2 ss = 0;
3 mm = 0;
4 measuring = false;
5 }
図
3.23:
中央ボタン押下の反応図
3.24:
右ボタン押下の反応3.3.4 ベル音の再生
経過時間が
5
分,7
分,10
分のときに,それぞれ1
回,2
回,3
回とベル音を鳴 らす通知機能を実装した。本製作では,図3.25
のダウンロードしたベル音のmp3
ファイル[2]
を図3.26
のmicroSD
カードを図3.27
のスロットに挿入,図3.28
の スピーカを通じて再生する方式とした。また,ベル音を鳴らすライブラリとして
ESP8266Audio
ライブラリを使用した。以下に導入の手順を示す。
図
3.29
に示すようにArduino IDE
を起動し、「スケッチ」→「ライブラリをイン クルード」→「ライブラリを管理」→ライブラリマネージャを起動した。その後,図
3.30
のように,
検索窓に「ESP8266Audio
」を入力→「ESP8266Audio
」を選択し 最新バージョン(
バージョン1.9.2)
でインストールした。リスト
3.7
より,ESP8266Audio
ライブラリの関数AudioFileSourceSD()
,Au- dioFileSourceID3()
,AudioOutputI2S,AudioGeneratorMP3()
を使用しmp3
ファイ ルをSD
カードから呼び出して再生するシステムを実装した。上記のシステムを経過時間ごとにベル音を鳴らすようにした。リスト
3.8
より,•
「ss
」の値が0
かつ「mm
」の値が5
のときplayMP3()
でベル音を1
回鳴らす。•
「ss
」の値が0
かつ「mm
」の値が7
のときplayMP3()
でベル音を2
回鳴らす。•
「ss
」の値が0
かつ「mm
」の値が10
のときplayMP3()
でベル音を3
回鳴 らす。上記の条件を満たす操作を実装した。
図
3.25:
ダウンロードしたmp3
ファイル図
3.26: microSD
カード図
3.27: microSD
スロット図
3.28:
スピーカ図
3.29:
ライブラリマネージャの起動図
3.30: ESP8266Audio
ライブラリの導入リスト
3.7: mp3
ファイルの再生1 void playMP3(char *filename) { //mp3フ ァ イ ル を 再 生 す る
2
3 file = new AudioFileSourceSD("/yobidashi-bell-2.mp3"); //mp3フ ァ イ ル をSDカ ー ド か ら 呼 び 出 す
4
5 id3 = new AudioFileSourceID3(file);
6 out = new AudioOutputI2S(0, 1); // builtInDACへ 出 力
7 out->SetOutputModeMono(true);
8 mp3 = new AudioGeneratorMP3();
9 mp3->begin(id3, out);
10
11 while (mp3->isRunning()) {
12 if (!mp3->loop()) mp3->stop();
13
14 }
15 }
リスト
3.8:
通知機能の実装1 if (ss == 0 && mm == 5) { //05:00の と き1回 鳴 ら す
2 playMP3("/yobidashi-bell-2.mp3");
3 }
4
5 if (ss == 0 && mm == 7) { //07:00の と き2回 鳴 ら す
6 playMP3("/yobidashi-bell-2.mp3");
7 playMP3("/yobidashi-bell-2.mp3");
8 }
9
10 if (ss == 0 && mm == 10) { //10:00の と き3回 鳴 ら す
11 playMP3("/yobidashi-bell-2.mp3");
12 playMP3("/yobidashi-bell-2.mp3");
13 playMP3("/yobidashi-bell-2.mp3");
14 }
3.3.5 マルチタスク機能の実装
ベル音を鳴らす処理において,
ESP8266Audio
ライブラリのmp3
ファイル再生 機能は再生中にブロックする仕様である。そのため,ベル音が鳴る間液晶画面の表 示更新が停止してしまうという問題がある。この状態を解決するため,
ESP32
のFreeRTOS
のマルチタスク機能を使用する ことにした。マルチタスク機能は,xTaskCreatePinnedToCore()
関数を使用するこ とで実装した。並列処理させる機能としてはリスト3.9
のように計時機能と通知機 能を選んだ。また,リスト
3.10
とリスト3.11
のように計時機能と通知機能を関数として分割して
while
文でループさせた。このとき,while
文の最後にdelay
を追加することでタスクを切り替えられるようにした。
リスト
3.9: xTaskCreatePinnedToCore()
関数1 /マ ル チ タ ス ク 機 能(タ イ マ ー 機 能)
2 xTaskCreatePinnedToCore(timer, "timer", 4096, NULL, 1, NULL, 0);
3 //マ ル チ タ ス ク 機 能(通 知 機 能)
4 xTaskCreatePinnedToCore(notification, "notification", 4096, NULL, 1, NULL, 1);
リスト
3.10:
変更後の計時機能の関数1 void timer(void *arg) { //タ イ マ ー の 時 間 計 測 機 能
2
3 while (1) { //マ ル チ タ ス ク の 処 理 は 無 限 ル ー プ さ せ る
4
5 M5.update(); //M5Stackの 更 新
6 if (M5.BtnA.wasReleased()) { //停 止 状 態 か ら カ ウ ン ト 中 状 態 に 遷 移
7 measuring = true;
8 delay(1);
9 }
10
11 if (M5.BtnB.wasReleased()) { //あ る 時 間 で 停 止 状 態 に 遷 移
12 measuring = false;
13 delay(1);
14 }
15
16 if (M5.BtnC.wasReleased()) { //00:00で 停 止 状 態 に 遷 移
17 ss = 0;
18 mm = 0;
19 measuring = false;
20 delay(1);
21 }
22
23 if (targetTime < millis() && measuring) { //1秒 ご と に 更 新
24 targetTime = millis() + 1000;
25
26 if (ss == 59 && mm == 99) { // 99:59で カ ウ ン ト 停 止
27 measuring = false;
28 }
29 else {
30 ss = ss + 1; //「 秒 」 の 値 を1増 加 さ せ る
31
32 if (ss == 60) { // 60秒 を 超 え る と き 「 分 」 の 値 を1増 加 さ せ る
33 ss = 0;
34 omm = mm;
35 mm++;
36 }
37 }
38 }
39 delay(1);
40 }
41 }
リスト
3.11:
変更後の通知機能の実装1 void notification(void *arg) { //通 知 機 能
2
3 while (1) {//マ ル チ タ ス ク の 処 理 は 無 限 ル ー プ さ せ る
4 if (ss == 0 && mm == 5) { //05:00の と き1回 鳴 ら す
5 playMP3("/yobidashi-bell-2.mp3");
6 }
7
8 if (ss == 0 && mm == 7) { //07:00の と き2回 鳴 ら す
9 playMP3("/yobidashi-bell-2.mp3");
10 playMP3("/yobidashi-bell-2.mp3");
11 }
12
13 if (ss == 0 && mm == 10) { //10:00の と き3回 鳴 ら す
14 playMP3("/yobidashi-bell-2.mp3");
15 playMP3("/yobidashi-bell-2.mp3");
16 playMP3("/yobidashi-bell-2.mp3");
17 }
18 delay(1);
19 }
20 }
3.4 動作確認
M5Stack
にプログラムの書き込みを行い,microSD
カードを挿入し次の手順で動作確認を行った。
•
図3.31
,図3.32
,図3.33 M5Stack
の電源を入れ,液晶画面の経過時間が「
mm:ss
」形式かつ「00:00
」で停止していることを確認する。•
図3.34
左ボタンを押してスタート,図3.35
中央ボタンを押してストップ,図
3.36
左ボタンを押してリセット機能がそれぞれ動作することを確認する。図
3.37
,図3.38
,図3.39
,図3.40
それぞれのボタンを同時に押したとき不 具合が生じないか確認する。•
図3.41
,図3.42
,図3.43
タイマーを経過時間が「05:00
」,「07:00
」,「10:00
」, の時にベル音がそれぞれ1
回,2
回,3
回と鳴ることを確認する。図
3.31: M5Stack
の電源ボタン図
3.32:
「mm:ss
」形式の確認図
3.33:
タイマーの初期状態図
3.34:
タイマーの開始図
3.35:
タイマーの停止図
3.36:
タイマーのリセット図
3.37:
左,中央ボタンの同時押し図
3.38:
中央,右ボタンの同時押し図
3.39:
左,右ボタンの同時押し図
3.40: 3
つのボタンの同時押し図
3.41:
経過時間「05:00
」図
3.42:
経過時間「07:00
」図
3.43:
経過時間「10:00
」3.5 考察
動作確認の結果,液晶画面への経過時間の表示については,初期状態,図
3.32
のいずれの場合も「mm:ss
」形式で表示されることを確認した。3
つのボタンへのスタート,ストップ,リセット機能の割り当ては仕様通り動作 し同時にボタンを押した場合においても,押されたいずれかのボタンの操作が動作 したため不具合を確認することはなかった。microSD
カード内のベル音mp3
ファイルによる通知機能については経過時間が「
05:00
」,「07:00
」,「10:00
」の時に1
回,2
回,3
回と鳴ることを確認した。以上のそれぞれが仕様通りに動作することを確認した。
また,マルチタスク機能についてもベル音が鳴るときに,液晶画面の表示に問題 がないことを確認しため動作していることを確認した。
3.6 ソースコード
リスト
3.12
に製作したプレゼンテーションタイマーのソースコードを示す。開 発環境にはArduino IDE
を使用し,言語はArduino
言語により製作を行った。リスト
3.12:
ソースコード(timer.ino)
1 /*
2 * M5Stackに よ る タ イ マ ー の 製 作 メ イ ン ソ ー ス
3 *
4 * copyright(c) 2021-2022 K. Abe and M. Kujirai
5 * [email protected], http://kujiraiken.sit.ac.jp/
6 */
7 8
9 #pragma mark - Depend ESP8266Audio and ESP8266_Spiram libraries
10
11 #include <M5Stack.h>
12 #include "AudioFileSourceSD.h"
13 #include "AudioFileSourceID3.h"
14 #include "AudioGeneratorMP3.h"
15 #include "AudioOutputI2S.h"
16
17 #define TFT_GREY 0x5AEB
18
19 AudioGeneratorMP3 *mp3;
20 AudioFileSourceSD *file;
21 AudioOutputI2S *out;
22 AudioFileSourceID3 *id3;
23
24 uint32_t targetTime = 0; // 1秒 間 タ イ ム ア ウ ト
25
26 static uint8_t conv2d(const char* p); //IDE 1.6.xに 必 要 な 前 方 宣 言
27
28 uint8_t mm = 0, ss = 0; // タ イ マ ー の 初 期 値00:00
29 boolean measuring = false; //時 間 計 測 切 り 替 え の 変 数(プ ロ グ ラ ム 開 始 時00:00で 停 止 状 態)
30 byte omm = 99, oss = 99; //byte型 の 変 数 の 宣 言 と 初 期 値 の 指 定
31 byte xcolon = 0, xsecs = 0; //byte型 の 変 数 の 宣 言 と 初 期 値 の 指 定
32 unsigned int colour = 0; //符 号 な し 整 数 の 宣 言 と 初 期 値 の 指 定 。
33 34
35 void timer(void *arg) { //タ イ マ ー の 時 間 計 測 機 能
36
37 while (1) { //マ ル チ タ ス ク の 処 理 は 無 限 ル ー プ さ せ る
38
39 M5.update(); //M5Stackの 更 新
40 if (M5.BtnA.wasReleased()) { //停 止 状 態 か ら カ ウ ン ト 中 状 態 に 遷 移
41 measuring = true;
42 delay(1);
43 }
44
45 if (M5.BtnB.wasReleased()) { //あ る 時 間 で 停 止 状 態 に 遷 移
46 measuring = false;
47 delay(1);
48 }
49
50 if (M5.BtnC.wasReleased()) { //00:00で 停 止 状 態 に 遷 移
51 ss = 0;
52 mm = 0;
53 measuring = false;
54 delay(1);
55 }
56
57 if (targetTime < millis() && measuring) { //1秒 ご と に 更 新
58 targetTime = millis() + 1000;
59
60 if (ss == 59 && mm == 99) { // 99:59で カ ウ ン ト 停 止
61 measuring = false;
62 }
63 else {
64 ss = ss + 1; //「 秒 」 の 値 を1増 加 さ せ る
65
66 if (ss == 60) { // 60秒 を 超 え る と き 「 分 」 の 値 を1増 加 さ せ る
67 ss = 0;
68 omm = mm;
69 mm++;
70 }
71 }
72 }
73 delay(1);
74 }
75 }
76 77
78 void notification(void *arg) { //通 知 機 能
79
80 while (1) {//マ ル チ タ ス ク の 処 理 は 無 限 ル ー プ さ せ る
81 if (ss == 0 && mm == 5) { //05:00の と き1回 鳴 ら す
82 playMP3("/yobidashi-bell-2.mp3");
83 }
84
85 if (ss == 0 && mm == 7) { //07:00の と き2回 鳴 ら す
86 playMP3("/yobidashi-bell-2.mp3");
87 playMP3("/yobidashi-bell-2.mp3");
88 }
89
90 if (ss == 0 && mm == 10) { //10:00の と き3回 鳴 ら す
91 playMP3("/yobidashi-bell-2.mp3");
92 playMP3("/yobidashi-bell-2.mp3");
93 playMP3("/yobidashi-bell-2.mp3");
94 }
95 delay(1);
96 }
97 }
98 99
100 void setup(void) {
101
102 M5.begin(); //M5Stackオ ブ ジ ェ ク ト を 初 期 化
103 M5.Lcd.fillScreen(TFT_BLACK); //背 景 色 設 定
104 M5.Lcd.setTextSize(1); //テ キ ス ト の サ イ ズ 設 定
105 M5.Lcd.setTextColor(TFT_YELLOW, TFT_BLACK); //テ キ ス ト の 色 設 定
106
107 xTaskCreatePinnedToCore(timer, "timer", 4096, NULL, 1, NULL, 0); //マ ル チ タ ス ク 機 能(タ イ マ ー 機 能)
108 xTaskCreatePinnedToCore(notification, "notification", 4096, NULL, 1, NULL, 1); //マ ル チ タ ス ク 機 能(通 知 機 能)
109 110 }
111 112
113 void playMP3(char *filename) { //mp3フ ァ イ ル を 再 生 す る
114
115 file = new AudioFileSourceSD("/yobidashi-bell-2.mp3"); //mp3フ ァ イ ル をSDカ ー ド か ら 呼 び 出 す
116
117 id3 = new AudioFileSourceID3(file);
118 out = new AudioOutputI2S(0, 1); // builtInDACへ 出 力
119 out->SetOutputModeMono(true);
120 mp3 = new AudioGeneratorMP3();
121 mp3->begin(id3, out);
122
123 while (mp3->isRunning()) {
124 if (!mp3->loop()) mp3->stop();
125 }
126 }
129 void loop() {
130
131 int xpos = 35; //タ イ マ ー の 表 示 す る 座 標 を 設 定 す る 。
132 int ypos = 85;
133 int ysecs = ypos;
134
135 if (omm != mm) { // 毎 分 再 描 画 す る
136 omm = mm;
137
138 if (mm < 10) xpos += M5.Lcd.drawChar(’0’, xpos, ypos, 8); //10分 よ り 前 の と き 「09」 と 前 に 「0」 を 表 示 す る
139 xpos += M5.Lcd.drawNumber(mm, xpos, ypos, 8); // 「 分 」 を 表 示 す る
140 xsecs = xpos; // 更 新 の た め 秒 のx座 標 を 指 定 す る
141 }
142
143 if (oss != ss) { //毎 秒 再 描 画 す る
144 oss = ss;
145 xpos = xsecs;
146
147 if (ss % 2) { // 2秒 に1回 「 : 」 を 点 滅
148 M5.Lcd.setTextColor(0x39C4, TFT_BLACK); // 「 : 」 の 色 設 定
149 xpos += M5.Lcd.drawChar(’:’, xsecs, ysecs, 8); // 分 と 秒 の 間 に 「 : 」 を 表 示 す る
150 M5.Lcd.setTextColor(TFT_YELLOW, TFT_BLACK); // 「 : 」 の 色 設 定
151 }
152 else {
153 xpos += M5.Lcd.drawChar(’:’, xsecs, ysecs, 8); // 分 と 秒 の 間 に 「 : 」 を 表 示 す る
154 }
155
156 if (ss < 10) xpos += M5.Lcd.drawChar(’0’, xpos, ysecs, 8); // 10秒 よ り 前 の と き 「09」
と 前 に 「0」 を 表 示 す る
157 M5.Lcd.drawNumber(ss, xpos, ysecs, 8); // 「 秒 」 を 表 示 す る
158 }
159 delay(5);
160 }
161
162 static uint8_t conv2d(const char* p) { //コ ン パ イ ル 時 に 文 字 列 か ら 数 値 を 抽 出 す る
163 uint8_t v = 0;
164 if (’0’ <= *p && *p <= ’9’)
165 v = *p - ’0’;
166
167 return 10 * v + *++p - ’0’;
168 }
第 4 章
結論
本製作では,
M5Stack
のみを使い卒業研究発表会で使用することを想定したプ レゼンテーションタイマーを製作した。開発環境として,
M5Stack
と互換性があり,開発が容易であるという点から,Arduino IDE 1.8.13
でArduino
言語を用いて実装した。M5Stack
では,M5Stack
ライブラリを使用することにより,同機固有の機能が使用できるようになる。ここでは同ライブラリの
M5Display
クラスに用意された 関数を用いて,経過時間表示を実装した。卒業研究発表会では発表時間は限られて いるため,時は表示せず分と秒のみ表示すれば良いので,その分フォントを大きく して見やすい表示とした。M5Stack
にはボタンが3
つあるため,これらを計時のスタート,ストップ,リセット機能にそれぞれ割り当てることにした。ただし,既存のタイマーアプリ等で は計時中でもストップ状態を経ずに直接リセット状態に入れるようになっているこ とが多い。これを考慮して,本製作では上記各ボタンの押下で状態遷移を行うよう に実装した。こちらは
Button
クラスを利用した。ベル音を鳴らす通知機能としては,ベル音の
mp3
ファイルをmicroSD
カードか ら再生する方式とした。計時時間が5
分,7
分,10
分経過するごとに1
回,2
回,3
回とベル音が再生される。ただし同ライブラリの再生機能は再生中にブロックす る仕様なので,その間液晶の表示更新が停止してしまうという問題がある。このため,
ESP32
のFreeRTOS
のマルチタスク機能を使い,音の再生をメインの処理から分離することでこれを解決した。
これら各機能の実装の後,動作確認を行った。結果として,液晶画面には「
mm:ss
」 形式で経過時間が表示されることを確認し,各ボタンの機能はボタンを同時押しし た場合にもいずれかの機能が正常に動作し,ベル音についても時間経過ごとに仕様 通り動作したことを確認した。4.2 今後の課題
今後の課題として,本製作で製作したタイマーは一目で操作を理解できるような 工夫が不十分であったため,それぞれのボタンの意味説明の表示を追加すること,
「
05:00
」,「07:00
」,「10:00
」でタイマーを停止させたときベル音が鳴り続けたため,ベル音の鳴る条件の改善が挙げられる。
謝 辞
本製作を行うにあたり,御指導頂いた鯨井 政祐 教授,御協力頂いた研究室の皆 様に感謝申し上げます。
参 考 文 献
[1]
武弓晃大, “RingableTimer Mini:
実鳴動型プレゼンテーションタイマーの小 型化”,
埼玉工業大学卒業論文, 2018
年度.
[2] On-Jin
〜音人〜,
https://on-jin.com
[3] Arduino
日本語リファレンス,
http://www.musashinodenpa.com/arduino/ref/
[4] M5Stack
ライブラリ,
https://knt60345blog.com/m5stack_api_list/
[5] M5Stack
を使ったタイマー製作,
http://kyokucho1989.chillout.jp/2019/10/02/
[6] M5Stack
でSD
カードからmp3
を再生,
https://qiita.com/ktansai/items/f0096495e2ca7fa38eb7
[7] Arduino-ESP32
のマルチタスク,
https://www.mgo-tec.com/blog-entry-arduino-esp32-multi-task-dual- core-01.html
[8] M5Stack
でマルチタスク,
https://qiita.com/Teppei_s/items/74f76725ad27304131fa
[9] M5Stack
でマルチタスク処理の実行,
https://qiita.com/nnn112358/items/733b5f52957980bb9fb1
[10] ESP32
で並列処理,
https://labo.mycabin.net/electronics/arduino-esp32/450/
[11] Web
タイマー,
https://timer.onl.jp/
[12]
下島健彦, “
みんなのM5Stack
入門”,
リックテレコム, 2019.