ESPboyというオープンソースの携帯ゲーム機を日本用に再設計してみた

ESPboyとは

ESPboy

ESPboyはESP8266をコアとする携帯ゲーム機です。

オープンソースハードウェアとして開発が進められており、回路図を参照することで誰でも同じ仕様のESPboyを作ることが出来ます。

また完成済みの製品も販売されています。 (後述しますが、これらの製品は日本で利用するには問題があります

こちらは初代バージョンで$75です。 www.tindie.com

こちらは改良版で$95です。筐体が違うだけで中の回路は論理的に等価です。 www.tindie.com

ESPboyで遊べるゲームは、いくつかに分類することが出来ます

まずはインディーズ携帯ゲーム機であるArduboyPokittoGamebuino METAなどのゲームです。 あまり耳なじみがないかもしれませんが、これらは最近この界隈では有名な(?)携帯ゲーム機です。

これらのゲームはバイナリ互換というわけではなく、ESPboy用に移植された各ゲーム機のSDKがあるので、それを使って再コンパイルしたものが遊べます。ゲームによってはハードウェア固有の機能を活用しているものもあり、そういったゲームはそのまま移植することが出来ない点に注意が必要です。

もう一つは、レトロゲーム機、パソコン用のゲームです

ZX spectrum 48k, GameBoy, Chip8/Schipのエミュレータが動作し、それらのプラットフォームで動くゲームを遊ぶことが出来ます。

最後が、ESPboy専用に作られたゲームです。

まだ数は少ないですがESPboyの性能をフルに活用したゲームを遊ぶことが出来ます。 もちろんゲーム開発用のSDKオープンソースなので、ゲームを自作することもできます。

後述するWeb App Storeの画面からもいくつかのゲームのスクリーンショットを見ることが出来ます。

なぜ自作したのか?

まぁ、そこに回路図があったからだ!というのも大きいのですが、一番の理由は「販売されているESPboyを日本で使うことが出来ない」からです。

どういうことかというと、販売されているESPboyに搭載されているESP8266のモジュールに技適がついていないのです。

もちろん特例申請を使ったりすることで、一時的に日本で使うことはできそうですが、そういったものを人に勧めることも難しく、いまいち購入する気にはなりませんでした。

しかしESP8266を使ったモジュールの中には技適のついた、日本でも利用できる「ESP-WROOM-02」というモジュールが存在します。ESP8266というコアのICは同じなので、うまく設計すれば、技適ありのESPboyが作れるのでは? と思いついたのが自作を始めたきっかけです。

回路図を作る

まぁこういう時はブレッドボードから、作るのが鉄則なのですが、最近は基板づくりも安くできるようになっているので、いきなり基板を発注してみることにしました。

まずは論理回路図を設計します。

と言ってもESPboyはオープンソースハードウェアなので、本家の設計を参考にすることが出来ます。

大まかな構成図は公式ページの下の方に掲載されています。

espboy.comから転載

さらに詳しい回路図はこちらのページにあります。

ESPboy_v4.3 - EasyEDA open source hardware lab

この回路図にはLOLIN-ESP8266というモジュールが存在しており、今回はこのモジュールが使えないのでこの中身も知りたいところです。

その回路図はここで見つけました。 LOLIN D1 mini — WEMOS documentation

このモジュールはESP8266を搭載し、USB端子からシリアル接続でArduinoとして書き込みができるというものです。

LOLIN-ESP8266と同等の機能を持ったESP-WROOM-02を搭載したモジュールとしては ESPr® Developer(ESP-WROOM-02開発ボード) - スイッチサイエンス がよさそうですが、今回は回路図もあるので、このモジュールの部分も自作基板に含めることにしました。

こうして出来上がったのがこの回路図です。

(元のESPboyのライセンスに従って CERN Open Hardware License とします) (このライセンスは本当は、さらに細かい区分があるようなので、ESPboyではどれに該当するのか聞いています・・)

USBシリアル変換はCH340G、自動リセット回路などに2回路入りトランジスタUMH3Nを利用しています。

LiPoバッテリーの充電に関しては、自分で実装せずに出来合いのモジュールを使うことにします。

部品の購入

大半の部品は秋月電子で購入しました。コアのモジュールであるESP8266、DACであるMCP4725や、I/OエキスパンダのMCP23017/SP、フルカラーLEDのWS2812Bなども秋月電子で扱っていました。

USB Micro端子、AP1117-3.3、UMH3N、TFT液晶、ボリューム、タクトスイッチ、スピーカー、LiPoバッテリー充電モジュールなどは、日本でも購入できるかもしれませんが、AliExpressで購入しました。

液晶モジュールはESPboyと同じものを利用しないと、初期化コードなどが異なりバイナリ互換がなくなってしまうので注意が必要です。

配線図の作成

ちょちょいのちょいで・・・とはいかず、色々と試行錯誤しました。 ESP-WROOM-02のアンテナ部分には配線を通していけないようなので、Keep Outゾーンとしました。

基板の発注

今回の基板はALLPCBに発注しました。というか発注したのは去年の12月ごろです。 そしてあれから半年程度、この基板は積まれていたのです・・・ いや、子育てとかいろいろ忙しくてですね・・(言い訳)

送料込みでこんなお値段。

部品の実装

この基板は表面実装部品ばかりで構成したので、実装も少し苦労しました。

ピッチの狭いICであるUMH3NやMCP3725も6ピンのパッケージで真ん中、左右の順に足を固定すれば手はんだでも実装できました。

一番気を遣ったのはMicro USB端子です、これはホットエアーガンを使って実装しました。(まぁHACHIBARで何度も実装したのでコツはなんとなくつかんでいました)

書き込みテスト

ESPboyはソフトウェアのデプロイ周りも充実しています。

まずはWebブラウザから書き込みできる Web App Storeというものがあります。ブラウザからゲームを選んで、書き込みボタンを押すだけでESPboyにゲームをインストールできます。

もう一つはWiFi経由でアプリをダウンロードできるApp Storeです。これはゲーム機同時にBボタンを押しっぱなしにすることで起動します。初期設定はWiFiSSIDやパスワードの入力が必要ですが、一度設定すると記憶されます。 一度設定するとインターネット上のAppStoreサーバからゲームの一覧を取得でき、そこからゲームをインストールすることが出来ます。まるでiPhoneAndroidのようです!(大げさ)

ケースの作成

ここまでで、一応動くゲーム機にはなりましたが、基板がむき出しで遊びづらいです。

ということで3Dプリンタでケースを作ります。

今回はFreeCADで設計しました。

(ディスプレイ固定具用のデータがあったのですが、保存せずに終了して失われてしまいました・・無念)

我が家には3Dプリンタがあるので、精度はともかく、ササっとプロトタイピングが出来て良いです。

ということでひとまず、そこそこ遊べるESPboy端末が出来ました。

まとめ

ということで、日本でも利用できるESPboyを作ることが出来ました。

基板製造、3Dプリント、AliExpressでの部品発注、ESP8266でのプログラミングなど、ここまでで得た知識を組み合わせることで、一つの製品を設計、開発できました。

オープンソースハードウェアを参考に、少し自分用に手を加えて自分のオリジナルのガジェットを作るというのは、非常に面白いので、腕の覚えのある方はぜひ挑戦してみてください。

また、ここで作った基板が数枚余っていますので、もしほしい人がいたら連絡ください。 (可能なら、ボツ基板交換的なノリで、何か自作の面白い基板と交換してもらえると嬉しいです。 私が提供できるボツ基板はこちらにまとめています。

かんたんUSBホストを試してみた

かんたんUSBホストとは

文字通り簡単にUSBホスト機能を実現するためのモジュールです。

かんたんUSBホスト、サポートページから抜粋

ArduinoなどのマイコンボードでUSBホスト(USB機器に対する「親」)を実現するためには、ちょっと工夫が必要です。

よく目にするのはUSB Host Shieldを使う作例です。

USB Host Shieldは汎用的なUSBホストを実現するためのモジュールで、様々な用途で利用できる反面、使い方が簡単とは言えません。

一方で今回紹介する「かんたんUSBホスト」はUSB接続のキーボードの制御に特化することで非常に簡単に利用できるのが特徴です。

(かんたんUSBホストの作者さんとは、知り合いで、実は以前に「かんたんUSBホスト」を頂いたのです。と言っても1年以上前のことで、折角頂いたのに「積み基板」となってしまっておりました・・、積んではいかんですね、ほかにも結構積んでいるので順番に試食していこうと思います。)

使い方

かんたんUSBホストは様々なオプションがあり、細かく制御することもできますが、まずはじめとしては、一番簡単な方法を見てみましょう。

GNDとVCCとVBUS、TX→RXの4つの配線をするだけです。

かんたんUSBホスト説明書より抜粋

これでArduinoのシリアル入力として簡単USBホストを利用することができます。

Arduinoは書き込みにシリアル入力を利用するので、Arduinoを書き込む際はTX→RXの配線を一時的に抜く必要があることに注意してください。 (SoftwareSerialなどでArduinoのハードウェアシリアルとは違うピンを利用してかんたんUSBホストと接続することで、この問題は解消できます。)

あとは簡単USBホストにキーボードを接続し9600bpsでシリアルポートを読み取れば、押したキーのキーコードが取得できます。

簡易ワープロを作ってみる

さて、実際の動作を試しがてら、ちょっとした作品を作ってみましょう。

作ったのはキーボードから入力した文字をディスプレイに表示する、というまぁ、これだけなんですが、いうなれば「簡易ワープロ」です。

ディスプレイとして利用するのは、たまたま家にあった、ちょっと大きめのOLEDです。

大きさの割には解像度は128x64とかわいらしく、ノスタルジックな見た目となっています。

このOLEDの制御は定番のu8g2ライブラリを利用します。

ソースコードはこんな感じです。

ほとんどがOLEDの制御コードで、かんたんUSBホストの制御は初期化と、キーの読み取りの部分だけです。

「簡易」という事で本当に最低限の動きしかしませんが、それでもここまで簡単にワープロもどきが作れるのは楽しいです。

かんたん 以外に出来る事

ここまで紹介してきたように、かんたんUSBホストは、かんたんにUSB接続のキーボード入力を得ることができますが、ほかにも様々な機能があります。

説明書から少しかいつまんで紹介すると・・

  • キー配列をJIS、USで切り替える
  • CapsLockなどを設定する
  • キーリピートの間隔を調節する
  • 特定キーの組み合わせに反応する
  • シリアル接続のボーレートの変更

他にも、制御とは関係ないところで以下のような機能も搭載しています

  • USB Hub経由でのキーボードの接続
  • 動作中のキーボードの抜き差しへの対応
  • キーリピート

USB Host Shieldとの違い

USB Host Shieldはキーボードに特化していないため、キーボード固有の処理はArduino側で実装する必要があります。CapsLockやNumLock, キーコードとASCIIコードとの変換、キーリピートの処理、などなど、実装コストも大きくなるし、Arduinoの限られたメモリを消費します。

また巷に出回っているMini USB Host Shieldはちょっと癖のある基板で、5VのArdunoで利用するためには謎の改造をする必要があったりと、使い勝手も悪いです。

そもそもUSB Host ShieldのコアとなっているMAX3421Eは、かんたんUSBホストのコアとなっているCH559と比べ高額なので、自然とそれを採用したボードの価格も高くなってしまいます。

などなど、これらの理由により、USB接続のキーボードをArduinoから利用する場合はかんたんUSBホストに軍配が上がりそうです。

一方でゲームコントローラや、Bluetoothドングル、USB-MIDIなど、キーボード以外のUSB機器を利用する場面ではUSB Host Shieldが適していることもあると思います。(CH559でもこれらに対応したファームウェアを作れば安価に対応できそうですが、作例もなく、いばらの道のように思います)

中身について

このかんたんUSBホストですが、コアとなるマイコンがCH559という、中国製のICです。

USB Host、Deviceの機能を持つ汎用マイコンにもかかわらず、比較的安価ですが、昨今の半導体不足の影響をあまり受けず、現在も簡単に入手できます。

最近半導体部不足が深刻になっており、様々な汎用ICの在庫がなくなる中、でこれらの中国製のICはアマチュア電子工作愛好家の間で、にわかに脚光を浴びています。

そんなトレンドに興味のあるMakerにとってもこのモジュールは魅力的だと思います。

かんたんUSBホストの作者の方が、CH559に関する開発周りの知見を惜しげもなく公開されており、こちらの資料も必見です。

q61.org

まとめ

かんたんUSBホストは、Arduinoでキーボード入力をサポートしたいときには非常に有用なモジュールです。

USB、キーボード周りの面倒な処理のほとんどをこのモジュールが処理してくれるため、Arduino側に余計な実装をする必要がなく、省メモリ、省実装コストを実現できます。

気になった方はスイッチサイエンス、BOOTHなどで購入できます。(同人ハードウェアの為、在庫はそんなにないかもしれません、気になったときが買い時ですよ!)

www.switch-science.com q61.booth.pm

JLCPCBに3Dプリントを発注してみた

※この記事はJLCPCBの提供でお送りします。

JLCPCBとは

jlcpcb.com

(↑こちらは日本語版のログインページで、お得なクーポンも配布されています。)

JLCPCBとは、プリント基板製造などで有名な中国の企業です。

日本からでもWebページでポチポチするだけでKiCADなどで作成した基板データの製造を依頼できます。

値段もかなりお手頃で、ホビー電子工作ユーザーの間では広く利用されています。

そんなJLCPCBですが、最近「3Dプリントサービス」を始めたようです。

ということで、今回はこの3Dプリントサービスがどんなものなのかを、実際の私の発注を例に紹介しようと思います。

今回発注するデータ

私は家に3Dプリンタを持っているので、これまでに多くの3Dプリンタ用のデータを作成してきました。

今回も、JLCPCBに3Dプリントを発注するにあたり、今まで作ってきた実績のある以下の2種類のデータを使うことにしました。

3Dプリンタの難しいところの一つに3Dプリントに適した設計というのがありますが、今回で言うと、この難しいところは過去の自分が頑張ってくれていたので、スキップすることが出来ました。

一度データを作ってしまうと、こうやって何度も作成できるのが、手作業による加工と違い、3Dプリントなど機械加工の便利なところです。

発注について

早速発注方法です。JLCPCBのユーザ登録は済ませているものとして、Web上での中も方法を少し紹介します。

と言っても、本当にデータをアップロードするだけで、特に難しいところは無いのですが・・

Webサービスの文字も中国の会社ですが英語で記載されており特に戸惑うところはありません。

注文データの登録

まず初めに、3DプリントではおなじみのSTLファイルを、注文ページからアップロードすると次のような画面が現れます。

ここで素材と、個数と説明を書くだけです。

素材は様々な樹脂や金属から選ぶことができますが、今回は安価なSLA(Resin)を選択しました。

さらにその中にも3種類の素材がありますが、これらの違いは微妙そうなので、大きな水切り棚については、一番安い9000R Resinを選択しました。

金額はほぼ体積で決まるようで、この水切り棚は$16.49でした。(体積は送料にも響いてくるので、注意が必要です)

Product Descというところにはそれが何かを説明する箇所です。今回は「Kitchen tool」としておきました。

次にRakuChordのパーツです。水切り棚に比べて体積の小さなパーツのみなので、非常に安価です。 最も小さなネジのパーツはたったの$1.0でした。

試しに同じSLA(Resin)の中の違う素材を選択してみました。

送料について

そして、次に送料の確認です。

非常に時間がかかるが安いもの、早いが高いもの、などいろいろありますが、今回は早くて若干高いDHLを選択しました。

というのも、普段AliExpressなどで安い運送業者を使うと、本当に雑に梱包されて届いたり、届くのに1か月かかったり、破損していたりと、様々なトラブルを経験したことがあるからです。

今回の送料はDHLだと $27.63でした。 (最安だとEconomical Global Direct Lineの $9.77というのがありました)

つくるモノが大きいと送料もそれだけ大きくなるので、いくら製造コストが安くても送料で損をしてしまうケースもあるだろうなと感じました。

レビューについて

3Dプリントをやったことがある人なら、形状によっては3Dプリントが難しいことを知っているかと思います。

という事でJLCPCBでは人手による(?)レビュープロセスが存在します。登録した注文データをOrderすると、支払い前にレビュープロセスで少し待たされます。

自分の場合は翌日にはレビューが完了していました。

一部の部品に非常に薄い箇所があり、この箇所は正しく出ないかもしれない、という警告が出ましたが、今回はそのまま進めてくれ(下の図で言うYES)を選択しました。

待つ

発注してから待つこと、、6日、DHLで我が家に造形物が届きました。

自分で設計したオリジナルの造形物が6日で届くというのは、個人的には「早いな」という感覚でした。

出来栄えについて(水切り棚)

今まで家庭用(?)の積層式の3Dプリンタしか扱ってこなかった自分にとって、光造形式の出力は非常に印象的でした。

積層痕もほとんど目立たず、中身もずっしりと樹脂が詰まっており、「これ、製品では?」と思うような質感でした。

レジンは白色の物しか選べないのですが、この無骨な白色が水切り棚という台所用品ともマッチしていて、無印あたりで売っていそうな雰囲気を感じさせます。

水切り棚については、単純な形状で、とても3Dプリンタにやさしい設計となっているため、造形の不具合なども全く見つかりませんでした。

また寸法もすでに家にある3Dプリンターで作ったもので合わせてあるため、即台所で使い始めることが出来ました。

比較相手としては全く適切ではないかもしれませんが、我が家の3Dプリンター(積層式)で作ったものとの比較です。

出来栄えについて(RakuChord)

こちらも家にある積層式の3Dプリンタで出力したことのあるデータだったのですが、水切り棚と比べると複雑な形状で、薄い部分も多く、3Dプリンタ的には難易度の高い造形でした。

案の定、薄く角がとがっている部分は少し反って出力されており、やっぱりプロがやってもこういうことがあるんだな、と感じました。

まぁ私の用途では許容範囲の反りですが、やはりデータ通りに作るというのは、難しいところがあるようです。

オーバーハングの個所が一部ありましたが、家の3Dプリンタでも出力できる程度の小さなものだったこともあり、特に問題なく出力されていました。

RakuChordは3Dプリンタ製のネジで電池ボックスを固定するのですが、このネジについても、特に問題なく噛み合い、固定することが出来ました。

出来栄えについて(まとめ)

もともと3Dプリンタで出力するように考慮して設計し、実際にも出力したことがあるデータだったため、大きなトラブルなく完成しましたが、手元に3Dプリンタがない状態で設計していきなり発注するのはちょっと難しいかも、と感じました。

水切り棚のような単純な造形物であれば、それも可能ですが、RakuChordのような複雑な形状の場合は、手元で実際に何度も作りながら造形をブラッシュアップしていく必要があるため、手元の3Dプリンタが必要だと感じました。

また、RakuChordの部品の各所で反りが発生しているのを確認しました。これは3Dプリンタあるあるなので、やはりか・・という感じですが、底面で鋭角の出っ張りを作るのを極力避けるか、側面が多少反っても問題ない設計にするなど、割り切りが必要だと感じました。

細かい部分では、発注した3Dデータそのまま、というわけにはいきませんでしたが、家にある積層式3Dプリンタで出力するよりは明らかにそれっぽい造形なので、ここぞ!という時に発注するのが良いかなと感じています。

安価な素材であるSLA(Resin)は乳白色しかないので、この色が許容できない人は、利用が厳しいかもしれないと感じました。

試していないですが、これに塗装するなど、ひと手間かければこの問題は解決できそうです。

3Dプリント以外のケース外注の選択肢

平面的な造形であれば、3Dプリントではなく、PCBを基板をケースとして設計する方法もあり、こちらの方が安価です。 (いわゆる基板サンドイッチ方式、パリピデストロイヤーなどがこの方式です)

またレーザーカットなども外注できるサービスがあるので、透明なアクリル板やある程度厚みのある板をカットする場合にはこれらも選択肢に入れると、安くで作ることができるかもしれません。

実際RakuChordの部品の一部はレーザーカットを外注しており、これは3Dプリントで同じものを外注するより安いうえに、精度が良いです。

一方RakuChordの筐体や、水切り棚のように3次元的な造形や、非常に分厚い造形については3Dプリンタや自由度の高いCNCでないと作ることができません。

まぁ、何が優れている、と言うよりは、適材適所の加工方法があるという事です。

まとめ

初めての3Dプリントの発注でしたが、思っていたより安く、品質も値段の割には良かったと感じています。

Webでの発注も非常に簡単で、気軽に利用できると感じました。

ただ、やはり家に3Dプリンタがあり、手元で一度試作をしたデータを発注するのが、時間面、金銭面においては賢い選択かなと思いました。

とにかく小さな造形物であれば数千円あれば発注できるので、興味のある人は、手元のデータを発注してみて、実物を見てみると良いと思います。

ホワイトボードの買い物リストを外から見えるようにする

ホワイトボードの買い物リスト?

我が家では台所にホワイトボードを設置しており、そこに「買い物リスト」を書いています。

(以前はLINEのチャットボットを使い、スマートフォンで買い物リストを管理していたのですが、在宅勤務中心となったためホワイトボードに移行しました。)

買い物に行くときは、スマートフォンでパシャッと、このホワイトボードのリストを撮影します。

しかし、何かのついでにふらっとスーパーに寄ったときなど、家の買い物リストに何が書かれていたかを知ることができず、必要な買い物ができない場合があります。

また、出かけるたびにホワイトボードをスマートフォンで撮影するのも面倒です。

ということで、「出先からホワイトボードを確認するための仕組み」を作ることにしました。

外から安全にホワイトボードを見たい

安直に考えれば、ホワイトボードが映るようにカメラを設置し、Webサーバか何かを外部に公開して、家の外から見えるようにするのが簡単です。

しかし、家にWebサーバを立てて外からアクセスできるようにするのは、我が家のセキュリティを強固に保つために、できればやりたくありません。

ということで、家にWebサーバを立てる案は却下です。

材料

さて、ここからはこの手法を実現するための材料を紹介します。

Google Drive

家にWebサーバを立てないということで、今回利用したのはGoogle Driveです。

ホワイトボードを撮影するカメラが撮影した画像を定期的にGoogle Driveにアップロードします。

これにより我が家のセキュリティを強固に保ったままホワイトボードの写真を外から見ることができるようになります。

TTGO T-Camera

写真の撮影はTTGO T-Cameraを利用します。

これはESP32-WROVER-Bとカメラモジュールの付いた、WiFiカメラを作るためのモジュールです。

似たようなボードは各種ありますが、今回利用するのは技適を取得しているESP32-WROVER-Bが搭載されたボードです。

(多分これかな? 自分はAliExpressで買いました)

Raspberry Pi 3

TTGO T-Cameraで撮影した映像をRaspberry Piから取得し、Google Driveにアップロードします。

もしかしたらTTGO T-CameraだけでもGoogle Driveにアップロードできるかもしれませんが、今回は簡単のためにRaspberry Piを利用しました。

丁度、我が家には「おうちサイネージ」として動かしているRaspberry Piがあるのでこれを利用することにしました。

inajob.hatenablog.jp

調理

さて、これらの材料を組み合わせてシステムを完成させていきます。

概要

これから構築するシステムの概要です。

TTGO T-Cameraで撮影した映像をRaspberry Piで定期的に取得し、Google Driveにアップロードします。

TTGO T-Cameraのファームウェアを我が家用に変更

TTGO T-CameraをWebカメラとして動作させるためには以下のソースコードを利用しました。 (というか購入時はこのファームウェアが入っていたようです)

github.com

WiFiのAPの設定を修正し家のWiFiに接続できるように再コンパイルして書き込みます。

起動すると画面にIPアドレスが表示されるので、そこにアクセスするとカメラの映像を確認できます。

我が家のルーターと相性が悪いのか、長く起動しているとWiFiの接続が切れてしまう問題が発生しました。

以下の記事を参考にし、WiFi接続が切れた時は自動的に再接続するようにしました。

randomnerdtutorials.com

TTGO T-Cameraを固定するための台

台所の壁に設置したホワイトボードを撮影するためには、TTGO T-Cameraを良い角度で固定する必要があります。

このためのカメラの脚を3Dプリンタで自作しました。

FreeCADを使ってこのような立体を作りました。

このパーツは2つくっつけるとこのようにL字型の蝶番のようになります。

TTGO T-Cameraのケース(写真に写る紫のケース)は 以下のモデルを使いました。

www.thingiverse.com

Raspberry Piにアップロード用スクリプトを仕込む

定期的にTTGO T-Cameraから画像を取得しGoogle Driveにアップロードするスクリプトを用意します。

Google Driveへのアップロードにはrcloneを利用します。

rcloneの初期設定はCLIのウィザードで実施することができます。CLIENT_ID, CLIENT_SECRETを設定するのがちょっと面倒だったのですが、設定しなくても一応動かすことはできます。(ただし共用のIDを使うことになりすぐに制限に引っかかってしまうので、常用するのには向きません)

スクリプトは以下のような感じです。

(convertコマンドにより画像を反転したり、日付を入れたり、過去にアップロードした画像を削除したりもしています。)

#/bin/bash

cd `dirname $0`

curl http://<TTGO T-CameraのIPアドレス>/capture -o todo.jpg
convert todo.jpg -rotate 180 -fill white -pointsize 25 -font Helvetica -draw "text 20,20 '`date`'" -background white todo.jpg

for f in $(rclone lsf "google drive:/ouchi-raspberry-pi/"); do
  echo "delete $f"
  rclone delete "google drive:/ouchi-raspberry-pi/$f"
done;

rclone copyto todo.jpg "google drive:/ouchi-raspberry-pi/todo-$(date "+%Y%m%d-%H%M").jpg"

同じ名前のファイルをどんどん上書きしても良いのですが、iPhoneGoogle Driveのアプリのキャッシュの処理などにより、画像が更新されないという問題が起きたので、日時に合わせて画像ファイル名を変更するようにしました。

Google Driveの共有設定

このようにしてアップロードした写真は、Google Driveの共有機能を利用すると他人と共有することもできます。

我が家でも妻と写真を共有し、夫婦どちらでも家の買い物リストを出先から見られるようにしました。

まとめ

TTGO T-Camera, Rasperry Pi, 3DプリンターなどIoT的な装置をフルに使ってホワイトボードの画像を外から見るためのソリューションを作ることが出来ました。

これでまた生活が便利になりました! 自分の知識を使って、生活を便利にするのは楽しいので、この記事をご覧の方もぜひ挑戦してみてください!

貧者のUSBケーブルチェッカーをセルフパワー化するケースを設計する

先に完成品の紹介

USBケーブルにイライラしたことはありませんか?

というのも市販の製品に同梱されているケーブルの中には、充電のみに対応しているものが結構多くあります。

データ通信に使いたい場面で、この充電のみに対応したケーブルを使っていると、当然通信できず、イライラすることとなります。

という事で、家にあるケーブルが充電のみに対応したものなのか、データ通信もできるのかを調べたくなります。

という事で作ったのがこちらです!↓

貧者のUSBケーブルチェッカーとは

USBケーブルチェッカーと言えばこの製品が非常に有名です。 (便宜上こちらは富者のUSBケーブルチェッカー、と呼んでいます)

この商品を買えば間違いはないのですが、自分の場合は、そこまで細かいスペックを知りたいわけではなく、単に「データ線が結線されていないUSBケーブルか否か」だけがわかれば良いという要件であることに気付きました。

となれば、単に指定したピンが両端のコネクタで結線しているかだけを見ればよいので、もっとシンプルな回路でチェックできそうです。

この観点でインターネットを探してみると・・ ズバリな商品がありました。

ja.aliexpress.com

ということで、早速これを購入してみました。

今回はこの基板の電源付きケースを設計した話です。

「この基板」では味気が無いので、私はこれを「貧者のUSBケーブルチェッカー」と呼ぶことにします。

セルフパワー化

この基板は外からUSBケーブルで電源を得るように設計されています。

そのため、テストしたいケーブルの両端に加えて、外部電源用のケーブルを接続する必要があり、利用する際にケーブルだらけとなってしまい煩雑だと感じました。

そこで基板にCR2032を取り付け直接電源を供給できるようにしました。

CR2032は3Vなので、USB電源とは電圧が違いますが、チェック用のLEDを光らせることが出来ることを確認できたので、結果オーライという事でそのまま結線しています。

基板上にテスト用のパッドが露出していたので、そこに導線をはんだ付けしました。

今回CR2032ホルダーも3Dプリンタで作ってみました。と言っても「口」の形で導線を通す穴を2つ開けただけの簡単なものです。

ここで紹介する設計手法について

私も3Dプリンター向けのデータをどうやって作るかを、まだ模索している段階なのですが、今回のやり方を文書化することで、新たな発見があるかも・・と思い記事にしてることにしました。

さらに良い方法があるよ、という方は是非教えてください。

利用するツール

今回は以下のソフトウェアを使って設計を行います

設計手法の紹介

ではここから具体的な設計方法について紹介します。

LibreCADで基板の部品を書き写す

基板上のでっぱりのあるコネクタのサイズなどを測定し、LibreCADで作図をします。やはりこういう作図はマウスが利用できるGUIのツールが便利です。 (ここは行き当たりばったりでやってたのでレイヤー名とか雑ですね・・)

作図補助レイヤーで垂直・水平のガイドを作図し、でっぱり部分をレイヤーで作図します。 (図で緑色と黄色の線が作図補助のための直線です。)

基板外形、でっぱりの高さが異なる部分は別のレイヤーにします。

OpenSCADではDXFファイルのレイヤーを指定してインポートできるので、便利です。

OpenSCADで作図する

今回はBOSL2というライブラリを使います。

このライブラリは、立体物にアンカーを設定して、そこに他の図形をアタッチする形で立体物を作成する機能を提供してくれます。

DXFファイルからレイヤーを指定して読み込む場合には以下のように書きます。

import (file = "board.dxf", layer = "rect-board");

論理演算で穴をあけるための造形物は以下のように書きます。(モジュール化もしています)

module hole()
  linear_extrude(height=3)
    import (file = "board.dxf", layer = "hole");
module hole2()
  linear_extrude(height=7)
    import (file = "board.dxf", layer = "hole2");

ケースの上部分はこのように書きます。

baseW = 57;  // 基板外形 幅
baseL = 46;  // 基板外形 奥行き
boardThickness = 1.6; // 基板厚
baseThickness = 2; // 底厚
baseSideThickness = 5; // 横壁厚
topH = 8; //ケース高さ

render() // ちらつき防止
diff("cut") // cutというtagの図形を切り抜く
yrot(180) // y軸中心に180度回転させる
cube([baseW, baseL, topH], anchor=[0,0,1]){ // 底面にアンカーを設定したケース外形の直方体を作成
  force_tags("cut"){ // 切り抜く部分をグループ化
    position([-1, -1, -1]){ // ケース外形の左-手前-下を原点とする
      hole();  // 基板上のでっぱりを引き算する(高さ別に4つのデータが存在)
      hole2();
      hole3();
      hole4();
      union(){ // バッテリー収納部を作図する(ここはLibreCADで作っていない)
        translate([44,22,0]) // 位置合わせ
        linear_extrude(height=topH - 1){ // バッテリー部分の壁厚は1mm
          circle(r = 10+1); // CR2032の半径=10mm+マージン1mmの円
          rotate([0,0,-90]) square([22+4, 14], center = true); // バッテリスナップ収納の為の矩形
        }
        translate([33,30,0]) // 位置合わせ
        linear_extrude(height=2) // 配線用のスペースを作図する(ここはLibreCADで作っていない)
          square([10,10]);
      }
    }
    // スナップフィットジョイントの作図
    xflip_copy() // X軸に対称にコピー
    position([-1, 0, -1]) // ケース外形の左-中央-下を原点とする
    yflip_copy()  // Y軸に対称にコピー
    up(baseH - baseThickness - boardThickness) // ジョイントの高さ位置合わせ
    back(10) // ジョイントの前後位置合わせ
    xrot(90) cyl(r=1, l=10, anchor=[0, 1, 0]); // ジョイントをシリンダで作成、アンカーは下面に設定
  }
}

ケース下部分はこのように書きます

baseH = 8;

render() // ちらつき防止
translate([0,50,0]) // 位置合わせ
diff("cut") //cutというtagの図形を切り抜く
cube([baseW+0.2, baseL, baseThickness + boardThickness], anchor=[0,0,-1]){ // 底面にアンカーを設定したケース外形(スナップ用の左右はみ出し部分を除く)の直方体を作成
  position([-1, -1, 1]) // ケース外形の左-手前-上を原点とする
    force_tags("cut") // 切り抜く部分をグループ化
      zflip() linear_extrude(height=boardThickness) // 基板外形を作図(linear_extrudeの向きが期待と逆なのでzflipしている
        board(); //DXFから基板外形を読み込む
  // スナップフィットジョイントと左右はみ出し部分の作図
  xflip_copy() // X軸に対称にコピー
    position([-1, -1, -1]) // ケース外形の左-手前-下を原点とする
      // 左右はみ出し部分は一部角丸の直方体として作図
      cuboid([baseSideThickness, baseL, baseH], anchor=[1,-1,-1], rounding=2, edges=["Z"], except_edges=RIGHT)
      yflip_copy()  // Y軸に対称にコピー
        position([1, 0, 1]) // 右-中央-奥を原点にする
          back(10) // ジョイントの前後位置合わせ
          xrot(90) cyl(r=1, l=10-1, anchor=[0, 1, 0]); // ジョイントをシリンダで作成、アンカーは下面に設定(1mm短くしてうまくハマるようにしている)
}

スナップフィットジョイントと書きましたが、市販品のような矢印状のものでは無く、単にかまぼこのような形の凹凸をはめ込むだけのジョイントです。

しかしこれでも十分に固定でき、かなり力を書けないと外れないケースを作ることが出来ました。

(説明をコメントになるべく書いてみましたが、なかなかわかりづらいですね。)

BOSL2所感

とにかくアタッチができるのが有用と感じました。

直方体を定義すると、その頂点または辺の中点を簡単にアタッチ原点と設定することが出来ます。

これにより相対的な立体図形の配置が出来るようになり、OpenSCAD単体で作図していると変数だらけになってしまう問題を解消できます。 (アタッチが出来ないので辺の長さをすべて変数に逃がす必要があった)

またxflip, yflip, zflipやup, down, left, rightなど軸を1つに限定した操作も可読性が良くなり良いものだと感じました。

cuboidには角丸のオプションがあり、フィレットが苦手なOpenSCADの弱点を少しは緩和させてくれます。 (それでもやはりフィレットは苦手ですが・・)

linear_extrudeの引き延ばした先にアタッチできないのが若干惜しい気持ちになりました。

まとめ

今回初めてLibreCADとOpenSCAD、そしてBOSL2を使った作図をしてみました。

LibreCADを使うとマウスを使って簡単に直感的な作図が出来ました。

立体的な造形はマウスよりコーディングの方が保守性が高いのでOpenSCADが有用だと感じました。

そしてBOSL2というOpenSCADのライブラリを使うことで、立体物の造形を比較的直観的に実現できました。

今回は試験的にツールを組み合わせただけなので、もっと良い方法があるかもしれません。

これより良い方法を思いついた方は是非https://twitter.com/ina_ani に教えてください。

ArduinoとCH9328でお手軽自作キーボード

CH9328とは

UARTを入力として受け取り USB HIDキーボードとして振舞うICのようです。

本来の用途としてはKVMスイッチなどでキーボードのエミュレーションを行うための物のようです。

今回はこのCH9328を搭載したモジュールボードを購入したので少し試食してみました。

f:id:inajob:20220405220253p:plain

自作キーボードとUSBデバイス

USB接続式の自作キーボードを設計するときに悩みの種となるのがUSBです。

まずUSBデバイス機能を搭載したマイコン、またはV-USBなどのソフトウェアエミュレーションに対応しているマイコンを用意する必要があります。

USBのプログラミングは煩雑で、メモリやCPUを結構消費します。

そして次の問題がVID/PIDです。作成したキーボードを個人で使う場合はそこまで問題となりませんが、販売するとなると正式には独自のVIP/PIDを取得しそれを利用するのが通常の流れです。

しかし、正規の方法でVIP/PIDを手に入れるためにはUSB-IFに申請し、結構多くのお金を納める必要があります。

同人ハードウェアなどの場合そこまでコストはかけられない、という事で、いくつかのベンダーがPIDのサブライセンスを行っているので、その仕組みに乗っかるなどしてPIDを取得している人もいるようです。

このあたりの事情は以下の記事が詳しいです。

qiita.com

CH9328とUSBのVID/PID

さて、今回扱うCH9328ですが、これはWCH社が販売しているICで、このICにはWHC社のVIDである0x1A86と、このIC固有の値であるPID 0xE026がデフォルト値として設定されています。 (この値は書き換えツールで変更できるようです)

この値をそのまま使う場合はWCH社のVID/PIDをそのまま使うことが出来ます(多分ライセンスとしてもこれでもないないはず、、USB Serial ICなどとやっていることは同じ)

Arduinoから使ってみる

ArduinoにはまさにCH9328を利用するためのライブラリである「CH9328-Keyboard」があります。

f:id:inajob:20220405212019p:plain

インストール出来たらHelloWorldのサンプルプログラムをArduino UNOに書き込んでさっそく実行してみます。

Arduino UNOで利用する際の罠

CH9328-Keyboardの内部で SERIAL_TX_ONLY という定数を使っていますが、どうもこれはESP8266などでのみ利用できる定数のようでArduino UNOではこのせいでコンパイルが実行できません。

インスール下ライブラリのCH9328Keyboard.cppの該当部分を削ることでコンパイルできるようになりました。

変更前
_Serial->begin(baud, SERIAL_8N1, SERIAL_TX_ONLY);

変更後
_Serial->begin(baud, SERIAL_8N1);

サンプルプログラムの実行

CH9328モジュールとArduino UNOはVCC,GND, TX, RXをそれぞれ接続します。

また動作モードを変更するジャンパのIO1,IO2をHIGHに設定します(このモジュールではジャンパをつけるとHIGHになるようです)

電力はCH9328モジュールからArduino UNOに送るのでArduino UNOはUSB接続する必要はありません。

Win+r押下の後 notepad + Enter を押下、その後Helloの文言が打ち込まれるというキーストロークのシミュレーションが行われ下記画像のようにメモ帳にメッセージが表示されました。

f:id:inajob:20220405212838p:plain

オリジナルキーボードの作成

ここまでくれば後は簡単です。

3キー搭載のマクロパッドを作ってみます。

自分のIDにちなんで「i」「n」「a」の3キーの存在するキーボードという事にします。

全く洗練されていませんがソースコードです。

#include <CH9328Keyboard.h>
#define PINRST 10
#define BAUDRATE 9600              //Default is 9600.
void setup()
{
  Keyboard.begin(&Serial, PINRST, BAUDRATE);
  delay(1000);
  Keyboard.releaseAll();

  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
}

unsigned int trigger_b1 = 0;
unsigned int trigger_b2 = 0;
unsigned int trigger_b3 = 0;

void loop()
{
  int b1 = !digitalRead(10);
  int b2 = !digitalRead(11);
  int b3 = !digitalRead(12);

  if(b1){
    if(trigger_b1){
        Keyboard.press('i');
    }
    trigger_b1 ++;
  }else{
    Keyboard.release('i');
    trigger_b1 = 0;
  }
  if(b2){
    if(trigger_b2){
        Keyboard.press('n');
    }
    trigger_b2 ++;
  }else{
    Keyboard.release('n');
    trigger_b2 = 0;
  }
  if(b3){
    if(trigger_b3){
        Keyboard.press('a');
    }
    trigger_b3 ++;
  }else{
    Keyboard.release('a');
    trigger_b3 = 0;
  }

}

配線は Arduino UNOの10, 11, 12番ピンをタクトスイッチの片方にそれぞれ繋ぎ、タクトスイッチのもう片方はGNDに接続するだけです。

f:id:inajob:20220405220321p:plain

全体像はこんな感じです。

f:id:inajob:20220405220610p:plain

CH9328についてもう少し・・

値段やデータシートはLCSCが参考になります。

lcsc.com

モジュールは600円程しましたが、IC単品だと$1.5程度で買えそうです。AliExpressだともっと安いものも見つかると思います。 データシートは中国語の物しか見つかりませんでした。

しかし基本動作はシリアルから来たコードをHIDキーボードのコードに変換するだけなので、中国語が読めなくてもそこまで困ることはなさそうです。加えてCH9328-Keyboardライブラリがあるので、そもそも仕様を意識する必要もあまりありません。

AliExpressでCH9328で調べると様々なモジュールが販売されています。

私が今回利用したのは以下ですが、ほかにも様々なモジュールが存在します。

ja.aliexpress.com

よく似た型番の別のICや、ジャンパの設定が出来ないもの、水晶発振子が搭載されたもの、など様々な変種が存在するので、目的に応じて適切なものを購入してください。

(同じCH9328でも内部バージョンの違うものがあるようで、古いものは水晶発振子が外付けで必要のようです)

まとめ

CH9328を使うとUSB HID周りの煩わしい問題をすべて肩代わりしてくれるので、非常に簡単にUSBキーボードを自作できることがわかりました。

CH9328と低機能・低価格のマイコンを組み合わせる事で、部品は増えてしまいますが、多機能マイコン1つで作るよりも、安く、わかりやすい自作キーボードを設計することが出来ます。

チップの値段も安いので、新たな自作キーボードの材料として検討してみてはいかがでしょう?

最後に動作の様子の動画を貼っておきます。

6.5秒で起動する日本語対応Vimマシンを作った

これは何?

Raspberry Pi は高性能で比較的安く、面白いボードですが、標準のRaspberry Pi OSだと起動時間が遅いのがネックです。

起動時間を早くする方法はいろいろあるのですが、ここではBuildrootを使ってシンプルなイメージを作る事で、高速起動を実現してみました。

シンプルなイメージということで、今回は「日本語入力ができるVim環境」の構築目指すことにしました。

※と言ってもBuildrootを普通に使っただけでそこまでの最適化は行っていないです。

(今値段を見てびっくり、半導体不足の影響ですね、、今は買わないほうがよさそうです・・)

Buildrootによるイメージの作成

f:id:inajob:20220331222650p:plain

先人の知恵を借りてBuildrootを使ってイメージを作成します。

以下の記事の内容が非常に簡潔でそのまま真似しました。

qiita.com

そのまま、と書きましたが実際にはWindows PCの上で動くDockerの中で実行しました。

コマンドを列挙するとこんな感じです。

# dockerでubuntuの環境を作成
$ docker run --rm -it ubuntu bash

# apt-get update
# apt-get install wget make build-essential gcc g++ bzip2 cpio unzip rsync bc libncurses-dev file
# wget https://buildroot.org/downloads/buildroot-2022.02.tar.xz
# tar xJvf buildroot-2022.02.tar.xz
# cd buildroot-2022.02
# make raspberrypi0_defconfig

ここまでが準備です。

必要なパッケージをインストールして、buildroot本体を取得し展開します。

makeを使ってRaspberry Pi Zeroの設定を読み込みます。

他のRaspberry Pi向けのイメージを作る際はmake list-defconfigsを実行してボードを探してみてください。

次に細かい設定を行います。胃かを実行するとCUIで動くメニューが起動します。

# make menuconfig

キーボードを使っていくつか設定を変更します。

f:id:inajob:20220331221730p:plain

今回は最低限の日本語入力ができることを目的としているため以下の設定変更を行いました。

  • Toolchain
    • C libraryを muslに変更
  • Target packages
    • Show packages that are also provided by busybox のチェックを入れる
    • Text editors and viewers
      • vim にチェックを入れる
    • Graphic libraries and applications (graphic/text)
      • fbterm にチェックを入れる
    • Development tools
      • git にチェックを入れる(これはあってもなくても良い)

このあとmakeを実行するとビルドが始まります(数時間かかります)

# make

ビルドが完了すると output/images/sdcard.img が生成されます。

以下のようなコマンドでコンテナからイメージファイルをホストマシンに取り出します。

$ docker cp コンテナのID:/root/buildroot-2022.02/output/images/sdcard.img ./

後は適当なツールを使ってこのイメージをSDカードに焼きます。 (自分はRaspberry Pi Imagerを使いました)

この状態から日本語入力を実現するためのアイデア

普通に考えるとuimなどの日本語変換の仕組みをインストールするのですが、慣れないBuildrootで、これを実現するのはちょっと面倒そうです(やってみると簡単なのかもしれませんが)。

ということで、今回はvim上で動作するskk.vimというのを試してみることにしました。

日本語表示・入力のための下準備

ここからの操作はext3をマウントできる仕組みが必要です。自分は今回使うのとは別のRaspberry Piに外付けSDカードドライブを取り付けてこの作業を実施しました。 (以降~などのパスが出てきますが、これはSDカードを使ってブートした時のパスを表しています、ホストのRaspberry Piのパスではありません。)

日本語表示はfbterm、日本語入力はvim上で動作するSKKで実現します。

日本語表示に必要なttfファイルを~/.fontsに配置します。

自分は源真ゴシック (げんしんゴシック) | 自家製フォント工房 を使いました。ダウンロードしたのちに等幅フォントの「GenShinGothic-Normal.ttf」だけを取り出し上記パスに配置しました。

fbtermの設定(~/.fbtermrc)でGen Shin Gothic Normalを指定することで、このフォントが利用できます (利用できるフォント名は fbterm -v を実行すると確認できます。)

次にvim上で動作するSKKの設定です。

今回は以下を利用します。

github.com

以下のページを参考にセットアップを実施します。

qiita.com

~/.vim以下にgitリポジトリpluginディレクトリをそのままコピーするだけです。

SKKの辞書も上記記事のまま、wgetで取得しホームディレクトリ直下に解凍しておきます。

今回は上記記事を真似てSKK-JISYO.Lを使いました。

~/.vimrcにも上記記事そのままの設定を書きました

let skk_large_jisyo = '~/SKK-JISYO.L'
let skk_auto_save_jisyo = 1

ブート、日本語入力

さて、ここまで準備出来たら、SDカードをアンマウントしRaspberry Pi Zeroに挿入します。

HDMIケーブルでディスプレイに接続、USB-OTGアダプタを経由してキーボードを接続し、電源USBを接続します。

f:id:inajob:20220331222505p:plain

起動するとHDMIケーブルで接続したモニタにコンソールが表示されます。

私の環境では6.5秒程度でログイン待ちコンソールが表示されました。

f:id:inajob:20220331222526p:plain

ログインコンソールにrootと入力するとログインできます。

さらにfbtermと入力し日本語が表示できるようにします。

そして満を持してvimを実行し、挿入モードに入ってCtrl+Jを押してしばらく待つとskk.vimの日本語入力モードに入ります。

f:id:inajob:20220331222545p:plain

ということで、ここまでで 高速起動する日本語入力できる環境を作ることが出来ました。

まとめ

Buildrootを初めて使いましたが、特に工夫しなくても6.5秒で起動するイメージが作れる素晴らしいものでした。

Raspberry Pi 3/4など、もっと性能の良いボードを使えばさらに高速化できると思います。

まだまだ最適化の余地はありますし、SDカードの種類などでも起動の速度は異なると思います。

さらに、vimだけあれば動作するSKK実装を使うことで、簡単に日本語入力環境を作ることが出来ました。

自作のポメラ的なガジェットを作る際にはこの知見が役立ちそうです。

この記事をご覧になっている方で、似たような挑戦をしたことがある方は、ぜひ https://twitter.com/ina_ani に教えてください。