Raspberry PiとSimulinkでLED調光+色変更

## この記事について
前回"Lチカ"で開発環境のセットアップと、基本的なモデル作成まで実施しました。

https://qiita.com/kureta90/items/5554117f0a94df89480d

今回は少し発展させて、3色LEDの光量調整や色の変更までを試します。ゆくゆくはこのモデルをMQTTでコントロールして、ホームLEDに発展させたいと思います。

https://qiita.com/kureta90/items/edbbf899cd218fe5cdf5

## ソフトウエア/ハードウエア
"Raspberry PiとSimulinkでLチカ！"と同じ構成です。色変更のモード管理をRaspberry Pi側で行う場合は"Stateflow"のライセンスが必要です(後述)

## Simulink エクスターナルモード
エクスターナルモードはシミュレーションと実機実装のいいとこどりです。コード生成してターゲット(Raspberry Pi)上で動作しつつも、ターゲットでのハードウエア入力をはじめ、内部変数をモニタできる特殊なモードです。エクスターナルモードでの生成コードはこの特殊動作を実現するためのコードで、デバックが終わって最終的なモデルをデプロイする際は、内部変数のモニタ機能を省いた、純粋にモデルを実行するためのコードが生成されます。詳細は上記前回記事を参照ください。

## Simulinkモデル(調光)
出力ポートのブロックをGPIOからPWMに変更すると、Dutyを入力して明るさを調整できるようになります(LEDへの電流値調整)。明るさを指定するためのアナログ入力があればよいのですが、あいにくRaspberry PiのIOピンにはアナログ入力がありません。
I2C経由のADCを使ったり、ADCピンを持つArduinoを経由してUSB接続することも可能ですが、
ゆくゆくホームLEDにするのであれば明るさの指定は通信経由になるので、ここはあまり凝らずにシミュレーション入力のみとしておきます。また別記事でMQTT通信入力で実機動作できるようにする予定です。

## Simulinkモデル(調光変化をゆっくり)
明るさ(=duty)の信号に、1サンプル前の値を重みをつけて足し込むようにすると、明るさがゆっくり変わるようになります。過去の重みを大きくすると、変化がゆっくりになります。

![Dimming.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583335/1fd2415a-8759-be8c-9201-e9deee158ee3.png)

シミュレーションを実施すると、明るさを変更したときにゆっくり変化している様子がscopeブロックで観察できます。
![sim_mode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583335/0041f826-6696-3857-d524-4279c309405e.png)

![Dimming_scope.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583335/436f3a42-fb53-9b12-f040-c1a0f59254a4.png)

重みはシミュレーション中も変更可能で、シミュレーション中に調整できます。
次にエクスターナルモードで実行すると、上のscopesブロックと同じように、GPIO 17に接続したLEDの明るさがゆっくり変わります。

![ext_mode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583335/48434297-e83f-3a3b-d7dd-599a346abecf.png)

エクスターナルモードちょっと便利♡

## Simulinkモデル(色変更)
いよいよ3色のLEDを点灯して、色を変えてみましょう。3色RGBのLEDはそれぞれ個別に明るさを設定できるので、組み合わせると自由に色を変更することができます。ただホームLEDにするときにコントローラから色変更することを考えると、色のモード管理をデバイス側で行うか、あるいはコントローラ側で行うかを決める必要があります。

コントローラ側でモードを管理する場合は、Raspberry Piには3色のそれぞれについてアナログ入力してもらう構成になります。この場合、コントローラから色を自在に設定することができます。モデルは上の構成が3系統あればよいでしょう。

今回は入力をシンプルにするため、モード管理をデバイス側で行う構成にします。Simulinkではモードやステートの管理に便利な"Stateflow"をモデルに組み込むことができます(Stateflowのライセンスが必要)。[col_change]という信号が入ればステートを遷移し、各ステートでdutyを設定しています。
各ステートは　ステート名 / du: 実行文　という構成で書かれています。
(en:ステートに入ったときに実施 / du:ステート内にいる間ずっと実施)　
![stateflow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583335/d71d93aa-f694-3ddd-2bd3-d7cddf599ede.png)


3種類の色モードに相当するステートを用意して、それぞれの色モードでRGB3色のLEDに入力する明るさ(=duty)を設定しておき、ステートを遷移することで色を変更します。各ステートで設定されているdutyは3次元でそれぞれR,G,BのLEDに対応しています。

モデルの全体像です。3色のLEDのduty(3次元)を、先の明るさ変更の出力と掛け合わせることで、調光と色変更ができます。色変更のトリガはシミュレーション用にプッシュボタン、あるいはスイッチ入力を用意します。ゆくゆくホームLEDにするときは、ここを明るさと同じくMQTT経由の入力としましょう。
![model_dimm_col.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583335/22443464-b8fd-d175-bde8-ba89215edd0a.png)

色変更の入力には、信号の立ち上がりを検出するため、以下のようなロジックを追加しています。
![lutch_up.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583335/a34b1307-4461-f874-5770-0675267be80a.png)

どんな色になるかは実機を光らせてた方が判りやすいため、ここは"エクスターナルモード"で実際のLEDを見ながらパラメータ調整しましょう。各ステートのdutyで定めた3色RGBの割合を0-1.0の間で調整します。

![stateflow1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583335/6f67901e-6691-8e7c-0b9a-df9d827f2e98.png)


残念ながらStateflowのステートに直書きしたパラメーターはエクスターナルモード実行中に変更することはできませんが、停止/再実行が煩雑ならステート外部から定数で与えるようにしておくこともできます。あるいは色を決定するための別の簡単なモデルを作ってもいいかもしれません。

エクスターナルモード超便利!

## デプロイ
エクスターナルモードでパラメーターを決定した後は、実機実装します。

![dep_mode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583335/74b35408-5844-d710-ffca-14d96df7fd13.png)

といっても今回、明るさを変える入力はシミュレーション入力しかなく、実機で有効な入力はありません。スイッチで色の変更のみ実施できます。直光含め実機で動作している様子は、次回投稿予定の"ホームLED編"でご紹介します。