C言語でEV3開発(19)
コマンド通信処理でEchoBackしてみた
どもです。
前回は、Bluetoothの接続状態の変化に伴う、状態遷移について書きました。
今回は、BluetoothでPCとEv3を接続してコマンドの送受信をしてみます。
1.コマンド
送受信するコマンドは、一番基本(と、考えている)の「EchoBack」コマンドです。
このコマンドでは、コマンドデータに乗せたデータがそのまま返されます。
コマンドフォーマットは、特に何かの規格に準拠する、というものではなく、完全に独自仕様としています。
具体的には、以下のように設計しています。
2.通信設計
通信をする場合には、送信側と受信側が存在します。
(当たり前ですね。)
そのため、通信を設計する際には、どちらを送信側にして、どちらを受信側にするかを決める必要があります。
「適宜切り替える」というのが、「もっともよい、あるべき姿」です。
しかし、この方式を実装するとなると、通信の制御がとても難しくなる。
「送信の衝突」を「0」から設計、実装することはできません。
スキルが足りません…。
なので、今回は以下のように固定します。
デバイス | 役割 |
---|---|
PC | 送信 |
Ev3 | 受信 |
PC側からEv3にコマンドを送信し、対応する処理を実施した後に結果/レスポンスを返すようにします。
コミュニケーション図は、下図の通りです。
送信側は、送信間隔を10msecに設計します。
従って、送信側は、コマンドを送信、レスポンスを受信後、10msec待ってから次のコマンドを送信します。
受信側は、受信したデータを、そのままレスポンスデータに乗せて返します。
コマンドデータを受信してからレスポンスを受信するまでは、特に間隔を設けません。
受信した先から、返信していきます。
ただし、次のコマンドを受信するまでは、少~し間隔を設けています。
また、Ev3では受信したデータをデバッグできません。
そのため、その代わりにコマンドを受信した回数をモニターするようにしました。
3.コマンド処理
実際にコマンドを受信、処理して返すまでの実装は以下の通りです。
void BtTask(intptr_t unused) {
while (bt_task_running) {
bt_task_count++;
port_check_connectoin();
port_read_data();
if (0 < bt_rcv_msg_len) {
cmd_hdl_count++;
cmd_sequence();
port_write_data();
port_reset();
}
dly_tsk(BT_TASK_INTERVAL);
}
}
処理の概要を説明すると、port_check_connectoin()でBluetoothの接続を確認し、port_read_data()でデータの読出しを行います。
データを受信していた場合には、cmd_sequence()で内容の確認とレスポンスデータの作成を行います。
cmd_sequence()の実装は、下記の通りです。
void cmd_sequence(void) {
cmd_latch_buff();
cmd_reset_snd_buff();
cmd_handle_main();
}
cmd_latch_buff()、cmd_reset_snd_buff()は、それぞれ関数名通りの処理を実施します。
で、cmd_handle_main()の中で実際にデータの処理を行います。
そのコードが、以下です。
void cmd_handle_main() {
char cmd_code = 0;
cmd_code = rcv_msg_buf[0];
switch (cmd_code) {
case 0x00: cmd_code00(); break;
default: cmd_invalid_code(); break;
}
}
void cmd_code00(void) {
uint8_t res = 0x00;
uint8_t cmd_data_len = 0x00;
uint8_t res_data_len = 0x00;
uint8_t sub_cmd_code = 0x00;
uint8_t sub_res_code = 0x00;
uint8_t *rcv_buf;
uint8_t *snd_buf;
int idx = 0;
rcv_buf = (uint8_t *)(&rcv_msg_buf[3]);
snd_buf = (uint8_t *)(&snd_msg_buf[4]);
sub_cmd_code = rcv_msg_buf[1];
cmd_data_len = rcv_msg_buf[2];
sub_res_code = sub_cmd_code;
if ((!(0 < cmd_data_len)) || (!(cmd_data_len < 30))) {
res = 0xFE;
}
if (0x00 != sub_cmd_code) {
res = 0xFD;
sub_res_code = 0xFF;
}
if (0x00 == res) {
for (idx = 0; idx < (int)cmd_data_len; idx++) {
*snd_buf = *rcv_buf;
snd_buf++;
rcv_buf++;
}
res_data_len = cmd_data_len;
} else {
res_data_len = 0;
}
snd_msg_buf[0] = 0x01;
snd_msg_buf[1] = sub_res_code;
snd_msg_buf[2] = res;
snd_msg_buf[3] = res_data_len;
snd_msg_len = 4 + res_data_len;
}
4.実際に動かしてみた
実際に動かしている様子の動画は、以下の通りです。
映像の後ろの方に映っているのは、PCツールで送信/受信しているデータです。
Ev3では、BLT_TSK_CNT、CMD_HDL_CNTの値が増加しています。
この値は、コマンドの受信/送信タスクと、実際に受信/送信(返信)したコマンドの数です。
PCツールからコマンドを送信、レスポンスを受信するタイミングと、Ev3の画面上のこれらの値が更新されるタイミングが一致しています。
このように、PCツールからEv3に対してコマンドデータを送信することが可能になりました。
5.まとめ
今回のエントリーでは、実際にコマンドを送受信する機能を紹介しました。
今後は、今回紹介した通信機能を用いて、Ev3で組み立てた車を制御していく仕組みを紹介します。
2017/07/15 追記
今エントリーのソースコード一式を公開しました。
ココからダウンロードできます。
ディスカッション
コメント一覧
まだ、コメントがありません