見出し画像

【Simulink】 Arduinoのピンをお手軽で,かつ大量に操作するTips

このTipsではSimulink初心者の私が,Arduinoの大量のピンを制御するためにぶつかった問題と解決方法を記載します.悩んでる時はあまりこの情報についての解決方法が少ないように感じたので,こうしてTipsに残すことで同じような悩みを抱えた人の参考になれば幸いです.

はじめに: 読み飛ばしても良いです

普段私はメディア装置に関する研究を行っているクリエイターであり,情報系出身なのでこれまで主に既存のモジュールを利用した組み込みを行っていました。

しかし,研究で100個ほどのDCモータを制御するシステムを作る必要があったため,これまで使ったことなかったのですがMathworksのSimulinkを使ってそれを実現しよう思いました.

その際,大量のArduinoのピンを操作する必要があったのですが,モデルベースデザインではブロック構築に途方もない時間がかかってしまいます.一応,コーディング中心のMATLABの方でもArduinoを動かすことはできますが,リアルタイムに強いSimulinkを使いたかったので今回はSimulinkにこだわりました.

問題: Arduinoブロックは大量のピン操作に向いていない

画像1

【Arduinoライブラリにあるブロックたち】

モデルベースデザインを採用しているSimulinkでは,ブロック線図を用いてシミュレーションを行っています.Arduinoを動かすための専用のライブラリが用意されており,Arduionのピンごとにブロックが配置することができ,簡単にArduinoを用いた制御シミュレーションを構築できます.

画像2

【扱うピンが多いと厳しい】

しかし,操作したいピンが大量になってくると使いたいピンごとに大量のブロックをいちいち自分で配置しなければならず,かつハンドコーディングよりも圧倒的にデバックしずらい.一応,コーディングによるブロックの自動配置なるものがあるが,だとしてもブロックのレイアウトを考慮してプログラム作る必要があるからこれも厳しい.

そこで,なんとかSimulinkの手軽さを味わいつつ,大量のピンを操作する方法を模索する必要がありました.

動作環境

PCスペック
OS: Windows 10
CPU: Core i7-11700
RAM: 16GB

Arduinoスペック
本体: Arduino Due
CPU: ARM Cortex M3
クロック周波数: 84MHz

Arduinoを扱っているライブラリ
Arduino Support from Simulink

解決概要

 1: MATLAB Function Blockを用いて大量のピンを操作するブロックをハンドコーディングで作成
2: 作成したMATLABFunction Blockにグローバル変数の入出力を設定し,ピン操作に応じてグローバル変数を更新
3: 更新したグローバル変数を使って制御系のブロック線図を作成

画像3

【Arduinoを利用したPID制御の例】

今回は例として,ArduinoによるDCモータを利用したPWM駆動のPID制御を想定したモデルで書いてみます.

解決方法

Arduinoの大量のピンを制御するために,今回はMATLAB Function Blockを使用した.これを用いることで,MATLAB言語でハンドコーディングしたブロックを自作することができます.さらに,このブロックはArduinoでの使用も想定されており,デジタルピンの読み取りはもちろん,I2C・SPI通信などあらかたのピン操作は実現できます.丁寧に公式ドキュメントも用意されているので詳しくはそちらから (色々制約はあるが...).

画像4

【MATLAB Function Blockによるグローバル変数の更新】

今回のPIDの例ではこのブロックの内部で,エンコーダの読み取り・およびPWMの書き込み作業を行います.ハンドコーディングなので,操作するピンの数が多くなっても楽々に制御することができます.うれしい.

このブロックでは,エンコーダの算出など,ピン操作に応じた計算も行えるので,制御系に関わる数値はここで計算しておくと良いです.

また,Simulinkはコーディングにおけるグローバル変数に当たるブロックが用意されており,Data Store Memoryという,一つのブロックでもさまざまな変数の型に対応しており,配列にも対応しています.今回の場合,このブロックに格納された値がPID制御の対象となります.

このData Store Memoryを先程作成したMATLAB Function Blockに入出力を設定し,Arduinoのピン操作に応じた変数をData Store Memoryに反映します

function encOutput = fcn(pwmIn)

   persistent arduinoObj;

   %使用するピンの設定
   if(isempty(arduinoObj))
       arduinoObj = arduino();
       arduinoObj.configurePin("D2", 'DigitalOutput');
       arduinoObj.configurePin("D3", 'DigitalOutput');
       arduinoObj.configurePin("D5", 'PWM');
       %{
           以下,同様にピン設定する
       %}
   end

   %PWMの出力
   arduinoPWMWrite-tekitou(pwmIn);
   
   %エンコーダの読み取り
   encOutput = arduinoENCRead-tekitou(arduinoObj);
end

function arduionPWMWrite-tekitou(pwm)
   %いい感じのコード
end

function arduinoENCRead-tekitou(arduinoObj)
   %いい感じのコード
end

【MATLAB Function Blockの中身の例】

一応,MATLAB Function Blockの中身の例を記述します.あくまで概念的なないようなので参考までに.

画像5

【グローバル変数を介したDCモータのPID制御】

最後にMATLAB Function Blockで得られたData Store Memoryを使って,ブロック線図を作成することで,Arduinoのブロックピンを用いず,かつモデルベーズデザインに基づいたSimulinkモデルを作成することができます.

つまり,Arduinoのブロックピンを用いないということは,大量のピンを考慮したSimulinkモデルが手軽にできます.めでたし,めでたし.

さいごに: 概ね便利だが,問題点も...

こうして,無事大量のピンを使って,スッキリしたSimulinkモデルを作ることができました.テストとして,複数のDCモータのPID制御を実装してみましたがちゃんと動作してくれました.よかった.

ただ,すこし引っかかってる点として,Simulinkで作ったArduinoは少し挙動が遅い点があります.ただこれは調べてみると,Arduinoに限らずもっと広く問題があるような感じがしていて,これに関してはまた別記事にしてまとめようかと思います.

ではでは,Tonaliでした.

###########################

普段,芝生で動画表示する研究をしています.
ご興味があればこちらもどうぞ,手動レコメンドです.

###########################

日々の呟きのTwittter

https://twitter.com/maison159777

映えではなく遺影を撮り続けるInstagram

https://www.instagram.com/tonali_insta/

Tonaliのポートフォリオ

https://tonali-kojiro.com

この記事が気に入ったらサポートをしてみませんか?