後輩たちのためのEV3rt講座⑪(UART通信)

#はじめに
事の始まりは2019年のロボカップジュニア・ジャパンオープン大会を観戦しに行った時、WROとは違いロボットの作製にあたって制限が少なく、個性豊かなロボットが多く見られた。
ロボカップとWROの難易度を比較するわけではないが、ロボカップの方がセンサーを多く使用しなければならない傾向にある。しかしながらEV3には入力ポートが4つしか無い。
ここで登場するのが**デイジーチェーン**である。
![6a0120a6ffc261970b019b002de736970d-320wi.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/ae66d1ed-26f0-049d-01cd-e10adeb4d124.jpeg)
(画像は[『ロボジョイくらぶ・マイスターブログ　EV3のデイジーチェーンモード』](https://nxt.typepad.jp/robojoy/2013/10/daisychain.html)より)
親機となるインテリジェントブロックに子機となるインテリジェントブロックを接続し、ポートを増やすという方法。
開発をEV3だけに統一することができるため、初心者によく用いられる簡単な手法である。

ここで私はあることを感じた。
「EV3rtでデイジーチェーンは可能なのか？？」

言うのを忘れていたが、EV3rtはデイジーチェーンをサポートしていない。
中の人によると今後の開発課題であるらしい。

私は選手が会場で競技を行っている中、[EV3rtのC言語Reference](https://www.toppers.jp/ev3pf/EV3RT_C_API_Reference/index.html)とにらめっこしていた。
そして、気になる記述を見つけた。
![スクリーンショット 2019-06-13 15.46.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/f52afc98-baf5-4ac2-dc6f-1c8d604c6c6e.png)

「『ゆーえーあーるてぃー』ってなんぞや？」

#UARTとは
界隈の人なら知ってて当たり前。~~「なんでお前知らんねん」~~

はい、頑張って調べました。
ざっくりいうと、**非同期式の通信部品・方式**の一つで、シリアル通信とパラレル通信を変換するものだそう。
NXTではI2Cで通信をしていたが、EV3ではこれに加えUARTで通信できるようになった。

詳しくはこちら->[電子工作初心者のために シリアル通信方式を分かりやすくまとめてみた](https://qiita.com/Gri_Gra/items/b6f901b35d3917ffc580)

#EV3rtとUART
[私のUARTの記事](https://qiita.com/koushiro/items/772dca79b25ed4e5bfbe)でお伝えしましたが、EV3はセンサーポート1からUARTの信号を入出力することが出来ます。
そして、EV3rtはソフト側でこれをサポートしています。
ここでキーとなるのが、[EV3rtのBluetooth通信](https://qiita.com/koushiro/items/e985c953116c0399bd47)です。
あの時、Bluetoothの接続を仮想シリアルポートに繋ぐものとし、１つの**ファイル**としてプログラムを組みましたよね。
なんと、UARTも、１つの**ファイル**として扱うことができるのです!!素晴らしい!!

百聞は一見にしかず、Referenceを見てみましょう。
![スクリーンショット 2019-06-13 16.11.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/533af913-f8d8-a523-db62-f78c9ae689ea.png)
引数を見ると**`serial_port_t`**となっているのがわかるでしょうか。
ここで先程の画像を見ていただきたいのですが、ここで引数に`EV3_SERIAL_UART`を指定することで任意のデバイスとUART通信ができるのです!!

#実際の使い方
もうここからはBluetoothの時とほぼ変わりませんが、とりあえずやってみましょう。
今回は[Connect to EV3](https://qiita.com/koushiro/items/dffdd4375d3ce110cb41)のソース・コード一部抜粋したものを例に見てみたいと思います。

##接続する時

```app.c
static FILE     *bt = NULL;  //ファイルポインタ   

switch (mode)
    {
        case 0:
            bt = ev3_serial_open_file(EV3_SERIAL_BT);
            ev3_lcd_fill_rect(0,0,EV3_LCD_WIDTH,EV3_LCD_HEIGHT,EV3_LCD_WHITE);
            ev3_lcd_draw_string("Please Start",20,0);
            ev3_lcd_draw_string("BT Mode",20,20);
            break;
        case 1:
            bt = ev3_serial_open_file(EV3_SERIAL_UART);
            ev3_lcd_fill_rect(0,0,EV3_LCD_WIDTH,EV3_LCD_HEIGHT,EV3_LCD_WHITE);
            ev3_lcd_draw_string("Please Start",20,0);
            ev3_lcd_draw_string("UART Mode",20,20);
            break;
        default:
            bt = ev3_serial_open_file(EV3_SERIAL_BT);
            ev3_lcd_fill_rect(0,0,EV3_LCD_WIDTH,EV3_LCD_HEIGHT,EV3_LCD_WHITE);
            ev3_lcd_draw_string("Please Start",20,0);
            ev3_lcd_draw_string("BT Mode",20,20);
            break;
    }
```

本プログラムは`mode`という変数でBT接続とUART接続を切り替えられるようになっています。
でも違いはファイルポインタ`bt`に**`ev3_serial_open_file(EV3_SERIAL_BT);`**と書き込むか、**`ev3_serial_open_file(EV3_SERIAL_UART);`**と書き込むかの違いだけです。
超簡単ですね!!

##データの受信

```app.c
while(1){
   uint8_t c = fgetc(bt);
   if(c=='1'){
       break;
   }
}
```

これはプログラム冒頭のPCとの同期部分です。
PC側から'1'という文字が送られてきたらbreakし、この先のメインプログラムのサイクルハンドラへと進んでいきます。
注目してもらいたいのは`fgetc関数`です。
BT通信のときにもお伝えしたとおり、C言語標準のファイル操作関数を使用できます。
ということは、fgetc以外にも…

```app.c
fgets(str,5,bt);
```
こんなのも使えます。
(意味はファイルポインタ`bt`から4文字分受け取り、char配列`str`にブチ込む。(指定引数が5なのは一番最後にヌル文字が入るからです。詳しくはググってください。))

##データの送信

```app.c
fprintf(bt,"%d\r\n",data[0][0]);
```
先程同様、C言語標準のファイル操作関数である`fprintf関数`を使用しています。
(意味はファイルポインタ`bt`にint二次元配列`data`のインデックス[0][0]の値と改行コード`\r\n`を送信)

ちなみに、あまりにもソースコードが汚かったためわかりやすくしましたが、実際この関数に引数を何十個も入れて全センサーの値をPC側に送信しています。

#デイジーチェーンの話はどこへ行った？
はい、今模索中です。
というのも学業及び生活のほうが忙しく、それどころではないので中断中ですが、来年になったらまた再開したいと思います。
最終目標はEV3rtでのデイジーチェーンです。
本物と遜色ない程度に仕上げたいですねぇ。

何かアドバイス等あればコメントお願いします。
うちのクラブでもEV3rtでロボカップ出場を若干検討していますので〜〜

次回:**未定**
前回:[第10回](https://qiita.com/koushiro/items/e985c953116c0399bd47)