ProjectSR が 2021年02月24日22時12分42秒 に編集
初版
タイトルの変更
MATLAB映像表示機能付き無線遠隔通信システム
タグの変更
MATLAB
RaspberryPi
Arduino
ロボット
ラジコン
WiFi
映像表示
秋葉原2021
メイン画像の変更
本文の変更
MATLABを使って,映像表示機能+遠隔操作機能付きロボットの システム構成を紹介します. 🔳知れる事 --- ◇MATLAB GUI製作 ◇ラズベリーパイとMATLABのワイヤレス接続 Wi-Fiを使う ◇無線で映像の受信と表示 ◇ジョイスティックでロボットを無線遠隔操縦 🔳概要・基本構成 --- ①MATLABでGUIの製作を行います. ②MATLABにジョイスティック,ウェブカメラ,ラズベリーパイの設定を行います. ③ラズベリーパイからMATLABへ映像の情報を送り,MATLABのGUIで表示します. ④MATLABからラズベリーパイへジョイスティックの操作量の情報を送ります. ⑤ラズベリーパイは,ジョイスティック操作量を受け取り,Arduinoへ転送します. ⑥Arduinoは操作量を受け取り,モータードライバーへ信号を送り,モータを駆動します. 🔳解説 --- 基本構成は, ①送信側のMATLABでジョイスティックの操作量を計算し,ラズベリーパイへ送信 加えて,ラズベリーパイからの映像の情報をGUIに表示 ②ラズベリーパイは,映像の情報をMATLABへ送信 加えてMATLABからの操作量を受け取り,Arduinoへ送信 ③Arduinoがモータを制御 解説動画 --- ユーチューブ ニコニコ動画 にて 解説もしています. ロボットがどのような動作をされるか見たい方は,ご参照ください. @[youtube](https://www.youtube.com/watch?v=qmKrijMCpvw) ### ニコニコ動画 [MATLAB映像表示機能付き無線遠隔通信システム](https://www.nicovideo.jp/watch/sm37628342) 構成 --- 基本構成は, ①送信側のMATLABでジョイスティックの操作量を計算し,ラズベリーパイへ送信 加えて,ラズベリーパイからの映像の情報をGUIに表示 ②ラズベリーパイは,映像の情報をMATLABへ送信 加えてMATLABからの操作量を受け取り,Arduinoへ送信 ③Arduinoがモータを制御 ![キャプションを入力できます](https://camo.elchika.com/71944f2dcc21489a85750709a7ff605be6551922/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65636165613738332d303336612d346532652d383632662d3732393461656431353662352f30626431386465342d376530642d346131652d386263332d366363646433333436343264/) ポイント --- ●Wi-Fi環境下なので,通信距離が伸びる事, 映像表示が可能になること ●遠隔操作と映像表示が1つのソフトでできる事 ●GUIをカスタマイズできること です. 現在,下記の課題があります. ①動作遅延が発生 ②MATLAB2018a以降では映像が表示できない. 今回はMATLABのguideというGUI作成ツールを使って ロボットの遠隔操縦を行います. このguideは,GUIのボタンや座標軸等を ドラッグ&ドロップで自分の好みに作成できます. 作成ができ,ファイルを保存するだけで, GUIを表示するプログラムが自動的にできるので, あとは表示機能に関するプログラムコードを 追加して記入して,今回のシステムを構築できます. ![キャプションを入力できます](https://camo.elchika.com/0fc6dd2e49d4f579a2ebec3ea38729f74ddd5088/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65636165613738332d303336612d346532652d383632662d3732393461656431353662352f37643265303232372d363131302d346631312d616265612d346338363764336266356265/) 0⃣前準備 --- ただし,パソコンにMATLAB2017aまたは2017bをインストールしていない人は,MathWork社から 購入する必要があります. MATLABは企業用や教育用他のeditionがありますが,個人で使う場合であれば,Home Licenseが利用できます. インストール時は,1日時間がかかるので,時間に余裕をもって行うとよいでしょう. ![キャプションを入力できます](https://camo.elchika.com/b5dd24bb76a2494b50cb3160e69d617c417113ce/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65636165613738332d303336612d346532652d383632662d3732393461656431353662352f38626562343239342d363462362d346666642d386332302d363737646162333539393262/) MATLABをインストールしたら,ラズベリーパイとの接続,ウェブカメラ情報のやり取りを行うために ツールボックス,サポートパッケージが必要です. 数年前にインストールしたので,ちょっと定かではありませんが,現在の私のMATLAB2017には 下記がインストールされています. 他に必要である場合は,MATLABがエラーメッセージを表示してくれるはずなので,適宜追加してください. (過剰だったらすみません.) ![キャプションを入力できます](https://camo.elchika.com/328fef223f0914f8ec3ac2a8557077b88cc4dcfb/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65636165613738332d303336612d346532652d383632662d3732393461656431353662352f35353339393830332d343436372d343637312d396530322d313534336130313533656534/) 今回使用するラズベリーパイ3Bの設定は,動画に掲載しましております. 1⃣ウェブカメラ映像表示 --- ラズベリーパイに装着したウェブカメラの映像表示を行います. guideでGUIを作成し,GUIで映像表示が可能になるように,プログラムコードを追加すれば機能します. 製作から,起動までの流れは動画に掲載しております. ⇓guideで作成した映像表示テスト用のGUIです. ![キャプションを入力できます](https://camo.elchika.com/a296b5134551eeb67e6fa173018f444d6bb9c769/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65636165613738332d303336612d346532652d383632662d3732393461656431353662352f38333336383730372d303233372d346136382d396238302d663662353534616665393137/) ↑のプッシュボタンを押せば ↓のように映像が表示されます. ![キャプションを入力できます](https://camo.elchika.com/db93c20e65f06d34e841ed3798a1a29c79674739/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65636165613738332d303336612d346532652d383632662d3732393461656431353662352f39636164313137622d363135322d343338392d393064372d626531353466303461393230/) ラズベリーパイはウェブカメラをつなげ, 電源を入れてからMATLABで接続をしてください. ↓ ![キャプションを入力できます](https://camo.elchika.com/a1577c50cbb21d118ffa2a55755d1e663263e41c/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65636165613738332d303336612d346532652d383632662d3732393461656431353662352f37666432356363372d386363662d343162352d623934322d633964626135653565303766/) 以下にプログラムコードの解説と,実際に駆動したときのプログラムを表示します. MATLAB guideで今回作成したGUIには,Opening関数,Callback関数,guidata関数 という3つの関数でGUIを機能させています. ➊Opening関数 ラズベリーパイ,ウェブカメラの接続に関する変数をここで定義して代入します. ・ラズベリーパイの設定に関する変数handles.raspiに接続したラズベリーパイの情報を格納 ・ラズベリーパイに接続されているウェブカメラの情報を取得するwebcamを使い,変数handles.wcam1に 情報を代入します ・プッシュボタンが押されていない場合はGUIは映像表示を行わないようにします. なので,handles.stateという変数を用意して,NOを代入します. ![キャプションを入力できます](https://camo.elchika.com/a1f2a6880bebed5dc06c6ec53d12294938fef8e8/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65636165613738332d303336612d346532652d383632662d3732393461656431353662352f65343937376232362d663561632d343136652d386664382d636531623135613065396461/) MATLAB guideでは handlesという構造体を使って変数を設定し, GUI作動に必要な関数が情報のやり取りを行い,機能します. Arduinoですと,構造体を使う必要はないのですが,MATLAB guideでは少し違う運用のようです. ちなみに構造体とは,左の図のようにintやdouble等多様な型式の変数を格納することができる変数の 枠みたいなもので,「変数を格納した変数」という言われ方もしています. MATLAB guideでは「handles.変数名」で変数を定義することができます. なので,たとえばラズベリーパイの変数ではhandles.raspiとしていますが,handles.abcとしても 問題ありません. ![キャプションを入力できます](https://camo.elchika.com/99dac9623f2f2c1431001e1dac4fca4d8b55b38d/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65636165613738332d303336612d346532652d383632662d3732393461656431353662352f34646631623766652d363336392d346438382d383738362d633330323132643733393263/) ❷Callback関数 プッシュボタンが押された後に映像が表示されるプログラムコードを追記します. つまり,プッシュボタンが押されたら,endまでの処理が実行されます. Opening関数で設定したhandles.state変数は'access'を代入します. 続くwhile文の条件でhandles.stateがaccessの時に映像表示が機能します. snapshotは,Opening関数で用意したhandles.wcam1の情報を呼び出して,ウェブカメラ映像の1フレームを 取得します.この1フレーム分のデータを変数img1へ代入し,imshowで使用します. imshowでは映像に関する情報と,表示範囲を指定するコードで,imshow(映像表示用変数,'Parent',表示範囲) 「表示範囲」は,guideで設定した座標軸axes1の変数handles.axes1をコードに記載しています. ![キャプションを入力できます](https://camo.elchika.com/530f3af7922a9bdb578b4c29f82f3f86a1799d01/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65636165613738332d303336612d346532652d383632662d3732393461656431353662352f66356339643035382d366662642d343233372d383733612d323365313538626236633463/) ❸guidata関数 Opening関数,Callback関数設定した変数では値を代入しましたが, 代入した内容を変数内に保存されていません. 例えばOpening関数で設定したhandles.wcam1に代入された内容は,pushbutton1_Callbak関数へそのまま 移行されません. 代入内容を移行するには,保存を行う必要があります.それを行うのがguidata関数です. guidata関数は,Opening関数やCallback関数の最後のほうに記入して,変数の内容を保存するという プログラムの処理が行われます. ![キャプションを入力できます](https://camo.elchika.com/b85ce3c697c4a67dfe32b88730a2b221b28f1cec/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65636165613738332d303336612d346532652d383632662d3732393461656431353662352f63636162393636632d363839312d346465372d383564372d393161313066643661383837/) 映像表示に関する主要な部分は以上です. 少しややこしったかもしれないので,簡潔に機能だけ説明すると, ⓵Opening関数でラズベリーパイ,ウェブカメラの情報をMATLABのプログラムを使って入手する. プログラムはMATLAB guideで作成されたコードに記入する 記入では「handles.変数名」という書き方で変数を定義し,情報を代入する. handles.stateをnoにしておく 必要な情報を変数で代入したら.guidata関数で保存を行う. ⓶Callback関数では,ボタンが押されたらウェブカメラの映像を表示する. handles.stateをaccessにする while文の条件分岐でhandles.state=accessにして,映像表示用のコードを実行する. Opening関数内のhandles.webcam1を呼び出し,snapshot,imshowを使って1フレーム分の画像表示を行う. guidata関数で上記内容を保存する ⇒結果.1フレームごとに画像が更新されるため,映像として表示される ※なお,MATLABのプログラムコードのみ記載しても,GUIの図figファイルがないため,エラーになります. 動画の通り,guide起動から図を作成して,プログラムを追記すると正常に動作します. 加えて,figファイルとプログラムが書かれたmファイルは,同じフォルダ内に格納すれば正常に動作します. 下記に映像表示テスト用のプログラム全文を記します. guideでGUIを作成後,プログラムコード追記の際に参考にしてみてください. ```html:□MATLAB-ラズベリーパイ+webカメラ映像表示用プログラム function varargout = PSR_WEBCAM_test_1(varargin) % PSR_WEBCAM_TEST_1 MATLAB code for PSR_WEBCAM_test_1.fig % PSR_WEBCAM_TEST_1, by itself, creates a new PSR_WEBCAM_TEST_1 or raises the existing % singleton*. % % H = PSR_WEBCAM_TEST_1 returns the handle to a new PSR_WEBCAM_TEST_1 or the handle to % the existing singleton*. % % PSR_WEBCAM_TEST_1('CALLBACK',hObject,eventData,handles,...) calls the local % function named CALLBACK in PSR_WEBCAM_TEST_1.M with the given input arguments. % % PSR_WEBCAM_TEST_1('Property','Value',...) creates a new PSR_WEBCAM_TEST_1 or raises the % existing singleton*. Starting from the left, property value pairs are % applied to the GUI before PSR_WEBCAM_test_1_OpeningFcn gets called. An % unrecognized property name or invalid value makes property application % stop. All inputs are passed to PSR_WEBCAM_test_1_OpeningFcn via varargin. % % *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one % instance to run (singleton)". % % See also: GUIDE, GUIDATA, GUIHANDLES % Edit the above text to modify the response to help PSR_WEBCAM_test_1 % Last Modified by GUIDE v2.5 17-Sep-2020 05:44:57 % Begin initialization code - DO NOT EDIT gui_Singleton = 1; gui_State = struct('gui_Name', mfilename, ... 'gui_Singleton', gui_Singleton, ... 'gui_OpeningFcn', @PSR_WEBCAM_test_1_OpeningFcn, ... 'gui_OutputFcn', @PSR_WEBCAM_test_1_OutputFcn, ... 'gui_LayoutFcn', [] , ... 'gui_Callback', []); if nargin && ischar(varargin{1}) gui_State.gui_Callback = str2func(varargin{1}); end if nargout [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); else gui_mainfcn(gui_State, varargin{:}); end % End initialization code - DO NOT EDIT % --- Executes just before PSR_WEBCAM_test_1 is made visible. function PSR_WEBCAM_test_1_OpeningFcn(hObject, eventdata, handles, varargin) % This function has no output args, see OutputFcn. % hObject handle to figure % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % varargin command line arguments to webcamtest_PSR_demo_webcam (see VARARGIN) handles.mypi=raspi; handles.wcam1 = webcam(handles.mypi,'UVC Camera (046d:081b) (usb-3f980000.usb-1.5):'); handles.state='No'; % Choose default command line output for webcamtest_PSR_demo_webcam handles.output = hObject; % Update handles structure guidata(hObject, handles); % UIWAIT makes PSR_WEBCAM_test_1 wait for user response (see UIRESUME) % uiwait(handles.figure1); % --- Outputs from this function are returned to the command line. function varargout = PSR_WEBCAM_test_1_OutputFcn(hObject, eventdata, handles) % varargout cell array for returning output args (see VARARGOUT); % hObject handle to figure % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % Get default command line output from handles structure varargout{1} = handles.output; % --- Executes on button press in pushbutton1. function pushbutton1_Callback(hObject, eventdata, handles) % hObject handle to pushbutton1 (see GCBO) handles.state='access'; while(strcmp(handles.state,'access')) img1 = snapshot(handles.wcam1); imshow(img1, 'Parent', handles.axes1); % hObject handle to pushbutton3 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) guidata(hObject, handles); end % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) ``` 長々と解説を書きましたが,以下にまとめの図を記載しました. ↓ ![キャプションを入力できます](https://camo.elchika.com/57948f176a5459cd343f8f3625970b1337c9b3e1/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65636165613738332d303336612d346532652d383632662d3732393461656431353662352f33326663326165642d306236362d346665642d396239362d313363313665343630623138/) 2⃣ウェブカメラ映像表示+ジョイスティック操作 --- プログラム作成手順は,1⃣と変わりません. 1⃣からの変更点として, ・ウェブカメラを2つに増やした ・ジョイスティックを使用して,走行ロボットNUEMK-Ⅰを操作できるようにした. ※下記に⓵モータドライバーTA7291Pのバージョンと②Plolu5019バージョンの回路図とプログラムコードを 示しますが,MATLAB側のプログラムは⓵,②いずれも同じコードを使用しているので,最後に記載します. ⓵ジョイスティックーモータ操作と2つのウェブカメラ映像表示 テスト目的で,ジョイスティックーモータ操作と2つのウェブカメラ映像表示を行うシステムを構築しました. まず電子回路ですが,ロボット側はラズベリーパイ - Arduino - モータドライバーで接続されています. ラズベリーパイには,アナログ出力ピンがないため,ArduinoとI2C接続を行い,モータドライバーへ アナログ信号を出力しています. ※Arduinoの電源が入っていなかったり,ArduinoとラズベリーパイがI2Cで接続されていない場合は, MATLABにエラーが表示されます. 後程記しますが,MATLABのプログラムでI2Cを探し,認識させるコードを書いているため, 探しても見つからない場合は,エラーが発生するというものです. ↓はテスト用の回路図です.モータードライバーはTA7291P ![キャプションを入力できます](https://camo.elchika.com/1b0278b1db432e31e89d97a4d301b33e3da893ac/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65636165613738332d303336612d346532652d383632662d3732393461656431353662352f32623764646562662d646233662d346666302d623766322d616161316234646437306563/) オペレータ(MATLAB)側ですが,PCにジョイスティックをつなぎ,8つの領域にジョイスティックが 操作されると,モータの回転方向が決まり,操作量が大きくなると,モータの回転速度が増すようにしています. ![キャプションを入力できます](https://camo.elchika.com/de41c7972b2054736a96f65f255a3c51df1f8e5a/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65636165613738332d303336612d346532652d383632662d3732393461656431353662352f39376234353233622d393738322d343237332d613533362d373935396262306461313931/) 続いて,プログラムコードを説明します. まずは,走行ロボット NUEMK-Ⅰに搭載されているArduinoのプログラムです. 制御フローで示すとこんな感じです. ![キャプションを入力できます](https://camo.elchika.com/f31752b788148d39217034cdc97aa9c7332a0540/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65636165613738332d303336612d346532652d383632662d3732393461656431353662352f32633962376137382d383736642d343063612d626364652d653038323161653263363763/) TA7291Pモータドライバーを使用したときのプログラムを下記に記します. 制御フローの条件分岐はswitch文で行っています. また,モータへの出力用コードは digitalWrite(ピン番号,HIGH); digitalWrite(ピン番号,LOW); analogWrite(ピン番号,ジョイスティック操作量); となっています. Wire.hはArduinoがI2C通信が可能にするヘッダーファイルです. これでラズベリーパイからのI2Cピンを受信し, 下記コードを書いて,情報を読み取ります. a = Wire.read(); b = Wire.read(); c = Wire.read(); ```html:□TA7291P仕様Arduinoプログラム #include <Wire.h> int a,b,c,y,z; void setup() { Wire.begin(8);// Slave ID #8 Serial.begin(9600); Wire.onReceive(test); pinMode(3,OUTPUT); pinMode(4,OUTPUT); pinMode(5,OUTPUT); pinMode(8,OUTPUT); pinMode(9,OUTPUT); pinMode(10,OUTPUT); } void loop() { //z = -1; //Serial.println(z); } void test(int numBytes){ y=Wire.available(); Serial.print("0"); Serial.print(numBytes); Serial.println("0"); if(numBytes > 0){ a = Wire.read(); b = Wire.read(); c = Wire.read(); //Serial.print("0"); //Serial.print(a); //Serial.print("0"); //Serial.print(b); //Serial.print("0"); //Serial.print(c); //Serial.println("0"); switch(a){ case 1: digitalWrite(3,HIGH); digitalWrite(4,LOW); analogWrite(5,b); digitalWrite(8,HIGH); digitalWrite(9,LOW); analogWrite(10,c); break; case 2: digitalWrite(3,LOW); digitalWrite(4,HIGH); analogWrite(5,b); digitalWrite(8,HIGH); digitalWrite(9,LOW); analogWrite(10,c); break; case 3: digitalWrite(3,LOW); digitalWrite(4,HIGH); analogWrite(5,b); digitalWrite(8,LOW); digitalWrite(9,HIGH); analogWrite(10,c); break; case 4: digitalWrite(3,LOW); digitalWrite(4,HIGH); analogWrite(5,b); digitalWrite(8,LOW); digitalWrite(9,HIGH); analogWrite(10,c); break; case 5: digitalWrite(3,LOW); digitalWrite(4,HIGH); analogWrite(5,b); digitalWrite(8,LOW); digitalWrite(9,HIGH); analogWrite(10,c); break; case 6: digitalWrite(3,LOW); digitalWrite(4,HIGH); analogWrite(5,b); digitalWrite(8,HIGH); digitalWrite(9,LOW); analogWrite(10,c); break; case 7: digitalWrite(3,HIGH); digitalWrite(4,LOW); analogWrite(5,b); digitalWrite(8,LOW); digitalWrite(9,HIGH); analogWrite(10,c); break; case 8: digitalWrite(3,HIGH); digitalWrite(4,LOW); analogWrite(5,b); digitalWrite(8,HIGH); digitalWrite(9,LOW); analogWrite(10,c); break; } //delay(10); } } ``` ②NUE MK-1のシステム例 NUEMK-Ⅰに搭載した際の製作例を示します. まずは回路図です. 変更点ですが モータドライバーはTA7291PからPololu5019に変更しています. サーボモータを2台動作できるようにしています. ラズパイ用バッテリーを設けています(スマホ用モバイルバッテリー) 車体駆動用バッテリーは乾電池から,リチウムイオンバッテリーをしよしています. (NUEには報道用カメラバッテリー DUO190を2台使用) ![キャプションを入力できます](https://camo.elchika.com/d22ede92569dc5638acea9e1b4ca8e772c8078f9/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65636165613738332d303336612d346532652d383632662d3732393461656431353662352f30393334643261362d643633662d343161652d383463382d616437653533656163346139/) ![キャプションを入力できます](https://camo.elchika.com/7564ad9840c69262d9e0190798df76c1e7b1b5c2/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65636165613738332d303336612d346532652d383632662d3732393461656431353662352f35386365363063382d393139312d343939612d383734352d323563666364316633613166/) 続いて,Arduinoのプログラムを示します. ⓵からの変更点ですが, ・ヘッダーファイル<DualVNH5019MotorShield.h>を追加 ・モータへの出力コードを変更 md.setM1Speed(); md.setM2Speed(); 例えば,MATLABからのデータを変数b,cに格納した場合, 前進なら md.setM1Speed(b); md.setM2Speed(c); 後退なら md.setM1Speed(-b); md.setM2Speed(-c); と記載しています. ```html:□Plolu5019モータードライバー仕様 #include <Wire.h> #include <DualVNH5019MotorShield.h> DualVNH5019MotorShield md; int a,b,c,y,z; int val; void stopIfFault() { if (md.getM1Fault()) { Serial.println("M1 fault"); while(1); } if (md.getM2Fault()) { Serial.println("M2 fault"); while(1); } } void setup() { Wire.begin(8);// Slave ID #8 Serial.begin(9600); Wire.onReceive(test); /* pinMode(3,OUTPUT); pinMode(4,OUTPUT); pinMode(5,OUTPUT); pinMode(8,OUTPUT); pinMode(9,OUTPUT); pinMode(10,OUTPUT);*/ Serial.println("Dual VNH5019 Motor Shield"); md.init(); } void loop() { //z = -1; //Serial.println(z); } void test(int numBytes){ y=Wire.available(); Serial.print("0"); Serial.print(numBytes); Serial.println("0"); if(numBytes > 0){ a = Wire.read(); b = Wire.read()/127; c = Wire.read()/127; /*Serial.print("0"); Serial.print(a); Serial.print("0"); Serial.print(b); Serial.print("0"); Serial.print(c); Serial.println("0"); */ switch(a){ case 1: md.setM1Speed(b); md.setM2Speed(c); //Serial.print(a); break; case 2: md.setM1Speed(b); md.setM2Speed(c); //Serial.print(a); break; case 3: md.setM1Speed(-b); md.setM2Speed(-c); //Serial.print(a); break; case 4: md.setM1Speed(-b); md.setM2Speed(-c); //Serial.print(a); break; case 5: md.setM1Speed(-b); md.setM2Speed(-c); // Serial.print(a); break; case 6: md.setM1Speed(-b); md.setM2Speed(-c); //Serial.print(a); break; case 7: md.setM1Speed(b); md.setM2Speed(c); break; case 8: md.setM1Speed(b); md.setM2Speed(c); //Serial.print(a); break; } //delay(10); } } ``` NUE用サーボモータ回転プログラム ジョイスティックのボタンが押され,ラズベリーパイのデジタルピンから,信号を受信して, サーボモータを駆動するために作成したプログラムです. ```html:□サーボモータ回転プログラム #include <Servo.h> Servo myservo; int a,b,c,y,z,val,h,i; void setup() { Serial.begin(9600); pinMode(3,INPUT); pinMode(4,INPUT); pinMode(5,INPUT); pinMode(6,INPUT); pinMode(2,INPUT); //pinMode(11,OUTPUT); pinMode(12,OUTPUT); //pinMode(13,OUTPUT); pinMode(7,OUTPUT); } void loop() { if(digitalRead(6) == HIGH){ /* シリアルポートに'A'を出力 */ val=1; } else if(digitalRead(2) == HIGH){ val=2; } else if(digitalRead(3) == HIGH){ val=3; } else if(digitalRead(4) == HIGH){ val=4; } else { val = 0; } switch(val) // Perform an action depending on the command { case 1://Move Forward h=h+1; myservo.attach(12); myservo.write(h); //Serial.println(1); delay(10); break; case 2://Move Backwards h=h-1; myservo.attach(12); myservo.write(h); //Serial.println(2); delay(10); break; case 3://Turn Left i=i+1; myservo.attach(7); myservo.write(i); //Serial.println(3); delay(10); break; case 4://Turn Right i=i-1; myservo.attach(7); myservo.write(i); //Serial.println(4); delay(10); break; default: Serial.println(0); break; } } ``` NUE操作用MATLABプログラム 最後に,MATLABのプログラムコードを解説します. 基本的にOpening関数,Callback関数内にコードを追加してゆくのですが, 1⃣の内容から,さらにコンテンツを加えています. Opening関数での追加内容 ・ウェブカメラ handles.wcam2←ウェブカメラ2台目用の変数 ・I2C scanI2CBus(handles.mypi,'i2c-1')←ラズベリーパイのI2C番号を取得 enableI2C(handles.mypi,10)←バススピードを指定して,I2C出力を可能にする handles.i2csensor = i2cdev(handles.mypi,'i2c-1','0x08') ↑MATLABとラズベリーパイのI2Cを可能にする handles.joy = vrjoystick(1) ↑PCに接続されているジョイスティックを認識させる Callback関数内での追加内容 ・ウェブカメラ2台目用の映像表示 img2 = snapshot(handles.wcam2); imshow(img2, 'Parent', handles.axes2); .ジョイスティック用ボタン a = button(handles.joy,1) ↑ボタンを認識 writeDigitalPin(handles.mypi,4,a) ↑ボタンが押されたら,ラズベリーパイのデジタルピンから信号を出力 ※一応ボタンはすべて出力できるようにしています. ・ジョイスティックレバー操作 モータ回転方向と回転速度にかかわる部分です 長いので一部分だけを使って基本的な構成を紹介します. 基本的な構成 if(joystickの縦・横の値が正or負?) if(joystick縦値>joystick横値) t=[領域の番号,右モータ値,左モータ値] try write(handles.i2csensor(i2c-1の事), t(上記値) ,’int8’) catch warning(‘Problem using I2C interface’) end else 以下1~8までの領域に対して同様のコードが書かれています. ```html:□Matlab_Plollu5019使用ロボットプログラム function varargout = webcamtest3(varargin) % webcamtest3 MATLAB code for webcamtest3.fig % webcamtest3, by itself, creates a new webcamtest3 or raises the existing % singleton*. % % H = webcamtest3 returns the handle to a new webcamtest3 or the handle to % the existing singleton*. % % webcamtest3('CALLBACK',hObject,eventData,handles,...) calls the local % function named CALLBACK in webcamtest3.M with the given input arguments. % % webcamtest3('Property','Value',...) creates a new webcamtest3 or raises the % existing singleton*. Starting from the left, property value pairs are % applied to the GUI before webcamtest3_OpeningFcn gets called. An % unrecognized property name or invalid value makes property application % stop. All inputs are passed to webcamtest3_OpeningFcn via varargin. % % *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one % instance to run (singleton)". % % See also: GUIDE, GUIDATA, GUIHANDLES % Edit the above text to modify the response to help webcamtest3 % Last Modified by GUIDE v2.5 12-Dec-2017 23:04:10 % Begin initialization code - DO NOT EDIT gui_Singleton = 1; gui_State = struct('gui_Name', mfilename, ... 'gui_Singleton', gui_Singleton, ... 'gui_OpeningFcn', @webcamtest3_OpeningFcn, ... 'gui_OutputFcn', @webcamtest3_OutputFcn, ... 'gui_LayoutFcn', [] , ... 'gui_Callback', []); if nargin && ischar(varargin{1}) gui_State.gui_Callback = str2func(varargin{1}); end if nargout [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); else gui_mainfcn(gui_State, varargin{:}); end % End initialization code - DO NOT EDIT % --- Executes just before webcamtest3 is made visible. function webcamtest3_OpeningFcn(hObject, eventdata, handles, varargin) % This function has no output args, see OutputFcn. % hObject handle to figure % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % varargin command line arguments to webcamtest3 (see VARARGIN) handles.mypi=raspi; handles.wcam1 = webcam(handles.mypi,'UVC Camera (046d:0825) (usb-3f980000.usb-1.4):'); handles.wcam2 = webcam(handles.mypi,'UVC Camera (046d:081b) (usb-3f980000.usb-1.5):'); scanI2CBus(handles.mypi,'i2c-1'); enableI2C(handles.mypi,10); handles.i2csensor = i2cdev(handles.mypi,'i2c-1','0x08'); handles.joy = vrjoystick(1); handles.state='No'; % Choose default command line output for webcamtest3 handles.output = hObject; %wcam1 = webcam(handls.mypi,'USB 2.0 Camera (usb-3f980000.usb-1.4):') %wcam2 = webcam(handls.mypi,'UVC Camera (046d:081b) (usb-3f980000.usb-1.5):') %img1 = snapshot(wcam1); %img2 = snapshot(wcam2); %imshow(img1, 'Parent', handles.axes1); %imshow(img2, 'Parent', handles.axes2); % Update handles structure guidata(hObject, handles); % UIWAIT makes webcamtest3 wait for user response (see UIRESUME) % uiwait(handles.figure1); % --- Outputs from this function are returned to the command line. function varargout = webcamtest3_OutputFcn(hObject, eventdata, handles) % varargout cell array for returning output args (see VARARGOUT); % hObject handle to figure % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % Get default command line output from handles structure varargout{1} = handles.output; % --- Executes on button press in pushbutton2. function pushbutton1_Callback(hObject,eventdata, handles) % hObject handle to pushbutton2 (see GCBO) handles.output = hObject; handles.state='access'; while(strcmp(handles.state,'access')) img1 = snapshot(handles.wcam1); img2 = snapshot(handles.wcam2); imshow(img1, 'Parent', handles.axes1); imshow(img2, 'Parent', handles.axes2); %if (handles.joy == vrjoystick(1)) a = button(handles.joy,1); b = button(handles.joy,2); c = button(handles.joy,3); d = button(handles.joy,4); e = button(handles.joy,5); f = button(handles.joy,6); g = button(handles.joy,7); h = button(handles.joy,8); i = button(handles.joy,9); j = button(handles.joy,10); k = button(handles.joy,11); l = button(handles.joy,12); %m = button(handles.joy,13); writeDigitalPin(handles.mypi,4,a); writeDigitalPin(handles.mypi,17,b); writeDigitalPin(handles.mypi,27,c); writeDigitalPin(handles.mypi,22,d); writeDigitalPin(handles.mypi,14,e); writeDigitalPin(handles.mypi,13,f); % writeDigitalPin(handles.mypi,14,g); writeDigitalPin(handles.mypi,5,g); writeDigitalPin(handles.mypi,6,h); writeDigitalPin(handles.mypi,19,i); writeDigitalPin(handles.mypi,26,j); writeDigitalPin(handles.mypi,15,k); writeDigitalPin(handles.mypi,16,l); %writeDigitalPin(handles.mypi,20,m); %A = [a,b,c,d]; %disp(A); w = axis(handles.joy, 1)*127; x = -axis(handles.joy, 2)*127; y = round(w); z = round(x); if(w>=0) && (x>=0) if(abs(w)>abs(x)) t = [2,round(abs(y-z/2)),round(abs(y-z))];%[1,e,f-150,c-127,d]%オフセット量をfとcに施している try write(handles.i2csensor,t,'int8'); catch warning('Problem using I2C interface.'); end else t = [1,round(abs(z-y/2)),round(abs(z-y))];%[2,e,f,c,d] try write(handles.i2csensor,t,'int8'); catch warning('Problem using I2C interface.'); end end elseif(w>=0) && (x<0) if(abs(w)>abs(x)) t = [3,round(abs(y+z/2)),round(abs(z+y))];%[3,e,f,c,d] try write(handles.i2csensor,t,'int8'); catch warning('Problem using I2C interface.'); end else t = [4,round(abs(z+y/2)),round(abs(y+z))];%[4,e,f,c,d] try write(handles.i2csensor,t,'int8'); catch warning('Problem using I2C interface.'); end end elseif(w<0) && (x<0) if(abs(w)>abs(x)) t = [6,round(abs(z-y)),round(abs(z/2-y))];%[6,e,f,c,d] try write(handles.i2csensor,t,'int8'); catch warning('Problem using I2C interface.'); end else t = [5,round(abs(y-z)),round(abs(y/2-z))];%[5,e,f,c,d] try write(handles.i2csensor,t,'int8'); catch warning('Problem using I2C interface.'); end end elseif(w<0) && (x>=0) if(abs(w)>abs(x)) t = [7,round(abs(z+y)),round(abs(z/2+y))];%[7,e,f,c,d] try write(handles.i2csensor,t,'int8'); catch warning('Problem using I2C interface.'); end else t = [8,round(abs(y+z)),round(abs(y/2+z))];%[8,e,f,c,d] try write(handles.i2csensor,t,'int8'); catch warning('Problem using I2C interface.'); end end else end if (i==1)&&(j==1) break end %end % Update handles structure guidata(hObject, handles); end % --- Executes on button press in pushbutton3. function pushbutton3_Callback(hObject, eventdata, handles) handles.state='access'; while(strcmp(handles.state,'access')) img1 = snapshot(handles.wcam1); img2 = snapshot(handles.wcam2); imshow(img1, 'Parent', handles.axes1); imshow(img2, 'Parent', handles.axes2); % hObject handle to pushbutton3 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) guidata(hObject, handles); end ```