iMCs04 コンポーネント

iXs Research製のラジコン用サーボモータコントローラ iMCs04の制御用RTコンポーネントを作りました.

これを使えばかなり簡単にラジコン用サーボモータを扱えます.

iMCs04について

iMCs04とは,最大4台のラジコン用サーボモータを制御できる,モータコントローラです.

すばらしいのはなんといってもそのサイズ.4.5cm×3cm×0.5cm!名刺の半分くらいのサイズでしょうか.

今回はアナログ4系統の入力についても扱えるように作りました.

ラジコン用サーボモータについて

ラジコン用サーボモータについて説明します.

ラジコン用サーボモータは,もともとラジコンカーやラジコンヘリの操舵を行うために販売されているモータで,簡単に角度制御ができ,小型でトルクが大きいのが特徴です.

また近年はロボット用途として,サーボゲイン調整機能や,現在角度のフィードバック機能がついたラジコンサーボが販売されています.

iMCs04は,2008年3月現在の仕様では,角度指定機能しかありませんが,これでも十分に遊べます.

ラジコン用サーボモータとコントローラは,基本的に3本の線で通信します.とはいえ1本目は電源,2本目はGNDですから,実質1本の信号線のみで角度を指定します.角度の指定方法はアナログではなく,0-5[V]のデジタル信号で,具体的にはパルスの幅で指定されます.

パルス幅は通常1500[us]を中心として1000[us]〜2000[us]程度.パルスの周期は22[ms]程度です.このパルスの幅に比例して,サーボモータが舵を切るわけです.

しかし近年ではいろいろなモデルが出ているので,モーターに付属しているマニュアルか,メーカーの公式ウェブサイトの情報を参照して下さい.

概要

iMCs04を簡単に使用できるRTコンポーネントを作ります.あくまで簡単に,というのが目的なので,機能はできるだけ削いで,モータの角度指令とアナログ値の取得にとどめました.

モータ,アナログ入力,ともに4系統ですので,4つの入力ポート,4つの出力ポートを持つプログラムになっています.

iMCs04コンポーネントプログラム

まずiMCs04を簡単に扱うことができるクラスライブラリ(iMCs04.h iMCs04.cpp)を作りました.この後にこれをコンポーネントに実装します.

#pragma once

/**
* iMCs04.h
* author: ysuga (ysuga.net)
* Copyright: ysuga.net 2008
**/


/// 最大のパルス幅値
#define MAX_DUTY 5600
/// 最小のパルス幅値
#define MIN_DUTY 1800

/// ニュートラル時のパルス幅
#define NEUTRAL_DUTY 3150


/**
* CiMCs04
* iMCs04をかんたんに使うためのライブラリ
*
**/

class CiMCs04
{
 private:
 // 制御用ハンドル
 void* m_husb;
 HANDLE m_hContinous, m_hCounter, m_hDesire;
 // 制御用バッファ
 struct urcout m_cmd;
 struct urcin m_AD_VAL;
 // USBの最大パケットサイズ
 DWORD m_MaxPacketSize;

public:
 // コンストラクタ
 // この時点でiMCs04をオープンします.
 // 失敗した場合は文字列へのポインタをthrowします.
 // try-catch節を用いて,失敗の原因文字列を取得してください.

 CiMCs04(void);

 // デストラクタ
 ~CiMCs04(void);

private:
 // 内部処理.USBのパケットデータの最大サイズを取得
 USHORT GetMaxPacket(HUSB husb, DWORD if_num, DWORD pipe_num);

public:
 // 初期化
 void Init(void);
 // 目標位置を取得
 // channel:チャンネル(0−3)
 // duty:パルス幅

 void SetTargetDuty(int channel, USHORT duty);

 // アナログ電圧取得
 // channel:チャンネル(0−3)
 // 返り値:アナログ電圧値をデジタル化した値(0−1024)

 USHORT GetAdValue(int channel);

public:
 // データをUSBデバイスから読み込む
 // GetAdValudeでアナログ電圧を取得する前に呼ぶこと.

 void Read(void);
 // データをUSBデバイスに書き込む
 // SetTargetDutyを呼び,パルス幅を設定した後に呼ぶこと.

 void Write(void);

 // サーボをオフにします.
 // KONDO科学製 KRS-4014HVで動作確認済み

 void ServoOff(void);
};

関数の実装については,iMCs04.cppファイルを参照してください.

コンポーネント側には,入力ポート4つと出力ポート4つを実装しますが,ソースコードを見ると配列で宣言していることがわかると思います.後々の処理に関して考えても,同様のポートを配列で宣言しておくのは有効です.これは適当に入力・出力ポートをRTCTemplateで宣言しておいて,手作業で配列化しました.

// iMCs04Component.hより
 TimedFloat m_VoltagePort[4];
 OutPort<TimedFloat> *m_pVoltagePortOut[4];

こうやって配列で宣言したときは,コンストラクタでポートをRTMに登録するときに,ちょっとした手作業が必要ですが,簡単ですよ.

次はiMCs04Componentのコンストラクタ内でポートの登録をします.registerOutPort,registerInPort関数を呼び出します.これも配列を使えばスッキリ♪

char stringBuffer[256];
for(int i = 0;i < 4;i++) {
 //入力ポートであるTargetDegreePort0〜3を登録します.
 sprintf(stringBuffer, "TargetDegreePort%d", i); //名前の文字列を作って…
 m_pTargetDegreePortIn[i] = new RTC::InPort<TimedLong>(stringBuffer, m_TargetDegreePort[i]); // ポートのインスタンスを作成して…
 registerInPort(stringBuffer, *m_pTargetDegreePortIn[i]); // 名前の文字列とポートのインスタンスを登録する

 //出力ポートであるVoltagePort0〜3を登録します.
 // やってることは入力ポートと一緒です.
 sprintf(stringBuffer, "VoltagePort%d", i);
 m_pVoltagePortOut[i] = new RTC::OutPort<TimedFloat>(stringBuffer, m_VoltagePort[i]);
 registerOutPort(stringBuffer, *m_pVoltagePortOut[i]);
}

そのほか,onActivateではファイルを開く作業です.USBを開くことが出来なかった場合(たとえばiMCs04の認識が失敗しているとかが原因)は,RTC_ERRORという値を返します.すると,コンポーネントはERROR状態に遷移します.状態遷移図を参考にして下さい.

rtc.confの設定

これまでと同様でかまいません.周期をゆっくりめに設定してもいいかな.

corba.nameservers:localhost:2809
naming.formats: %n.rtc
logger.log_level: TRACE

まとめ

とにかく使ってほしいRTCの第1弾.非常にシンプルに動作します.不具合を見つけてくれた方は連絡をください.

ダウンロードはこちら→iMCs04Component.zip (ver. 0.4.1)

iMCs04Component042.zip (ver. 0.4.2)


RTミドルウェア入門