#3 アプリケーション開発のおやくそく【もっと!後輩たちのためのEV3rt講座】

# 目次

| 章 | タイトル | 内容 |
|:-:|:-:|:-:|
| 1 | [はじめに](#1-はじめに) | 今回やることの説明 |
| 2 | [SDカードに入れるファイルについて](#2-sdカードに入れるファイルについて) | SDカード内に保存する各種ファイルについて説明 |
| 3 | [プロジェクトについて](#3-プロジェクトについて) | 1つのプロジェクト単位について説明 |
| 4 | [プロジェクト内のファイルについて](#4-プロジェクト内のファイルについて) | 4つのファイルの役割について説明 |
| 5 | [テンプレートプロジェクトの作成](#5-テンプレートプロジェクトの作成) | 新しいプロジェクトを作るときのテンプレートを作成しておく |
| 6 | [コンパイルの方法について](#6-コンパイルの方法について) | プロジェクトのコンパイルについて説明 |
| 7 | [まとめ](#7-まとめ) | 今回のまとめ |

# 1. はじめに

前回までの2回で、開発環境構築を行ってきました。

特に前回はエディタを導入し、より開発しやすい環境が整ったと思います。

さて、今回はEV3rtでプログラムを製作して行く上での**お約束ごと**について記していきます。

未だプログラム製作の本格的なところに入れていませんが、こういった重箱の隅までしっかり把握出来ていれば、より良いプログラムが作れると思いますので、頑張って学んでいきましょう。

# 2. SDカードに入れるファイルについて

#1 の最後に、SDカードにファイルをコピーして、EV3rtが起動するところまで確認したと思います。

しかし、**どのファイルが何か**といった説明を省いておりましたので、その辺りの詳しい説明をしていきたいと思います。

## sdcardフォルダ

![sdcard_folder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/05db9952-9daa-f783-cc96-140a1a7b04a4.png)

#1 の最後に、EV3rtの`sdcard`フォルダ内のファイルをSDカードにコピーしました。
コピーしたのは、`uImage`というファイルと`ev3rt`というフォルダでした。

`uImage`というファイルについて、詳しい話をすると難しいので省略しますが、「EV3の起動時に一番初めに読み込まれるファイル」といった認識で良いかと思います。
このファイルにより、EV3rtが実際に起動します。

`ev3rt`というフォルダの中には、EV3rt内で使用する**実行ファイル**や**設定ファイル**などが入っています。

## 「ev3rt」フォルダ

![ev3rt_folder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/e63a7e9b-f902-ea54-cdff-f297ebede3a6.png)

ev3rtフォルダの中には、`apps`、`etc`、`res`の3つのフォルダがあります。

順番に見ていきましょう。

### 「apps」フォルダ

![apps_folder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/4ee2f472-8f4e-3b75-a4f1-4c70ab866456.png)

`apps`フォルダは、PCでコンパイルして生成した **「実行ファイル」を置く場所** です。

EV3rtを起動して、「Load App」を押すと以下の画像の真ん中のようなメニューが表示されます。
ここで「SD card」を選択すると、**appsフォルダ内に保存されている実行ファイルが選択できます。**

![loadapp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/dbd01636-c3de-fe3a-a842-db5a4416863c.png)

逆に言えば、プログラムを作成して実行ファイルが生成出来たら、**EV3を接続してこのappsフォルダ内に実行ファイルを置けば良い**のです。

EV3rtはUSBでの接続をサポートしているので、わざわざSDcardをEV3から抜いてPCに挿さなくとも、インテリジェントブロックのUSB mini B端子とPCを接続すれば、SDcardの中身を見ることが出来ます。

![IMG_7113.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/8c888bc7-f63b-ea65-3147-c00acec7956f.jpeg)

![ev3_connect.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/8bf110bf-273f-67de-ec03-6b4c4fb892b5.png)

プログラムを修正して、コンパイルが完了したら、appsフォルダ内の実行ファイルを置き換えて、プログラムを走らせるようにしましょう。

### 「etc」フォルダ

![etc_folder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/69cb0643-773a-860e-a2ab-659814ed4780.png)

`etc`フォルダには **「rc.conf.ini」** というファイルが保存されています。

このファイルは**EV3rtの設定を記述するファイル**です。

エディタを使えば開くことが出来るので、VSCodeでファイルを開いてみましょう。

![rcconfini.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/c33f4117-e3c5-b374-428b-873749a278b0.png)

デフォルトでは上の画像のように少ししか設定項目がありませんが、以下のような設定項目を自分で増やして設定することが出来ます。

```ini:rc.conf.ini
[Bluetooth]
LocalName=Mindstorms EV3
PinCode=0000
TurnOff=0
DisablePAN=0
IPAddress=10.0.10.1
[Debug]
DefaultPort=LCD
LowBatteryWarning=1
[Sensors]
DisablePort1=0
[USB]
AutoTerminateApp=1
```

それぞれの設定項目について見ていきます。

#### [Bluetooth]

| 設定項目 | 内容 | 指定方法 |
| --- | --- | --- |
| LocalName | Bluetooth接続時にPCに表示される名前 | 任意の文字列 |
| PinCode | Bluetooth接続時に必要なパスコード | 任意の数字4桁(半角) |
| TurnOff | Bluetoothのオン・オフ | 0ならオン / 1ならオフ |
| DisablePAN | Bluetooth PAN(Personal Area Network)のオン・オフ | 0ならオン / 1ならオフ |
| IPAddress | Bluetooth PAN に使うIPアドレス | 任意のIPアドレス |

#### [Debug]

| 設定項目 | 内容 | 指定方法 |
| --- | --- | --- |
| DefaultPort | ログの表示場所 | LCD / UART / BT から選択可能 |
| LowBatteryWarning | バッテリー電圧低下時の警告表示 | 0ならオフ / 1ならオン |

#### [Sensors]

| 設定項目 | 内容 | 指定方法 |
| --- | --- | --- |
| DisablePort1 | ポート1の無効化(UART出力ポートとして使用) | 0ならオフ / 1ならオン |

#### [USB]

| 設定項目 | 内容 | 指定方法 |
| --- | --- | --- |
| AutoTerminateApp | USB接続時にアプリを自動終了する | 0ならオフ / 1ならオン |

基本的には、上のコード部分に記した設定で良いかと思いますが、例えば今後紹介するBluetoothの機能を使うときや、ポート1をUARTのシリアルポートとして使用するときなどは、これらの値を変更することで設定を変えることが出来ます。

WROに出場する方は、大会時には(原則的に)無線通信はオフにする必要があるので、`[Bluetooth]`の`TurnOff`は`1`にしなければなりませんね。

```ini:rc.conf.ini
[Bluetooth]
TurnOff=1
```

この設定の方法を覚えておいて下さい。

### 「res」フォルダ

![res_folder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/c5d65c51-69d8-d228-1245-b0848de945a8.png)

`res`フォルダには、プログラムで使用する「画像ファイル」や「音声ファイル」を置くことが出来ます。

デフォルトの状態では「HelloEV3」のプログラムを動かすのに必要な`test.bmp`と`test.wav`が入っています。

尚、今後のファイルを扱う回で詳しく解説しますが、これらは必ずしもresフォルダに置かなければならないという事ではありません。

**res=resouces=素材**
つまり「素材フォルダ」に素材はまとめておきましょう、というだけの話です。

必要に応じて、新しいフォルダを作ることも可能です。

# 3. プロジェクトについて

EV3ソフトウェアでプログラムを作るとき、一つのファイルを「プロジェクト」と呼びますよね。

![ev3soft_project.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/247858d0-5ddd-51b5-4148-0a8527712d63.png)

このシリーズにおいても、一つのプログラムの単位を **「プロジェクト」** と呼ぶことにします。
まずはそのプロジェクトの置き場所について説明します。

## workspace フォルダ

前回、VSCodeのワークスペースの話をしましたが、それとは別です。

プロジェクトを置くためのフォルダとして、 **「workspace」** というフォルダがあります。

場所は `ev3rt-1.1-release/hrp3/sdk/workspace` です。

ここには**プロジェクトごとのフォルダ** と **コンパイルした結果生成される実行ファイル（app）** が配置されます。

![workspace_folder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/6c1d2519-298e-1d87-6fbf-411a15e9a352.png)

このように、一つのプロジェクトは、そのプロジェクトの名前をつけたフォルダにまとめられて配置されます。

新しいプロジェクト作る時は、このworkspaceフォルダに新しいフォルダを作り、さらにその中にプログラムファイルを配置していくということになります。

では次の章で、一つのプロジェクトに必要なファイルについて見ていきましょう。

# 4. プロジェクト内のファイルについて

:::note warn
ここから、 **拡張子だけ異なる同じ名前のファイル** を扱っていきます。
そのため、**拡張子を表示**させるようにしておきましょう。

👇表示方法の参考はこちら
[HP PC - ファイルの拡張子を表示する方法(Windows 11/10/7)](https://support.hp.com/jp-ja/document/c01967336)
:::

プロジェクト内のファイルは、自ら追加した場合を除き、4つのファイルから構成されます。
以下の4ファイルです。

- app.c
- app.h
- app.cfg
- Makefile.inc

![temp_folder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/fb443f12-b7ec-1d24-9cf6-605c618ed16d.png)

順番にそのファイルの役割について見ていきましょう。
(書き方については別にそれぞれのテーマで詳しく記します。)

## app.c (ソースコードファイル)

**プログラムの基幹となるファイル**です。
基本的には、このファイル内の`main_task`という関数内に、プログラムを書いていきます。


## app.h (ヘッダーファイル)

`app.c`を**サポートするようなファイル**になります。
関数のプロトタイプ宣言(詳しくは関数の章で解説)や定数の定義などが行われています。

## app.cfg (コンフィギュレーションファイル)

主に**タスクの管理等を行うファイル**となります。
EV3rtではマルチタスク(異なる2つのプログラムを同時に走らせること)を実現することが出来ますが、そのタスクの作成、および設定をこのファイル内で行います。

## Makefile.inc 

EV3rtのコンパイルには`make`という仕組みが用いられています。
この仕組みによりコンパイルにかかる面倒な手間が省けたりするのですが、`Makefile.inc`はそれに必要な設定ファイルといった位置づけです。
主に、ソースコードファイルを追加したい時などに使用します。

# 5. テンプレートプロジェクトの作成

今後のプログラム開発にあたり、テンプレートとなるプロジェクトを作成しておきましょう。
新しいプロジェクトを作成するときは、テンプレートフォルダをまるごとコピーして、そこにプログラムを作成していけば良いかと思います。
フォルダ名=プロジェクトの名前は適宜変更してくださいね。

## プロジェクトフォルダの作成

まずは、`hrp3/sdk/workspace`フォルダを開きましょう。
開けたら新しいフォルダを作成して、`temp`とでも名前を付けましょう。
(名前について特に指定はありませんが、テンプレートだと分かる名前を付けておいてください。)

![workspace_temp_folder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/3eccc78d-b97f-5603-044d-0cb36d420a6c.png)

作成出来たら、フォルダ内に入りましょう。

## 各ファイルの作成

では、前章で説明した4つのファイルを作成していきましょう。
ここからはVSCodeを使用した方が楽だと思います。
VSCodeでは以下のようにアイコンを押すことで、新しいファイルを作ることが出来ます。

![VSCode_newfile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/8fbc528a-359a-df17-d526-5778394f8f96.png)

### app.c

まずは`app.c`という名前でファイルを作成します。
作成出来たら、中に以下のコードを書きましょう。

```c:temp.c
#include "ev3api.h"
#include "app.h"
#include <stdio.h>

void main_task(intptr_t unused)
{
    //プログラムをここから書く
}

```

これが`app.c`の基本となる形です。
`ev3api.h`はEV3rtのAPI(各種機能を簡単に使えるようにしたもの)が記述されたファイル、`app.h`は前述のとおりこのプロジェクト内のヘッダーファイルであり、どちらも**インクルードが必須**です。

一方、`stdio.h`は文字やファイルの入出力を扱う、C言語の標準ライブラリです。
インクルードは必須ではありませんが、非常に良く使うのでテンプレ段階でインクルードするようにしています。
(不必要であれば3行目だけ消しても構いません。)

そして5行目以降ですが、これがプログラムを記述する`main_task`という関数です。
EV3rtのルールで、プログラムが実行されるとこの`main_task`という関数が実行されます。
よって、この関数内にプログラムを書いていくということになります。

### app.h

同様の手順で`app.h`という名前でファイルを作成し、中に以下のコードを書きましょう。

```c:app.h
/*
 *  TOPPERS/ASP Kernel
 *      Toyohashi Open Platform for Embedded Real-Time Systems/
 *      Advanced Standard Profile Kernel
 *
 *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
 *                              Toyohashi Univ. of Technology, JAPAN
 *  Copyright (C) 2004-2010 by Embedded and Real-Time Systems Laboratory
 *              Graduate School of Information Science, Nagoya Univ., JAPAN
 *
 *  上記著作権者は，以下の(1)〜(4)の条件を満たす場合に限り，本ソフトウェ
 *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
 *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
 *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
 *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
 *      スコード中に含まれていること．
 *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
 *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
 *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
 *      の無保証規定を掲載すること．
 *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
 *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
 *      と．
 *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
 *        作権表示，この利用条件および下記の無保証規定を掲載すること．
 *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
 *        報告すること．
 *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
 *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
 *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
 *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
 *      免責すること．
 * 
 *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
 *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
 *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
 *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
 *  の責任を負わない．
 *
 *  $Id: sample1.h 2416 2012-09-07 08:06:20Z ertl-hiro $
 */

/*
 *  ターゲット依存の定義
 */
#include "target_test.h"

/*
 *  各タスクの優先度の定義
 */

#define MAIN_PRIORITY	5		/* メインタスクの優先度 */
								/* HIGH_PRIORITYより高くすること */

#define HIGH_PRIORITY	9		/* 並行実行されるタスクの優先度 */
#define MID_PRIORITY	10
#define LOW_PRIORITY	11

/*
 *  ターゲットに依存する可能性のある定数の定義
 */

#ifndef STACK_SIZE
#define	STACK_SIZE		4096		/* タスクのスタックサイズ */
#endif /* STACK_SIZE */

#ifndef LOOP_REF
#define LOOP_REF		ULONG_C(1000000)	/* 速度計測用のループ回数 */
#endif /* LOOP_REF */

/*
 *  関数のプロトタイプ宣言
 */
#ifndef TOPPERS_MACRO_ONLY

extern void	main_task(intptr_t exinf);

#endif /* TOPPERS_MACRO_ONLY */

```

ファイルの上半分を占める日本語で書かれた文ですが、これはライセンスにより記述が必要な文ですので書くようにして下さい。
(プログラムには一切関係ありません。)

その後の部分ですが、基本的にEV3rtのアプリに共通で必要なヘッダーファイル・定数等が定義されています。

開発で触る可能性があるところといえば、下から3行目あたりの **関数のプロトタイプ宣言** の部分くらいです。
前述のとおり、関数を追加するときなどにここにプロトタイプ宣言をします。
書き方については今後の関数の回で詳しく紹介します。

### app.cfg

同様の手順で`app.cfg`という名前でファイルを作成し、中に以下のコードを書きましょう。

```cfg:app.cfg
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");

```

前述のとおり、このファイルにはタスク管理について記述していきます。
これも説明すると長くなるので、今後のマルチタスクの回で詳しく説明します。

### Makefile.inc

同様の手順で`Makefile.inc`という名前でファイルを作成し、中に以下のコードを書きましょう。

```inc:Makefile.inc
APPL_COBJS +=

```

実は`Makefile.inc`は、ソースコードの追加を行わない場合は何も記述しなくてもコンパイルは通るのですが、今後`app.c`にプログラムを沢山書き、プログラムファイルを分割したくなった時に備えて、テンプレではその準備だけしておきます。

意味としては、`APPL_COBJS` の後ろに新しく作成したソースコードを追加していくといった感じです。
こちらに関しても、詳しい書き方は別の回で紹介します。

# 6. コンパイルの方法について

最後に、コンパイルの方法について改めて確認しましょう。

コンパイルとは、「人間が読める言葉」を「機械が読める言葉」に変換することでした。
#1 の最後の動作確認時に一度コンパイルを行っていますが、改めて方法を説明します。

まず、Ubuntuのターミナルを開き、EV3rtの **ワークスペースフォルダ** `/mnt/c/ev3rt-1.1-release/hrp3/sdk/workspace` に移動します。
移動には以下の`cd`コマンドを使用します。

```terminal:Ubuntu
$ cd /mnt/c/ev3rt-1.1-release/hrp3/sdk/workspace
```

次に、以下のコマンドでプロジェクトをコンパイルします。

```terminal:Ubuntu
$ make app=(プロジェクト名)
```

ここで、**`(プロジェクト名)`** とは、`workspace`フォルダに作成した**プロジェクトのフォルダ名**です。

例えば、#1 の動作確認では`helloev3`というプロジェクトのコンパイルを行いました。
その場合は以下のようになります。

```terminal:Ubuntu
$ make app=helloev3
```

今回はテンプレートプロジェクト`temp`を作成しましたね。
これも、以下のようにしてコンパイルを行うことが出来ます。

```terminal:Ubuntu
$ make app=temp
```

するとターミナルに文字がザーっと流れて、コンパイルに完了すると以下のような文言が表示されます。

```terminal:Ubuntu
$ make app=temp
rm -rf /mnt/c/ev3rt/hrp3/sdk/workspace/.././OBJ/
Generating Makefile from ../common/Makefile.app.
make[1]: Entering directory '/mnt/c/ev3rt/hrp3/sdk/OBJ'
rm -f cfg1_out cfg1_out.o cfg1_out.c cfg1_out.syms cfg1_out.srec module_cfg.h module_cfg.c \#* *~ *.o
make[1]: Leaving directory '/mnt/c/ev3rt/hrp3/sdk/OBJ'
make[1]: Entering directory '/mnt/c/ev3rt/hrp3/sdk/OBJ'
  CFG[1]  module_cfg.h
[cfg.rb] Generated cfg1_out.c
  CFG[2]  module_cfg.h
[cfg.rb] Generated module_cfg.c
[cfg.rb] Generated module_cfg.h
make[1]: Leaving directory '/mnt/c/ev3rt/hrp3/sdk/OBJ'
make[1]: Entering directory '/mnt/c/ev3rt/hrp3/sdk/OBJ'
  CC      module_cfg.c
  CC      ../../library/t_perror.c
  CC      ../../library/strerror.c
  CC      ../../library/vasyslog.c
  CC      ../../target/ev3_gcc/TLSF-2.4.6/src/tlsf.c
  CC      ../workspace/temp/app.c
  CC      ../common/ev3api/src/ev3api.c
  CC      ../common/ev3api/src/ev3api_battery.c
  CC      ../common/ev3api/src/ev3api_brick.c
  CC      ../common/ev3api/src/ev3api_fs.c
  CC      ../common/ev3api/src/ev3api_speaker.c
  CC      ../common/ev3api/src/ev3api_lcd.c
  CC      ../common/ev3api/src/ev3api_motor.c
  CC      ../common/ev3api/src/ev3api_newlib.c
  CC      ../common/ev3api/src/ev3api_sensor.c
  LD      app
make[1]: Leaving directory '/mnt/c/ev3rt/hrp3/sdk/OBJ'
```

最後から2行目の`LD app`が表示されればコンパイル完了です。
また、エクスプローラで`workspace`フォルダに生成された`app`ファイルの作成日時を見ることでも、コンパイル出来たかどうかを確認できるかと思います。

## 実行ファイルの名前

さて、実行ファイルは`app`という名前で生成されますが、生成後に名前を変えることが出来ます。
方法は単純で、エクスプローラでファイル名変更を行うだけです。

![name_edit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/e7a91a4d-d950-732f-b9d1-87fb818259af.png)

例えばWROにおいては、競技で走らせる際のファイル名を`runWRO`とすることが義務付けられています。
そうした時は、コンパイル後に`app`ファイルを`runWRO`と名前変更すれば良いということになります。

![runWRO.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183170/d2c160ee-8afd-c540-851a-da9b31854c11.png)

# 7. まとめ

今回はEV3rtでのプログラム開発で覚えておきたいお約束事についてまとめていきました。
地味なお話ではありましたが、頭の片隅に置いておくと良いかと思います。
特にSDカードの設定などについては、必要になった時のこの記事を開いて、設定方法を確認してみてください。

さて、次回はいよいよ本格的にプログラムを書いていきます。
ただ、モータやセンサを使う前に、C言語のキホン的なところについて押さえておきたいと思います。
次回も頑張っていきましょう!!

前回: [#2 エディタを使おう(VisualStudio Code)](https://qiita.com/koushiro/items/35f74cce0961fc442b11)
次回: [#4 C言語のキホン➀](https://qiita.com/koushiro/items/18e0c8dde12f3a8e3aad)