###1.MATLAB Support Package for Arduino Hardwareのインストール
おまけのおまけ編です。
2018年のLightning talkの前半は、温度センサの情報をarduino経由でMATLABに取り込む方法を紹介しました。備忘録を兼ねて書いてみます。
まず、Support Packageのインストールですが、Simulinkのサポートパッケージと同じようにして、Addonをインストールします。下の図の「アドオン」から「ハードウェアパッケージの入手」を選択します。
ブラウザから「MATLAB Support Package for Arduino Hardware」を選択して、インストールします。
今年(2019年)の5月にバージョンアップがあったようで、今現在のインストールは、結構、手数が多くなっており、途中でArduinoをつないで認識させる、というような作業も必要となります(たぶんドライバのインストールのためと思われます)。
手数が多いですが、最後までやらないと動きませんので、根気よくやってください。私は一度、途中で省略したら動かなくなり、やり直しました。
###2.I2CメモリとArduinoを接続する
使い方の簡単な例として、秋月電子で売っていたIchigoJam用のEEPROM(秋月品番K-12061)で読み書きをやってみます。接続は下記のようにします(arduino Unoの場合)。IchigoROMの説明書には電源3.3Vと書いてありますが、搭載されているEEPROM(オン・セミコンダクターのCAT24M01)は5Vでも大丈夫なので、Arduinoにダイレクトに接続できます。
###3.メモリを読み書きする
ArduinoとPCを接続します。MATLABのコマンドウィンドウに「Arduino XX detected.(以下省略)」と出ていない場合は、再度、接続しなおしてください。それでも出ない場合は、アドオンが正常にインストールされていないと思われます。
「Arduino XX detected.」が出た場合は、コマンドウィンドウから、「a = arduino」と入力し、リターンします。
下記のように表示されます。
COMポートが24番、Arduinoのボード名がUnoで、その他の情報が表示されます。
次に、「addrs=scanI2CBus(a)」と入力します。
アドレスは0x50,0x51の2つが表示されています。これは、メモリのアドレスバスが17bitあり、一方でI2Cのアドレスは8bit区切りなので、最上位の1ビットをI2Cのアドレスに回したためです。
メモリの前半分は0x50、後ろ半分は0x51として扱うわけです。
ここでは前半分の0x50をアドレスとして使うことにします。
「clear a;」と入力し、arduinoをいったん開放します。
読み書きの一例を下記に示します。
a=arduino('COM24','Uno','Libraries','I2C');
%CAT240=i2cdev(a,'0x50');% I2Cデバイスをつくる
CAT240=device(a,'I2CAddress','0x50','bitrate',100000);% I2Cデバイスをつくる
pause(0.1);
%特定のアドレスに1つデータを書き込み/読み出す
A_MSB=0;%アドレスの上位8ビット
A_LSB=1;%アドレスの下位8ビット
W_data=25;%書き込むデータ
write(CAT240,[A_MSB A_LSB W_data],'uint8');% 書き込み
%読み出し
Num=1;%読み出しデータ数
write(CAT240,[A_MSB A_LSB],'uint8');% 読み出しアドレス指定
data1=read(CAT240,Num,'uint8');
data1
%特定のアドレスから複数のデータを書き込み/読み出す
A_MSB=1;%アドレスの上位8ビット
A_LSB=2;%アドレスの下位8ビット
W_data=[31 32 33 34];%書き込むデータ
dum=[A_MSB A_LSB W_data];
write(CAT240,dum,'uint8');% 書き込み
%読み出し
dum=[A_MSB A_LSB];
Num=4;%読み出しデータ数
write(CAT240,dum,'uint8');% 読み出しアドレス指定
data2=read(CAT240,Num,'uint8');
data2
clear CAT240 a;
まず、先頭3行目の「CAT240=device(a,'I2CAddress','0x50','bitrate',100000);」ですが、
これは、2019年5月の新しいバージョンで追加されたコマンドです。
以前のバージョンで実行すると「deviceというコマンドはない」とエラーが出ます。
その場合には、先頭2行目のコメントアウトしてある「CAT240=i2cdev(a,'0x50');」を代わりに使ってください。
前半が8bitデータ1コを読み書き、後半は4コ連続で読み書きする場合です。
データ1コを書く場合のI2Cシーケンス(データシートから引用)とコマンドを比較します。
データ書き込みは、
そして、データ読み込みは、
というようになります。この場合は前半が読み出すアドレスの指定、後半が指定したアドレスからのデータ読み出しです。slaveアドレスの一番後ろのビットが0だと「書き」、1だと「読み」になります。このビットはMATLAB Addonの場合にはwriteと書くか、readと書くかで自動的に制御されています。
I2Cでの入出力コマンドとしては、writeRegisterや、readRegisterもあるのですが、これらについては、次の章で説明します。
###3.温度センサからの情報取得
ここではテキサス・インスツルメント社の温度センサtmp275からArduinoのI2C経由でPCにデータを取り込みます。Arduinoとtmp275の接続は次のとおりです。
a = arduino でCOMポート番号を確認し、addrs=scanI2CBus(a) でセンサのI2Cでのアドレスを確認します。今、tmp275のアドレス設定が、A0=A1=A2=0であった場合、I2C上のアドレスは0x48となります。
MATLAB-arduino-tmp275を接続したところで、温度を測る前に、センサの設定を行なう必要があります。この温度センサの場合には、出力ビット数とか、スリープモードとか、最高/最低温度を警告する場合のしきい値温度とかを設定できるようになっています。これらの設定にwriteRegister、設定状態の確認にreadRegisterが使われます。
writeRegisterは下記のようになります。
RegNumはレジスタのアドレス、RegInがレジスタに入力するデータです。ここでは該当のレジスタがconfigrationレジスタなので、入力するデータは8bit x 1となります。
このwriteRegisterコマンドは、writeコマンドで書いても同じ制御内容となります。
writeRegister(tmp275,RegNum,RegIn,'uint8'); は、
write(tmp275,[RegNum RegIn],'uint8'); と書いても同じ出力となります(意味は変わりますが)。
逆にレジスタに入っているデータを出力させるには、readRegisterを使います。
data=read(tmp275,DataNum,'uint8');
レジスタが16bitの場合には「'uint8'」が「'uint16'」に変わります。
注意点としては、writeRegister(tmp275,RegNum,RegIn,'uintXX');で
RegInのビット数はuintXXを「uint8」と書くか、「uint16」と書くかで長さを変えることができますが、RegNumに関しては8bit固定になっています。ですので、前章で取り上げたメモリに書き込みの場合、アドレスが16bitになるので、writeRegisterでなく、writeで書く必要があります。
サンプルプログラムとしては、こんな感じになります。
a=arduino('COM24','Uno','Libraries','I2C');
%tmp275=i2cdev(a,'0x48');% I2Cデバイスをつくる
tmp275=device(a,'I2CAddress','0x48');% I2Cデバイスをつくる
% 初期設定書き込み
RegNum=1;%書き込むレジスタ番号
RegIn=hex2dec('60');%レジスタに書き込むデータ
writeRegister(tmp275,RegNum,RegIn,'uint8');
%write(tmp275,[RegNum RegIn],'uint8');
RegData=readRegister(tmp275,1,'uint8');
dec2hex(RegData)
write(tmp275,0,'uint8');% データ要求
pause(0.5);
DataNum=2;%読み出すデータ数
data=read(tmp275,DataNum,'uint8');% データ取込み
% 生データから温度への変換
temperature = (double(bitshift(int16(data(1)), 4)) +...
double(bitshift(int16(data(2)), -4))) * 0.0625;
temperature = round(temperature * 10)/10;
X = sprintf('%2.1f [deg]',temperature);
disp(X);
% クリア
clear tmp275 a;
おつかれさまでした。