見出し画像

M5PaperでVolumioリモコンを作るよ!①

まえおき

さてさて、

前回の

このテクニックを使って、ちょっと前に作った音楽プレイヤー

の手元リモコンを(例によって多分試行錯誤しながら)作ってみたいと思います。

なぜって、M5Paperはご存じの通りEインクでタッチセンサー、さらにWiFiまでついての全部入り! VolumioはWiFiでWeb経由のコントロールができちゃう。ならこれでリモコンつくれたらたのしそうじゃん? ってわけです。

※Volumioのリモコンのスマホアプリとかもう良いのあるじゃないの? なんて野暮はいいっこなしです。そこに山があるからのぼるんです(違う)

事前の準備と情報あつめ

Volumio側のAPI情報

こんなページを見つけました。Volumioを外部からコントロールする命令の一覧です。ふむふむ、WebSocketでいろいろできるんね。これは便利~☆

さらに知りたいことを日本語で解説してくれている便利ページ

も見つけてラッキー☆ 

このページではcurlコマンドを使ってVolumioに動作命令を投げつけるというすてきにシンプルな方法をとっています。いろいろ面倒なやりかたが苦手なワタクシにピッタリの乱暴な方法で大好きです(おい)

画像1

↑ここらへんをメモ。

※本格的にやるなら、もうちょっとしっかりしたやり方のほうが良いです。それについては本家のAPI情報をお読みくださいネ。(英文ですけでどわかりやすくかいてあります)

M5Paper側

M5EPDの使い方情報

本家はこちら

https://github.com/m5stack/M5EPD

なんですぐぁ、なかなかこれがわかりにくい!><

このページ

と、こちらのページ

の情報に助けてもらってなんとか理解。

↑に書かれている通り、

基本的な流れは

// 既存 canvas の削除
canvas.deleteCanvas();

// 新規 canvas の生成 (幅 350 x 高さ 25 [pixel])
canvas.createCanvas(350, 25);

// canvas に文字を書く (canvas の原点起点)
canvas.drawString("test", 0, 0);

// canvas に図形を描く (canvas 座標系において (5, 5) を起点とする幅 30 x 高さ 15 [pixel] の矩形)
// 引数の末尾は 16 階調の色(濃さ)で最も濃い
canvas.drawRect(5, 5, 30, 15, 15)

// canvas を表示 (画面座標系において (185, 10) を起点に)
// 引数の末尾は update_mode (DU4 は最も高速,GC16 は低速ながら高画質で画像描画向き)
canvas.pushCanvas(185, 10, UPDATE_MODE_DU4);

で良いのですが、最初にEペーパーを何度かpushCanvasすると、前の情報が残っていたり残っていなかったり(deleteCanvasが聞かない!?)なんて摩訶不思議世界が展開してしまってめちゃくちゃ悩みました。

どうやら、(まだちゃんと調べていないので確定ではないですが)プログラムの基本設定を記述する setup()の中で書かれたCanvas系の命令は一緒くたにされて(最適化?)実行されてしまうよう。上記の基本的な流れが正しく実行されるのはloop()内からじゃないとダメ。、っぽい。のです。これに気が付くのに2日かかりました。うがー><

いやあ、クセのある子です。優秀なハッカーさんだとこういうのに出会うと腕がなるのでしょうが、ワタシのようなひよっこには荷が重い。そろそろ放り投げそう(だめ

画面デザインちっぷす

M5Paperの表示は 540x960 @ 4.7" のEペーパーです。スマホっぽい縦型なので割合デザインはしやすそう。ただし、まだ「ボタン動作」みたいなライブラリは公開されておらず、全部自分で作らないといけません><

ちょっと(かなり)めんどくさい><

だれかチックルチーコ(古い。Tcl/Tkのこと。ウィンドウをデザインするいにしえのスクリプト言語です)みたいなのつくってくれないかなー?(他力本願)

しゃあないので、前々回の

UIFlowさん登場。

こちらのUIで画面デザインをさくさくつくります。

画像2

こんなかんじで画面にGUIボタンや表示部とかを見ながらセットしていくわけです。

で、非常に原始的ですが、ここでセットしたX,YやWidth,Heightなどを紙にメモ(!)して、いま造ってるプログラムのほうにコピーしてくるというわけ。わたしはこれでやっちゃいましたが、

あんまり原始的なんで何とかならないかとおもったら手段ありましたw

UIFlowのプログラムは、ローカルにダウンロード可能なので、そのファイル

画像3

をVSCodeで開いてみましょう(テキストファイルでした)

画像4

このぐじゃっと書かれてる中で、Rectangleとか、それっぽいのの後ろに、ちゃんと "x":100,"y":650,"width":100,"height":100 のように必要な情報かかれていますね。これを読み取って、プログラムに入れ込むのが楽っぽいです。

(できれば自動で読み取ってくれちゃったりすると……もっとできればプログラムまで自動で変換してくれちゃうと超クールだけど、面倒なのでそれは誰かにお願いしますw)

仮組みするよ

面倒そうな画面まわりは後まわしにして、とりあえずM5Paperの脇についている操作スイッチ

画像5

↑裏面からみたコレね

を使って動作テストしてみます。

まずWiFi

 #include  <string>  
using namespace std; 

string SSID = ""; // SSIDとキー、最初に自分の環境のを入れておく
string PASS = "";

void WiFi_setup()
{
    //connect to WiFi
    if( SSID.length() == 0){
      Serial.print("SSID Length = 0  -> Default Connect.");
      WiFi.begin();                 // 一度接続が成功したらこちらでOK.
     }else{
       WiFi.begin(SSID.c_str(), PASS.c_str()); // SSIDに文字列があればこちらで接続
     } 

      while (WiFi.status() != WL_CONNECTED) {
          delay(500);
          Serial.print(".");
      }
      Serial.println("CONNECTED");
}

こんなふうなのでWiFiに接続させて、(setupから呼び出します)

ボタン(スイッチ)のテスト関数

void ButtonTest(char* str, int cmd)
{
 // cmd = 1:pause/pley 2:rev 3:fwd

   HTTPClient http;

   string CmdStr = VolumioURL;

   switch (cmd) {
     case 1:
       CmdStr += "/api/v1/commands?cmd=toggle";
       //http.begin("http://192.168.1.86/api/v1/commands?cmd=toggle");
       http.begin(CmdStr.c_str());
       break;
     case 2:
       //http.begin("http://192.168.1.86/api/v1/commands?cmd=prev");
       CmdStr += "/api/v1/commands?cmd=prev";
       http.begin(CmdStr.c_str());
       break;
     case 3:
       CmdStr += "/api/v1/commands?cmd=next";
       http.begin(CmdStr.c_str());
       //http.begin("http://192.168.1.86/api/v1/commands?cmd=next");
       break;
   }
       
   int httpCode = http.GET();
   if (httpCode > 0) {
     String response = http.getString();
     //以降、データに応じた処理
     //canvas.drawString(response, 0, 0);    //画面表示。これはあとで
     Serial.println(response);
   } else {
     Serial.println("Error on HTTP request");
   }
   http.end();

   delay(500);
}

日本語で言うと、HTTPClient の begin でVolumioAPIのURLに getメソッドを投げつけてレスポンスを返してもらう。というかんじ(全然日本語じゃないw)

メインループ

void loop()
{

   if( M5.BtnL.wasPressed()) ButtonTest("Prev",2);
   if( M5.BtnP.wasPressed()) ButtonTest("Play/Pause",1);
   if( M5.BtnR.wasPressed()) ButtonTest("Next",3);
   M5.update();
   delay(100);
}

メインループは簡単、スイッチ押されたら呼びだすよ。というだけ。

てなかんじでやってみると……

画像7

おおお。ちゃんと動く!! 操作できちゃう!!

ログを見てみると

画像6

play や next 、prev とばっちり操作できていることがわかります。

すばらしい!!

いやー、テストがサクッと動くとうれしいですねー☆

なんかこれだけでもうリモコンできちゃうじゃん。画面操作いらなくない? っておもうところですが、せっかくなのでそれもちゃんとやりたいなー。いろいろ準備もしたしねー。という気運が高まったところで長くなったし今日はこれまで!! またらいしゅー!☆

―――

↑つづきはこちらー☆

#M5Paper #スマートリモコン #Volumio #リモコン自作 #M5 #ほんとに来週かな#らせん工房

よろしければサポートお願いします!いただいたサポートはクリエイターとしての活動費にさせていただきます!感謝!,,Ծ‸Ծ,,