Simulink Support Package for ArduinoでI2Cデバイスを触る

## はじめに
ということで、12月20日分のMATLAB/Simulink Advent Calendar をお届けします。

Simulink Support Package for Arduinoについては、[１日目で紹介されています](https://qiita.com/motorcontrolman/items/291955cbc3fb1c7e4d43)ので省略して、本論に入ります。


## １．Simulink Support Package for Arduinoで温度センサを使う

　まずお手軽なところで、TI社の温度センサ、TMP102をArduinoにつなぎ、Simulinkでプログラムを書き込んでみます。

　なぜ、TMP102がお手軽かというと、初期設定なしで、いきなりデータの取得ができることです。ですが、電源とデータは3.3Vレベルである必要があり、データ線の間にレベルコンバータを入れる必要があります。
![tmp102配線図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434947/97b1f24c-7129-c530-d6db-fb07261a7bad.png)
回路図において、レベルコンバータは特定の部品を表しておりません。適当なものを使ってください。
　プログラムですが、最初から用意されているTMP102用のサンプルプログラムを使ってみましょう。
コマンドウィンドウで、"arduino_I2C_temp"　と入力し、リターンキーを押すと、しばらくして、サンプルプログラムのウィンドウが開きます。
![図１.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434947/b4aec789-d298-89ef-821e-dee1dbc2ea27.gif)
ウィンドウの中、左側にある"Arduino"と書いてあるブロック①がArduinoからデータを読み出すものです。
![図２.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434947/d29fc23c-4fa6-9023-5871-d218400f0a4d.gif)
ダブルクリックで開いてみます。
![図３.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434947/da72dba5-d482-96d8-d5ac-8138d30dd159.gif)
I2Cの読み出し専用のブロックです。上からTMP102のI2C上のデバイス番号（０）、アドレス（0X48）、シリアルデータの送られている順番（Big_Endian:上位ビットから送られる）、レジスタを触れるか（触れないに設定）、データタイプ（ uint16:符号なし16ビット）、データの個数（１個）、出力エラーを出すか（出さない）、サンプリング間隔（0.1秒おき）、というように設定してあります。OKを押して窓を閉じます。
![図２.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434947/07432899-1fb4-e928-1695-27974bcfa534.gif)
このブロック①から得た符号なし16ビットを、次のデータ変換器②で符号ありの16ビットに変換し、ゲイン調整器③で0.0625/16をかけると、温度の値となります。
上にあるディスプレイ④はSimulink上のもので、スタンドアロンで動かす場合は見えません。右に延びている線の先は比較器⑤で、入力が27（℃）より大きい場合は１を出力、小さい場合は０を出力します。さらに右に"Arduino"と書いてあるブロック⑥があり、
これはArduinoのD13（UNOなどではLEDが接続されているピン）に１ビットの出力を送ります。
さて、動かして見ましょう。
PCとArduino基板をUSBケーブルで接続します。
ウィンドウ左上の"ハードウェアボード"が使っているボードと異なる場合は、"ハードウェア設定"の歯車マークをクリックし、使うボードを選択します。下の図ではArduino Mega 2560になっています。
![図５.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434947/17ced9bb-76c6-4094-3e93-70100fdf0ab8.gif)
![図６.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434947/12e6e573-ce53-b56c-6b79-c7a9ce89ff47.gif)
これで準備ができました。"監視および調整"の三角マークをクリックすると、コンパイルされ、Arduinoボードに送られます。
![図７.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434947/04d1e5d1-a388-ce56-ef0f-76150aa575d9.gif)
ブロック図が赤くなりますが、これはエラーではありません。
![図８.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434947/e0d751e3-a7ae-b077-c24a-be259db08874.gif)
順調に動作していれば、Simulinkウィンドウのディスプレイに温度が表示され、温度が27℃より上か、以下かでArduinoのLEDが点灯もしくは消灯します。
うまくいったでしょうか。

## ２．初期設定のあるデバイスを使う

　TMP102は初期設定なしで、いきなり温度データが取得できました。しかし、多くのセンサは何かしらの初期設定を必要とします。ここではTMP102と同じTI社製の温度センサTMP275を用いてみましょう。
TMP275は5Vに対応していますので、Arduinoとの接続が楽です。
TMP275の3本のアドレス線（5,6,7pin）はGNDに接続してください。
![tmp275配線図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434947/8ae8a891-e7cb-a4ab-e004-58e2a6aadde1.png)
コマンドウィンドウで、"arduino_I2C_temp_init"と打ち、リターンします。

このサンプルは中身を書き換えるので、まず、別の名前で保存してください。
![図９.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434947/d9988265-331c-ed17-3fd1-091191f05fc1.gif)
このサンプルでは、２つのSubSystemブロック①、②があります。①が初期設定用ブロック、②がその後の温度計測ブロックです。
左上に"１"があり、ユニットディレイに入ります。したがって、最初の１クロック分はユニットディレイの出力は０、その後は１となります。
最初の１クロックでは、NOTのある①のブロックがライブになり（最初の１回のみ動作する）、その後は②のブロックがライブになります。
①のSubSystemブロックを編集するためにダブルクリックで開けます。
![図１０.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434947/ac9c7ce5-b884-35f6-37ba-bac10ca1c506.gif)
このようにブロックが配置されており、上の２つは、設定した信号をI2CでTMP102に書き込む動作、下の２つはTMP102からI2Cで設定値を読み出す動作を行います。
動作の順序は上から下へとなります（サンプルプログラムはTMP102のためのもので、書き換えてTMP275で使います）。
下の２つのブロックはTMP275では不要のため削除し、上のブロックを書き換えます。
![図１１.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434947/bdfa322d-76ff-706c-996f-ef88be9185ea.gif)
左側のブロックは定数値を１６進数のE0に、出力データ型をuint8に書き換えます。SubSystem①は、これで終わりで閉じます。
次に、SubSystem②を開け、ゲインを1/256に変更します。
![図１２.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434947/5023e418-ca78-fa81-e56f-d6e2878e7cf1.gif)
これで"監視および調整"の三角印をクリックしてみましょう。うまく動いたでしょうか。

## ３．これ以外の方法
　simulinkでArduinoを動かす方法としては上記の他に、[Simulink Device Driver Blockのガイド](https://jp.mathworks.com/matlabcentral/fileexchange/39354-device-drivers)があります。これには４つの方法が書かれています。
　・Sファンクションによる方法
　・レガシーコードツール（C言語記述）
　・MATLAB Function Approach
　・MATLAB System Block Approach
今回は詳細は省略します。時間があるときに、内容を紹介してみたいと思います。
ただし、これらはSimulink Support Packageを「使う」というより「作る」といった感じが近いです。

## おまけ：ブログは日本語だけでなく英語でも書くべきなのか？
　書くべきだと思います。というか、私は書いていますが。
　ただし、どんな内容でも英語で書くべきかというとそうでもないように感じます。
　「広く浅い内容でバズるけれど、１ヶ月すると誰も見ていない」というようなものは、日本語で十分なように思います。
その対極にあるようなニッチで、しかも世界中にニーズがあるような領域が向いているのではないかと個人的には思っています。
　必要とする人は多くはないけれど、必要な人が「とにかく１行でも２行でも参考になる情報がどこかに転がっていないだろうか」と心底から思っているような情報は、英語でブログに書く価値があるのではないかと。
そういう情報は、例えばgoogle検索を10ページめくったところにあっても探してもらえるので、ネット上のどこに置いても探してもらえるでしょう。
あとは、「解法」とか「理解の仕方」などで、「こんな視点で見るとわかりやすい」というような内容も良いと思っています。
（あくまでも個人的な見解ですので）。

以上で、MATLAB/Simulink Advent Calendar 2019 12月20日分を終わります。

おつかれさまでした。