Simulinkを使ってNucleo STM32F411REでCAN通信(2ch)とアナログ入力

## 概要
モデルベース開発をしているような研究室で、Simulinkベースで車両を動かしたい、Simulinkで開発できるECUを用意したいというケースも多いと思います。そこで今回はSimulinkを使ってNucleo STM32F411REでCAN通信(2ch)とアナログ入力を動かすというところまでやってみたいと思います。

##環境/使用機材
* ECU : [STM32 Nucleo Board STM32F411RE](https://akizukidenshi.com/catalog/g/gM-10175/)
* CANシールド : [MCP2515 CANボード拡張ボード 2ch](https://www.amazon.co.jp/dp/B08HH8F5MZ/ref=cm_sw_r_tw_dp_QTG22BDCRS7XBTSCVXQN?_encoding=UTF8&psc=1)
* PC : ThinkPad X280, OS Windows10Home ビルド19042.1052, CPU i5-8250U, RAM 8GB
* MATLAB/Simulink : R2017b  
(最初2019bで試したのですが、なぜかDACブロックがあると動きませんでした。また、ファイルパスにスペースがあると不要なトラブルが発生する可能性があるようなので、C:\MATLAB\R2017b\にインストールしました)
* MATLAB/Simulink アドオン :  
[Simulink Coder Support Package for STMicroelectronics Nucleo Boards](https://jp.mathworks.com/matlabcentral/fileexchange/58942-simulink-coder-support-package-for-stmicroelectronics-nucleo-boards)  
[CAN device driver mcp2515 for Arduino and Raspberry Pi](https://jp.mathworks.com/matlabcentral/fileexchange/64782-can-device-driver-mcp2515-for-arduino-and-raspberry-pi)  
MTALAB Coder  
Simunk Coder  
* その他 : miniUSB(これがないとPCとSTM32を接続できない)、ブレッドボード、ポテンショメータ、ジャンパ線、CAN確認用のデバイス(PCAN-USB)

##STEP1 ST-LINK USBドライバのインストール
最初STM32とPCを接続する場合、ST-Link Debugが不明なデバイスとなっていて気持ち悪いので、ドライバのインストールをします。必ずしも必要かは微妙です。
まず、ドライバをダウンロードし、解凍します。
[STSW-LINK009 USB driver signed for Windows7, Windows8, Windows10](https://www.st.com/ja/development-tools/stsw-link009.html)
次に、STM32とPCをUSBケーブルで接続し、デバイスマネージャーを開きます。
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463446/29ee3211-f6f0-875a-bb13-0a3e69888fee.png)
するとST-Link Debugが不明なデバイスとして認識されているので、右クリック>プロパティ>ドライバータブ>ドライバーの更新をクリックし、コンピューター上のドライバーを参照のところで、先程解凍したファイルを設定し、ドライバーをインストールします。
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463446/e059dbe6-9eee-ce0c-df54-57c6a8fe0634.png)
ついでに後でSimulinkでの設定で必要になるCOMポート番号もここでチェックしておきましょう。
![stm32_driver_005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463446/85ecec16-b4b8-a696-6492-4cfb69c001d9.png)
とりあえずCOM10として認識していることを確認しました。これでOKです。

##STEP2 MATLAB/Simulinkのセットアップ
前述の環境/使用機材に記載のように、アドオンの追加で[Simulink Coder Support Package for STMicroelectronics Nucleo Boards](https://jp.mathworks.com/matlabcentral/fileexchange/58942-simulink-coder-support-package-for-stmicroelectronics-nucleo-boards)、[CAN device driver mcp2515 for Arduino and Raspberry Pi](https://jp.mathworks.com/matlabcentral/fileexchange/64782-can-device-driver-mcp2515-for-arduino-and-raspberry-pi)をインストールします。注意点としては、

* MATLABはバージョンによってはNucleo用のDACブロックあたりで問題が発生したので2017bあたりが良い 
* Program Filesのようなスペースを含むディレクトリにMTALABをインストールすると問題が発生する可能性があるので、スペースを含まないディレクトリにインストールしたほうが良い 
* Simulink Coder Support Package for STMicroelectronics Nucleo Boardsインストール時、サードパーティ製のソフトウェアインストールでコケるときがあり、何回か挑戦したら入った  

という感じです。

##STEP3 Exampleモデルを使った動作チェック
まずは、Exampleで動作チェックしましょう。MATLABからアドオン>アドオンの管理をクリックし、Simulink Coder Support Package for STMicroelectronics Nucleo Boardsからドキュメンテーションを開くをクリックします。
![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463446/c4514e9b-2c1e-5e17-f797-ce8f338d5991.png)
なんでもよいのですが、今回はこのExampleを使って動作確認したいと思います。右下のOpen Modelをクリックし、モデルを開きます。
![stm32_driver_007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463446/086bd063-5347-ce77-626f-9f98c084eeeb.png)
モデルを開いたらモデル コンフィギュレーション パラメータ(歯車アイコン)を開きます。
そしてハードウェア実行からハードウェア ボードをF411REにセットし適用をクリックし、Target hardware resourcesからExternal modeをクリックし、前項で確認したCOMポート番号を設定し、OKをクリックします。(ハードウェア ボードを切り替えるとCOMポート番号がリセットされるようなので、一つずつ適用したほうが良さそう)
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463446/6e1b46c5-10fe-b103-6de5-96abac1d44f5.png)
その後、実行やハードウェアに展開が問題なくできれば動作チェック完了です。
![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463446/1b1b58c9-1f7f-75a4-ad22-5dd92b9947f3.png)
ここで、実行とハードウェアに展開の違いについてメモしておきます。

* 実行 : エクスターナルモードになっている状態で実行すると、DisplayなどをリアルタイムでPCで見ながらモデルを実行することができます。開発中はこちらを基本使用します。
* ハードウェアに展開 : ハードウェア上でモデルを動かすことができます。最後、車に搭載するときはこちらを選択します。

##STEP4 モデルの作成(アナログ入力)
先程のExampleモデルをベースにモデルを作成していきます。Exampleモデル別名で任意のディレクトリに保存します。
次にコンフィギュレーション パラメーター>ソルバーからシミュレーション終了時間をinfに設定し、(Externalモードが時間で終了しないよう)追加パラメーターの固定ステップサイズを、制御対象に合わせた周期に設定します。(何秒毎に計算するかの設定)
![006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463446/691c9832-a857-0838-68fc-1f19ae865b7f.png)
次に一旦すべてのブロックを消して、Simulinkライブラリ ブラウザーからSimulink Coder Support Package for STMicroelectronics Nucleo Boards>Common>Analog InputブロックとDisplayブロックをドラッグアンドドロップして配置します。
また、ポテンショメータを下記のようにSTM32に結線します。  

|STM32|Potentiometer|
|:-:|:-:|
|3V3|Vcc|
|A0|Output|
|GND|GND|

ピンマップを見てもよく分からなかったのですが、Pin16=A0ピンみたいです。これで実行してポテンショメータをグリグリ動かして、値が変化すればOKです。
![007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463446/f6891a93-1027-b35e-341a-1dafe2a5cf99.png)

##STEP5 モデルの作成続き(CAN通信)
SPI通信を使ってCANシールドと接続しCAN通信を行いたいのですが、1から作るのは大変なので今回は[CAN device driver mcp2515 for Arduino and Raspberry Pi](https://jp.mathworks.com/matlabcentral/fileexchange/64782-can-device-driver-mcp2515-for-arduino-and-raspberry-pi)を改造し、STM32に適合させる形で行います。  
MATLABからアドオン>アドオンの管理>CAN device driver mcp2515 for Arduino and Raspberry Pi>フォルダを開くをクリックし、MATLABに戻りmcp2515/example/arduino_CAN_Echo.slxを開きます。そして、モデルを一通りコピーします。
![008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463446/d9c4c0ef-d501-1261-4ad8-524d1b54fb37.png)
CANbeginの設定で、Oscillatorを16Mhz(CANシールドの部品に小さく書いてあります)、CAN Bus Speedを制御対象のCANボーレートに合わせます。また、ModelはArduinoのままで、Chip Selectは適当で大丈夫です。(上手に改造すればChip Selectの機能は活かせると思いますが、今回の改造方法ではこの機能は失われます)
ブロック左下の下矢印をクリックし、サブシステムの中に入っていきます。
![009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463446/e845bc1b-dd09-45ef-0d32-0f45492b0956.png)
そして中にあるArduino用のSPIブロックをすべてSTM32用のSPIブロックに置き換えていきます。(合計10個ぐらいあるので探してください。またCANbeginだけではなく、CANreceive、CANtransmit内にも2個ずつぐらいあります)
![010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463446/b7035530-e4b5-25d2-b53c-429cf8002b8a.png)
ここで、Slave selectはCAN ch0用には7(D7ピン)、CAN ch1用には4(D4ピン)としました。これはCANシールドのCS0、CS1それぞれにつながるデジタルピン番号となります。最終的にはこのような形となりました。サブシステム内にはSPIブロックを置き換えたarduino_CAN_Echo.slx内ブロックが入っています。
![011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463446/e9199a1b-1c8e-e543-c011-02f5a495a82a.png)

##STEP6 STM32とCANシールドの結線(CAN通信)
前述のポテンショメータはA0ピン、Slave selectはCAN ch0用には7(D7ピン)、CAN ch1用には4(D4ピン)としたので、最終的には下記のような形で結線しました。

|STM32|Potentiometer|
|:-:|:-:|
|3V3|Vcc|
|A0|Output|
|GND|GND|

|STM32|CAN shield|
|:-:|:-:|
|3V3|5V|
|GND|GND|
|MISO/D12|MISO|
|PWM/MOSI/D11|MOSI|
|SCK/D13|SCK|
|D7|CS0|
|D4|CS1|

また、CANシールドのジャンパ線は3V3にしています。役に立つか分かりませんが、こんな感じです。
![012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463446/2e76cc75-d481-0a85-6a8f-fc2458859663.png)
画像のようにCANシールドのジャンパ線を終端抵抗有りにして、動作確認用のPCAN-USBにも終端抵抗を取り付け動作確認をしました。
![013.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463446/80cb6c65-a72b-a11e-d52f-e0ce33c8d3e6.png)
PCAN-Viewを使ってCANメッセージを送ってあげるとちゃんとEchoされて来ました。Extended IDも対応しています。  
後は好きなようにモデルを組んで動かしてください！