STEP 4-1CPUボードにおける入力ポートの使い方
今度は入力ポートを使って、CPUボードのモータ・LED・ブザーを制御するプログラムを作成してみたいと思います。入力ポートの使い方は、原則として先ほどの確認用プログラムとほぼ同じ方法で簡単に作成できます。
STEP 4-2プロジェクトを作成する
では、実際にRTコンポーネントのプロジェクトを作成して見ましょう。eclipseを起動して、メニューより「File」→「Open New Builder Editor」をクリックしてください。
各設定項目は、基本的にテストプロジェクトの作成と同じです。
先ほどと同様に「データポート」の項目を設定します。メモリマップの仕様に合わせて、Data Typeの型を設定します。
各ポートの概要は下記の通りです。
- Mt1Gain/Mt2Gain・・・ch1/ch2のモータのゲインを入力します。数値は0〜255の範囲で、数値が大きいほどゲインが強くなります。
- Mt1Spd/Mt2Spd・・・ch1/ch2のモータのスピードを入力します。数値は-127〜127の範囲で、符号の向きで回転方向が逆転し、数値が0から遠いほど速度が速くなります。
- LED1/LED2・・・緑・オレンジのLEDの点滅を入力します。数値は-1〜32767の範囲で、0で消灯、負の値で点灯します。1以上の場合、その数値×0.1msecだけ点灯して消灯します。
- BuzPitch・・・ブザーの音程を設定します。
- BuzTime・・・ブザーの発声時間を設定します。
- Mode・・・CPUボードの動作モードを設定します。CPUボードの仕様により、モータを動作させる場合はこの数値を'1'にしないと動作しません。
追加したら、これまでと同様に「コード生成」でプロジェクトを作成し、新規作成したプロジェクトのフォルダを開いて「copyprops.bat」を実行してください。
続いて、VS-WRC003 SDKをソース・ファイルともに組み込み、Visual Studioからプロジェクトを開いてください。開いたら、onExecute関数を次のように変更します。
RTC::ReturnCode_t OUTPUT_TEST::onExecute(RTC::UniqueId ec_id)
{
//データを受信したかを記録するフラグ
int send_que=0;
//Modeを受信
if(m_ModeIn.isNew()){ m_ModeIn.read(); send_que++; }
//モータのゲインを受信
if(m_Mt1GainIn.isNew()){ m_Mt1GainIn.read(); send_que++; }
if(m_Mt2GainIn.isNew()){ m_Mt2GainIn.read(); send_que++; }
//モータの速度を受信
if(m_Mt1SpdIn.isNew()){ m_Mt1SpdIn.read(); send_que++; }
if(m_Mt2SpdIn.isNew()){ m_Mt2SpdIn.read(); send_que++; }
//LEDの点灯時間を受信
if(m_LED1In.isNew()){ m_LED1In.read(); send_que++; }
if(m_LED2In.isNew()){ m_LED2In.read(); send_que++; }
//ブザーの発声時間と音程を受信
if(m_BuzTimeIn.isNew()){ m_BuzTimeIn.read(); send_que++; }
if(m_BuzPitchIn.isNew()){ m_BuzPitchIn.read(); send_que++; }
//何らかのデータを受信したか
if(send_que){
//受け取った数値をCPUボードへ書き込み
//2byteの場合は、1byteずつ送信する。上位バイトから順番に送信する
if(CWRC_Connect()){
CWRC_WriteMemMap(4, (BYTE) m_Mode.data);
CWRC_WriteMemMap(8, (BYTE) m_Mt1Gain.data);
CWRC_WriteMemMap(9, (BYTE) m_Mt2Gain.data);
CWRC_WriteMemMap(14, (BYTE) (m_Mt1Spd.data >> 8));
CWRC_WriteMemMap(15, (BYTE) m_Mt1Spd.data);
CWRC_WriteMemMap(16, (BYTE) (m_Mt2Spd.data >> 8));
CWRC_WriteMemMap(17, (BYTE) m_Mt2Spd.data);
CWRC_WriteMemMap(42, (BYTE) (m_LED1.data >> 8));
CWRC_WriteMemMap(43, (BYTE) m_LED1.data);
CWRC_WriteMemMap(44, (BYTE) (m_LED2.data >> 8));
CWRC_WriteMemMap(45, (BYTE) m_LED2.data);
CWRC_WriteMemMap(50, (BYTE) (m_BuzTime.data >> 8));
CWRC_WriteMemMap(51, (BYTE) m_BuzTime.data);
CWRC_WriteMemMap(52, (BYTE) (m_BuzPitch.data >> 8));
CWRC_WriteMemMap(53, (BYTE) m_BuzPitch.data);
CWRC_WriteExecute(FALSE);
CWRC_Disconnect();
}
}
return RTC::RTC_OK;
}
|
入力ポートからのデータ読み込みは、先ほどの確認用プログラムと同じです。CPUボードとの通信は、最後にまとめて行なうようにしています。また、通信データ量の削減及び入力が無かった数値が勝手に書き換わらないように、入力のあった数値だけを書き換える仕組みにしています。
変更したらプロジェクトをビルドしてください。
STEP 4-3確認用テスト表示プログラムの作成
続いて、作成したRTコンポーネントの動作が正しいか、確認用のプログラムを作成してみましょう。確認用プログラムは、下記のように各入力ポートに対応する出力ポートを持つプログラムを作ります。
プロジェクトを作成したらVisual Studioでプロジェクトを開き、onExecute関数を下記のように書き換えます。それぞれの出力ポートの数値を、プロンプト画面でキーボードから入力させる形式です。
#define GETPARAM(txt) printf(txt); gets(str);
RTC::ReturnCode_t INPUT_CHECK::onExecute(RTC::UniqueId ec_id)
{
char str[256];
GETPARAM("\nget 'mode' ");
m_Mode.data = atoi(str);
m_ModeOut.write();
GETPARAM("\nget 'mt1gain' ");
m_Mt1Gain.data = atoi(str);
m_Mt1GainOut.write();
GETPARAM("\nget 'mt2gain' ");
m_Mt2Gain.data = atoi(str);
m_Mt2GainOut.write();
GETPARAM("\nget 'mt1spd' ");
m_Mt1Spd.data = atoi(str);
m_Mt1SpdOut.write();
GETPARAM("\nget 'mt2spd' ");
m_Mt2Spd.data = atoi(str);
m_Mt2SpdOut.write();
GETPARAM("\nget 'LED1' ");
m_LED1.data = atoi(str);
m_LED1Out.write();
GETPARAM("\nget 'LED2' ");
m_LED2.data = atoi(str);
m_LED2Out.write();
GETPARAM("\nget 'BuzTime' ");
m_BuzTime.data = atoi(str);
m_BuzTimeOut.write();
GETPARAM("\nget 'BuzPitch' ");
m_BuzPitch.data = atoi(str);
m_BuzPitchOut.write();
return RTC::RTC_OK;
}
|
プログラムを書き換えたらビルドしてください。
STEP 4-4プログラムの実行
続いて、CPUボードに正しくデータを書き込んで制御できるか確認してみましょう。Naming Server及びRTC System Editor RCPを起動して、System Diagramへ入力側・出力側の各プログラムを追加し、対応するポート同士を接続してください。
接続したらAll Activeボタンをクリックして、出力側のプログラムより下記のように入力してみてください。
モータが動くように、modeには1を入力します。
ゲインは200程度で問題ありません。
スピードは±100程度にします。余り小さすぎると本体の重みでモータが動かない場合があります。
LED1、2は、点灯させる適当な時間を入力します。
BuzTimeは発声させる適当な時間を入力します。
BuzPitchは発声させる適当な音程を入力します。
なお、プログラムを実行すると分りますが、最後まで数値を入力しなくても、入力した数値が適時ロボットに反映されます。これは一見間違った処理に見えますが、INPUT_CHECK側は「入力された数値をすぐにwrite()関数で出力」、INPUT_TEST側は「一定間隔でonExecute関数を実行し、isNew()関数でデータ更新が判明したポートがあれば逐次ロボットへ送信」という処理が行われているためです。