Simulink と Arduino Mega で『制御工学』を学ぶ、はじめの一歩

# <font color="#33CC33">1. はじめに</font>

　電子工作好きの方々は <b><font color="#0070C0">Arduino</font></b> を動かすのに Sketch とかを利用しているんでしょうね．でも
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/4c611543-73ea-9614-9acd-faa9ee9bf696.png)
 
 のお勉強で <b><font color="#0070C0">Arduino</font></b> を動かすのであれば，日頃から使い慣れた <b><font color="#0070C0">Simulink</font></b> を利用したいですよね！

　本記事では，<b><font color="#0070C0">Simulink Support Package for Arduino Hardware</font></b>（以下，<b><font color="#0070C0">Simulink Support Package</font></b> と略記）を利用して <b><font color="#0070C0">Arduino Mega 2560 R3</font></b>（以下，<b><font color="#0070C0">Arduino Mega</font></b> と略記）で<b>エンコーダ</b>付きの <b>DC モータ</b>の角度制御を行う方法について説明します．
 
　<font color="#E48312">I2C 通信が必要な <b>6 軸センサ MPU6050</b> の利用方法についても説明する！って思っていたのですが，間に合いませんでした．接続方法は記述しており，書く気でいたんですが...　後日，機会があれば...
　ということで，以下に，続きを書きました！(2025/01/06)<font>

https://qiita.com/Carter/items/1417e53ae08726dc04ae

　なお，今回もグダグダの記述になってしまいましたが，ご容赦ください．

　<font color="#E84746"><b>Simulink モデルは GitHub で公開</b></font>しています（R2023b ~ R2021b 用）．

https://github.com/Prof-Carter/arduino_mega

# <font color="#33CC33">2. Simulink Support Package for Arduino Hardware</font>

## <font color="#33CC33">2.1　インストール</font>

　今回使用するのは，

 * MATLAB
 * Simulink
 * Control System Toolbox

および無償で提供されている

 * <b><font color="#0070C0">Simulink Support Package for Arduino Hardware</font></b>

です．執筆時点の最新バージョン <b><font color="#E84746">R2023b</font></b> で説明しますが，<b><font color="#E84746">R2021b</font></b> 以降のバージョンなら問題ないかと思います．

　<b><font color="#0070C0">Simulink Support Package for Arduino Hardware</font></b> のインストール手順については，たとえば，Qiita の記事

https://qiita.com/Carter/items/cc7faa5084aa4a69f4e7

の 3 章を参照してください．


## <font color="#33CC33">2.2　ライブラリに含まれるブロック群</font>

　私のパソコンにはいくつかの MATLAB のバージョンがインストールされていますが，最も古いバージョンは <b><font color="#E84746">R2015aSP1</font></b> です（Windows11 では挙動が…ですが）．<b><font color="#E84746">R2015aSP1</font></b> の

 * [<b><font color="#0070C0">Simulink Support Package for Arduino Hardware</font></b>](https://jp.mathworks.com/help/supportpkg/arduino/)
 
で提供されているブロック群は

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/0ceda426-a0f9-be4b-3061-a4dc320e7a6e.png)


とわずかでした．それに対し，本記事の執筆時点での最新バージョンである <b><font color="#E84746">R2023b</font></b> では<b>随分とブロックの数が増えました！</b>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/7353110b-af75-e19a-2a8b-4f7d71be37ff.png)


## <font color="#33CC33">2.3　動作確認：Simulink モデルの設定</font>

　まずは MATLAB を起動してください（今回は <b><font color="#E84746">R2023b<font></b> を使用しています）．私のパソコンには，

* <b><font color="#0070C0">MATLAB Support Package for Arduino Hardware</font></b>
* <b><font color="#0070C0">Simulink Support Package for Arduino Hardware</font></b>

がインストールされています（<b><font color="#0070C0">MATLAB Support Package for Arduino Hardware</font></b> はインストールされていなくても良いです）．そして，<b><font color="#0070C0">Arduino Mega</font></b> を USB ケーブルでパソコンと接続すると，MATLAB コマンドウィンドウに以下のメッセージが表示されます．

```matlab:Arduino Mega を接続したときのメッセージ
 >> 
Arduino Mega 2560 detected.
This device is ready for use with MATLAB Support Package for Arduino Hardware. Get started with examples and other documentation.
This device is ready for use with Simulink Support Package for Arduino Hardware. Get started with examples and other documentation.
```

<b><font color="#0070C0">Arduino Mega</font></b> 互換ボードはこのメッセージが表示されなかったり（自動認識されなかったり），使用できなかったりすることがあるので，お高いですが，まずは，<b><font color="#E84746">純正ボードを使用することをお勧めします</font></b>． 

　それでは，配布する Simulink モデル "$\tt sample\verb+_+mega.slx$" を利用して，<b><font color="#0070C0">Simulink Support Package for Arduino Hardware</font></b> の動作確認をしましょう．

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/4e3bdd2c-66bc-f6a4-fca9-5fac9a6192c0.png)|
|:-:|
|<b>Simulink モデル "$\tt sample\verb+_+mega.slx$"</b>|

この Simulink モデルは，コンフィギュレーションパラメータが以下のように設定されています（Simulink モデルの空白部分を右クリックすると，コンフィギュレーションパラメータが表示されます）．

:::note info
コンフィギュレーションパラメータの設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/07273570-a52f-4b44-605a-cd9ccab5761c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/1645a01a-0988-b501-cf96-a99aabcd4f36.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/692c2a68-4385-e688-df76-33d14ae4d755.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/228faed2-c54d-44bf-bdcd-f2c04f51d7ea.png)
:::

Simulink モデル "$\tt sample\verb+_+mega.slx$" のタグを「ハードウェア」にして「監視と調整」をクリックすると，実行が開始されますので，Simulink ブロック "$\tt Scope$" により信号を観測してみてください．環境が整っていれば，10 秒周期のデューティ比 10% の ON/OFF 信号がリアルタイムで観測されるはずです．実験の様子は，以下の動画で確認してください．

https://youtu.be/sJt0Pwf2v6c?feature=shared

# <font color="#33CC33">3. とりあえず，接続！</font>

## <font color="#33CC33">3.1　部品</font>

　今回は，[MinSeg 社](https://minseg.com) の [MinSegShield M2V5](https://minseg.com/collections/minseg-kits/products/minsegshield-m2v5-dual-axis-balance-minseg-kit-new) を模擬することを目指して，環境を整えます．

　使用した部品は以下のとおりです．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/9d1be116-e6dd-34d8-7526-85d935d80b43.png)

|   |型番|メーカー|購入先|価格|
|---|---|---|---|---|
|マイコンボード|Arduino Mega 2560 R3|Arduino|https://jp.rs-online.com/web/p/arduino/7154084|7,035 円|
|モータドライバ<br>（はんだ付けオプション）|DRV8833|-|https://electronicwork.shop/items/633fb0a5f3de5c361ebadc45|150 円<br>（+500 円）|
|6 軸センサ<br>（はんだ付けオプション）|MPU6050 (GY-521)|-|https://electronicwork.shop/items/6262bf96be482f6d864f08c9|360 円<br>（+500 円）|
|ミニブレッドボード|BB-601|-|https://akizukidenshi.com/catalog/g/gP-05158/|150 円|
|基板用端子台<br>（2.54mm ピッチ 1 列 3 極）|790-1092|RS PRO|https://jp.rs-online.com/web/p/pcb-terminal-blocks/7901092|144 円|
|プロトタイプ開発用シールド|DFR0131|DFRobot|https://www.digikey.jp/ja/products/detail/dfrobot/DFR0131/6588456|2,049 円|
|エンコーダ付ギヤード DC モータ<br>（減速比 50:1，エンコーダ分解能 7PPR）|FIT0482|DFRobot|https://www.digikey.jp/ja/products/detail/dfrobot/FIT0482/7087159|1,883 円|
|AC アダプタ<br>（9V/1.3A，内径 2.1mm，外径 5.5mm，センタープラス）|SSCI-017954|スイッチサイエンス|https://www.switch-science.com/products/1795|1,463円|

これらに加えて，適当なブレッドボード用のジャンパ線も使用しています（下の接続例ではジャンパワイヤを使用しました）．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/0561ad0f-0d5b-de8f-984d-cbd85b0329e5.png)




## <font color="#33CC33">3.2　Arduino Mega とエンコーダ，DC モータの接続</font>

　接続の説明は後述しますので，まずは，接続図を示します．


### <font color="#33CC33">3.2.1　シールドを利用する場合</font>

　2 個のエンコーダ付ギヤード DC モータを使用する場合の接続例を以下に示します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/27f369d6-8fd7-a61e-fc88-2d4185b3632d.png)


### <font color="#33CC33">3.2.2　シールドを利用しない場合</font>
　プロトタイプ開発用シールドを使用しない場合は，以下のように接続してください．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/274673b0-88f1-8db2-8a6d-fb2472e85fd3.png)





## <font color="#33CC33">3.3　Arduino Mega と 6 軸センサの接続</font>
　6 軸センサの接続例を以下に示します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/e3dbfa49-9835-91a9-696b-55f5b542959c.png)







 

# <font color="#33CC33">4. Arduino Mega とエンコーダ</font>
## <font color="#33CC33">4.1　接続例</font>

　<b><font color="#E84746">R2021a</font></b> までは，Simulink Support Package for Arduino Hardware ではエンコーダのカウント数を取得する Simulink ブロックが提供されていませんでした．そのため，上記の Qiita の記事の 4 章で説明したように，[MinSeg.com](https://minseg.com/) さんが提供している無償の Simulink ライブラリ

* [<b><font color="#0070C0">Rensselaer Arduino Support Package Library (RASPLib)</font></b>](https://jp.mathworks.com/matlabcentral/fileexchange/62702)

をインストールし，それに含まれているエンコーダ入力の Simulink ブロックを利用していました．

　一方で，<b><font color="#0070C0">Simulink Support Package</font></b> においても，<b><font color="#E84746">R2021b</font></b> から各種の Arduino や ESP32 で利用可能な Simulink ブロック <font color="#0CA274">"$\tt Encoder$"</font> 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/9433bbc8-71d3-57ea-6a9e-6c5b21c8c391.png)

が追加されました．Simulink ブロック <font color="#0CA274">"$\tt Encoder$"</font> では，インクリメンタル型のエンコーダのカウント数を，<b>4 逓倍（ていばい）</b>で取得することができます．

https://youtu.be/pD3XZSAv1CI

https://youtu.be/nykT08oSK2E

今回使用するエンコーダは DC モータの後部に取り付けられており，エンコーダの分解能が 7PPR，モータのギヤ比が 50:1 なので，モータ軸が 1 回転すると，
```math
\begin{align}
   7 \times 4 \times 50 = \mbox{1,400}\ {\rm [カウント/回転]}
\end{align}
```
が得られます．
 
 　<b><font color="#0070C0">Arduino Mega + Simulink Support Package</font></b> で使用できるエンコーダ入力のピンは

* $\tt 2$, $\tt 3$, $\tt 18$, $\tt 19$, $\tt 20$, $\tt 21$ 番ピン

ですので，<b>A, B 信号を合計で 6 本，入力できます</b>．たとえば，以下のように <b><font color="#0070C0">Arduino Mega</font></b> とエンコーダを接続し，Simulink ブロック <font color="#0CA274">"$\tt Encoder$"</font> のパラメータを設定します．

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/713b1311-832a-bb1d-afaa-dfd8c31a145f.png)|
|:-:|
|エンコーダの接続例 1（$\tt 2$, $\tt 3$ 番ピンを使用）|

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/b509d635-fe94-a189-e6df-7a6b64350368.png)|
|:-:|
|エンコーダの接続例 2（$\tt 18$, $\tt 19$ 番ピンを使用）|

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/36454763-50c5-66fe-5aac-e2c1c22de7e2.png)|
|:-:|
|エンコーダの接続例 3（$\tt 20$, $\tt 21$ 番ピンを使用）|

:::note warn
<b><font color="#0070C0">Arduino Mega + Simulink Support Package</font></b> では，<b>3 個のエンコーダを同時に使用可能</b>です．
:::

:::note info
「<b><font color="#33CC33">5.3　接続例</font></b>」（エンコーダ付き DC モータ，モータドライバとの接続）では，<b>エンコーダの接続用</b>に

 * $\tt 2$, $\tt 3$ 番ピン
 * $\tt 18$, $\tt 19$ 番ピン

を使用しています．
:::



## <font color="#33CC33">4.2　Simulink モデルの実行例</font>

### <font color="#33CC33">4.2.1　カウント数を確認！</font>

　Simulink モデル "$\tt sample\verb+_+encoder1.slx$" を実行すると，Simulink ブロック "$\tt Display$" にカウント数が 4 逓倍で表示されます．

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/a80cc51a-55d6-aab3-de60-b8f310a0993f.png)|
|:-:|
|<b>Simulink モデル "$\tt sample\verb+_+encoder1.slx$"</b>|

先に説明したように，使用するギヤード DC モータは，モータ軸が 1 回転すると，
```math
\begin{align}
   7 \times 4 \times 50 = \mbox{1,400}\ {\rm [カウント/回転]}
\end{align}
```
が得られるはずです．Simulink モデル "$\tt sample\verb+_+encoder1.slx$" を実行すると，

https://youtu.be/LgiDJ9ytlb0

のようになり，モータ軸を正面にして，モータ軸を回転させると，

* 時計回りに 1 回転させると $-1,400$ カウント
* 反時計回りに 1 回転させると $+1,400$ カウント

となることが確認できます．


### <font color="#33CC33">4.2.2　エンコーダから出力される信号の型や配列を確認！</font>

　Simulink モデル "$\tt sample\verb+_+encoder2.slx$" を作成します．

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/66069899-8ab6-85f8-ab96-ba11e0ea4d43.png)|
|:-:|
|<b>Simulink モデル "$\tt sample\verb+_+encoder2.slx$"</b>|

Simulink モデル "$\tt sample\verb+_+encoder2.slx$" は 10 秒間で実行が終了するように設定されているので，実行が開始してから 10 秒以内に手でエンコーダの軸を適当に回転させてください．

https://youtu.be/3c5JeLX6wrk

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/d688e222-c588-e965-3fe2-0313d6c5873f.png)


その結果，Simulink ブロック "$\tt Scope$" では上図のように，リアルタイムで $\tt double\verb+_+data$ がグラフに表示されます．そして，

```matlab:Simulink モデル "$\tt sample\verb+_+encoder2.slx$" の実行結果の保存
>> save('encoder_data.mat', 'raw_data', 'reshape_data', 'double_data')
```

と入力すると，ワークスペースにある取得されたデータ

* $\tt raw\verb+_+data$
* $\tt reshape\verb+_+data$
* $\tt double\verb+_+data$

が $\tt encoder\verb+_+data.mat$ という名前の mat ファイルで保存されます．それでは，これらデータを順番に確認してみましょう．

　まず，コマンドウィンドウで以下のように入力し，関数 $\tt class$ によりデータの型を確認します．
 
```matlab:Simulink モデル "$\tt sample\verb+_+encoder2.slx$" の実行結果の確認
>> class(raw_data)
ans =
    'int32'
>> class(reshape_data)
ans =
    'int32'
>> class(double_data)
ans =
    'double'
```

これより，Simulink ブロック "$\tt Encoder$" からは $\tt int32$ 型（32 ビット符号付き整数）のカウント数が出力されていることが確認できます．Simulink モデルのなかで数値積分や数値微分を行うためには，データを $\tt double$ 型に変換する必要があります（いわゆる，キャスト）．そこで，配布する Simulink モデル "$\tt sample\verb+_+encoder2.slx$" では，Simulink ブロック "$\tt Data\ Type\ Conversion$" を利用して，$\tt double$ 型に変換しています．

　つぎに，Simulink ブロック "$\tt Reshape$" の役割について説明します．コマンドウィンドウで以下のように入力し，関数 $\tt size$ によりデータのサイズを確認してみましょう．
 
```matlab:Simulink モデル "$\tt sample\verb+_+encoder2.slx$" の実行結果の確認
>> size(raw_data)
ans =
           1           1        2001
>> size(reshape_data)
ans =
        2001           1
>> size(double_data)
ans =
        2001           1
```

これより，Simulink ブロック "$\tt Encoder$" からは $1 \times 1 \times 2001$ の 3 次元配列としてデータが出力されていることがわかります（2001 なのは，サンプリング周期 0.005 秒で 10 秒間，実行したからです）．通常，スカラのデータは 1 次元配列で取り扱いますので，Simulink ブロック "$\tt Reshape$" を利用して 3 次元配列を 1 次元配列に変換しているのです．つまり，

* $\tt raw\verb+_+data$：$\tt int32$ 型の $1 \times 1 \times 2001$ の 3 次元配列
* $\tt reshape\verb+_+data$：$\tt int32$ 型の $2001 \times 1$ の 1 次元配列
* $\tt double\verb+_+data$：$\tt double$ 型の $2001 \times 1$ の 1 次元配列

となっています．

　最後に，以下のように入力して，501 番目から 505 番目までのデータを確認します．
 
```matlab:Simulink モデル "$\tt sample\verb+_+encoder2.slx$" の実行結果の確認   
>> raw_data(501:505)
  1×1×5 の int32 配列
ans(:,:,1) =
   -334
ans(:,:,2) =
   -336
ans(:,:,3) =
   -338
ans(:,:,4) =
   -340
ans(:,:,5) =
   -342
>> reshape_data(501:505)
ans =
  5×1 の int32 列ベクトル
   -334
   -336
   -338
   -340
   -342
>> double_data(501:505)
ans =
  -334
  -336
  -338
  -340
  -342
```

　以上のように，Simulink ブロック "$\tt Encoder$" を利用してエンコーダのカウント数を取得した場合，Simulink ブロック "$\tt Reshape$" および "$\tt Data\ Type\ Conversion$" を利用して，データを変換するようにしましょう．


 ### <font color="#33CC33">4.2.3　カウント数から角度を算出！</font>

　Simulink モデル "$\tt sample\verb+_+encoder1.slx$" の実行結果からわかるように，使用しているモータ軸を時計回りに 1 回転させると，$- 1,400$ カウントとなりました $(7 \times 4 \times 50 = 1,400)$．時計回りを正にしたいので，極性を変更する必要があります．また，モータ角を制御したいのであれば，エンコーダのカウント数 ${\tt cnt}$ を角度 ${\tt ang}$ (rad) に変換する必要があります．そこで，Simulink ブロック "${\tt Gain}$" を利用して，
```math
\begin{align}
  &{\tt ang} = {\tt Gain2} \times {\tt Gain1} \times {\tt cnt}
  \\
  &\quad
  {\tt Gain1} = \dfrac{2\pi}{7 \times 4 \times 50},\ 
  {\tt Gain2} = -1
\end{align}
```
という演算を行います．MATLAB/Simulink では，円周率 $\pi$ は $\tt pi$ であることに注意してください．このことを考慮して，Simulink モデル "$\tt sample\verb+_+encoder3.slx$" を作成します．

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/7fb539e8-0ee8-fb53-935b-6abcc5312e2b.png)|
|:-:|
|<b>Simulink モデル "$\tt sample\verb+_+encoder3.slx$"</b>|

https://youtu.be/mMV4pGsZaHk

Simulink モデル "$\tt sample\verb+_+encoder3.slx$" を実行すると，

* 時計回りに 1 回転させると $+360\ {\rm [deg]}\ (= +2\pi\ {\rm [rad]})$
* 反時計回りに 1 回転させると $-360\ {\rm [deg]}\ (= -2\pi\ {\rm [rad]})$

となることが確認できます．



# <font color="#33CC33">5. Arduino Mega とモータドライバ，DC モータ</font>

## <font color="#33CC33">5.1　モータドライバ</font>
### <font color="#33CC33">5.1.1　動作モード</font>

　今回使用するモータドライバは，
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/d8d2525c-2241-fed6-a6a4-19318c9fe391.png)

です．DRV8833 は 2 個の DC モータを動作させることができます．以下では，モータドライバの入力ピン <font color="#FF6699">$\tt IN1$</font>, <font color="#00B0F0">$\tt IN2$</font> と出力ピン <font color="#0CA274">$\tt OUT1$</font>, <font color="#0070C0">$\tt OUT2$</font> を使用するとして説明していますが，入力ピン <font color="#FF6699">$\tt IN3$</font>, <font color="#00B0F0">$\tt IN4$</font> と出力ピン <font color="#0CA274">$\tt OUT3$</font>, <font color="#0070C0">$\tt OUT4$</font> を使用する場合も同様です．

　モータドライバの入力ピン <font color="#FF6699">$\tt IN1$</font>, <font color="#00B0F0">$\tt IN2$</font> に $\tt H$, $\tt L$ のいずれかを与えるかによって，DC モータは
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/b76be768-28eb-26f0-125a-996cc963dcc8.png)

のように動作します．


### <font color="#33CC33">5.1.2　正転と逆転</font>

　正転，逆転は以下のように動作させます．

:::note warn
モータドライバに <font color="#FF6699">$\tt IN1 = H$</font>，<font color="#00B0F0">$\tt IN2 = L$</font> を加えると，モータドライバの出力は <font color="#0CA274">$\tt OUT1 = H$</font>, <font color="#0070C0">$\tt OUT2 = L$</font> となり，DC モータには <font color="#0CA274">${\tt M+ = VCC}\ [\rm V]$</font>, <font color="#0070C0">$\tt M- = 0\ [\rm V]$</font> が加わります．その結果，DC モータは一定の角速度で<font color="#FF6699"><b>正方向に回転（正転）</b></font>します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/6316c6cc-1260-135a-2b44-020e228dae24.png)
:::

:::note warn
モータドライバに <font color="#FF6699">$\tt IN1 = L$</font>，<font color="#00B0F0">$\tt IN2 = H$</font> を加えると，モータドライバの出力は <font color="#0CA274">$\tt OUT1 = L$</font>, <font color="#0070C0">$\tt OUT2 = H$</font> となり，DC モータには <font color="#0CA274">${\tt M+ = 0}\ [\rm V]$</font>, <font color="#0070C0">$\tt M- = VCC\ [\rm V]$</font> が加わります．その結果，DC モータは一定の角速度で<font color="#00B0F0"><b>逆方向に回転（逆転）</b></font>します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/4a9b9f1d-e99d-0aaa-6a38-8b11b781bb47.png)
:::

しかし，<b>「駆動（正転・逆転）」</b>の動作だけでは，回転速度を思うように変化させることができません．そこで，<b>「駆動」</b>と<b>「惰性」</b>や<b>「ブレーキ」</b>の動作を組み合わせます．以下では，<b>「駆動」</b>と<b>「ブレーキ」</b>を組み合わせた方法について簡単に説明します．


### <font color="#33CC33">5.1.3　正転/ブレーキの切り替え</font>

　<b><font color="#8497B0">「ブレーキ」</font></b>では，切り替わる前の動作を維持しようとします（回生ブレーキ）．そのため，<b><font color="#FF6699">「正転」</font></b>から<b><font color="#8497B0">「ブレーキ」</font></b>に切り替えると，<b><font color="#FF6699">じわっと減速</font></b>します．また，<b><font color="#8497B0">「ブレーキ」</font></b>から<b><font color="#FF6699">「正転」</font></b>に切り替えると，再び，力強く回転します．この<b><font color="#8497B0">「ブレーキ」</font></b>と<b><font color="#FF6699">「正転」</font></b>の切り替えの割合（<b>デューティ比</b>）を設定し，短時間（サンプリング周期 $h$）で切り替えを行うことにより，回転速度を変化させることができます．

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/7ca77c25-6009-5f5f-2dcd-e676597938f3.png)

　具体的には，以下に示すように，<font color="#FF6699">$\tt IN1 = H$</font> としたまま，サンプリング周期 $h$ の間，設定した<b>デュ―ティ比</b>で <font color="#00B0F0">$\tt IN2 = L$</font> （<font color="#FF6699"><b>正転</b></font>）と <font color="#00B0F0">$\tt IN2 = H$</font>（<font color="#8497B0"><b>ブレーキ</b></font>）を切り替えます．つまり，

* <b><font color="#00B0F0">$\tt IN2$ のデュ―ティ比が 0% に近い</font></b>ほど<b><font color="#FF6699">高速で正転</font></b>する
*  <b><font color="#00B0F0">$\tt IN2$ のデュ―ティ比が 100% に近い</font></b>ほど<b><font color="#FF6699">低速で正転</font></b>する

ことになります．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/55979948-906b-b002-2cba-4685d67cc0e8.png)


　以上をまとめると，<font color="#FF6699">$\tt IN1 = H$</font> としたまま，周期 $h$ ごとにデュ―ティ比が設定された <b>PWM (Pulse Width Modulation：パルス幅変調) 信号</b>を <font color="#00B0F0">$\tt IN2$</font> に加えると，<b><font color="#FF6699">正転の回転速度を変化</font></b>させることができます．


### <font color="#33CC33">5.1.4　逆転/ブレーキの切り替え</font>

　同様に，<b><font color="#00B0F0">逆転の回転速度を変化</font></b>させることができます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/188a086d-1186-242d-cf6e-3b4bc4d47f1e.png)

　具体的には，以下に示すように，<font color="#00B0F0">$\tt IN2 = H$</font> としたまま，サンプリング周期 $h$ の間，設定した<b>デュ―ティ比</b>で <font color="#FF6699">$\tt IN1 = L$</font> （<font color="#00B0F0"><b>逆転</b></font>）と <font color="#FF6699">$\tt IN1 = H$</font>（<font color="#8497B0"><b>ブレーキ</b></font>）を切り替えます．つまり，

* <b><font color="#FF6699">$\tt IN1$ のデュ―ティ比が 0% に近い</font></b>ほど<b><font color="#00B0F0">高速で逆転</font></b>する
*  <b><font color="#FF6699">$\tt IN1$ のデュ―ティ比が 100% に近い</font></b>ほど<b><font color="#00B0F0">低速で逆転</font></b>する

ことになります．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/e652bb02-ebb4-557d-41f3-7d3845295517.png)

　以上をまとめると，<font color="#00B0F0">$\tt IN2 = H$</font> としたまま，周期 $h$ ごとにデュ―ティ比が設定された <b>PWM 信号</b>を <font color="#FF6699">$\tt IN1$</font> に加えると，<b><font color="#00B0F0">逆転の回転速度を変化</font></b>させることができます．





## <font color="#33CC33">5.2　Arduino Mega の PWM 出力ピン</font>

　このように，DC モータの回転速度を変化させるためには，モータドライバ <b><font color="#0070C0">DRV8833</font></b> の入力ピン <font color="#FF6699">$\tt IN1$</font>, <font color="#00B0F0">$\tt IN2$</font>（あるいは入力ピン <font color="#FF6699">$\tt IN3$</font>, <font color="#00B0F0">$\tt IN4$</font>）に PWM 信号を加える必要があります．つまり， <b><font color="#0070C0">Arduino Mega</font></b> の PWM 出力ピンとモータドライバ <b><font color="#0070C0">DRV8833</font></b> の入力ピンを接続します． 
 
　<b><font color="#0070C0">Simulink Support Package</font></b> では，PWM 出力を行うための Simulink ブロックとして，"$\tt PWM$"

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/78b2e361-c944-ce4e-a033-fc7ed402726a.png)

が提供されています．ここで，以下のことに注意してください．

:::note info
Simulink ブロック "$\tt PWM$" に入力する値は出力したい PWM 信号のデューティ比です．<b>デューティ比 (0～100%) は整数値（0～255）で指定します</b>ので，たとえば，デューティ比を 20% としたいのであれば ${\tt 51}\ (= {\tt 255} \times 0.2)$ を，デューティ比を 80% としたいのであれば ${\tt 204}\ (= {\tt 255} \times 0.8)$ を入力します．
:::

:::note info
Simulink ブロック <font color="#0CA274">"$\tt PWM$"</font> に入力できるデータの型は $\tt uint8$ 型（符号なし 8 ビット整数型）です．そのため，Simulink ブロック "$\tt Data\ Type\ Conversion$" により $\tt uint8$ 型に変換した後，Simulink ブロック <font color="#0CA274">"$\tt PWM$"</font> に入力する必要があります．
:::

　<b><font color="#0070C0">Arduino Mega</font></b> では $\tt 2$〜$\tt 13$ 番ピンと $\tt 44$〜$\tt 46$ 番ピンを PWM 出力用のピンとして使用できます．[とみっくす](https://tomixrm.wordpress.com/)さんのブログ
 
 * [Arduino Mega のタイマー情報](https://tomixrm.wordpress.com/2017/08/24/arduino-mega%E3%81%AE%E3%82%BF%E3%82%A4%E3%83%9E%E3%83%BC%E6%83%85%E5%A0%B1/)

に詳しく書かれています．簡単にまとめると，下表のようになります．

| タイマー | ピン |
|:-:|:-:|
|Timer0 (8bit timer)| $\tt 4$, $\tt 13$  |
|Timer1 (16bit timer)| $\tt 11$, $\tt 12$  |
|Timer2 (8bit timer)| $\tt 9$, $\tt 10$  |
|Timer3 (16bit timer)| $\tt 2$, $\tt 3$, $\tt 5$  |
|Timer4 (16bit timer)| $\tt 6$, $\tt 7$, $\tt 8$  |
|Timer5 (16bit timer)| $\tt 44$, $\tt 45$, $\tt 46$  |

　なお，<b><font color="#0070C0">Arduino Mega</font></b> の PWM 出力として割当可能な $\tt 2$〜$\tt 13$ 番ピンと $\tt 44$〜$\tt 46$ 番ピンについて，以下のことに注意してください．

:::note warn
タイマーカウンタと同期して PWM 信号を生成しているので，<b>同一のタイマーに接続されているピンを利用する</b>ようにしましょう．
:::

:::note warn
Simulink ブロック <font color="#0CA274">"$\tt Encoder$"</font> では，エンコーダ入力として $\tt 2$, $\tt 3$ 番ピンを使用します．そのため，$\tt 2$, $\tt 3$ 番ピンを PWM 出力用に割り当てないようにしましょう．
:::



## <font color="#33CC33">5.3　接続例</font>

　たとえば，以下のように <b><font color="#0070C0">Arduino Mega</font></b> とモータドライバ <b><font color="#0070C0">DRV8833</font></b> および DC モータを接続し，Simulink ブロック <font color="#0CA274">"$\tt PWM$"</font> のパラメータを設定します．

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/ec36f9fd-1a0f-76fe-3bd5-3f6e29d907a6.png)|
|:-:|
|モータドライバ，DC モータの接続例 1（$\tt 6$, $\tt 7$ ピンを使用）|

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/91d0884c-70ad-6c5c-46be-dd15f375e359.png)|
|:-:|
|モータドライバ，DC モータの接続例 2（$\tt 9$, $\tt 10$ ピンを使用）|

:::note info
「<b><font color="#33CC33">3.2　Arduino Mega とエンコーダ，DC モータの接続</font></b>」では，<b>DC モータの接続用（PWM 出力用）</b>に

 * $\tt 6$, $\tt 7$ 番ピン
 * $\tt 9$, $\tt 10$ 番ピン

を使用しています．
:::



## <font color="#33CC33">5.4　Simulink モデルの実行例</font>

### <font color="#33CC33">5.4.1　正転/ブレーキの切り替えを行う！</font>

　「<b><font color="#33CC33">5.1.3　正転/ブレーキの切り替え</font></b>」で説明した動作を実現する Simulink モデル "$\tt sample\verb+_+motor1.slx$" は以下のようになります．

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/0c1e4914-7ca4-787a-c393-4f1d1a38237c.png)|
|:-:|
|<b>Simulink モデル "$\tt sample\verb+_+motor1.slx$"</b>|

Simulink モデル "$\tt sample\verb+_+motor1.slx$" を「監視と調整」で実行すると，<font color="#00B0F0">"$\tt PWM\ (IN2)$" ($\tt 7$ 番ピン)</font> や <font color="#00B0F0">"$\tt PWM\ (IN4)$" ($\tt 10$ 番ピン)</font> への入力が小さな値 (<font color="#00B0F0">$\tt 51$</font>) なので，<b><font color="#FF6699">低速で正転</font></b>します．そして，"$\tt Manual\ Switch$" をダブルクリックすると，入力が大きな値 (<font color="#00B0F0">$\tt 204$</font>) に切り替わるので，<b><font color="#FF6699">高速で正転</font></b>することが確認できます．

https://youtu.be/TsEerjPnXh0

### <font color="#33CC33">5.4.2　逆転/ブレーキの切り替えを行う！</font>

　「<b><font color="#33CC33">5.1.4　逆転/ブレーキの切り替え</font></b>」で説明した動作を実現する Simulink モデル "$\tt sample\verb+_+motor2.slx$" は以下のようになります．

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/0f6a5fc5-bf73-a7bf-8b1c-a083d1349abe.png)|
|:-:|
|<b>Simulink モデル "$\tt sample\verb+_+motor2.slx$"</b>|

Simulink モデル "$\tt sample\verb+_+motor2.slx$" を「監視と調整」で実行すると，<font color="#FF6699">"$\tt PWM\ (IN1)$" ($\tt 6$ 番ピン)</font> や <font color="#FF6699">"$\tt PWM\ (IN3)$" ($\tt 9$ 番ピン)</font> への入力が小さな値 (<font color="#FF6699">$\tt 51$</font>) なので，<b><font color="#00B0F0">低速で逆転</font></b>します．そして，"$\tt Manual\ Switch$" をダブルクリックすると，入力が大きな値 (<font color="#FF6699">$\tt 204$</font>) に切り替わるので，<b><font color="#00B0F0">高速で逆転</font></b>することが確認できます．

https://youtu.be/WqooERsGTA0


### <font color="#33CC33">5.4.3　正負の指令電圧により回転方向と速さを切り替える！</font>

　以下のように，正負の指令電圧（整数値）を与えて，正転と逆転を切り替えた方が使いやすいです．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/3b06aabe-55b3-ebda-e074-cabf1790706c.png)

　この例の上図では，<font color="#0CA274"><b>指令電圧として正の値</b> $\tt 51$</font> を与えています．その結果，

* <font color="#FF6699">"$\tt PWM\ (IN1)$" ($\tt 6$ 番ピン)</font> への入力が <font color="#FF6699">$\tt 255$</font>
* <font color="#00B0F0">"$\tt PWM\ (IN2)$" ($\tt 7$ 番ピン)</font> への入力が <font color="#00B0F0">$\tt 204$</font>

なので，<b><font color="#FF6699">低速で正転</font></b>します．

　一方，この例の下図では，<font color="#0CA274"><b>指令電圧として負の値</b> $\tt -51$</font> を与えています．その結果，

* <font color="#FF6699">"$\tt PWM\ (IN1)$" ($\tt 6$ 番ピン)</font> への入力が <font color="#FF6699">$\tt 204$</font>
* <font color="#00B0F0">"$\tt PWM\ (IN2)$" ($\tt 7$ 番ピン)</font> への入力が <font color="#00B0F0">$\tt 255$</font>

なので，<b><font color="#FF6699">低速で反転</font></b>します．

　そこで，以下に示す Simulink モデル "$\tt sample\verb+_+motor3.slx$" を「監視と調整」で実行してみます．

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/a9d0329b-11d2-c758-485c-9aa27e451024.png)|
|:-:|
|<b>Simulink モデル "$\tt sample\verb+_+motor3.slx$"</b>|

実行後，マウスでダイヤルを回転させることにより，回転速度や回転の方向を変化させることが確認できます．

https://youtu.be/X5VH6PwZZCU




### <font color="#33CC33">5.4.4　モータ角の比例制御を行ってみる！</font>

　最後に，モータ角の P 制御を行ってみましょう．

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/e49d53dd-af9b-47d6-6b62-2f92e494e619.png)|
|:-:|
|<b>モータ角の P 制御</b>|

　制御出力であるモータ角 $y$ は，「<b><font color="#33CC33">4.2.3　カウント数から角度を算出！</font></b>」で説明したように，カウント数から角度を算出することができます．
 
 　一方で，「<b><font color="#33CC33">5.4.3　正負の指令電圧により回転方向と速さを切り替える！</font></b>」で説明したように，指令電圧を正負の整数値（デューティ比）として与えることで，モータの回転方向と速さを切り替えることができました．ここではさらに，以下のことを行います．

* 9V/1.3A の AC アダプタを使用していることを考慮し，便宜的に，電圧値 ($-9\ {\rm [V]} \sim +9\ {\rm [V]}$) を $-255 \sim +255$ の整数値に割り当てることにします．

* モータに正の指令電圧を加えると，反時計回りに回転することが確認できたので，時計回りが正になるように極性を変更します．

以上の操作を行うため，そのために，Simulink ブロック "${\tt Gain}$" を利用して，
```math
\begin{align}
  &{\tt u\mbox{_}int} = {\tt Gain2} \times {\tt Gain1} \times {\tt u}
  \\
  &\quad
  {\tt Gain1} = \dfrac{255}{9},\ 
  {\tt Gain2} = -1
\end{align}
```
という演算を行います．



|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/14ead23e-bf17-ab89-a001-9e4ba0e0996b.png)|
|:-:|
|<b>Simulink モデル "$\tt sample\mbox{\_}motor\mbox{\_}encoder\mbox{\_}pcont\mbox{\_}dual.slx$"</b>|

 　AC アダプタを接続しない場合は，DC モータには USB ケーブルを介して電力が供給されますので，弱々しく動きます．

https://youtu.be/87HDwCRzf-U


 　一方で，AC アダプタを接続した場合は，DC モータには AC アダプタから電力が供給されますので，力強く動きます．

https://youtu.be/2rNRExiI3fU





# <font color="#33CC33">6. おわりに</font>

　昨年末に続き，今年もなんとか 2 編，投稿できて良かったです！（2 編目は予定のところまでは完成しませんでしたが…）
 
　機会を与えていただき，ありがとうございました，モータ制御マン (@motorcontrolman) さん！

　今にして思えば，コロナ禍での様々なストレスの気晴らしで始めたネット上での技術的な配信ですが，今後も，こそーっと，この趣味を続けていければと思う次第です．

 （おしまい）

 

# <font color="#33CC33">付録 A　Arduino Uno の場合はどうなの？</font>

　<b><font color="#0070C0">各種の Arduino（もしくは ESP32）+ Simulink Support Package</font></b> で使用できるピンは

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/effefb1a-98c3-4722-82d1-2d1a627943ad.png)

により

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/2c9ce431-4e20-8baa-3063-65a48041835f.png)

のように確認できます．たとえば，以下のようになります．

:::note warn
<b><font color="#0070C0">Arduino Uno + Simulink Support Package</font></b> で使用できるエンコーダ入力のピンは $\tt 2$, $\tt 3$ 番ピンのみですので，<b>1 個のエンコーダをのみが使用可能</b>です．
:::



# <font color="#33CC33">付録 B　Rensselaer Arduino Support Package Library (RASPLib) との違い</font>

　<b><font color="#0070C0">Simulink Support Package</font></b> と [<b><font color="#0070C0">Rensselaer Arduino Support Package Library (RASPLib)</font></b>](https://jp.mathworks.com/matlabcentral/fileexchange/62702) の利用するピンの違いについて少し説明します．[<b><font color="#0070C0">RASPLib</font></b>](https://jp.mathworks.com/matlabcentral/fileexchange/62702) は [MinSeg.com](https://minseg.com/) さんの製品を使用することを前提として Simulink ブロックが提供されています．

　エンコーダ信号を取得するためのピンは以下のとおりです．
| <font color="#0070C0">Simulink Support Package</font> | <font color="#0070C0">RASPLib / <font color="#0070C0">M2V5 Library</font> | <font color="#0070C0">RASPLib / MinSegMega Library</font> | <font color="#0070C0">RASPLib / M2V3 Library</font> |
|:-:|:-:|:-:|:-:|
| $\tt 2$, $\tt 3$ | $\tt Encoder0:$ $\tt 2$, $\tt 3$ |
| $\tt 18$, $\tt 19$ |  | $\tt Encoder1:$ $\tt 18$, $\tt 19$ | $\tt Encoder1:$ $\tt 18$, $\tt 19$ |
| $\tt 20$, $\tt 21$ |  |
| | | $\tt Encoder2:$ $\tt 6$, $\tt 7$ | |
| | | | $\tt Encoder3:$ $\tt 15$, $\tt 62(A8)$ |
| | $\tt Encoder4:$ $\tt 11$, $\tt 12$ |

　また，PWM 出力をするための（モータドライバに入力するための）ピンは以下のとおりです．
| タイマ | <font color="#0070C0">Simulink Support Package</font> | <font color="#0070C0">RASPLib / M2V5 Library</font> | <font color="#0070C0">RASPLib / MinSegMega Library</font> |
|:-:|:-:|:-:|:-:|
|Timer0 (8bit timer)| $\tt 4$, $\tt 13$  |
|Timer1 (16bit timer)| $\tt 11$, $\tt 12$  |
|Timer2 (8bit timer)| $\tt 9$, $\tt 10$  | $\tt 9$, $\tt 10$  |
|Timer3 (16bit timer)| $\tt 2$, $\tt 3$, $\tt 5$ |
|Timer4 (16bit timer)| $\tt 6$, $\tt 7$, $\tt 8$ | $\tt 6$, $\tt 7$ |
|Timer5 (16bit timer)| $\tt 44$, $\tt 45$, $\tt 46$ | | $\tt 44$, $\tt 45$ |

PWM 出力については，以下の点に注意してください．

* [<b><font color="#0070C0">RASPLib</font></b>](https://jp.mathworks.com/matlabcentral/fileexchange/62702) では，モータドライバに入力するための Simulink ブロックが提供されています．これは，基本的に，「<b><font color="#33CC33">5.4.3　正負の指令電圧により回転方向と速さを切り替える！</font></b>」で説明した Simulink モデルをマスク化したものです．