画面付きのWiFiマイコンボード、M5StackにGUI環境であるM5ezを組み合わせるととても「お楽」で良いです。しかしM5ezに含まれていない機能も多々あります。その一つがファイラーじゃないでしょうか。microSDカード上のファイルを操作する機能。とりあえず簡易的なものの実装を始めてみたです。まだ途中。
※「IoT何をいまさら」投稿順Indexはこちら
本投稿は、以下のM5ezを使ったメニューシステムにいろいろ機能を追加してきている投稿の「差分」であります。「先だって」の投稿を御覧になっていないと意味不明な部分もあるかと思われるので、まずは先行する投稿へのリンクを「順に」リストしておきます。
鳥なき里のマイコン屋(113) M5Stack、M5ez、本当にイージー M5StackにM5ezのせると本当にお楽という話。メニューの原型。
IoT何をいまさら(77) M5Stack、M5ez GUIからNode-REDへMQTT M5Stack からWiFiネットワークを介してサーバー機のMQTTブローカにpublishしてNode-REDダッシュボードに表示。メニューシステム拡大。
IoT何をいまさら(80) M5Stack、BB風拡張PCA9306 I2CバスのSCAN機能などをサブメニュー化して追加
システマティックにやっているわけでなく、思いつくまま切れ切れにやっていてすみません。そこで今回は、新たなサブメニュー Filer というものを作成です。ぶっちゃけ、ミニ、いやマイクロ、いやいやナノな簡易ファイラー。とりあえず今回は、
-
- SDカードのファイルシステム内のファイル名が画面に表示できること
- テキストファイルの内容が画面表示できること
のミニマム機能のみです。Windowsのcmd.exeでいったら DIR と TYPE だけ。今後必要に応じて機能は追加して行きたいと思います。
さて、M5StackのSDカード、何にお使いですかね。私は取得したデータの記録などに用いております。後でPCなどで読みやすいようにもっぱらCSV型式のテキストファイルとして記録することが多いです。まあ環境によっては取得の都度、それこそMQTTに載せてサーバーに送ってしまっても良いですが、持ち運びに便利なM5Stackです。必ずしもWiFi使える環境があるわけでないので、一旦、SDカードにも記録できるのは安心です。また、用途によっては画面に表示する画像などを置いておくストレージとしての使用方法もあるでしょう。
M5StackをESP32のArduino環境で使用している場合、SD.hというヘッダをインクルードすればSDカードにアクセスするための関数群を使えるようになります。以下にArduinoのSDライブラリのAPIリファレンスへのリンクを貼っておきます。
SDクラスとFileクラスという2つのクラスが定義されていて、それらを使えば必要な処理はバッチリじゃないかと思います。また、Exampleコードも掲載されており。といってそのままではM5ezのGUI画面の中に納まる筈もなく、当方必要なのはそれらファイルアクセス機能をM5ezのGUI画面から使えるようにする、という点であります。
まず、メイン・メニュー側に「Filer」というサブメニューを呼び出すエントリを追加し、サブメニューを呼び出せるようにいたしました。呼び出したサブメニューが左です。今のところ機能は2つだけ。
- ルートディレクトリのファイル名をリストする
- メインメニューに戻る
ファイラーなどという程の機能はまだありません。その部分のコードが下に。
サブメニュー
void filerSubmenu() { ezMenu subMenu("Filer"); subMenu.addItem("LIST ROOT", filerRoot); subMenu.addItem("Back | Back to main menu"); subMenu.run(); } void filerRoot() { File root = SD.open("/"); fileList(root, "ROOT"); }
さて「ルートディレクトリのファイル名をリストする」を実行した場合の表示は以下のようです。左端にDの文字があるのはディレクトリ、無いのは通常のファイルです。先頭の “System Volume Information” はシステムが勝手に生成する隠しディレクトリのようです。なお、現状のUIはとてもヘボくて、1アイテム表示する毎に一端停止、”NEXT”ボタンで次のアイテムを表示、”BACK”ボタンでサブメニューに戻り、”SEL”ボタンで選択という具合です。大量にファイルがある場合、「やってられない」UIですが、それほどなファイル数で「運用」することを考えていないので今のところ「許している」ゾンザイな実装。
ディレクトリ表示部分の関数はこちら。表示領域とフォントはキメウチ、1画面10行前提です。
ディレクトリ表示のリスト
void fileList(File dir, const char* title) { int item = 0; ez.header.show(title); ez.canvas.font(&FreeMono9pt7b); ez.canvas.lmargin(7); ez.canvas.clear(); ez.canvas.y(30); while (true) { File entry = dir.openNextFile(); bool dflag = false; if (! entry) { break; } item++; if (item > 9) { ez.canvas.clear(); ez.canvas.y(30); item = 0; } if (entry.isDirectory()) { dflag = true; ez.canvas.print("D "); ez.canvas.println(entry.name()); } else { ez.canvas.print(" "); ez.canvas.println(entry.name()); } String comStr = ez.buttons.wait("BACK # NEXT # SEL"); if (comStr == "SEL") { if (dflag) { fileList(entry, entry.name()); } else { fileDump(entry, entry.name()); } ez.header.show(title); ez.canvas.clear(); ez.canvas.y(30); } if (comStr == "BACK") { entry.close(); return; } entry.close(); } ez.buttons.wait("BACK"); }
先ほどの「ディレクトリ表示」内で、ディレクトリをSELすると、SELしたディレクトリをターゲットに再度「ディレクトリ表示」します。SELしたのが通常のファイルであれば、当面、「テキストファイルと見なして」ファイル内容を画面にダンプ(WindowsのTYPE、Linuxのcat)します。その様子が以下に。
ここでも表示領域とフォントはキメウチ、1画面10行前提です。ファイル途中ではNEXTボタンが表示されるので、NEXTで次の部分へ、末尾に至るとBACKと変わるのでボタンを押すと「ディレクトリ表示」画面にリターンします。既に分かっている問題として、行幅が画面幅を超える場合上手くいかないです。
ファイル内容表示の関数がこちら。
ファイルダンプのコード
void fileDump(File dfile, const char* title) { int lin = 0; ez.header.show(title); ez.canvas.font(&FreeMono9pt7b); ez.canvas.clear(); ez.canvas.lmargin(7); ez.canvas.y(30); while (dfile.available()) { char c = dfile.read(); ez.canvas.print(c); if (c=='\n') { ez.canvas.println(); lin++; } if (lin > 9) { ez.buttons.wait("NEXT"); lin = 0; ez.canvas.clear(); ez.canvas.y(30); } } ez.buttons.wait("BACK"); }
「問題あるある」で「へぼいUI」ですが、ま、今後改善していく、ということで。