突然ですが、すっかりデジタル化に取り残されているデバイスを見つけてしまいました。 小学校義務教育の中でも習うので、ほとんどの方が知っているはずの、そうそろばんです。 完全にデジタルの特性があるのに、何故かデジタル機器扱いされていない…かわいそうな奴です。 せっかく学校で習っても、一生使うことがないのではないでしょうか?
という流れで、そろばんを物理的に動かすとともに、数値を読み取ってコンピュータ制御できるようにすることで、デジタル化演算機を作成しました。
ステッピングモータの制御は初めての試みだったので、ガイドレールへの引っかかりや脱調が起こりまわって大変でした。 最初の1か月はまともに動かす事が出来ませんでした。 その後も 3Dプリント部品を何度か作り直して、ようやくまともに動くようになりました。 まだ、動作音が大きすぎるという問題は残っていますが。
爪の形状も苦労しました。最初は長めのサーボホーンをそのまま使っていましたが、厚さ3mm 程あると、隣をひっかけたり、フレームを押し上げてしまったりしたので、薄さ 0.75 のプラスチック版 (100円ショップ下敷き) をサーボホーンの先に取り付けて対処しました。それでも条件によっては引っかかります。今にして思えば、ストレートではなく、「くの字型」形状にしておけばよかったと思います。
そのあと待っていたのは、珠の位置(爪を入れる)調整です。0.数ミリの単位でもずれてしまうと、ちゃんと動かなかったり、隣を巻き込んだりして、±1の数値差になってしまっていました。 細かくテーブルを作り、アプリ側に調整機能を組み込み、ひたすらすべての位置の平均を何度も取って調整しました。これだけで1週間程掛かりました。
全体が動くようになった時点でも、少しずつずれが積算する問題が勃発ました。 計算をひととおり行って、次に珠を操作すると微妙にずれていて、弾き損ねたり間違えた珠を弾いたりしました。 どこかでまだ脱調しているのか、引っかかっているのか、判明していません。 ストレートであるべきガイドレール部品を 3Dプリンタで作成しているのが間違えの様な気はします。
画像認識部分も結構苦労しました。 最初は OpenCV ベースの画像認識を試していたのですが、理解困難なうえに、結局ちゃんと動作するところまで出来ませんでした。 SPRESENSE を試して、その認識率の高さに感動しました。
3種類のコンピュータのソフトを同時に作り上げるのは大変でした。 どこが悪いか不明なことは日常茶飯事、ちょっとした変更でいじっていないソフトのバグが顔を出したり・・・
アプリ側は、Visual Studio C# でアプリを作るの事態が2年ぶりとか忘れまくっていたこともあり、バグが多発して大変でした。
他にも、いろいろと連携できそうです。
早速時計にしてみましたし…
掛け算、割り算を実装するにはもっと桁数の多いそろばんでも対応できるようにしたいし、
それには、もっと移動速度も上げたい。
移動速度を上げるには、アルミフレーム使ってちゃんとレールの精度を上げてとなって、
流石に一から作り直す時間はなかったので、今回はこの形で断念しています。今後の発展はメカ作り直しから…
吹けば吹っ飛ぶ(というより [×] を押すと消えてしまう)電卓アプリと違って、 机の上をガッツリ占領する重量感が大事です。
メカがゴリゴリ優雅に動くのはエンジニアのロマン。ずっと見ていたいし、やめられませんよね。
目にも止まらない一瞬で計算結果を出すなんて邪道です。 計算過程が目に見えてとっても安心ですよね。 小さい時に、計算は答えじゃなくてそれを導き出した過程が大事って習いませんでした?
コンピュータを3種類以上も使ったり、たくさんの技術を使ったりと、「様々なリソースを駆使したシステム構成で動いている感」がたまらないですね。
技術の無駄遣いのせいというかなんというか。 詰め込みすぎて、疲れました。
最大の問題点は、開発者自身が そろばん 素人なこと。 数十年前に授業で習っただけやし、覚えてないし。実は正しい動きしていない可能性も…
またやってしまった、技術の無駄遣い… ふぅ。
「HeroesLeague2022 応募時デモ動画(初回バージョン)」 YouTube by TakSanMade
「HeroesLeague2022 審査用動画(バージョン2)」 YouTube by TakSanMade
「ヒーローズリーグ IoAT賞審査会2022 by IoTLT」 YouTube by IoTLT チャンネル
審査>5:13:41 付近~
⇒負けた。第二位 orz
「ヒーローズリーグ 2022 予選 in 第二部」 YouTube by MAちゃんねる
発表>49:44 付近~
⇒負けた。第三位 orz
本作品は メカ部、画像解析部、制御部 の3部構成です.以下各部を順に説明していきます。
上の写真の様に、縦横にステッピングモータで自由に動く台を作り、その上に珠を弾くため爪を付けた構造になっています。(3DプリンタやCNC(数値制御工作機械) 等と同様の仕組みです。)
爪は、台が移動中に他の珠に接触しないように、サーボモータで上下させて(というより傾けて)います。
ステッピングモータはサーボモータと違い、電源投入時に今の位置が判らないので、原点調整の為にと可動範囲外まで動いてメカを壊してしまわないようにする為、リミット検知スイッチを付け接触すると止まるように制御しています。
構成部品は、殆どを 3Dプリント部品で構成しています。(精度の悪さにちょっと後悔)
制御コンピュータは、毎度おなじみの M5Stack (GRAY) を使用しました。 リミットスイッチ4つ分の入力と、ステッピングモータの制御線出力2×2本、サーボの制御線1本を接続しています。 ステッピングモーターは 12V 駆動なので、3Dプリンタ等でよく使われているモータドライバー A4988 を使用しました。
基本的な機能としては、通知されるコマンドの解釈、モーターの制御、演算の実行となります。
実質 XYZ-3軸制御構造なので、制御は 3Dプリンタと酷似したものとなっており、3Dプリンタで使用されるプロトコルである Gコード を使用しました。 Gコードとは位置制御が必要な機械を動かす為のプロトコルで、基本的には動かす軸、各軸の移動距離と移動速度を指示してその通り動かすというものです。 3Dプリンタは大量のGコードを順次シーケンシャルに実行することで実現されています。
制御部からは、現在の画像認識数値、演算命令、リセット命令等コマンドが指示されますが、これを全て複数の Gコードに変換・展開して実行する仕組みを組み込んでいます。
制御部から来る、画像認識数値、演算命令、リセット命令等のコマンドプロトコルを解釈し、それによりモーター制御部や演算処理部に指示する機能です。 コマンドプロトコルは、自前で作ったシンプルなものです。 シリアルで指示されたコマンドや、変換後の Gコードは、 M5Stack 側の LCDモニタに表示してデバッグしています。
ステッピングモータは、細かい制御をしたかったので、割り込みを使って自前で実装しています。 脱調しないように、ゆっくり動かし始めて加速し、目標に近づくと減速して徐々に止まるように制御するためです。 サーボモータは、ESP32 でよく使われる LEDC のライブラリの機能で実装しています。
コマンド解釈部から計算が指示されたら、全桁に対して順次演算値を計算していきます。 画像解析部から制御部経由で通知された数値により各桁の現在の値が判っているので、その現在の値に対して計算を行っていきます。 計算結果により、繰り上がりや繰り下がりが発生した場合は隣の桁を計算し、そこでさらに発生した場合はさらに隣の桁を計算するというのを繰り返し行って計算します。 全桁の計算が終わったら終了となります。
現状、足し算と引き算のみできます。 掛け算と割り算については、自分があまり理解できていない為か、バグが多発し今回は断念しました。 将来の課題とします。(というか、桁数足りないかも、ハードの作り直しが必要か?)
画像解析はそれだけでかなりの CPUパワーを使ってしまうことを想定されたため、モーター制御とは別のコンピューターで実行することにしました。
画像解析は、元々ラズパイベースで Python+ OpenCV + テンプレートマッチ 等、色々試してみましたがいまいちだったので、それより認識率が高く高速だった、「SPRESENSE を使ったニューラルネットワークによる機械学習での数値認識」の仕組みを使用しました。
まず、構成は写真の通りです。写真は左半分が上から撮った写真、右半分が下からとった写真です。 カメラは下向きに、そろばんを上から撮影する方向で設置しています。
3Dプリンタで作った SPRESENSE 基板取り付けフレームを、白のワイヤーフレームを結束バンドで止めた台に結わえ付けています。 (余談ですが、ワイヤーフレームを結束バンドで止めたボックス、昔からよく使いますが安定してて便利です)
「そろばん撮影用カメラ」とあるのが SPRESENSE に直接接続されたカメラで、画像認識はこのカメラを使って実行しています。 「動作デモ動画撮影用カメラ」は、作品投稿用の動画を撮影するための Webカメラで PC に接続して使っています。(システムとしては不要ですがデモ動画の為です。)
SPRESENSE 本体には「デバッグ+位置調整用 LCD モニタ」を接続しています。 このモニターには、現在のカメラの入力と数値の認識結果を、リアルタイムに常時表示しています。 カメラの固定位置調整用にも使用します。
画像解析のみを繰り返し実行しそろばんの今の数値を全桁認識させ、その数値をシリアルで制御部(PCアプリ)に送信し続けるのが、基本的な機能となります。 毎回送ると通信量が多くなってシステムが重くなるので、前回の認識結果から変化があったときのみ送るようにしています。
そろばんの位置は自動で走査して認識させるようにすると、処理が重くなるのとプログラムが複雑化するので、今回はカメラ側の位置を合わせこむ方式としました。
「デバッグ+位置調整用 LCD モニタ」の表示された赤枠にそろばんの外枠が収まるように、カメラ台(ワイヤーフレーム)側を調整します。その後すべての緑枠が1桁分の珠を囲むように微調整します。
それ以外の機能として、画像の転送要求を受信したときに現在の撮影写真を転送する機能があります。 これは、Twitter 投稿時に画像を添付するために使用されています。 PCアプリ側が計算結果を受信したタイミングで、転送要求を通知してくるので、それに応答します。 フルカラーだと時間がかかるので、グレイスケールに変換してから Base64 へエンコードしてシリアルで転送し、制御側でデコード復元しています。
SONY さんが用意してくれている手書き数字の画像認識のサンプルをベースに、手書き文字サンプル画像を全て SPRESENSE で撮影したそろばんの1桁分の画像に置き換えて、再学習させました。 下記写真の通り千枚近い画像データを学習させています。
学習した結果以下のようになり、
スコアもかなり高い結果となりました。
そして、実際使う SPRESENSE カメラで同じアングルで撮った同じ被写体の写真を使っている為、かなりの認識率になりました。調整枠からずれない限りめったに誤認識はしませんでした。
SPRESENSE と M5Stack を連携させるため、そして UI 部分を実装するため、今回は Windows PC 上で専用アプリを作成しました。
そして UI や ネット関連のインタフェースの役割も担っている
下の写真の様なソフトです。
単なる Windows10 PC です。
SPRESENSE や M5Stack とは USBシリアルにて接続し、シリアルでデータを送受信することで連携しています。 もちろんネットにもつながっています。
計算式をアプリのキーパッドで入力したら、その内容を M5Stack に シリアルコマンドで伝えています。 そして、SPRESSENSE から数値の通知があったら、ディスプレイに反映するとともに、 M5Stack 側に転送して状態を同期しています。(計算中には赤文字表示となっています。) M5Stack は アプリからのコマンドをもとに、計算を行い結果が出たら応答してきます。 その応答内容を、アプリの表示に反映し(緑色で表示します)
M5Stack 側から結果が届いたら、同時に Tweet の準備を始めます。
まずは投稿用の画像を SPRESENSE 側にシリアルコマンドで要求します。 SPRESENSE 側はコマンドを認識したら、Base64 形式に変換してシリアルでデータを送ってきます。 アプリ側ですべての画像データがそろったことが確認出来たら、
以下の写真の様に投稿します。
Microsoft Azure Cognitive Service の Speech 機能を使って、ネット経由で音声をテキストに変換します。 変換したテキストが数式の条件を満たしていたら、その内容を M5Stack にシリアルコマンドで伝えます。 計算には少し時間が掛かるので、M5Stack からの応答待ちを始めたら「計算するからちょっと待ってな」と AITalk にしゃべらせています。 この、「計算するからちょっと待ってな」の様な固定音声はあらかじめダウンロードした WAV ファイルを使用しました。 M5Stack から応答があったら、その内容をテキストにして、AITalk に要求をかけ、音声に変換してもらいます。 Web API に HTTP GET で要求したら、返信ボディーに WAV ファイルが載ってくるので、それを再生しています。
他にも、制御アプリ側には様々なデバッグ機能を埋め込んでいます。
シリアルラインにどんなデータが流れているとか、アプリログとかや
各機能のテスト用モジュールや、珠の位置テーブルを作ったりモータを動かしてテストするためのモジュール
等です。