前回、BrainuxをリビルドしてUSB CDC ACMを有効にしたことで、MachiKaniaとのpcconnect接続ができるようになりました。
電子辞書 Brain のLinux (Brainux) をリビルドしてUSB CDC ACMを有効にする(Windows11 WSL2でクロスコンパイル)
今回はその続きで、MachiKania用のpcconnectをBrainux上で動かしつつ、BASICファイルの転送・実行・結果表示・リセット復帰までを自動化するよう改良してみました。
Raspberry Pi Picoで動作するMachiKania Type-Pと、SHARP Brain上で動作するBrainuxを組み合わせて、BrainuxからMachiKaniaのプログラムを開発できる環境を作っています。
MachiKaniaはBASICインタプリタではなく、BASICプログラムをその場でコンパイルして実行する仕組みになっています。(自動でコンパイルされる)
今回の目的は、
- Brainux上でBASICファイルを編集
- MachiKaniaへ転送 & コンパイル・実行
- 実行結果をBrainuxのターミナルで確認
- MachiKaniaをリセット(手動)
- 再度自動的にBASICを転送
という開発サイクルを、できるだけ簡単に繰り返せるようにすることです。
そのため、MachiKania用のPC接続プログラムpcconnectをBrainux上で動作させ、さらにUSB接続が切れた場合や、MachiKaniaをリセットした場合にも自動的に復帰できるよう(ChatGPTの力を借りてw)改良しました。
1. MachiKaniaのpcconnectの動作を確認
MachiKaniaにはPCとのファイル転送を行うためのpcconnectがあります。
詳細は下記
MachiKania type Pの開発環境 » 電子ブロック工房
Brainuxをリビルドして USB CDA ACMを有効化することで、このプログラムをBrainux上でコンパイルして動かすことができ、MachiKaniaへMACHIKAP.BASなどのBASICファイルを転送できるようになりました。
Brainux側ではUSB CDC ACMを使用しているため、MachiKaniaとの通信には /dev/ttyACM0 を使用します。
オリジナルの connect.c は、MachiKaniaから決められた16バイトのコマンドを受信すると、それに応答してファイルを転送するという構造でした。
基本的な通信シーケンスは次のようになっています。
MachiKania → Brainux
MACHIKAP
Brainuxから
OK
を返すと、MachiKaniaから
SENDCMDS
が送られてきます。
その後、Brainux側からディレクトリ変更、ファイル名、ファイルサイズ、ファイル本体などを送信します。
最終的には
DONEDONE
を送信し、MachiKaniaから
ALL DONE
が返ってくる。という流れです。
これを繰り返します。
2. 「MachiKaniaは何を送っているのか」を調べる
BrainuxからMahciKaniaにファイル転送はできるようになりました。
そして、これは偶然なのですが、何度かMachiKaniaでリセットを繰り返しているうちにMachiKaniaの画面で表示されるはずのPRINT文での表示がBrainux画面に表示されたことがあり、もしやと思いChatGPTと相談しながらMachiKaniaから何が送られてきているのかの解析を開始しました。
ChatGPTの指示のもと pcconnect にデバッグ処理を追加して、USBシリアルから受信したデータを記録して確認しました。
すると、MachiKaniaをリセットした後には、
MachiKania BASIC System
Ver Phyllosoma 1.7.1.0
BASIC Compiler KM-1513 by Katsumi
LCD, File, & Keyboard systems by KENKEN
Compiling MACHIKAP.BAS
3848 micro seconds spent for compiling
といった文字列が送られてきていることが分かりました。
さらに、送信したプログラム(PRINT "HELLO MachiKania")の実行結果
HELLO MachiKania
もUSBシリアル経由で送られてきていることを確認。
つまり、「MachiKaniaのLCDに表示されている情報の一部を、Brainux側でもUSBシリアルから受信できる」ことが分かりました。
ここで重要なことが分かりました。
USB CDC ACMの通信では、
read(fd, buf, sizeof buf);
を1回呼んだからといって、必ず1つのメッセージが返ってくるわけではありません。
例えば、
MACHIKAP........
を受信した直後に、
MachiKania BASIC System
まで同時に受信することがあります。
逆に、1つの通信データが複数回のread()に分割される場合もあります。
そのため、read()したデータ = 1つのコマンド、と考えてしまうと、通信処理が不安定になります。
また、元のwait4command()は、受信したデータを16バイト単位のコマンドとして検索していました。
例えば、
char request[16];
に1バイトずつ入れて、
if (!strncmp(request,command,16))
return;
という方法です。
これは基本的な通信には使えますが、1回のread()で、
MACHIKAP........
MachiKania BASIC System...
のように複数の情報を受信した場合、目的の16バイトを見つけたところで関数から戻ってしまい、その後ろに続いていたデータを取りこぼす可能性があります。
そこで今回の改修版では、
unsigned char g_rx_buffer[RX_BUFFER_SIZE];
int g_rx_length=0;
という受信バッファを追加しました。
受信したデータを一度バッファに保存し、その中から目的の16バイトコマンドを検索します。
コマンドを見つけても、その後ろに続くデータは消さずに残します。
これが今回の改修で重要なポイントの一つです。
3. MachiKaniaをリセットするとttyACM番号が変わる
さらに実際に使っていると、
/dev/ttyACM0
だったMachiKaniaが、リセット後に
/dev/ttyACM1
になることが稀にですがありました。
これはUSBデバイスが一度切断されて再接続されるためです。
そのため、/dev/ttyACM0 を一度開いたらそのデバイスをずっと使い続ける、という設計では不十分でした。
そこで改良版では、
/dev/ttyACM0
/dev/ttyACM1
/dev/ttyACM2
...
/dev/ttyACM9
を順番に探すようにしました。
これにより、MachiKaniaのリセット後にLinux側でttyACM0からttyACM1へ変わっても、自動的に再接続できます。
また、USBケーブルを抜いたりMachiKaniaをリセットしたりすると、シリアルデバイスが一時的に消えることがあります。
そこで通信待ちにはpoll()を使用しました。
poll(&pfd,1,100);
でシリアルポートの状態を監視し、POLLERR / POLLHUP / POLLNVAL などを検出した場合は、
- 古いファイルディスクリプタを閉じる
- /dev/ttyACM0~/dev/ttyACM9を探す
- 新しいシリアルポートを開く
- 通信を再開する
という処理を行います。
これによって、USB接続が一度切れても、プログラムを再起動せずに復帰できるようになりました。
4. ファイル転送後のMachiKaniaの出力を受信する
元のpcconnectではファイル転送が完了すると、「All done!」となりますが、ここでプログラムを終了するのではなく、そのままMachiKaniaから送られてくる文字を表示するようにしました。
例えば、
--- MachiKania output --- Hit any key to continue.
MachiKania BASIC System
Ver Phyllosoma 1.7.1.0
BASIC Compiler KM-1513 by Katsumi
LCD, File, & Keyboard systems by KENKEN
Compiling MACHIKAP.BAS
3848 micro seconds spent for compiling
HELLO MachiKania
というように、MachiKania側の実行結果をBrainuxのターミナルで確認できます。
ここで表示している「--- MachiKania output --- Hit any key to continue.」は、一時停止するためのプロンプトではありません。そのままMachiKaniaからの出力を表示し続けます。
5. BASICが無限ループしてもキー入力で戻れるようにする
この機能を作っていて、もう一つ重要な問題がありました。
例えば、
10 PRINT "HELLO"
20 GOTO 10
のようなプログラムをMachiKaniaで実行すると、いつまでもHELLOと出力され続けます。
そこでBrainux側では、MachiKaniaの出力を受信している最中でもキーボードを監視するようにしました。
Brainux側で何かキーを押すと、
Key pressed. Waiting for the next MachiKania reset...
と表示され、MachiKaniaからの出力表示を抜けます。
そして「Waiting for request...」に戻り、MACHIKAPという次のリセット要求を待ちます。
つまり、
- BASIC実行
- MachiKania出力を表示
- 無限ループしてもOK
- Brainuxでキー入力
- 次のMachiKaniaリセット待ち
- MachiKaniaをリセット
- BAS転送
- コンパイル・実行
という開発サイクルになりました。
6. 最終的な動作
最終版では、Brainux上でプログラムを起動すると、
Opening INI file...
found
Serial port: /dev/ttyACM0
Transfer files in : machikap/
Transfer following files:
machikap/MACHIKAP.BAS
open serial port...opened as 5
Waiting for request...
という状態になります。
MachiKaniaをリセットすると、
Request detected!
Waiting for SENDCMD...OK
...
All done!
となり、続いて
--- MachiKania output --- Hit any key to continue.
MachiKania BASIC System
Ver Phyllosoma 1.7.1.0
BASIC Compiler KM-1513 by Katsumi
LCD, File, & Keyboard systems by KENKEN
Compiling MACHIKAP.BAS
...
HELLO MachiKania
と表示されます。
何かキーを押すと、
Key pressed. Waiting for the next MachiKania reset...
となり、再びリセット待ちになります。
この状態でMachiKaniaをリセットすれば、再度BASファイル転送から自動的に始まります。
7. 確認手順
今回の環境を再現する場合は、次の順番で確認できます。
① MachiKaniaを接続する
BrainuxとMachiKaniaをUSBで接続します。
まず、
ls -l /dev/ttyACM*
でUSB CDC ACMデバイスを確認します。例えば /dev/ttyACM0 が表示されます。
② 転送するBASICファイルを用意する
connect.iniの設定に合わせたディレクトリにMACHIKAP.BASを置きます。
ls machikap/
としてMACHIKAP.BASが確認できればOKです。
③ コンパイル
gcc -O2 -Wall -o connect_receive_wait_reconnect connect_receive_wait_reconnect.c
④ プログラムを起動
./connect_receive_wait_reconnect
すると「Waiting for request...」となります。
⑤ MachiKaniaをリセット
MachiKaniaをリセットすると「Request detected!」となり、BASICファイルの転送が始まります。転送完了後「All done!」となります。
⑥ MachiKaniaの実行結果を確認
続いて「--- MachiKania output --- Hit any key to continue.」の後ろにMachiKaniaの起動メッセージ、コンパイル結果、BASICプログラムの出力などが表示されます。
⑦ キー入力で次のリセット待ちへ
MachiKaniaの出力表示中にBrainux側で何かキーを押します。
Key pressed. Waiting for the next MachiKania reset...
となれば成功です。そのままMachiKaniaをリセットすると、再びBASファイル転送が始まります。
8. 通信プロトコル
今回使用している通信プロトコルは、元のpcconnectに記載されているものを基本的に維持しています。
概要は次の通りです。
MachiKania → Brainux
MACHIKAP + 8個のBS
↓
Brainux → MachiKania
OK + 4組のOK/BS
↓
MachiKania → Brainux
SENDCMDS + 8個のBS
↓ ファイル転送(CD: / CP: / SIZE: / SENDFILE / BASICファイル本体を256バイト単位で送信 / DONEDONE)
↓
ALL DONE
という流れです。
今回の改修では、この既存プロトコルを変更するのではなく、USB切断・再接続への対応、受信バッファ、MachiKania出力の受信、キー入力による復帰を追加しています。
9. 改修版プログラム(connect_sndrcv.c)
改修したプログラムはGitHubにアップしています。
GitHub - momoji-san/mk_connect_sndrcv: MachiKania file send and receive · GitHub
( [<>Code] ボタンをクリックして Download ZIP でダウンロード)
ダウンロードした zipファイルの中にある connect_sndrcv.c をBrainに転送して、下記でコンパイルしてください。(実行ファイルを b.out とした場合)
gcc -O2 -Wall -o b.out connect_sndrcv.c
基本的な使い方はオリジナルのconnect.c(a.out)と同じですが、上記 GitHubに使い方を記載しています。
まとめ
今回の改良で、MachiKaniaとBrainuxの関係が、「単にBASICファイルを転送するだけ」から、「BrainuxをMachiKaniaの開発環境として使う」ところまで可能になりました。
そして、MachiKaniaからプログラムの実行結果をターミナルに表示できることが確認できたので、AIを利用した最近はやりの「バイブコーディング」も将来的には可能になるかもしれません。
下記、このプログラムの実行動画です。
動画では、ターミナルを Alt+矢印キーで切替えて、転送するプログラムを修正しています。
BrainuxでAlt+矢印キー(左右)でターミナル切替ができるのか!(tty1~6)知らなかった なので、tty1でpcconnectでファイル転送&MachiKaniaのコンパイル結果表示して、tty2でBASファイルを編集&保存ってことができる #MachiKania #Brain https://t.co/FyngsEP9lX
— momoji (@XGT66860) September 29, 2026
















