【Simulink】Simulink Support Package for Raspberry PiでSunFounderを動かす(3)

# はじめに
Simulink Support Package for Raspberry PiでSunFounderを動かす(1)(2)の続き記事です。
これまでの記事では、[Simulinkモデルの構造と実行制御部の説明](https://qiita.com/nrykot/items/ece75417703b90ae2b4c)、および、[初期化処理サブシステム](https://qiita.com/nrykot/items/ae3c6dd8b08b3e1a1938)について説明しました。
本記事では、周期処理サブシステムの概要について説明します。

# 周期処理サブシステムの概要
Sunfounderのステアリング制御と前後進制御を行う周期処理サブシステムは、下図のように作成しています。
![periodic_task.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/a04dd6e7-1395-9dce-9280-b7de4ce89b48.png)

右側には、ステアリング制御と前後進制御の処理単位ごとに複数のFunction-Call Subsystemを配置し、左側にあるサブシステムで、ステアリング制御と前後進制御の処理の実行順を制御するようにしています。

ステアリング制御と前後進制御のFunction-Call Subsystemの内容は下表の通りです。
もう少しサブシステムをまとめることも可能だと思いますが、動かすことを優先したため、このような構成になっています。
| # | Function-Call Subsystemの処理内容（上から） |
|:-:|:-|
|1|ステアリング初期位置を設定|
|2|ステアリングを左方向に少しずつ操舵|
|3|ステアリングを右方向に少しずつ操舵|
|4|加速制御|
|5|減速制御|
|6|前後進の停止|
|7|駆動方向の設定|

# 実行順を制御するモデルの概要
実行順を制御するモデルは、下図のように作成しました。
![CallingSequenceManager.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/04827a66-cb4b-a708-080b-ae922eac0ba2.png)

Switch Caseブロックを使用して、実行ステップを制御するようにしています。
あらかじめ決めていおいた実行回数を実行したら、次のステップに移行するようにしています。
各ステップの概要を下表に示します。
| # | 実行ステップ | 次の実行ステップ | 次ステップの実行回数 |
|:-:|:-|:-|:-|
|1|ステアリング初期位置設定|ステアリング左方向制御|1|
|2|ステアリング左方向制御|ステアリング右方向制御|1|
|3|ステアリング右方向制御|制御ステップ変更|1|
|4|制御ステップ変更|前進加速駆動制御|9|
|5|前進加速駆動制御|前進減速駆動制御|9|
|6|前進減速駆動制御|前後進の停止|1|
|7|前後進の停止|後進加速駆動制御|9|
|8|後進加速駆動制御|後進減速駆動制御|9|
|9|後進減速駆動制御|前後進の停止|1|
|10|前後進の停止|制御ステップ変更|1|

実行制御のステップは、以下のような列挙型定義ファイルで設定しています。
```matlab:enumSunFounderOperation.m
classdef enumSunFounderOperation < Simulink.IntEnumType
    enumeration
        ChangeStep(0),                      % 実行ステップ変更
		SteerToInitPosition(1),             % ステアリングを初期位置に設定
		SteerToLeft(2),                     % ステアリングを左に操舵
        SteerToRight(3),                    % ステアリングを右に操舵
        AccelerateInForwardDirection(4),    % 前進方向の加速
        DecelerateInForwardDirection(5),    % 前進方向の減速
        AccelerateInBackwardDirection(6),   % 後退方向の加速
        DecelerateInBackwardDirection(7),   % 後退方向の減速
        StopMovingForwardAndBackward(8)     % 前後進の停止
    end

    methods (Static)
        function defaultValue = getDefaultValue()
            defaultValue = enumSunFounderOperation.SteerToInitPosition;
        end

        function dScope = getDataScope()
            dScope = 'Auto';
        end

        function desc = getDescription()
            desc = 'SunFounder動作確認用Simulinkモデルで使用する呼び出し機能名';
        end

        function fileName = getHeaderFile()
            fileName = '';
        end

        function flag = addClassNameToEnumNames()
            flag = true;
        end
    end
end
```
以下、各Switch Case Action Subsystem内を示します。

## ステアリング初期位置設定呼び出し
![CaseSteerToInitPosition.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/e87a3325-4e76-1b7d-7f47-eb2c03e8d1e0.png)

## ステアリング左方向制御呼び出し
![CaseSteerToLeft.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/0c641990-3565-59d9-1ced-01c2262ee13f.png)

## ステアリング右方向制御を呼び出し
![CaseSteerToRight.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/06f74c7c-b5e1-1ada-6e3e-e5bd98d44d07.png)

## 制御ステップ変更
![CaseChangeStep.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/c38de521-6b0c-3b92-1fb6-ab5abf73e04d.png)

## 前進加速駆動制御を呼び出し
![CaseAccelForward.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/1df611a7-4a59-f930-190e-a405e1ffbc65.png)

### 回転方向設定
![SetRotationDirection.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/f891111e-dac3-e50b-1874-e9cffdbb97fd.png)

## 前進減速駆動制御を呼び出し
![CaseDecelForwardDirection.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/5642d7a6-8c1b-98fa-d02e-68205d5effdb.png)

## 前後進の停止
![CaseStop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/a9225819-e641-08fc-acda-581f300d6ae8.png)

### 次制御ステップ選択
次制御ステップは、前ステップが前進減速駆動制御ステップか後進減速駆動制御ステップかにより変わります。
![CaseStop_NextStep.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/bbaa2388-6db2-f8da-1ca4-b6bae9511c4b.png)

#### 前ステップが前進減速駆動制御ステップの場合
前ステップが前進減速駆動制御ステップの場合の次ステップは、後進加速駆動制御ステップになります。
![CaseStop_NextStep_CaseDecelForward.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/41f75bde-46b5-2a72-f691-844181bde3e5.png)

#### 前ステップが後進減速駆動制御ステップの場合
前ステップが後進減速駆動制御ステップの場合の次ステップは、制御ステップ変更になります。
![CaseStop_NextStep_CaseDecelBackward.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/6c90dc7a-71d4-72fc-2414-d559b0dfdb88.png)

## 後進加速駆動制御を呼び出し
![CaseAccelBackward.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/f28141cd-3807-0f6b-5284-64515e954c77.png)

## 後進減速駆動制御を呼び出し
![CaseDecelBackward.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/60d56c06-fa3a-d988-749b-2f72880f87b4.png)

# ステアリング制御
「[MATLAB Support Package for Raspberry PiでSunFounderを動かす](https://qiita.com/nrykot/items/243359681d0b9fa7d86f "MATLAB Support Package for Raspberry PiでSunFounderを動かす")」の記事で書いたMATLABプログラムと同等の処理をSimulinkでモデリングしています。

## ステアリング初期位置の設定
ステアリング初期位置を設定するモデルを以下に示します。
![SteerToInitPosition.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/233dfe2c-cb52-2cf4-83a8-7212cb7d7b3c.png)

以下の4つのレジスタを順番に設定するため、本例ではFunction-Call Generatorブロックの反復回数を4に設定して、それぞれのレジスタを設定するFunction-Call Subsystemを実行しています。
* LED0_ON_L_REG
* LED0_ON_H_REG
* LED0_OFF_L_REG
* LED0_OFF_H_REG

レジスタを設定するFunction-Call Subsystem内では、Simulink Support Package for Raspberry Pi HardwareのI2C Master Writeブロックを使用し、I2C通信でPCA9685のレジスタを設定するようにしています。
![SetRegister_LED0_ON_L_REG.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/76b905e8-e5d5-7581-5aaf-f072327d4194.png)

I2C Master Writeブロックのパラメーター設定例を下図に示します。
![I2cMasterWriteExample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/d07a25a6-18c9-1713-62b9-d3d8bfe5614f.png)

レジスタアドレスの値は、モデルワークスペースにMATLAB変数として定義しています。
![ModelWorkspace.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/d38ec6bd-ea4f-08c4-76eb-bafe4ccf818b.png)

ステアリング用サーボモーターを駆動するPWM信号のデューティ比を計算するサブシステムは、以下のように作成しています。
![CalcPwmDuty.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/1b763788-c63d-8810-5188-b2421406e884.png)

## ステアリング左方向操舵
ステアリングを左方向に少しずつ操舵する処理は、For Iterator Subsystemを使用して、以下のようにモデリングしています。
![SteerToLeft.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/0bc4d6e1-88b3-c9b8-6573-7d2ce040904a.png)

For Iterator Subsystem内のモデル構造としては、初期位置設定用のFunction-Call Subsystemとほぼ同じです。
ステアリング制御角度を5度刻みで入力する箇所と待機処理部が異なります。
![SteerLeftLittleByLittle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/ad6b0b95-37cc-11c5-5618-333a3e2fcd96.png)

### 待機処理
ステアリングを少しずつ操舵するための待機処理は、下図のようにモデリングしています。
時刻取得には、ROS ToolboxのCurrent Timeブロックを使用しています。
本記事内では行いませんが、ホストPCとRaspberry PiをROSネットワークに接続して、ホストPCからRaspberry Piを制御することも考えていたため、ROS Toolboxを使用しています。
![Wait.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/e513d54f-86de-6679-292d-c4d375790a95.png)
![WhileIteratorSubsystem.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/26f058b5-a69f-4a08-b06c-05c9dd71a499.png)

## ステアリング右方向操舵
ステアリングを右方向に少しずつ操舵する処理は、ステアリング制御角度を設定するConstantブロックの値（[0:5:30]）を除いて、左方向への操舵と同じようにモデリングしています。

# 前後進制御
ステアリング制御部と同様に、「[MATLAB Support Package for Raspberry PiでSunFounderを動かす](https://qiita.com/nrykot/items/243359681d0b9fa7d86f "MATLAB Support Package for Raspberry PiでSunFounderを動かす")」の記事で書いたMATLABプログラムと同等の処理をSimulinkでモデリングしています。

## 加速制御
加速制御部のモデルを以下に示します。
シミュレーションステップごとに速度テーブルの値を読み進めていくようにしています。
速度テーブルは、モデルワークスペースに定義しています。
![Acceleration.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/86d66e59-4842-c710-3ce6-585802c3651b.png)

### 前後進制御用PWM出力値を計算
速度テーブルの値からモーター制御用PWM信号のデューティ比を計算します。
![CalcPwmDutyForDrive.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/43cb7389-92d1-70ed-d7c1-840401ddc3cf.png)

### 後輪駆動制御モデル
右後輪を制御するモデルを以下に示します。
![DriveRightRearWhile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/8dd67c30-8da1-1fd4-a29f-d27288178a69.png)

以下の4つのレジスタを順番に設定するため、本例ではFunction-Call Generatorブロックの反復回数を4に設定して、それぞれのレジスタを設定するFunction-Call Subsystemを実行しています。
* LED4_ON_L_REG
* LED4_ON_H_REG
* LED4_OFF_L_REG
* LED4_OFF_H_REG

左後輪駆動部では、以下のレジスタを設定しています。
* LED5_ON_L_REG
* LED5_ON_H_REG
* LED5_OFF_L_REG
* LED5_OFF_L_REG

## 減速制御
減速制御のモデル構造は、加速制御のモデルと同じです。
異なる箇所は、速度テーブルの値だけです。

## 前後進駆動の停止
前後進駆動の停止処理モデルを以下に示します。
![StopMoving.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/cdce09c0-c5a3-7ca9-9cc0-c488f4ddf818.png)

左右後輪の駆動処理モデルは、加速制御と減速制御で使用したものと同じです。
入力のデューティ比を0%にすることで、回転を停止するようにしています。

## 駆動方向の設定
前後進の駆動方向を設定するFunction-Call Subsystemを以下に示します。
GPIO17とGPIO27の値で、駆動方向を設定しています。
![SetDriveDirection.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400007/b91ea7ed-0152-27dd-3f2c-58de621e5eee.png)

[次の記事](https://qiita.com/nrykot/items/8f1569fe1235f261b60e "次の記事")に続きます。

# 参考
1. [SunFounder_PiCar-V](https://github.com/sunfounder/SunFounder_PiCar-V "SunFounder_PiCar-V")
1. [SunFounder_PCA9685](https://github.com/sunfounder/SunFounder_PCA9685 "SunFounder_PCA9685")
1. [TB6612 DC Motor Driver Module](http://wiki.sunfounder.cc/index.php?title=TB6612_DC_Motor_Driver_Module "TB6612 DC Motor Driver Module")