見出し画像

ESP32で自作マウス〜その3〜

前回のあらすじ

前回は3次元マウスの実装までやって、コアとなる機能が揃ってきました。

今回は3Dモデルを作って実際にマウスの形にしてから、スイッチなんかを配線して動くようにするまでをやろうと思います。


3Dモデル作成

本題の前に、前回のESP32の記事を書いてからかなり時間が空いているわけですが、なぜかと言うと夏休み中に3Dモデルをさくっと作れると思っていたのが、トラブルがあって時間がかかった(のと単純に時間なかった)からなんです。
じゃあ実際どんなトラブルがあったかを見ていきます。

Blenderで3Dプリンタ用のモデルを作ってはならない

タイトルのままなんですが、最初は「CADとか使ったこと無いし、Blender最強やろ」見たいなノリで、Blenderで造形してソリッド化すればうまく行くと思っていた自分がいました。
しかし、いざモデルができてソリッド化すると、見事にぶっ壊れた上に、よく考えたら寸法もヤバそうなことに築きます。絶望です。めっちゃ時間かけたモデルがパーな上、このままだと画用紙でケースを作ることになってしまいます…

OnShapeを使おう

そこで急いでLinuxで使えるフリーのCADソフトを探したところ、ほとんどがダメor有料ななか、OnShapeはブラウザでできるからマルチプラットフォームな上使いやすいとの情報をGET!
実際使うと非常に操作性が高く、特にiPadのApple Pencilとの相性が最強で十数時間かけてBlenderで作ったモデルを(考えながら作ってたので単純に比較はできませんが)、たった2~3時間でほぼ作り直せました。

いざ出力

というわけで3Dモデルが完成したので、学校の3Dプリンタで出力しました。正直初めてで勝手がわからず、何も考えずにサポート剤をつけたせいで一部サポート剤が剥がせない場所ができてしまいましたが、それを除けばとても良くできていて驚きました。

ちゃんとホイールの寸法があってて一安心

クリック再実装

以前にもクリックの実装はしたんですが、改めて配線し直したのでピン番号が変わっていますし、前回はチャタリングの対策が不十分だったのでもう少ししっかりとした対策を取りたいと思います。

チャタリング防止

そうは言ってもスペースが限られている以上、シュミットトリガー回路などで軽減することはできないので、ソフトウェア側で対処します(というか調べた感じそれが一般的らしい)。
クリックなどのアクションがあると、長くても10msほどチャタリングした後再び安定するので、この間だけGPIOの電圧の上下を無視すれば良いことになります。
このときループで回していれば上下した回数による制限でなんとかできたりもするんですが、僕は割り込みでスイッチを実装するので、一時的に割り込みを無効化して、10ms後にタイマー割り込みで再びGPIOピンによる割り込みを有効化することでかなりいい感じに対処できました。

長押し対応

という感じでチャタリングの防止コードを組むときに気づいたことがあって、この10ms後に入る割り込み時にGPIO入力がHIGHかLOWかをみれば長押しかどうかがわかりますよね。ということでHIGHだった場合はそのまま長押しのコマンドをBLEで送って、電圧上昇時用の割り込みの代わりに電圧降下時の割り込みをセットして、その割り込みで長押しを解除するようにしました。
ここまででだいぶマウスっぽくなってきたので、途中経過の動画がこれです。

ただ相変わらずカーソルの操作が思うように行かないのが残念なところです。

ホイールの実装

ホイールはロータリーエンコーダーを使って実装します。が、ゼロから実装するのは面倒なので、電圧の上下から回転情報への変換は以下のリポジトリにあるライブラリに頼ります。

おかげでたったこれだけのコードでホイールが実装できました(一部略):

void update_wheel() {
  encoder.tick();

  int new_pos = encoder.getPosition();
  if (pos != new_pos) {
    if (bleMouse.isConnected()) {
      bleMouse.move(0, 0, char(encoder.getDirection()) * 4);
    }
    pos = new_pos;
  }
  detachInterrupt(GPIO_PIN_ROTARY_A);
  timerWrite(timer_wheel, 0);
  timerStart(timer_wheel);
}

void enable_wheel() {
  attachInterrupt(GPIO_PIN_ROTARY_A, update_wheel, CHANGE);
  timerStop(timer_wheel);
}

void initialize_wheel() {
  attachInterrupt(GPIO_PIN_ROTARY_A, update_wheel, CHANGE);
  attachInterrupt(GPIO_PIN_ROTARY_B, update_wheel, CHANGE);
}

やってる処理はロータリーエンコーダーから接続しているピン2つに入力電圧が変化したときにトリガーされる割り込みをセットして、そこで状態を更新して反映するだけです。
これも若干もっさりしてますが、カーソル移動に比べたらだいぶスムーズで、ちゃんとホイールの3Dモデルにギザギザをつけたおかげで操作性も悪くない出来です。
↓これが試した時の動画です。

まとめ

というわけで今回はホイールまでの実装を終わらせて、ほぼマウスに必須の機能が揃いました。あとやりたいこととしてはカーソル移動の改善と、バッテリー駆動用の回路の実装です。
ちなみに、夏休み中にPCで作業していたら、まさかの自分が普段使っているEX-Gマウスのホイールが壊れてしまいましたwwwなので、早いとこマウスをまともに使えるようにして、ホイールが使える生活に戻りたいです。
次回はいつになるかわかりませんが、バッテリー駆動の実装をメインでやることになると思います。

今回の作業終了時点の様子(ぐちゃぐちゃ…)

いいなと思ったら応援しよう!