目次
前
次
API設計
MCR_VCマシンのファームウエアを設計する場合、ハードウエアを
抽象化したカタチで使えるようにした方が楽です。
C/C++で利用するとして、ハードウエアを抽象化するためAPI
(Application Programming Interface)を定義します。
3ブロックに分けて、APIを定義します。
モータ制御用API
モータは、3種を使えるようにします。
モータは以下の3種。
- DC motor
- Pulse motor
- Servo motor
各モータのAPIは、以下。
- send_dc
- send_pulse
- send_servo
DCモータの場合、どのピンからPWM波形を出力するかを指定し
DUTY比を指定すればよいでしょう。パラメータは1種ですむ
ように構造体変数で与えられるようにと考えました。
typdef unsigned char UBYTE ;
typdef struct {
UBYTE xpin ;
UBYTE xduty ;
} DCPARAMP ;
構造体変数として定義しておけば、パラメータ数が増えたとしても
構造体の中にある変数を増やすだけで対応できます。
構造体変数としておけば、パルス、サーボのどちらでも対応可能に
なるだろうと判断。
サーボモータの場合、角度を制御するので、角度にするのか
パルス幅の値を処理するのかを指定できるようにします。
typdef struct {
UBYTE xformat ;
UBYTE xvalue ;
} SERVOP ;
サーボモータの場合、角度とパルス幅の関係を変換してやらないと
制御できないので、変換式を定義してテストします。
角度を0から180として、パルス幅のカウント値が100から200に
なるよう、計算式を算出。
定義域が0から180で、値域が100から200なので
傾きを求め、1次式に。
傾き => (200-100)/(180-0) = 100 / 180 = 5 / 9
始点 => (0,100)
変換式 => y-100 = (5/9)(x-0) => y = (900-5x)/9
スクリプト言語のPythonを利用して、変換が正しいのかを
実際に計算して確認。スクリプトは以下。
ee = range(0,181)
for x in ee :
y = (900 + 5 * x) / 9
print y,"<-",x
APIを使う場合、次の変換を入れれば充分でしょう。
yvalue = xvalue ;
if ( xformat ) {
yvalue = (900 - 5 * xvalue) / 9 ;
}
パルスモータの場合、パルス数と回転方向を指定するだけに。
パルスモータでは脱調しないように、利用するパルスの周波数も指定
できるようにします。
typdef unsigned short UWORD ;
typdef struct {
UBYTE xdirection ;
UWORD xcount ;
UBYTE xfrq ;
} PULSEP ;
パルスモータの場合、2相励磁であればビットパターンの
組み合わせで、回転方向が決まります。
正転 => 9 -> 3 -> 6 -> C
逆転 => 9 -> 6 -> 3 -> C
xdirectionを利用して、出力ビットパターンを決めていきます。
*(msg+0) = 0x09 ;
*(msg+1) = 0x03 ;
*(msg+2) = 0x06 ;
*(msg+3) = 0x0c ;
if ( xdirection ) {
*(msg+2) = 0x03 ;
*(msg+1) = 0x06 ;
}
/* impress */
for ( i = 0 ; i < xcount ; i++ ) {
j = i % 4 ;
PORT = *(msg+j);
}
パラメータを受け取ってから、ハードウエアをどう動かすのかは
利用するマイコン、デジタル回路で千差万別になります。
センサー用API
センサーは、3種を使えるようにAPIを定義します。
- Reflector
- Game Boy Camera
- Bar Code Scanner
Reflectorは、密着タイプの路面センサーに使います。
返値は、最大8ビットのゼロあるいは自然数に。
移動に必要な情報は、少ない方が制御を単純にできるので
どのセンサーでも、返す値を同じにします。
文字列で扱えるように、マクロ定義。
#define ALL_BLACK 0
#define ALL_WHITE 1
#define LEFT_WHITE 2
#define RIGHT_WHITE 3
#define CENTER 4
#define TINY_RIGHT 5
#define RIGHT 6
#define BIG_RIGHT 7
#define TINY_LEFT 8
#define LEFT 9
#define BIG_LEFT 10
#define BOTH_WHITE 11
#define ILLEAGAL 12
どのセンサーを利用しても、関数get_sensor()で済ませます。
その他のAPI
モータ、センサー以外で必要になるAPIを考えます。
時間待ちが必要となれば、ms単位の処理を用意すれば充分でしょう。
パラメータは1から65537と16ビットで扱える範囲に。
delay_ms(xcnt)でxcntを1から65537とします。
システムタイマーがあれば、次のような構造で実現できます。
void delay_ms(UWORD xcnt)
{
ULONG target ;
/* calculate */
target = xtim + xcnt ;
/* watch */
while ( target > xtim ) ;
}
スタートゲートセンサーを使うのならget_startをAPIを用意。
スイッチスタートも認められているので、スイッチとセンサーの
2つのAPIを用意し、次のように処理します。
UBYTE get_start()
{
UBYTE result ;
/* default */
result = 0 ;
/* get start switch */
result |= get_start_sw();
result <<= 1;
/* get start sensor */
result |= get_start_sensor();
return result ;
}
ハードウエアに密着した最下層の関数
get_start_sw()
get_start_sensor();
を使い、開閉の状態を2ビットにまとめます。
スタートスイッチの場合、押されていれば1を返し
センサーの場合、ゲートが開いていれば1を返すと
仕様を決めて対応。
単純な数値では、わかりにくいのでマクロ定義した
文字列を利用。
#define CLOSED 0
#define OPENED CLOSED+1
目次
前
次