2021年12月10日金曜日

Bangle.jsを購入して電源を入れるまで

Banlge.jsを買いました

興味本位でBangle.jsのKickstarterプロジェクトにBackしまして、実機が2020年に届きました。

  • Javascriptが動き、自分でコードを書いてアプリが作れる。
  • アプリのインストールはWeb Bluetooth APIを通してブラウザから。

と、なかなかにおもしろそうだったのですが、この時点で工事設計認証の取得は明確になっていませんでした。ダメならダメで電源を入れなければいいだろうと思いBackすることに。

総務省の特例制度を活用することに

「技適未取得のWi-Fi機器が180日使える。実験等の特例制度に申請」

Bluetoothを動かすにあたり、工事設計認証を取得していない機器でも正直かつ適切に申請すれば実験を認めてくれる制度を活用することとしました。実物が届くまでの間に始まったような気がしています。FCCの申請は済んでいてIDが発行されていることから、総務省に申請書類を持参して数日後にメールでOKの連絡を受け取りました。総務省で書類を受けてくださった方が「近々オンラインで完結するようにします」と話していましたが、今ならもうそのようになっているようです。ありがたいですね。

実機を動かしてみる

アプリを動かしたり心拍数をはかったりなんかして使い心地・動作感を見たりなどしました。Web Bluetooth APIの是非は別にして、アプリのインストールもすべてブラウザから直接Bluetoothで制御するのは、機能としてはおもしろかったです。スマホだと対応機種を持っていなかったため、常にノートパソコンとともに使う機種ではありました。

少し触ったあとの廃止届出と管理措置

わりとすぐ飽きたというか、Web Bluetooth APIが前提なのはちょっと勝手が悪いなというのもあって、半月くらい触ったあと、一応実験期間いっぱいまで自宅に放置していました。仕組みがよく整えられていて、期間終了が近づくと登録したメールアドレスに総務省からお知らせが届きました。廃止届出はWebで完結するようになっており、メール受信後忘れないうちに済ませることができました。その後、Bangle.js本体は自宅で電源を入れることなく保管しています。今はもうリチウム電池が過放電しているかもしれず、そろそろ廃棄してもいいかなと思ってきました。総務省の特例制度はとても便利かつ擦り寄ってきてくれている印象があって、互いの信頼感を損ねないよう襟を正して活用していきたいと思います。

2021年10月14日木曜日

Raspberry Pi 4をTime Capsuleにする

長年Macのバックアップとして使っていたTime Capsuleだったが、AC電源直結の勝手の悪さ・発熱・フットプリントのでかさから、Raspberry Pi 4で置き換えることにした。下記の順序で実装できた。64bitのOSを使いたかったので、Raspberry Pi OSではなく、Ubuntu Server 20.04をもとにしている。

  1. avahiのインストールと設定
  2. ハードディスクの設定
  3. sambaのインストールと設定

avahiのインストールと設定

$ sudo hostnamectl set-hostname RPi4
$ sudo apt-get install avahi-daemon
$ sudo mv samba.service /etc/avahi/services/samba.service
$ sudo service avahi-daemon restart

hostnameを設定することで、MacのFinderに表示される名前が決まる。わかりやすい名前にするとよい。

3行目でコピーしている設定ファイルはこちら。設定ファイル内にTime Capsule対応を謳うことで、Mac側から認識できるようにする。Redditのスレッドに書いてあったが、参考になった投稿が見つからない。

ハードディスクの設定

$ ls -lha /dev/disk/by-uuid # Time Capsule用HDDのUUIDを確認
$ sudo vi /etc/fstab # fstabにUUIDを記載。オプションはリポジトリ内のfstabを参考に。

USB 3.0対応の外付けハードディスクを接続した。ハードディスクのファイルシステムは、Macからは関係ないのでなんでもいい。Linuxなのでext4にしている。ハードディスクのUUIDをfstabに記載することで、特定のハードディスクが接続されたときだけ定位置にマウントできることを知った。

sambaのインストールと設定

$ sudo apt-get install samba
$ sudo adduser timemachine # パスワードは自分がわかるもの、アカウント情報は空白でよい。
$ sudo smbpasswd -a timemachine # SMBパスワードの設定
$ sudo mkdir /mnt/timemachine
$ sudo chown -R timemachine: /mnt/timemachine
$ sudo mv smb.conf /etc/samba/smb.conf
$ sudo service smbd reload

Raspberry Pi側に、samba用のユーザーを作成する。ユーザー用・SMB用のそれぞれにパスワードを設定する。SMB用パスワードは、Macから接続するときに使用する。

マウントポイントはfstabに記載したとおりの場所にする。マウントポイントのオーナーをsamba用アカウントに設定しないと、ファイル書き込みのできない共有になってしまうので注意する。

コピーしている設定ファイルはこちら。ファイル末尾のfruit行がTime Capsule用設定となっている。

おわりに

これでRaspberry PiをTime Capsuleとして設定することができた。Raspberry PiはSDカードが壊れるので、GitHubに何も考えずに復旧できるよう手順をまとめている。今後はAnsible等で自動的に展開できるようにしたい。

2020年6月4日木曜日

ゲームボーイの画面にアニメーションを表示する

おもしろ半分でParty Parrotをゲームボーイで動かしたら、結構な数の皆さんに回覧いただきました。せっかくなので、仕組みをまとめておきます。

実装までの流れ

次のフローで組み立てていきます。

  1. 絵を用意する
  2. ゲームボーイの表示データに変換する
  3. 順番に表示する

絵を用意する

Party ParrotはWikipediaのものを使いました。gifアニメを各コマに分解し、4階調に変換します。これはimagemagickを使いました。

この白黒画像を、ゲームボーイの画面表示に合わせたビット列に変換していきます。

ゲームボーイの表示データに変換する

任意の絵をゲームボーイにする方法が例示されているので、それに従います。リンク先の解説でいくつか挙げられている注意点がさらに厳しくなるので気をつけてください。

  • 8x8サイズのパーツが255種類に収まるように絵を描きます→127種類に収めてください
  • Pic2Tilesで生成されたC言語のファイルからconstを外すよう記載がありますが、一部を除き外してはいけません。

パーツを127種類に収める点について。1枚絵の表示であれば255種類すべて使えるのですが、アニメにする関係で半分に制限されます。1枚表示している間にもう一方の絵を用意し、整ったところで一気に表示を切り替える方法をとっているため、このもう一方を用意するために半分ずつしか使えないということになります。

constを外してはいけない点について。現時点のGBDKではコンパイルエラーが出なくて問題がないことと、constなしでは起動時にRAMに展開されるために今回のように10コマ使用すると、5コマ以上でRAMがオーバーフローするためゲームボーイが落ちます。画像のデータそのものは動的に変化する必要がないので、基本的にconstのままROMにとどめておくようにしてください。例外はmap.Cのうち偶数枚目のコマのものです。変換時に生成されるCファイルには「タイル内のデータ」と「どの位置にどのタイルを並べるかを定義したデータ」が含まれています。後者のデータは常にタイル内データが専用の領域の先頭から並んでいる前提で生成されるので、偶数コマのデータは128個分のオフセットが必要になります。あらかじめ数字を書き換えておくか、constを外してゲームの起動時に初期化の一環として一気に書き換える必要があります。今回のParty Parrotでは面倒だったので起動時に書き換えましたが、コマが多かったり他の用途でRAMを使っていたりで容量が逼迫しているとconstのまま書き換えておいたほうがよいです。

順番に表示する

GBDKに用意されているタイル表示用の関数を使います。基本的に下記のコードを繰り返すだけです。

set_bkg_data(0,100,TileData_pp0); set_bkg_tiles(0,0,20,18,MapData_pp0); delay(50); set_bkg_data(100,100,TileData_pp1); set_bkg_tiles(0,0,20,18,MapData_pp1); delay(50);

set_bkg_dataでタイル内のデータを専用領域にコピーします。第1引数の数字がコピー位置のオフセットです。Party Parrotの場合はどのコマもタイル数が100以下だったので100としています。set_bkg_tilesは、指定した範囲をマップデータに従って書き換えるものです。

次のコマのタイルデータを書き込む際、多少時間を空けないと表示が崩れることがあったのでdelayを入れています。

さいごに

ポケットカメラの撮影時プレビューを見ると、明らかにタイルデータでは間に合わなさそうなドット画像の動画が表示されているので、まだ改善の余地はあるのかもしれません。この記事のやりかたでも、タイルとマップデータをカートリッジに入りきるだけ用意すれば、それなりの時間のアニメーションを表示させることもできるなど、可能性は残しています。

2020年5月16日土曜日

Nordic SDKのサンプルコードにないHIDサービスを実装する

Nordic nRF5 SDKには、HIDの実装例としてキーボードとマウスが公開されています。HIDはそれ以外の使われ方も定義されていますが、サンプルは公開されていないうえインターネットでも実装例は少ないです。Gamepadの実装をやってみたところいろいろな苦労があったので、参考のためにまとめておきます。

マウスを参考にして、USBのHIDを載せる。

とフォーラムに書いてあります。基本的に、次の流れで調整すると動きます。

  1. レポートディスクリプタの中身を整える (コード内ではrep_map_data[]に定義)
  2. レポートディスクリプタに記載したルールに従ってバイト列を作る
  3. データを送信する (コード内ではble_hids_inp_rep_send()関数で送信)

レポートディスクリプタの中身を整える

レポートディスクリプタは、送信したビット列のデータをどのように解釈するかを定義したものです。なので、中身は自分で必要なものをきちんと定義する必要があります。Gamepadの場合はどのように指定すればいいのかは、下記のリンクが参考になりました。

今回は下記のように指定しています。ゲームボーイのキー操作を入力としたいので、8ビットの入力を4つのボタンと1つの方向キーとして扱います。

static uint8_t rep_map_data[] ={
    0x05, 0x01,             // USAGE_PAGE (Generic Desktop)
    0x09, 0x05,             // USAGE (Gamepad)

    0xa1, 0x01,             // COLLECTION (Application)

    0x05, 0x01,             // USAGE_PAGE (Generic Desktop)
    0x09, 0x39,             // USAGE (Hat switch)     // 十字キー
    0x15, 0x00,             // LOGICAL MAXIMUM (0)    // このデータは0〜7の範囲
    0x25, 0x07,             // LOGICAL MAXIMUM (7)    
    0x35, 0x00,             // PHYSICAL MINIMUM (0)   // 0〜7が
    0x46, 0x3b, 0x01,       // PHYSICAL MAXIMUM (315) // 0〜315に対応
    0x75, 0x04,             // REPORT SIZE (4)        // SIZEとCOUNTで
    0x95, 0x01,             // REPORT COUNT (1)       // 4ビットが1個の意味
    0x65, 0x14,             // UNIT (Degrees)         // 単位は角度
    0x81, 0x42,             // INPUT (DATA, VARIABLE, ABS, NULL)

    0x05, 0x09,             // USAGE_PAGE (Button)    // ボタン単体
    0x15, 0x00,             // LOGICAL MINIMUM (0)    // このデータは0〜1の範囲
    0x25, 0x01,             // LOGICAL MAXIMUM (1)
    0x19, 0x01,             // USAGE MINIMUM (1)
    0x29, 0x04,             // USAGE MAXIMUM (4)
    0x75, 0x01,             // REPORT SIZE (1)        // SIZEとCOUNTで
    0x95, 0x04,             // REPORT COUNT (4)       // 1ビットが4個の意味
    0x81, 0x02,             // INPUT (DATA, VARIABLE, ABS)

    0xc0,                   // END_COLLECTION
};

ルールに従ってバイト列を作る

レポートディスクリプタで指定したルールに従った値を並べます。レポートディスクリプタに記載した順序がそのままバイト内のビット列になるので、下位4ビットが十字キー・上位4ビットがボタン単体となるよう組み立てます。

データを送信する

組み立てたデータは、関数ひとつで送信できます。

err_code = ble_hids_inp_rep_send(&m_hids,
                                 INPUT_REP_BUTTONS_INDEX,
                                 INPUT_REP_BUTTONS_LEN,
                                 buffer);

  • INPUT_REP_BUTTONS_INDEX: マウスのサンプルのように、レポートディスクリプタのなかに複数のIDがある場合はここで指定します。今回の例ではひとつしかないので、0になります。
  • INPUT_REP_BUTTONS_LEN: 送信するデータのバイト数です。今回は1バイトなので1です。
  • buffer: データ本体のポインタ。

動作例

データの受信側で確認する方法

HTML5 Gamepad Testerを使っています。ペアリングし、レポートディスクリプタの指定もうまくいっている場合は、キー操作に反応します。

ペアリングできていてもキー操作に反応しない場合、レポートディスクリプタの記載内容がきちんと合っていない可能性があります。バイト列が送信されているかどうかは、Macを使っていると確認が楽です。Appleの開発ツールとして公開されているPacket Loggerを使うと、どのデバイスからどのデータが飛んでいるかを確認できます。バイト列の中身をPacket Loggerで確認できれば、ペアリングと通信はうまくいっているので、おかしいのはディスクリプタだと推測できます。

2020年2月8日土曜日

ポケットカメラの画像をM5Stackに送信して表示する

前回の記事で、ポケットカメラの画像をPCに送信することができました。でもこれではPCとNucleoボードが必要で、若干大掛かりだなと思っていました。これをM5Stackで受信できれば、画面に映せるし無線LANでTwitter等にアップロードも可能だなと思い、移植してみました。

M5Stackと通信ケーブルを接続する

ゲームボーイの通信ケーブルの信号線は5V駆動なので、5VトレラントではないM5Stackでは、とりあえず分圧抵抗で降圧します。M5Stack→ゲームボーイの方向は、昇圧せずとも動くことはカートリッジ自作の際にわかっているのでとりあえずそのままにしました。

M5Stackに接続する際、当初は向かって上側(21〜23のピン)に接続していたのですが、23番が内部でディスプレイ制御に使われているのに気付くまでディスプレイが動かないと困りました。GPIOとしても使用できますが、ディスプレイ初期化後にGPIOとして設定してしまうため、それ以降はディスプレイの信号を受け付けなくなります。

M5Stackでデータを受信し画像として表示する

データ受信までは、DholeさんのSTM32側コードの移植で済みました。移植の際、Arduinoではうまく動かず、ESP-IDFの環境を使っています。データ受信後、ドット情報を抽出しビットマップに整えてから画面に表示するのですが、表示の際はM5.Lcd.drawBitmap()が必要になり、ESP-IDFにArduinoライブラリを追加しました。バージョンが異なるとうまく動かないらしく困りましたが、こちらの記事が参考になりました。結局、この方のリポジトリをクローンしてアプリを作っています。

動作の様子

2020年1月13日月曜日

ポケットカメラの画像を取り出す

かつてゲームボーイのカートリッジからカメラが伸びているポケットカメラというソフトがありました。撮影した画像は通信ケーブルを使い、ポケットプリンタからロール紙に印刷するという形で現像していましたが、印刷部を適宜加工することで画像を他環境へ転送することができます。例によってDholeさんの実装例があったので、まずはそれを後追いして検証しました。

動作までの流れ

下記のフローで実装を行いました。

  1. 通信ケーブルを改造する
  2. 疑似ポケットプリンタ基板を実装する
  3. 基板が出す画像データを受け取るアプリを実装する

通信ケーブルを改造する

通信ケーブルのデータを基板で受信するために、通信ケーブル本体を切断しています。通信ケーブル用のソケットがAliexpress等で購入できればよかったのですが、初代ゲームボーイ用の大きいサイズはさすがに作られていないようで、泣く泣くカットしました。配線はGNDを含めて4本なので、秋月電子のUSBコネクタDIP化基板を利用して扱いやすくしました。

疑似ポケットプリンタ基板を実装する

ポケットプリンタのフリをして、ゲームボーイ側には正しい応答を返し続け、PC側に画像信号を転送する基板を実装します。基本的にDholeさんのリポジトリのコードを使用しますが、ヘッダファイルだけがなかったりフレームワークの内容に変更があったりするのでその点だけ修正しました。修正後のリポジトリはこちらです。例ではNucleo-F411REでしたが、手元にあったのはF401REだったのでクロックを遅くするよう設定しています。

基板が出す画像データを受け取るアプリを実装する

こちらもDholeさんのサンプルを使用します。基板がシリアル通信でデータを渡すので、それを受信し画像に変換して保存します。

動かしてみる

疑似プリンタ基板が接続されているPCで受信アプリを起動し、ポケットカメラ側で印刷を実行します。各部が正常に接続・動作している場合、ゲームボーイの画面はデータ送信中となり、PCに画像が保存されます。

印刷される画像そのものが出てくるので、写真+フレームのPNG画像で保存されます。

2019年12月8日日曜日

STM32のUARTのDMA送信におけるバッドノウハウ

STM32F4のDMAを使ったUART送信、下記の仕様なのでちょっと勝手の悪いところがありました。

Circular
一度Enableにすると、メモリ上のデータを繰り返し送信し続ける。
Normal
送信後、各種フラグをクリアする必要があり、CPUの命令を消費してしまう。

ゲームボーイのカートリッジでRAMの値を外部に送信しようとすると、NormalではCPUを使う時間が増えるため、動作に支障が出ます。かといってCircularでは、同じ値を送信し続けるので受信側に工夫が必要になってしまいます。最低限必要なデータを、最低限のCPU消費で送信したいのです。

今回のバッドノウハウ

今回は1バイトだけ送信したいので、Circularモードに設定したうえで次のようにENABLEの直後にDISABLEを続けると、ちょうど1バイトだけ送信したところでDMAが止まり、Circularモードなので何事もなく再開します。

DMA_Cmd(DMA1_Stream6, ENABLE);
DMA_Cmd(DMA1_Stream6, DISABLE);

ただこれはボーレートとの兼ね合いもたまたまちょうど良かっただけかもしれません。複数のバイト列を送信する場合には使えないので、そのときは改めて方法を考える必要があります。

2019年11月9日土曜日

ゲームボーイの上で動くソフトウェアと通信をする

ゲームボーイのカートリッジを自分で作って遊んでいます。いままでカートリッジ側のROM・RAM・MBCをすべてマイコンに実装したものを作って遊んでいましたが、カートリッジの外からRAMにデータを書き込む方法が見つからず難儀していました。

マイコン側CPUの処理を使うとゲームボーイが止まる

このカートリッジでは、ゲームボーイに対するROMデータの出力をマイコンのCPUがまかなっています。

  1. ゲームボーイ側がカートリッジにアドレスを渡す。
  2. マイコンがアドレスを受け取る。
  3. Read/Writeのどちらか、バンク設定があるのかを判断して、返すべきデータを決める。
  4. マイコンがデータを出力する。

1バイトとはいえ、どのデータを返すかが決まるまでにいくつかの条件分岐が入ります。なので、外部通信等で他の処理がCPUを使用すると、このデータを返す処理が間に合わずゲームボーイ側がハングアップします。

外部通信の受信をDMAに任せたらどうか

今回、受信したデータをそのままカートリッジRAMの領域に直接書き込む形にしたら問題が解決しました。DMAのサンプルコードをみると、受信したあとそのデータを確かめるためのコールバック関数があったりしますが、その部分が動くとCPUを使ってしまうため、その部分は絶対に使わないようにします。ゲームボーイのソフト側は、DMAの書き込み先に合わせた特定のアドレスだけを読むようにすれば、カートリッジRAMに書き込んだデータをゲームボーイ内で扱うことができます。

実装例

ゲームボーイのカートリッジRAMにMIDIデータを書き込み、MIDIノートオンのときにゲームボーイ側で音を鳴らす仕組みです。

MIDIは、フォトカプラで受信後はbaudrateが31250のUARTとしてそのまま扱えるので、マイコンのDMAで直接RAMに書き込むことができます。書き込まれる予定のアドレスをゲームボーイ側は常時監視し続け、MIDIノートオンのメッセージを受信したら、ノート番号に合わせた音程で音を鳴らすという仕組みになっています。

2019年7月1日月曜日

大量のセンサーデータの可視化にKibana+Elasticsearchが最適だった話

第52回のIoTLTで話した内容を、改めて記載します。

センサーの測定値を数分おきに取得していたんですが、2年ほど動かしていると結構な量になりまして、CSVに変換してExcelでグラフにしようとすると描画まで強烈に待たされるようになってました。何かいい方法はないかと困っていたところ、同じく3月のIoTLTで発表のあったKibanaを使って可視化をがんばる話を聞き、これは良さそうと思って試しました。

Kibanaについて

Kibanaは全文検索エンジンElasticsearchのフロントエンドとして動くWebアプリなので、Kibanaを使うにはElasticsearchも合わせて使います。Elasticsearchにどんどんデータを溜め込み、ブラウザ経由でKibanaに接続してグラフを設定します。

基本機能はオープンソースになっていて無料で使えるのもありがたいです。

Linuxだと環境構築がすごく楽

たまたま持て余していたPCにLinux (Ubuntu 18.04) を載せて動かしています。公式に記載のaptを使った手順に従うと、光の早さで構築できました。最初はもともと入っていたWindows 10で動かそうとしたのですが、特にKibanaのZipパッケージはNode.jsのモジュールがまるっと入っており(KibanaはNode.jsのWebアプリとして動作する)、解凍で何年も待つくらい遅くてあきらめました。

数万件のセンサーデータからのグラフ描画が速い

まずElasticsearchが全文検索エンジンなので、溜め込んだデータの中から特定の条件にマッチするデータの抽出が非常に速いです。さらに、すべての時系列データを描画するのではなく、細かい範囲ごとに最大最小や平均などでデータを間引きしてから描画するので、長期間の動きをサクッと確かめることができます。

データの追加について

今手元で生成され続けているデータは、コマンド出力結果そのままのテキストだったりバイナリ生データだったりするので、Elasticsearchに投げ込むには一手間加えてJSONにする必要があります。今この部分はNode.jsを使って変換しています。これはNode.jsが使い慣れているだけで、実際はどの言語を使ってもいいと思います。

ちょっと困っているところ

グラフをディスプレイに表示し続けるとテレメトリーのようでかっこいいのですが、無料枠ではこの表示中も編集可能でロックはできません。ライセンス購入になると一気にいい値段になってしまうようで二の足です。

2019年4月15日月曜日

技術書典6のふりかえり

技術書典6で机をいただいたので、展示とPDFの頒布を行ってきました。どちらかと言えば本を売るよりもMaker Faire気分で、作ったものの自慢に出てました。

被チェック数

前回の2倍以上の数になっていて驚きました。サークルカットにわかりやすい画像を設定したせいかな、と思っていましたが、いくつかのニュースサイトに掲載されていることに気付きました。

それぞれあからさまに「自分で作るゲームボーイのカートリッジ」と書いてくれていました。ありがたい限りです。開催中も「お友達から買ってくるように言われた」という方が3人くらいおられまして、興味を持ってもらえるのは嬉しいけど参考になるだろうか?と若干不安です。

チップチューンのみなさんからの期待

もともとは「できそうだから」という軽い気持ちで作っていた自作カートリッジなんですが、LSDjを動かすためのカートリッジが年々減っているなかのポッと出てきた新作、かつ日本語で対応できるとのことで湧き上がっているとうかがいました。思わぬ方向からの援軍にモチベーションが高まりますね。

今後の課題

  • もう少し展示に気を遣う
  • そろそろ量産できそうかな
  • M3にも出てみようかな
  • ゲームボーイカラーの対応

お持ちいただいたゲームボーイカラーだと、起動ロゴ以降アプリケーションが動作しませんでした。旧ゲームボーイ用カセットということで動いてくれないものか…と期待していたのですが、一筋縄ではいかなさそうです。

2019年2月24日日曜日

ゲームボーイの自作カートリッジでLSDjが動くようになった

ゲームボーイのカートリッジを自分で作り、技術書典に本を出してから、LSDjが動くといいねという話をよく聞いていました。やっと動くようになったのでつまずいていた点を記載します。

マイコンの容量を増やす

今までの基板ではSTM32F407を使っていました。1MBのFlashを持っているのですが、これだと前述の512KBのROMイメージと128KBのRAM領域を確保できなかったので、ROM容量の多いSTM32F427(2MB)/STM32F413(1.5MB)の2種類を試しました。パッケージサイズは同一でピンアサインもほぼ同一です。

STM32F413でもROM/RAMの領域を確保でき、ソフトの起動を確認できました。413は427に比べてQSPIが載っているので、外部Flashを活用するならこちらのほうがいいのかもしれません。でも2MBの427は大して単価もかわらないのに容量がでかいのでもう全部これでいい気がしています。

MBC5の動きに対応したコードを追加する

今までも動いてはいたんですが、上記のように実装を間違えていて、音がぶつぶつと途切れるようにしか鳴らないし全くテンポどおりに動かない(超遅い)動作になっていました。リンク先のドキュメントと、もとのコード(コメントアウトになっているところ)を見てて気付きました。

音が鳴るようになりました

お知らせ

技術書典6に出ます。前回出展時の本に加筆修正を加えて、第2版として出します。値上げするけど、今まで買ってくれた人はそのままダウンロードできるようにする予定です。「い06」でデモ機と見本誌を用意して展示します。

バッテリーバックアップについて

外部Flashに保存かな〜と考えていたのですが、2MBだと容量の余裕がすごいので内蔵Flashに保存でいいのかもしれません。

2018年12月25日火曜日

enebularはNode-REDの一発デプロイツールとして超便利なのでは

先日ウフルのenebular meetupに参加するので、Node-REDを常時動かすためにherokuにデプロイしてみました。公開されている手順でherokuにNode-REDの環境がサクサクと立ち上がりました。このときに「enebular=IoTをよしなにするツールだと思っていたけど、Node-REDを即デプロイできるツールとしても便利なのでは?」と思いました。

Webhookを受け取る環境をサクッと立ち上げられる

過去にWebhookを受け取りたい場面があり、その都度サーバーの設定をするのは面倒だなと思っていました。その当時はngrokを使いましたが、enebularでWebhookを受け取るフローをつくりそれをherokuにデプロイしておけば、ngrokのようにローカルでプロセスを動かしている必要はないなと。ちょっと試してみました。

入力にHTTP Inputを置き、まずはそのままHTTPの出力につなぎます。こちらの3項にあった「HTTPの入力は本当に入力しかしないので、HTTPの出力につながないとWebhookの発行側がエラーになる」という内容を参考にしています。入力のHTTPを分岐し、とりあえずデバッグで中身を全部出力するようにします。

Webhook発行側に登録するURLは、herokuデプロイ前なら「デプロイボタンの左にある(i)のボタンで表示されるドメイン+HTTP Inputに設定したパス」が使えます。これで動作確認ができれば、そのまま先ほどの手順に従ってHerokuにデプロイしてWebhookを常時待機できるようになります。

2018年12月16日日曜日

なぜnanoloopのカートリッジは基板だけで差し込めるのか

ゲームボーイ用カートリッジのnanoloopは、カートリッジ本体が基板のみで、いわゆるカートリッジらしい樹脂筐体を含みません。nanoloop monoはさらに、カートリッジの端子幅だけしか本体サイズがありません。なぜこれで差し込みに問題ないのか、差し込み時の位置合わせは正確に行えるのかが疑問でした。この理由がわかれば、今自分で作っている基板も他のカートリッジから筐体を借りなくて済むので、調べてみました。

厚みについて

カートリッジと本体側ソケットそれぞれの端子が接していれば動作します。一般的なカートリッジの端子部の厚みを基板に合わせれば動作すると考えました。

2.1mmなので、厚みがおおよそ2.0mmあればおそらく大丈夫だろうと思います。

差し込みについて

厚みがわかったので、差し込み時の位置合わせやガイドについて調べました。カートリッジのふたを開けた状態で差す様子をみると、この状態では筐体(矢印で示している箇所)が位置を合わせているように見えます。

ここで、厚みをおおよそ2.0mmに調整したカートリッジ基板を差し込んでみます。

正しい位置に収まり、カートリッジも正常に動作しました。このときにわかったのですが、位置合わせのガイドとなっているのはカートリッジ筐体ではなく、本体ソケットの突起でした。次の写真は差し込み口を上から見た図です。

正しい厚み・正しい幅の板が上から降りてくるとき、ソケットのガイドに従って差し込まれるので、端子同士がまっすぐ接触するようになっています。

結論

基板厚み2.0mmでカートリッジ基板を製造すれば、筐体なしでもカートリッジは機能する。

機能検証(とカートリッジをもとのゲームに戻す)のために、上で差した基板の厚みを2.0mmにしたものを製造中です。届き次第試します。

2018年12月14日金曜日

AE-TYBLE16にBLE-MIDIを実装するための途中経過

秋月電子通商のBLEモジュール AE-TYBLE16 は、SWDの書き込み端子が出ているのでファームウェアを書き換えられます。NordicのnRF5 SDKのサンプルコードをいろいろ使うだけでも十分できるのですが、興味のあった MIDI over BLE はサンプルがなかったので実装に挑戦しました。アドベントカレンダーに投稿するのに間に合わなかったので、今回は途中経過を記載します。

Nordic nRF5 SDKでサービスの実装が大変

仕様をみると、次のように実装することとあります。

The following service and characteristic are defined:

  • MIDI Service (UUID: 03B80E5A-EDE8-4B33-A751-6CE34EC4C700)
  • MIDI Data I/O Characteristic (UUID: 7772E5DB-3868-4112-A1A9-F2669D106BF3)
    • write (encryption recommended, write without response is required)
    • read (encryption recommended, respond with no payload)
    • notify (encryption recommended)

「このUUIDのサービスとキャラクタリスティックを実装すればいいんだろ」と思っていましたが、この時点でまず大変でした。

今回のようにサービスとキャラクタリスティックでUUIDが異なっていると、「フルサイズのUUIDをいくつも使うぞ」という設定が必要でした。フォーラムのやり方でそれっぽいのを見つけて実装しデバッグすると、ログにメッセージが出ます。「ユーザーが使うメモリの割当を次のように変えろ」というメッセージが出るので、それに従ってリンカスクリプトを修正します。これでやっと電波が飛ぶようになります。

仕様の「encryption recommended」にひっかかる

電波が飛ぶようになったのですが、MacはMIDIポートとして設定してくれません。おそらく仕様の「encryption recommended」が欠けているのが原因のようで、Mac側としてはマウスやキーボードのようにペアリング動作を完了できないとMIDIポートとして設定されないようです。もともとベースにしていたサンプルコードがペアリング処理のないものだったので、ペアリング処理のあるサンプルに移植するのもめんどうだなとなって放置気味になってきたところで今日に至っています。

まとめ

すごく手間なので、Arduino環境でつくるほうに乗り換えようかちょっと考えています。でもペアリングの動きとか後ろ側の動きについてかなり勉強になった感じはするので、なしではないです。

2018年11月12日月曜日

秋月のBLEモジュールでHIDを扱えるようにする

秋月に太陽誘電のBLEモジュール AE-TYBLE16 が販売されています。このモジュールは端子が底面からのみ出ているので、基板実装をしないと扱いづらいのですが、秋月がその基板実装を行った状態で販売しているので非常に扱いやすくなっています。

このモジュールは中のnRF51822に対してあらかじめファームウェアが書き込まれており、電源が入ると独自のサービスを飛ばします。UARTで適切なコマンドを入力すると、その中のキャラクタリスティックにデータが送りこまれると聞いています。

この秋月モジュールは電源・GPIOに加えてSWDIO・SWDCLKが出ているので、JLink等のライターを使用すると自分で作ったファームウェアに置き換えられます。

ファームウェアの書き込み

Before

After

J-LINKから書き込むにあたって、最低限次の配線接続があれば動作します。

  • SWDIO
  • SWDCLK
  • リセット
  • Vref
  • GND

20ピンJ-LINKだと、これに加えて5V供給とUSB-UART変換が使えるのでそれもつないでいます。5V供給をLDOで3.3Vに落とすとモジュール電源とVrefに使えるので、外部電源を容易せずともデバッグができるようになります。当初はブレッドボードにワイヤーを刺していましたが、持ち運びがめんどうなのでユニバーサル基板に実装しました。配線がつながった状態でnrfjprogをつかうと書き込みができるようになります。

nRF5 SDKのサンプルコードを動かす

今回はゲームボーイのカセットに組み込みたいので、nRF5 SDK 12.3.0のうちHID over GATTのマウスサンプルを使いました。

ble_app_hids_mouse/pca10028/s130/armgcc でmakeを実行するとビルドはできますが、サンプルの前提となっている環境と AE-TYBLE16 で異なる箇所があるのでそのままでは動きません。下記を修正しました。

sdk_config.h

  • CLOCK_CONFIG_XTAL_FREQ 255→0
  • CLOCK_CONFIG_LF_SRC 1→0

components/boards/pca10028.h

#define NRF_CLOCK_LFCLKSRCの中身を直す

RTCはモジュールに載っていないので、nRF51822内蔵を使うようにします。

  • .source        = NRF_CLOCK_LF_SRC_XTAL→NRF_CLOCK_LF_SRC_RC
  • .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM→NRF_CLOCK_LF_XTAL_ACCURACY_250_PPM

components/toolchain/system_nrf51.cとsystem_nrf51422.c

16MHzを32MHzに変更します。

#define __SYSTEM_CLOCK      (16000000UL)→(32000000UL)

ここまで直してNRF_LOGの中身がJLinkRTTのなかに表示されるようになります。APP_ERROR:ERROR:Fatalとだけ表示されるので、マイコンは動いていますがアプリは止まっています。

main.c

ble_stack_initのクロック設定を直します

nrf_clock_lf_cfg_t clock_lf_cfg = NRF_CLOCK_LFCLKSRC;の行は削除。かわりに

    nrf_clock_lf_cfg_t clock_lf_cfg;
    clock_lf_cfg.rc_ctiv = 16;
    clock_lf_cfg.rc_temp_ctiv = 2;
    clock_lf_cfg.source = NRF_CLOCK_LF_SRC_RC;
    clock_lf_cfg.xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_250_PPM;
を追加。

ここを直すとJLinkRTTにAPP:INFO:HID Mouse Start!というメッセージが表示されて、BLEの電波も飛ぶようになります。

直したけど関係なさそうな箇所

接続はするがペアリングはされない、という状況が起きていて、こういう投稿があったので試してみたら動いたんですが、このブログを書くにあたって再度いちばん最初の段階からやり直してみたら、この変更なしでもペアリングが済んでいて頭を抱えています。

2018年10月13日土曜日

ESP32をBluetoothマウスにする

ゲームボーイを無線マウスにした際に、Bluetooth側はESP32を使って実装しました。キーボードのサンプルコードに記載の関数群でマウスまでまかなえたので、使い方を記載しておきます。

ESP-IDFを使う

ESP-IDFのBluetooth Low Energyサンプルのうち、HID over GATTを使います。

ESP-IDF BLE HID device demo

ble_hidd_demo_main.cではほとんどConsumer Keyの送信しかしていないのですが、esp_hidd_prf_api.hにはきちんと関数が実装されています。

  • void esp_hidd_send_consumer_value(uint16_t conn_id, uint8_t key_cmd, bool key_pressed);
  • void esp_hidd_send_keyboard_value(uint16_t conn_id, key_mask_t special_key_mask, uint8_t *keyboard_cmd, uint8_t num_key);
  • void esp_hidd_send_mouse_value(uint16_t conn_id, uint8_t mouse_button, int8_t mickeys_x, int8_t mickeys_y);

いずれも、キー操作情報等の最低限のデータを入れればよしなに成形して無線で飛ばしてくれます。

マウス利用時のmouse_buttonは、レポートディスクリプタの0バイト目にああたります。下位3ビットに3ボタンマウスのそれぞれが割り当てられています。下から右・左・中ボタンになります。

2018年10月9日火曜日

技術書典ふりかえり

技術書典に本を出す側で参加したのでその記録です。

出した内容

  • ゲームボーイのカートリッジ基板の作り方をまとめたPDF
  • 実際に作ったカセットのデモ

本はPDF版のみにし、購入もすべてBoothで行ってもらう方法にしました。なので、現場での授受はそのBoothのURLとQRコードを印刷したカードのみです。ひとりチームなので金銭のやりとりとか決裁のトラブルとか抱えたくないのと、今後更新を行うときに購入してくれた人に損がないようにと考えてPDF版のみかつBoothのプラットフォームで更新通知を容易にしたいなと思ってこういう形にしました。もともと自分が調べたことを忘れないように書いた本の内容に、今後調べたり試したりして新しいことがわかったらとか改良の余地がありまくるので、そういうのが増えたら追記・更新したいんですよね。

カードの裏面は著者(というかおれ)の名刺代わりにしたので、余ってもあとで名刺として配ってアピールできるなと。

当日の様子

机の上は見本として印刷したPDFの中身と、実際に動作するゲームボーイのデモを置いておきました。他の振り返りの記事にあった「見本誌は2冊あったほうがいい」という内容を、本とデモ機でうっかり満たした感じがしました。

個人的には本を買ってもらうよりも「俺が作ったものが超おもしろいからおまえらも見ろ」という感じでデモ推しの気持ちだったので、Bluetoothマウスにしたゲームボーイを触ってもらって、おもしろかったらカードを持ち帰ってもらう、みたいな流れに落ち着きました。特定の年齢層だけは、説明する前から操作方法がバッチリはまる様子に最高に笑いました。

その他電気の気付き

  • マウスのデモに使ったMacBook Proは終了の17時ちょうどに電池が切れたのでギリギリもった
  • Bluetoothに使ったESP32がおもいのほか大健闘
    • モバイルバッテリーから電源を取ったが、容量ゲージが減る気配がない。
    • 会場の電波が落ち着いていて混信がなく、常時問題なく動作。

ESP32はデータシート上だと電流がそんなに消費しないと書いてあって本当かよって思っていましたが、Bluetoothだけだと本当にそんなに消費しないっぽいです。今度測ってみます。

https://niccolli.booth.pm/items/1026724

もし当日の本に興味があれば、上記リンク先から購入ください。デモがないとおもしろいところがわかりにくいと思いますが、何らか参考になれば幸いです。カードを持ち帰りいただいた方から、結構な数の購入をいただいた通知が来まして、ありがたい限りです。

2018年9月29日土曜日

ゲームボーイを無線マウスにする

ひとつ前の投稿でゲームボーイのカセットを作って遊んでいましたが、カセット側のRAMに値を保存すれば周辺部品と通信できるという仕組みは正式な製品でもたくさんつかわれている手法らしい。なので実装に挑戦しました。

とりあえずやりやすそうだった無線マウスをやってみたところ、期待どおり動いて安心。カセット側RAMはマイコンの中にいるので、保存された値はマイコンからいじり放題です。そのカセット側RAMにキー操作情報を入れて、マイコンからESP32に飛ばしています。

というような話をPDFにまとめて、技術書典5で紹介します。なんらか操作できるものを置いておく予定なので、試して笑う程度でも歓迎です。

2018年6月23日土曜日

ゲームボーイのカセットをつくった

よくよく考えてみたら、ゲームのカセットは中身が基板なので、このご時世ならつくるのはたやすいのではないかと思ってやってみたら、遠回りをしつつもうまく動いた。

なぜゲームボーイにしたのか

手元にあったから

実家に置きっぱなしだったのを回収してきて以来、電源の確保が容易なのでずっと遊んでいる。最近はSwitchを買ってしまいスプラトゥーンとプリパラが楽しいのでほったらかしになってきた。

どうかしてる機能を積んだカセットが多かったから

ファミコンやスーパーファミコンは、拡張機能は本体のポートに専用コントローラーやサテラビューみたいなのをつないで実現していたけれど、ゲームボーイはその辺をカセットの延長でつくっていた印象があって。ポケットカメラやカービィの傾きセンサーなんかがその例(個人の感想です)。今やるならBluetoothとか各種無線通信を載せていきたい。

作り方

海外は作っている人が少なからずいるので、そのへんの人の作例を参考に。

http://www.happydaze.se/wolf/
https://github.com/dwaq/Homebrew-Gameboy-Cartridge

カセット側の動作は基本的に

  • 16ビットのアドレスを受けて対応する8ビットの値を
    • 返す (ROM/RAM)
    • 保存する (RAM)
  • バンクを切り替える

なので、このあたりの配線がつながっていればOK。速度が速度なので、等長配線を気にする必要もない。

https://dhole.github.io/post/gameboy_cartridge_emu_1/

dholeさんがSTM32F4Discoveryをつかって、バンク切り替えの任天堂ASICの擬態を行いつつROM/RAMまでSTM32マイコンでまかなう方法を書いてくれているので、この通りに信号線をつなぐとこうなります。

直したい点

穴位置を間違えた

基板の端子情報をライブラリにしてる人がいるのでそのデータを使おうとするも、Eagleが慣れないのでCircuitMakerに持ってくる際に、大きいほうの穴位置がずれたらしく、カートリッジの筐体にすんなりはまらない。次つくることがあったら直す。

電源の使い勝手

ふつうカセットは外から何かするわけじゃないので、ゲーム機から電源をもらって動くのは当たり前の動作だけど、ゲーム機の電源とカセットの電源を別にしておかないと、マイコン側のデバッグで困る。ゲームボーイ本体の電源が入っていないと動作をデバッグできない。ジャンパ等で切り替えられるようにしたい。

2017年12月9日土曜日

100円SIMのいいところと面倒なところ

2017年7月、NTTコミュニケーションズが100円SIMのサービスを発表しました。価格から惹かれるところがあり内容を伺ったところ、周囲の人からも「あれどう?」ときかれたことがあったのでメモを残しておきます。

Arcstar Universal Oneのオプションのような位置づけ

NTTコミュニケーションズのVPNサービスArcstar Universal Oneの契約が必須(VPNに接続する回線の設置工事等も必要)であり、100円SIM単独での利用はできません。さくらやSORACOMのようにSIMを購入して使うのではなく、VPNサービスへの入り口としてSIMが100円で提供されるというものです。

Arcstar Universal Oneは仮想とはいえ閉じているので、デバイスからのセンシティブなデータでも比較的安全に送信ができます。保存するデータベースは、NTTコミュニケーションズが提供するVPN内のサーバを使うパターンと、VPNからAWSやMicrosoft Azureなどの各種クラウドサービスに接続するパターンが用意されています。

大規模な業務用途向け

最低発注数量は100枚という記載もどこかにあったので、外部に絶対に流出させたくないセンサーデータを安全かつ大規模に収集するような用途等、業務用として使うものということでした。また、記載のような業務用なので、NTTコミュニケーションズの営業さんへの見積もりが必須です。個人もしくは小規模での3G/LTE回線がほしいという話ならば、sakura.ioやSORACOMの利用を検討したほうがよいと思います。