arduino(及びraspi) MATLAB連携とSimulink連携の微妙な違い

# はじめに
MATLAB/SimulinkはarduinoやRaspberryPiといった、ハードウェアと連携することが可能です。
連携方法としてはMATLABと連携する方法、Simulinkと連携する方法が準備されています。

MATLAB/Simulinkなんだから、どっちと連携させても大体同じでしょ！と思いきや連携のさせ方や使い勝手が結構違います。本記事においては、どこがどう違うのかを述べることで用途ごとの適切な連携方法の選択、および素早い技術開発の実現を目指すものとします。

参考
[MATLAB連携：MATLAB Support Package for Arduino Hardware](https://jp.mathworks.com/matlabcentral/fileexchange/47522-matlab-support-package-for-arduino-hardware)
[Simulink連携：Simulink Support Package for Arduino Hardware](https://jp.mathworks.com/matlabcentral/fileexchange/40312-simulink-support-package-for-arduino-hardware)

インストールはアドオンからが楽です。
[おまけのおまけ：MATLAB Support Package for Arduino Hardwareチュートリアル](https://qiita.com/Monzo_N/items/6a9f7a7756aca2198fe3)

本記事にて紹介しない隠しメニュー「Arduino IO」についてはこちら。
https://qiita.com/motorcontrolman/items/bd962021be8c5fdcc48b

# 先に結論を述べると
arduinoを例に取ると下記の表のようになります。RaspberryPiの場合でもだいたい同じです。
（あえて違いを挙げるなら設定の容易性。MATLAB連携でIPの設定が必要になる）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/1fd1677d-05b8-bcb2-48ea-c16d9bb70944.png)



以降では上記の項目それぞれについての説明を行います。
細かいことはいいから具体例知りたい！って方は[6.MATLAB連携とSimulink連携の実例](#6matlab連携とsimulink連携の実例) まで飛ばして下さい。


# 1.主従関係
MATLAB/SimulinkのインストールされたPCと、マイコンの一種であるarduinoを連携させる際には２機間に主従関係が発生します。分かり易さ優先で主従関係と書きましたが、正しくは「どちらがプログラムを実行するのか」が連携方法によって変わります。

## (a) MATLAB連携の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/67b0157f-2594-fbd5-da02-3ca7561f6baf.png)

プログラムを実行するのはMATLABの入ったPCで、arduinoは命令通り動くだけです。これを実現するため、arduinoのマイコンにはMATLABの命令を受け取るためのプログラムが書き込まれます。

プログラムの書き込みは、下記に示すMATLAB・arduino接続コマンドを打った際に自動で行われます。

```matlab
%MATLABとarduinoを接続
a = arduino();
```

プログラムが書き込まれる際のみ下記の文字列がMATLAB画面に表示され、数分間待つことになります。逆に言うと、<b>既にプログラムが書き込まれていれば待ち時間なしです。</b>表に示した「実行までの待ち時間0」はこの特徴に起因します。
>Updating server code on board Uno (COM5). This may take a few minutes.


## (b) Simulink連携の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/4a12e63e-4dd9-637c-0425-6f484062ac7f.png)
プログラムを実行するのはarduinoで、Simulinkの入ったPCは信号を送受信するだけです。

SimulinkとMATLABを連携させる場合、プログラムを実行させる方法として<b>『エクスターナルモードでの実行』</b>と<b>『ハードウェアでの実行』</b>の２パターンが存在します。このうちPCとの送受信を行うのはエクスターナルモードのみで、ハードウェア実行は完全スタンドアロンです。

エクスターナルモードでの実行では、Simulink画面上で信号をON／OFFできたり、ゲインを変更できたりするのでプログラムがPC側で実行されているような気持ちになりますが、やっているのはあくまで信号送受信だけです。

arduinoに書き込まれるプログラムは、Simulink画面上にてエクスターナルモード実行またはハードウェア実行を行った際にSimulinkブロックから自動コード生成・ビルドされてarduinoへと書き込まれます。<b>この手続きには数分かかります。</b>表に示した「実行までの待ち時間数分」はこの特徴に起因します。

ちなみにこの待ち時間、Simulinkモデルを変更⇒arduinoにて実行する際には毎回発生するもので、Simulinkブロックの規模が小さくても数分かかります。また変更の規模がわずかでも一律に同じ待ち時間が発生します。

このため、頻繁な調整を要するような作業(例えば、センサやモータの動検)をSimulink連携でやるのにはかなりストレスがあります。一方、MATLAB連携の場合は待ち時間が0なので、こうした作業には適しています。

<b>追記・備考</b>：2019bからエクスターナル／ハードウェア実行の呼び出し画面が変わりました。Simulink連携のブロックを配置するとメニューに「ハードウェア」が表示され、「監視および調整」でエクスターナル実行が、「ビルド、配布および開始」でハードウェア実行が呼び出されるようになりました。
なんとも言えない変更だなぁ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/ff878323-50fa-e515-fa78-89d955caf2f4.png)


# 2. arduinoのスタンドアロン化
1.の説明から想像がつくかとは思いますが、一応説明しておきます。
## (a) MATLAB連携の場合
プログラムがMATLAB側で実行されるため、スタンドアロン化は不可です。

## (b) Simulink連携の場合
プログラムがarduino側で実行されるため、スタンドアロン化が可能です。
ちなみに、エクスターナルモードでの実行中にPCとarduinoの接続をぶった切ってもarduinoのプログラムは動き続けます(要外部電源供給)。またarduinoのリセットを押すことでプログラムを最初から実行することが出来ます。

# 3. 実行までの待ち時間
1. の文中にて説明しているのでここでの説明は割愛します。

# 4. 設定の容易性
## (a) MATLAB連携の場合
<b>設定自体がそもそも不要です、超らくちん。</b>
PCとarduinoを接続、とりあえず　a = arduino(); を打てばarduinoの種類を自動検出してプログラムを流し込んでくれます。

## (b) Simulink連携の場合
コンフィグレーションパラメータにて接続するarduinoの種類を設定する必要があります。慣れればなんてことないですが、Simulink初心者にはちょっとつらいと思います。
慣れている人であっても、開発途中でarduinoの種類を変更した際にエラーが出て嫌な気持ちになることはままあります（エラー出るまでに数分かかるため）。

参考までにコンフィグレーションパラメータの起動方法は下記。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/e55501b0-baf1-62b8-047a-1323fe67ec71.png" width=400>

arduino種類の設定画面は下記。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/d310b073-591d-2c7a-f8a7-93149eeed015.png)

# 5. GUI
## (a) MATLAB連携の場合
ちょっとしたMATLAB関数の記述や、[App Designer](https://jp.mathworks.com/help/matlab/app-designer.html)でアプリ作成する必要があります。慣れればなんということはないですが、Simulinkほど楽ちんではないという観点から△にしています。



## (b) Simulink連携の場合(エクスターナルモードでの実行)
Simulinkブロックを使うことができるため、わざわざ準備する必要がありません。
Scopeブロックが利用できるのはもちろんのこと、[dashbord](https://jp.mathworks.com/help/simulink/ug/tune-and-visualize-your-model-with-dashboard-blocks.html)を利用することで幅広いGUIが使えます。


# 6.MATLAB連携とSimulink連携の実例

## [MATLAB]センサ、モータなどハードウェアの動作検証
下記の動画は、最終的にはSimulink連携(エクスターナルモード実行)を行っていますが、その開発初期はステッピングモータの動作検証を短時間で行う目的でMATLAB連携を使いました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">MATLAB simulinkでステッピングモータ制御芸できた！State Flow出力信号直結でモータ回したのは世界初なのでは（他にいたら怖い） <a href="https://t.co/vaJFOKAXSJ">pic.twitter.com/vaJFOKAXSJ</a></p>&mdash; モータ制御マン (@motorcontrolman) <a href="https://twitter.com/motorcontrolman/status/1126863802501189633?ref_src=twsrc%5Etfw">May 10, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

参考まで動作検証用のコードは下記。なおこのコードはSimulink連携時には使っていません、というか使えません。Simulink連携の場合、LEDの点滅にはSimulinkブロックを使う必要があります。

```matlab
while 1
writeDigitalPin(a, 'D2', 1);
writeDigitalPin(a, 'D3', 0);
writeDigitalPin(a, 'D4', 0);
writeDigitalPin(a, 'D5', 0);
pause(0.01);
writeDigitalPin(a, 'D2', 0);
writeDigitalPin(a, 'D3', 0);
writeDigitalPin(a, 'D4', 1);
writeDigitalPin(a, 'D5', 0);
pause(0.01);
writeDigitalPin(a, 'D2', 0);
writeDigitalPin(a, 'D3', 1);
writeDigitalPin(a, 'D4', 0);
writeDigitalPin(a, 'D5', 0);
pause(0.01);
writeDigitalPin(a, 'D2', 0);
writeDigitalPin(a, 'D3', 0);
writeDigitalPin(a, 'D4', 0);
writeDigitalPin(a, 'D5', 1);
pause(0.01);
end
```
## [MATLAB]MATLAB関数でarduinoをリアルタイムに動かす


下記の動画では、wiiヌンチャクのジョイスティック値をarduino経由でリアルタイムにMATLABに表示させています。
動画ではやっていませんが、ジョイスティックと連動させてサーボモータを動かしたりも簡単に出来ます。AIや最適化など、高度なMATLAB関数と組み合わせることで色々なことが出来そうです。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">MATLAB芸、動画にしたら微妙な感じになった・・・wiiヌンチャクでfigureにお絵描き、Zでリセット。元ネタはarduinoのライブラリで、mファイルへの書き換えを手動で実施。勉強にはなった。 <a href="https://t.co/mUFy5xDqaS">pic.twitter.com/mUFy5xDqaS</a></p>&mdash; モータ制御マン (@motorcontrolman) <a href="https://twitter.com/motorcontrolman/status/1113803549203238913?ref_src=twsrc%5Etfw">April 4, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ところでGUIはというと、whileループ内で既存データに新データを結合⇒axisを指定してplotしています。これも参考までにコードを下記貼りますが、動かなかったらすいません。

```matlab
a = arduino();
dev = i2cdev(a,'0x52');

x55 = hex2dec('55');
xF0 = hex2dec('F0');
x00 = hex2dec('00');
xFB = hex2dec('FB');

writeRegister(dev,xF0,x55);
writeRegister(dev,xFB,x00);

X_out = 127;
Y_out = 127;

figure(1);
while 1
    out = read(dev,6);%uint8のデータを取得
    out16 = int16(out);%uint8のままだと処理できないのでuint16に格納
    X = out16(1);
    Y = out16(2);
    X_out = horzcat(X_out,X);
    Y_out = horzcat(Y_out,Y);
 
    plot(X_out,Y_out,'r','LineWidth',2);
    grid on;
    axis([0 250 0 250]);
    refresh;
    pause(5e-3);
end
```

## [Simulink]arduinoに組み込む制御を短時間で設計・実装する
詳しくは下記の記事を閲覧下さい。
[Lightning Talk の舞台裏：”動いたり光ったりする宇宙船の3Dプリントモデルのコード生成 ”](https://blogs.mathworks.com/japan-community/2019/11/13/lightning-talk-3dprintmodel-of-spaceship/)

>モータや LED を制御するには、同時に実行されるプロセス（いわゆる「マルチタスキング」）が必要です。直接に C++ 言語で書くことがなかなか大変ですが、Simulink でプログラムを作った場合に、Simulink は自動的にマルチタスキングを管理してくれます！

MATLAB EXPO2019のLTにて、ご本人が仰っていたのですが<b>「三角波やのこぎり波をCで書くのは面倒だがSimulinkはライブラリ使うだけだから時短になる」</b>というのは目から鱗でした。レートリミットなんかもそうですが、Simulinkは「機能は単純だがCでの実装は手間」なものとの相性がよいですよね。

## [MATLAB]手の込んだGUIでarduinoを動かす
これも同様の記事が具体例となります。
[Lightning Talk の舞台裏：”動いたり光ったりする宇宙船の3Dプリントモデルのコード生成 ”](https://blogs.mathworks.com/japan-community/2019/11/13/lightning-talk-3dprintmodel-of-spaceship/)
>６．操作
スカイロンを操作するために、MATLAB の AppDesigner を用いてユーザインターフェイス (UI) を作成しました。UI から LED の色や明るいさを調節したり、サーボモータを動かしたりすることができます

[AppDesigner](https://jp.mathworks.com/help/matlab/app-designer.html?s_tid=CRUX_lftnav)はMATLAB用のGUIアプリケーション開発環境です。MATLABにある程度慣れた人であれば、容易にGUIを作ることが出来ます。arduino用のGUI開発環境ってあまり聞かないので、やりたい人からすればこれだけでもかなり魅力的なのでは？（あったらすいません）

## [Simulink]モデルベース開発を電子工作に導入する
2020/1/14追記：下記の事例が秀逸なのでまずは参考下さい！
[電子工作にモデルベース開発(Model Based Development: MBD)を適用してみた](https://qiita.com/mana_544/items/3fe4d150441b12d89ebf)

モデルベース開発(MBD)は自動車業界にて主に導入されている手法です。
詳しいことはここでは説明しませんが、要するに「実機を使った技術検証は極力抑えて、シミュレーション主体で技術検証しようぜ！」「そのために、実機の<b>振る舞い</b>を模擬したモデルを使おうぜ！」という開発手法です。


<b>振る舞い</b>の例としては、ノイズや遅延を含むセンサ出力や、モータの動的特性等が挙げられます。振る舞いが素直なものであれば実機だけの技術検証でなんとかなりますが、癖のあるものであれば苦労することになります。MBDは後者に対する効果的手法であり、MATLAB/SimulinkはMBDのための代表的なツールとして挙げられます。

Simulink連携では、シミュレーション用のモデルをそのままセンサやモータと接続したarduinoへと書き込むことが可能なためMBDを非常に簡単に導入することが出来ます。
arduinoなので複雑な処理・速度を必要とする処理は実装できませんが、おそらく最もお金をかけずにMBDを実現する方法と考えられるのでぜひお試し下さい。

一例として下記に、[心拍センサー](https://www.amazon.co.jp/dp/B079HW2PPS/)値をもとにLEDを点滅させるプログラムのモデルを示します。シミュレーション用のブロックとarduino用のブロックが同居しているのが分かると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/0ea144c0-dcc3-4cda-3032-6b8e2ef1a527.png)
スイッチのように見えるのは[Variant Source／Variant Sink](https://jp.mathworks.com/help/simulink/ug/variant-source-and-variant-sink-blocks.html)で、無効側のポートに接続されたブロックをコメントアウトする機能があります。

シミュレーションにて検証する場合は、arduino用のブロックを無効化した上でシミュレーションのモードを「ノーマル」に設定、モデルの作りこみを行います。「シミュレーションの速度早すぎ、実時間にして！」という場合は[ペーシングオプション](https://jp.mathworks.com/help/simulink/ug/simulation-pacing.html)が有効です。

ある程度作りこみが終わったら、シミュレーション用のブロックを無効化した上でシミュレーションのモードを「エクスターナル」に設定してarduinoへの書き込み・実行を行います。

# おわりに
事例をもとに、似たように見える２つの連携方法の違いを示しました。
どちらか片方の連携だけでも強力ですが、違いを分かった上で使い分けることでその本領が発揮されるものと思います。本記事がそのための助けになれれば幸いです。