MATLABからRaspberry Piにデプロイする方法

# はじめに
先日、[はじめてのMATLAB x Raspberry Pi 連携](https://qiita.com/aoimidori/items/514b069cece37e9be4cf)というタイトルで2年ぶりにQiita記事を書きました。今日は、Raspberry Piをスタンドアロンで動かす方法について調べたので備忘も兼ねて記事にしたいと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521542/5f31e7f9-bd97-17b3-4da6-ebd82af0bf54.png)

実際に試したのは、MathWorks社から出ている以下の例題です。

https://jp.mathworks.com/help/supportpkg/raspberrypiio/ref/getting-started-with-deploying-a-matlab-function-on-the-raspberry-pi-hardware.html

偶然にも、前回の記事で取り上げた例題をやっていればできる内容だったので、事前準備もほぼ不要で試すことができました。よろしければ1つ前の記事も併せてご覧くださいね。

# 使用した環境

* MATLAB R2022a  (Raspberry Pi 4 Model BはR2020a以降のバージョンで利用可能です）
* MATLAB Coder
* Raspberry Pi 4 Model B
* イーサネットケーブル
* Raspberry Pi用の給電ケーブル

# 例題のサマリー

上記の例題では、Raspberry Pi のLEDをチカチカさせるプログラムをデプロイし、スタンドアロンで動かせるようにする流れが紹介されていました。以下のようにMATLAB側で関数を作っておき、それをMATLABからRaspberry Piにデプロイする流れを学びます。

```matlab:blinkLED.m
function blinkLED()
% Create a Raspberry Pi object
r= raspi();
% Blink the LED for 100 cycles
for count = 1:100
    % Turn on the LED
    writeLED(r,"LED0", 1);
    % Pause for 0.5 seconds
    pause(0.5);
    % Turn off the LED
    writeLED(r,"LED0", 0);
    % Pause for 0.5 seconds
    pause(0.5);
end
end
```

なお、この例題を見て初めて知ったのですが、関数は引数や返り値を持たせてはいけないそうです（as of R2022a）。

### MATLABからRaspberry Piを操作
上記の関数ができたら、以下のコマンドによって、MATLABからRaspberry Piを操作します。

```matlab
run blinkLED
```

この時は、MATLABとRaspberry Piは繋いだ状態にしておきます。上記のコマンドを実行すると、Raspberry Pi上のLEDが0.5秒毎に点滅しました。ひとたびデプロイしてしまってからエラーがあると、デバッグが難しくなるので、この時点でしっかり、ハード上で動作するかを確認しておくのが無難です。

### Raspberry Piにデプロイ
デプロイする際には、作成しておいたblinkLED.mを1行だけ書き直す必要があるようです。

```matlab:blinkLED.m
function blinkLED() %#codegen
```

デプロイする際には、内部的にMATLABスクリプト-->Cコードへの変換が行われ、Raspberry Piで実行可能な形式のファイルへと変換されてからデプロイされるようです。なので、この`%#codegen`という書き方によってCコード変換が有効になるのかなと理解しています...。

### デプロイ

デプロイ自体はたったの2行でできたので拍子抜けしました。まずは以下のコードでターゲットを指定し、

```matlab
board = targetHardware('Raspberry Pi')
```
以下の関数でターゲットと関数を指定してデプロイするだけです。
```matlab
deploy(board,'blinkLED')
```
上の関数を実行すると、少し時間を要しますが、Raspberry Piをスタンドアロンで動かすことができるようになりました。

# 例題には載ってなかった話
実は、例題をなぞる部分は書いてある通りに動かすだけなのでそんなに難しくありませんでした。しかし、その後どうやってスタンドアロンで動かすの？という点を調べるのに少し時間がかかりました。自分が参考にしたリソースなども貼りながら、ここで実際に行った処理をまとめていきたいと思います。

### デプロイしたファイルはどこにあるのか
この謎を解いてくれたのが、以下の動画です。

https://jp.mathworks.com/videos/deploy-an-edge-detection-algorithm-on-raspberry-pi-1591967219707.html

4:30辺りで、エッジ検出を行う実行ファイルをコールしているのですが、ターミナルが以下のような画面になっていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521542/a593683f-77a3-18b2-51aa-66a322c4c56c.png)

上図では、画像に文字を上書きしていますが、おそらく
`/home/pi/MATLAB_ws/R20xxx`
までは共通で、その後ろに、MATLABで作業をしていた時のディレクトリ名が入ります。自分の場合、この辺りを深く考えずにMATLABのディレクトリを命名していたので、デプロイした後もわかりやすいフォルダ名で作業をしておくと後々良いかもしれません。

上の動画ではその後、そのフォルダの中にある`edgeDetection.elf`をコマンドで実行しています。

```terminal
./edgeDetection.elf
```

### 電源起動時にプログラムを走らせたい場合は？

この回答は以下のドキュメンテーションにありました。

https://jp.mathworks.com/help/supportpkg/raspberrypiio/ug/run-matlab-function-on-reboot.html

具体的には、デプロイをする前に、ターゲットボードの設定を1行加えてあげると良いようです。以下のコードになります。


```matlab
board = targetHardware('Raspberry Pi')
board.EnableRunOnBoot = true
deploy(board,'blinkLED')
```
これによって、Raspberry Pi再起動時に自動的にLED点滅を走らせることができました。

# おわりに
今回はRaspberry Piのデプロイを試しました。簡単なコードだったとはいえ、結構すぐにできたので感動的でした。また、Raspberry Pi上で実行ファイルの場所もわかったので、次は外部機器も接続させてスタンドアロンで動かしてみたいなと思います。
最後までお読みいただきありがとうございました。