かれこれこのシリーズも10回目ですね(正確には12本記事がありますが…)
#前回のおさらい#
前回の記事、Bluetooth環境開発編で、PCとEV3を接続することまでは完了しました。
今回は、実際にプログラムを書いてPCとEV3との間でデータをやりとりしてみたいと思います。
#通信には大きく3つある#
PCとEV3の間でデータをやりとりする方法は以下の方法があります。
①HRP2カーネルのシリアルインターフェスドライバを利用する
②ログタスクsyslogを使用する
③ファイルとして扱う
①に関しては私は全く無知です。ただEV3rtのホームページに載っているのでそれを確認していただけたら良いかと思います。
②はEV3rtのログとして出す方法です。デフォルトではEV3rtのログは本体のコンソールに表示されますが、その設定を変更することでBluetoothで接続されたPCに出すことが出来ます。
詳しくは @yamanekko さんの記事『EV3RTでログをリアルタイムに見る方法』を御覧ください。
詳しく紹介してくださっています。
ということで、今回私が紹介するのは③の「ファイルとして扱う」方法です。
#通信の基本概念#
C言語にはファイルを扱う関数が標準搭載されていますよね。
stdio.h
をincludeすることで使うことが出来ます。
これは通常の場合、そのハードのボリュームにあるファイルに対して、操作を行うことが出来ますが、この関数をBluetooth通信に用いる事ができるのです。
この方法、何がいいかと言うと、新たに特殊な関数を用いる必要がないのです。
今まで通り、ファイルに書き出すかのように通信ができるのです。
僕は非常に便利な機能であると思っています。
ということで、実際にどのようにプログラミングするのかを以下記します。
#プログラミング方法#
##設定##
#include "ev3api.h"
#include "app.h"
#include <stdio.h> /* ファイル関数を使うため*/
#if defined(BUILD_MODULE)
#include "module_cfg.h"
#else
#include "kernel_cfg.h"
#endif
#define DEBUG
#ifdef DEBUG
#define _debug(x) (x)
#else
#define _debug(x)
#endif
static FILE *bt = NULL; /* Bluetoothファイルポインタの宣言*/
void main_task(intptr_t unused)
{
まずはここまでの説明を。
先程言ったように、#include <stdio.h>
でファイル操作関数が使えるようにします。
続いて、static FILE *bt = NULL;
では、ファイルポインタを宣言しています。
今はNULLになっていますが、このあとBluetooth経由仮想シリアルポートを開通させて指定します。
では続きを・・・
void main_task(intptr_t unused)
{
bt = ev3_serial_open_file(EV3_SERIAL_BT);
assert(bt != NULL);
さて、bt = ev3_serial_open_file(EV3_SERIAL_BT);
の文ですが、これだけはEV3rt専用関数ですね。
ここで先程定義したファイルポインタbtに対して、Bluetooth経由仮想シリアルポートを指定します。
実際にファイルが作成されるわけではありません。あくまでデータのやりとりです。
そしてその下のassert(bt != NULL);
ですが、これはbtがちゃんと設定されているかをチェックするものです。
失敗しているとここでプログラムが停止します。
ここまで出来たら、もう設定は完了です!!
あとは基本的に好きなように通信ができます。
##通信##
では、いくつか通信の例を出してみます。
###fgetc関数(PC→EV3)###
while(1){
uint8_t c = fgetc(bt);
if(c=='1'){
bt_cmd = 1;
}
if (bt_cmd == 1){
break;
}
}
こちらはfgetc関数を使った例です。
fgetcは1文字単位で読み込む関数です。
例では、PC側から1
を送信したらbreakするというようになっています。
###fgets関数(PC→EV3)###
char str[5];
while(1){
fgets(str,5,bt);
ev3_lcd_draw_string(str,30,0);
}
fgets関数はfgetcと似ていますが、読み込む文字数を指定できます。
例の場合、「strというchar配列に、5-1=4文字分、btから取得する」という感じです。
この5-1=4文字分というのがミソで、配列の最後にナル文字(\0)が入るため、読み込みたい文字数nに対してn+1を指定しないと正しく通信できません。
ここで注意点ですが、指定文字数の違う関数は混ぜて使わないほうが良いです。
通信するライン(専門的にはstream)は1本しかないので、「A用のデータがBにいっちゃった」なんてこともありえます。
特にコマンド等に使用する場合は、文字数を一つに決めておきましょう。
###fprintf関数(EV3→PC)###
fprintf(bt,"%d\r\n",ev3_color_sensor_get_reflect(0));
これは単純明快ですね!
ファイルポインタbtを用いてカラーセンサーの値を送信します。
今回3つの関数を紹介しましたが、他にもファイル操作関数はたくさんあります。
自分の用途にあったものを選択すると良いでしょう。
#PC側の操作#
ここまでずっとEV3側の話をしてきましたが、PC側はどうすればよいのか?
その話を最後にしておきます。
##WindowsのTeraTermは特に問題ない##
Windowsユーザーの方々は基本的にapp送信にTeraTermを使用していることと思います。
TeraTermは特に設定しなくても、あの真っ黒の画面を用いてデータの送信、受信ができます。
送信するときは当然ながらキーボードで入力してください。
##問題はMacユーザー…##
Macは非常に複雑です。
状況を整理すると、Macユーザーは基本的にapp送信にminicomを使用しているでしょう。
しかし、minicomはデータの送信が出来ません。(受信は出来たり出来なかったり、僕もよくわからん…)
ということで対処法をお伝えします。
###screenコマンドを使う###
Linuxデバイス同士で使うことができるコマンドです。
これを使うにあたってEV3の端末名が必要です。
デフォルトでは/dev/tty.MindstormsEV3-SerialPor
になっています。
(見覚えのある人はなかなか鋭い)
確認する方法は
$ ls /dev/tty.*
です。Macに保存されているデバイスの一覧が出てきます。
それでは実行していきますが、minicomは起動した状態でおいておきましょう。
ターミナルの違うウィンドウ(もしくはタブ)を開いて、以下のようにします。
$ screen /dev/tty.MindstormsEV3-SerialPor
実行しても何も出てきませんが、ちゃんと接続されていれば、この状態でデータの送受信が出来ます。
#まとめ#
ということで、今回はBluetoothを介したデータのやりとりについて紹介しました。
あ、ちなみに、
私が年末発表したEV3rt汎用Bluetoothロガーは、この技術をもとに開発しました。
なかなかいい感じに出来ているので良かったら見てください〜