Think threshold

中の人のIYHにいたる顛末と購入レビュー。ときどき自宅システム構築備忘録。

M5StickC de 遊ぶ。(M5StickC+Joystick HATでBTポインティングデバイス作成)

本来は冬場のチャリで利用するはずだったのですが。。。

 

M5Stackシリーズを使い、お勉強を兼ねた小物デバイスを作ろうと考え、Bluetoothで接続し、マウスがわりとなるポインティングデバイスを作成しました。

 

 

●冬場のチャリライド時にスマホの簡単な操作がしたい

冬場のチャリライドは基本的に手袋を利用して手の寒さ対策をしているのですが、手袋をつけている状態だとスマホのタッチ操作ができません。都度外す必要があるため非常に手間となります。これを解決するにはBluetoothでマウスを装着してやればよいのですが(Androidは昔からUSB/Bluetoothでマウスを接続するとポインタが表示される)、そんな小型なマウスはありません。

これを解決するために、小型で扱いやすいM5StickCを利用してBTポインティングデバイスを作成します。

 

●M5StackシリーズはBluetoothが搭載されている+BTマウスライブラリがある

今回の作成にするのはM5StickCです。ESP32を搭載し、小型LCD(OLED)、バッテリ、WiFiBluetoothを標準で搭載、Type-Cコネクタを装備しています。RAMもArduino UNOと比べると非常に広大となっており、重いライブラリでも難なく動かすことが可能です。

M5StickC ESP32-PICO Mini IoT Development Kitshop.m5stack.com

M5StickCには液晶サイズが大きくなったPlusもあります。

 

また、M5Stickシリーズは「HAT」と呼ばれる拡張モジュールを搭載することが可能です。今回はM5StickC用に作成されているJoystick HATを利用し、X/Y軸のポインタの移動およびボタン操作をM5StickCに入力することにしました。

専用設計なので筐体の相性もバッチリです。内部的にはI2Cを利用してM5StickCと接続されています。

M5StickC Joystick HATshop.m5stack.com

 

●各種調査

作るにあたって、各種必要なライブラリを探します。

makoroさんは久しぶりのCライクなプログラミングなので、いろいろ忘れていて思い出すのが大変でした。

 

・M5StickCの画面やバッテリ等の情報表示ライブラリ

M5Stackシリーズは本体に各種センサや小型ディスプレイ、ボタン、バッテリが搭載されています。

これらのボタン入力の取り扱い、バッテリ電圧を返してくれる関数、ディスプレイ描画を行ってくれるライブラリを用いて、Joystick HATの入力値やバッテリの状態を確認します。

なお、M5StickCのバッテリは4.2~4.3Vでフル充電とのこと。

docs.m5stack.com

make-muda.net

lang-ship.com

 

Bluetooth Mouseライブラリ

まずはこれから。M5StackシリーズをBLE Mouseとして動作させ、

スマホやPCの入力デバイスとして扱うことができるライブラリです。

ポインタ操作、左右クリック、スクロール等をサポートしています。

今回やりたいのはAndroidでのマウス操作なので、これらの機能で十分です。

公式に書いてあるチュートリアルを確認するとわかりますが、かなり簡単に扱えるようです。

neocat.hatenablog.com

qiita.com

github.com

 

・Joystick HATライブラリ

今回はJoystick HATを利用するため、こちらもライブラリを活用します。

Joystick HATはM5StackC本体とI2Cで接続され、定期的にデータを読み出すことで利用できます。

docs.m5stack.com

 

Arduino IDEでのM5Stack開発

今回はArduino IDEを利用してコードを書いていくので、ArduinoIDE環境の設定です。

qiita.com

 

Arduino IDEにM5シリーズのバイナリをインストールし、書き込み設定を変更しておきます。

 

●作成

各種のパーツをつなぎ合わせていきます。

・ディスプレイの方向を使いたい方向へ

lang-ship.com

今回は自転車のハンドルバーに取り付ける関係上、Joystickを左側にした横配置となります。

そのため、標準の描画方向と異なるため、以下のように方向を指定します。

(併せて文字サイズの設定と画面初期化を行っています)

//LCDRotate,setTxtSize

M5.Lcd.setRotation(3);
M5.Lcd.setTextSize(2);
M5.Lcd.fillRect(0, 0, 80, 160, BLACK);

 

 

・バッテリ電圧を表示

こちらはM5Stackシリーズ標準で用意されているバッテリ情報取得用関数を利用しました。

vbat = M5.Axp.GetVbatData()

こちらはint型ではなくfloat型のため少し注意が必要です。

 

・Joystick HATの入力が使いたい方向と異なるので変換

こちらもJoystickの入力方向が動かしたい方向と異なるため変換します。

入力はx/y軸ともに±127の範囲で行われ、端子を下にした状態でX/Y軸の移動量が決定されます。


lang-ship.com

こちらも回転させるため、以下のような(超絶泥臭い方法で)方法で変換しています。

基本はx/y軸の正負の入れ替えや値の入れ替えで対応してます。

//cursor position rotate
x_data_rotate=y_data-3;
y_data_rotate=(-1)*x_data+5;

今回購入したJoystick Hatを一切触らないときの読み出し数値がX軸Y軸ともに0ではないため、-3および+5は実質マジックナンバーとして記載しています。

(個体差でしょうし、ホントは冒頭にdefineで定義したほうがいいのでしょうけど)

 

 

・Joystickから入力されたスティック移動量をマウスポインタの移動量へ変換してポインタを操作する/左クリックを実装する

こちらも悩んだところでした。Joystickのx/yをそのままポインタの移動量としてBLEマウスライブラリに渡してしまうと、入力に対して移動量が多すぎるため、丸めてやる必要があります。

実際には2段階の加速があればよいだろうという判断の元、泥臭いというか、こちらもマジックナンバー的なやり方で対応しています。調整していったところ、下記の数値で自分の操作感と合うようになりました。

 

また、Joystickは押していないときの戻り値が1、押した際の戻り値が0となるため、押されている際は左クリックを行うように設定。

 

  if (Wire.available()) {
    // read joystick data
    x_data = Wire.read();
    y_data = Wire.read();
    button_data = Wire.read();

    //cursor position rotate
    x_data_rotate=y_data-3;
    y_data_rotate=(-1)*x_data+5;
    
    M5.Lcd.setCursor(1, 1);
    M5.Lcd.printf("x:%4d y:%4d\n", x_data_rotate, y_data_rotate);
    M5.Lcd.setCursor(1, 17);
    M5.Lcd.printf("button:%d\n", button_data);
    M5.Lcd.setCursor(1, 34);
    M5.Lcd.printf("Volt: %.2fV", vbat);

    if(bleMouse.isConnected()) {
      //moving x position calculate
      if(x_data_rotate==0){
        x_delta=0;
      }else if(x_data_rotate>0){
        x_delta=(x_data_rotate/64+1)*3;
      }else{
        x_delta=(x_data_rotate/64-1)*3;
      }

      //moving y position calculate
      if(y_data_rotate==0){
        y_delta=0;
      }else if(y_data_rotate>0){
        y_delta=(y_data_rotate/64+1)*-3;
      }else{
        y_delta=(y_data_rotate/64-1)*-3;
      }
      
      //display moving delta
      M5.Lcd.setCursor(1, 51);
      M5.Lcd.printf("Conn%3d:%3d",x_delta,y_delta);
      bleMouse.move(x_delta,y_delta);

      //left click function
      if(button_data==0){
        bleMouse.click(MOUSE_LEFT);
        delay(200);
        //button_data=1;
      }
      
    }else{
      M5.Lcd.setCursor(1, 51);
      M5.Lcd.printf("Disconn.");
    }
    
  }

 

●完成。

一応、自分が思うようなものが作れました。

電源を入れると「ESP32 Bluetooth Mouse」なるデバイスが出現するので、スマホ側からタップして接続。パスコードはありません。

f:id:makoro2_0:20220130155739p:plain


本当はGitHubとかにも載せて管理を、とも思ったんですが、Webのいろんなサイトを参考につなぎ合わせただけのソースなこと、参考元のサイトのライセンスが不明なため非公開のほうが良さそうと判断しました。

 

●使うはずだった、のですが。。。

実は・・・

makoro.hatenablog.jp

Redmi Note 9sのタッチ感度が高く、手袋を付けていても反応してくれるため、実は使用していません。。。(笑)

JoyStickまであるので、なにかに活用は効きそうですが、現状作ったのに空振りという結果に。。。

 

 

●まとめと感想

久しぶりにArduinoとCライクなプログラミングをやって、ホビーで触るにはほんとに便利な時代になったよなと実感。

M5Stickを始めとしたM5Stackは、WLAN/BT搭載、バッテリ搭載、液晶搭載、最低限のボタンを搭載とホビー電子工作を行ううえでの欲張り基本セットがパッケージングされていることに加え、Type-Cでの簡単接続が可能です。

またArduinoベースの簡単なプログラミングで動作すること、標準ライブラリで多数の便利な機能が実装されていることから、Arduino UNOのからのステップアップには最適だなと思いました。そりゃ人気になるわけだ、と使ってみて実感。