はじめに
今年Cube Scramblerという作品を作ったのですが、LEGO x M5Stack x Node.js x Web UIで作ってみたら個人的にとても作りやすくしっくりきました。
本記事では実装にあたり使用した技術スタックを紹介したいと思います。
Cube Scramblerとは
ルービックキューブを自動で崩したり揃えたりする、レゴとM5Stackで作れるロボットです。
このロボットを実際に作るにあたって使った技術を紹介していきます。
システム構成
図のように以下の3つのカテゴリーに分けて紹介していきます。
- ハードウェア
- ソフトウェア(バックエンド)
- ソフトウェア(フロントエンド)
ハードウェア
ルービックキューブの回転機構
2つのサーボモーターの組み合わせでルービックキューブ全面の回転を行っています。
1つは土台部でルービックキューブの横回転を、もう1つはアーム部でルービックキューブの縦回転を担当しています。
このしくみはルービックキューブソルバーロボという既製品を参考にさせていただきました。
LEGO
筐体はLEGOで作っています。
3Dプリンタを持っていればそれ用のものを作りたかったのですが、持っていないため先述のルービックキューブソルバーロボを参考にLEGOで作りました。
結果としてとてもポップな見た目と、誰でも作れるオープンソース性があってとても良かったと思います。
またオープンソース性というところでGitHubにて組立説明書を公開しています。
まるで本物のLEGOの説明書のような出来ではないでしょうか。
これはStudio 2.0というソフトを使って作っています。
Studio 2.0はBrickLinkというLEGOパーツ売買サイトが作ったLEGO専用3D CADみたいなソフトで、PC上でLEGOの設計やレンダリング、組立説明書の作成ができます。
また使用するブロック一式を直接BrickLinkから購入したりもできます。
M5Stackデバイス
サーボモーターを制御するマイコンにはM5Stackデバイスを使っています。
開発時はAtom Liteで実装していましたが、最終的にどのM5Stackデバイスでも使えるようになりました。
特に画面付きデバイスでは某スタックチャンらしき顔がディスプレイに表示されます。
オススメはバッテリーや画面も付いているM5Stack Core2ですが、安価に作りたい場合はATOMS3 Liteがオススメです。
M5Stackデバイスの制御には後述するopnizを使用しており、デバイス自体に書き込むコードは1行も書いておらずopniz CLIを使ってopnizデバイス化しただけです。
opnizデバイスの内部ではM5Unifiedが使われています。
GeekServo
レゴとくっつくサーボモーターです。
グレーの270度タイプのものを2つ使っています。
これをM5Stackデバイスへつないで制御します。
M5Stackデバイスとの接続はGrove サーボ用2分岐ケーブルを使っています。
配線がすっきりして便利です。
ソフトウェア(バックエンド)
Node.js & TypeScript
バックエンド環境はNode.jsにて実行され、コードはTypeScriptで書きました。
Node.jsではM5Stackデバイスの制御用にopnizと、フロントエンド用にExpressを起動しています。
opniz
M5Stackデバイスの制御にはopnizを使用しています。
opnizはM5StackデバイスをNode.jsから遠隔制御するオープンソースのIoTフレームワークです。
M5Stackデバイスを一度opnizデバイス化してしまえば、以降デバイスへの再書込不要でNode.js上から自由に制御できます。
Express
後述するフロントエンドを提供しているWebサーバーにExpressを使用しています。
UIのHTMLの静的配信と、UIから呼び出されるAPIを提供するAPIゲートウェイとして使用しています。
ルービックキューブのロジック
揃えるロジック
ルービックキューブを揃える(解く)アルゴリズムとしては「Two-Phase-Algorithm」というアルゴリズムが一般的です。
このTwo-Phase-AlgorithmのJavaScript実装である「min2phase.js」というライブラリを使いました。
崩すロジック
ランダムだったり、ある特定の状態に崩すアルゴリズムというのが見当たらなかったため、こちらは自分で考えました。
と言ってもしくみは単純で、まずランダムにキューブの状態を生成します。
しかしランダムなキューブ状態だとそもそも揃えることが可能な状態ではない可能性があるため、先述のmin2phase.jsを通して揃えることができるかチェックします。
この「ランダム生成→min2phase.jsチェック」をひたすら繰り返し、揃えることのできる崩れた状態を引き当てる、というしくみで実装しました。
ソフトウェア(フロントエンド)
Web UI
フロントエンドはWeb UIで提供しています。
また一応インターフェースという意味ではCLIとM5Stackデバイスのボタンもインターフェースとして機能提供しています。
Alpine.js
シンプルなUIだったため、フロントエンドフレームワークとしては軽量フレームワークであるAlpine.jsを使いました。
はじめて使ってみたのですが軽量ゆえにTypeScriptではなくJavaScriptでそのまま書くコンセプトであり、書いている途中でバックエンド同様TypeScriptで書きたくなってきたりと辛みがでてきました。
ただ後述するTailwind CSSとの組み合わせで作られたUIライブラリ等の情報が多く公開されており、コピペしていじくるだけでAlpine.jsの学習と実装を賄えられて便利でした。
Tailwind CSS
これもはじめて使いましたが、UIパーツを適切にコンポーネント化する場合はTailwind CSSがいい感じだと思いました。
CSS用クラスのグローバルな名付けに脳リソースを割かなくてよくなるので。
おわりに
以上「LEGO x M5Stack x Node.js x Web UI」な技術スタック構成の紹介でした。
この構成なら3Dプリンタを持っていなかったり、電子工作よく分からないWeb系な方でも気軽にものづくりできる構成なんじゃないかと思います。