EV3RTを使ってみる(2)

Toppers/EV3RTを使ってプログラムを作成したときの記事です。
この記事を書いた時のEV3RTのバージョンはβ3です。
目次はこちら

前回サンプルプログラムを動作させることができましたので、今回は自分で作ったプログラムを動かしていこうと思います。最初に作るプログラムといえばHelloですね。公式Wikiにも開発方法の説明がありますが、Wikiに書かれている方法とは少し違って、スクラッチから書いていく方法を試してみます 1

まずは、workspace(サンプルプログラムが入っている場所)に新しいディレクトリを作成します。適当にhelloというディレクトリを作成しました。

$ mkdir hello
$ ls
Makefile  gyroboy  helloev3      linetrace  test-cpp  trike
common    hello    hwbrickbench  loader     test-cyc

作成したディレクトリの中にプログラムを作っていくのですが、作成したプログラムをビルドするときに必要となるファイルが上のcommonディレクトリに入っていますので、最初にcommonディレクトリの中のファイルをhelloディレクトリにコピーします。あと、Makefile.incという名前のファイルも必要なので空ファイルを作っておきます。

$ cp common/* hello/
$ touch hello/Makefile.inc
$ ls hello
Makefile.app  Makefile.appmod  Makefine.inc  app_common.cfg

app_common.cfgというファイルまでコピーされていますが、このファイルは無くても問題ありません 2

次に、プログラムを書いていきます。必ずapp.cという名前のソースファイルが必要となるので、app.hとapp.cを作成して、メインの処理を行う関数main_taskを書いていきます 3

まず、app.hは関数の宣言を書くだけです 4

extern void main_task(intptr_t exinf);

次に、ソースファイルを作成していくのですが、単純にHelloと表示するだけでは寂しいので、0.1秒おきにバッテリ電圧とシステム時間を表示するプログラムにしてみました。ev3_*という関数はEV3を制御するためのAPIです。また、tslp_tskという関数はtoppersのAPIで、C言語のselectやJavaのwaitと同じような使い方ができそうです。

#include "ev3api.h"
#include "app.h"

void main_task(intptr_t unused) {
  int battery;
  ulong_t time;
  char battery_str[32];
  char time_str[32];

  while(1){
    battery = ev3_battery_voltage_mV();
    get_tim(&time);

    sprintf(battery_str, "Battery: %d", battery);
    sprintf(time_str, "Time: %ld", time);

    ev3_lcd_set_font(EV3_FONT_MEDIUM);
    ev3_lcd_draw_string("HELLO", 20, 20);
    ev3_lcd_draw_string(battery_str, 20, 40);
    ev3_lcd_draw_string(time_str, 20, 60);

    tslp_tsk(100);
  }
}

最後に、これらのファイルをビルドするための設定ファイルを用意します。この設定ファイルの名前もapp.cfgにしなくてはなりません。このファイルで関数main_taskをタスクに登録するため、main_taskの宣言をしているapp.hを読み込む必要があります。また、コンパイル後にできたオブジェクトファイルapp.oを組み込むように登録しておきます。CRE_TSKというのはToppersの静的APIというものだそうで、この部分で関数main_taskを実行するタスクを作成しています 5

INCLUDE("app_common.cfg");

#include "app.h"

DOMAIN(TDOM_APP) {
CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, TMIN_APP_TPRI + 1, STACK_SIZE, NULL });
}

ATT_MOD("app.o");

最終的に用意したファイルの一覧です。

$ ls hello
Makefile.app     Makefile.inc  app.cfg  app_common.cfg
Makefile.appmod  app.c         app.h

後はビルドしてEV3に転送すれば作成したプログラムが動作します。ビルドとEV3への転送方法は前回と同じ方法で行いました。

$ make mod=hello
rm -rf /opt/ev3rt/workspace/OBJ
configure: Generating Makefile.appmod from ../hello/Makefile.appmod.
...
  LD      app
$ lsz app > /dev/tty.MindstormsEV3 < /dev/tty.MindstormsEV3
Sending: app
Bytes Sent:  88383   BPS:3753                            

Transfer complete

実行すると、Helloという文字列とバッテリ電圧とシステム時間だけが表示されます。EV3のバッテリ電圧は安定しているみたいですね。
2015-03-04-1

Notes:

  1. 現在(2015年3月4日)のところは既存のサンプルプログラムを拡張する方法が書かれています。
  2. あっても問題ありません
  3. 後でこの関数名を登録するので、他の関数名にしても動かすことはできます。
  4. サンプルプログラムではTOPPERS_MACRO_ONLYという定義のチェックをしていますが、これはアセンブラからC言語のヘッダファイルを読み込むための定義のようですので、アプリケーションには不要、、、だと思います。
  5. このタスクを自動で実行するためにTA_ACTを指定しています。あとはタスクの優先度とスタックサイズを指定しています。

EV3RTを使ってみる(1)

Toppers/EV3RTを使ってプログラムを作成したときの記事です。
この記事を書いた時のEV3RTのバージョンはβ3です。
目次はこちら

ETロボコンに参加しようと思っているので、その準備を開始しました。先日、ETロボコン2015の実施説明会も開催されたようですし、去年のように本番直前になって慌てるなんてことにならないようにしなければ。

というわけで、2012年に買ったMacBookAir(OSX ver.10.9.5)に開発環境の1つであるEV3RTをインストールしてみました。公式のWikiにインストール方法が丁寧に説明されていますので、これに従ってインストールすればサンプルプログラムをコンパイルするところまで行けます。ただし、GNUツールチェーンのバージョン違いには注意。1つ古いバージョンのGNUツールチェーンではサンプルプログラムをコンパイルできませんでした 1

2015-03-03-1さて、サンプルプログラムをEV3本体で動かすためにmicroSDカードを買ってきて 2、そのmicroSDカードのルートディレクトリにアプリケーションローダであるsdcard/uImageをコピーして、このSDカードをEV3のスロットに入れて電源を入れるとアプリケーションローダの画面が表示されます。ちなみに、差し込んだSDカードは簡単には取り出せません。テープを巻いて取り出しやすくしている人もいるようですが、私は「毛抜き」で無理やり抜いています 3

次に、コンパイルしたサンプルプログラムをEV3に移すのですが、なんとかコマンドラインからBluetooth経由で転送したいので、ZMODEMのプロトコルを話すソフトウェア lrzsz (ver.0.12.20) をインストール。このソフトウェアに lsz という名前のプログラムが入っていて、このプログラムがZMODEM経由のファイル送信をしてくれます。

あとは、EV3本体側をBluetoothからアプリケーションをロードする状態にして、ノートPCとEV3本体のBluetooth通信をペアリングして、コンパイルしたサンプルプログラムをEV3本体に転送すればEV3本体でサンプルプログラムが動作します。

というわけで、サンプルプログラムのコンパイルからEV3本体に移すまで:

まずは、サンプルプログラムのコンパイル。今回はhelloev3を試してみました。作業するディレクトリや作成されるファイルの名前などは公式Wikiに書いてあります。

$ make mod=helloev3
rm -rf /opt/ev3rt/workspace/OBJ
configure: Generating Makefile.appmod from ...
...
...
  LD      app

次にプログラムを転送する前に、Bluetoothのペアリングをして、Bluetoothのシリアルポートデバイスを確認。環境によってデバイスの名前が違うかも。

$ ls -l /dev/tty.MindstormsEV3
crw-rw-rw- 1 root wheel 33, 12  3  3 17:42 /dev/tty.MindstormsEV3

このシリアルポートデバイスを経由してファイルデータを転送します。ZMODEMは応答メッセージを返すタイプのプロトコルですので、lszの入力側にもリダイレクトが必要です。また、データ量の割に時間がかかるので気長に待ちます 4

$ lsz app > /dev/tty.MindstormsEV3 < /dev/tty.MindstormsEV3
Sending: app
Bytes Sent: 127963   BPS:3787                            

Transfer complete

とりあえず、成功しました。
2015-03-03-2

Notes:

  1. ちなみに、同じバーションのGNUツールチェーンでEV3RTとNextOSEKの両方に対応できます。NXTの開発もできます。たぶん、私はしませんけど。
  2. 人生で初めてmicroSDカードを買いました。もちろん、既に手元にある人はそれを使っても構いません。
  3. お手軽ですがお勧めはしません(笑)
  4. 私の環境だと10秒〜20秒ぐらい。