モータドライバのパルス入力を使い、サーボモータやステップモータを制御します。
計算で推定した角度をフィードバックに使うので、サーボモータでも角度エンコーダの信号は必要ありません。
3種類の異なるやり方でドライバへのパルス指令を生成しています。

ソースコードやプロジェクトファイルのダウンロードはこちら → drivePulse.zip

【注意】サーボモータの場合は、パルス駆動モードを備えたドライバが必要です。

(1)実運転用のプログラムです。シミュレーションもできます。
ブロック図
プログラム
// ユーザ関数:パルス指令の発生
genPulse( vc, gain, step, pos, dead, rem )
{
    dir = 2 * ( vc > 0 ) - 1;            // 回転方向指令(±1)
    freq = gain * abs( vc );             // 指令周波数	
    if freq > dead                       // 不感域を設ける
    {
        gen = w_sqr( 1/freq, 0, 1 );     // パルス生成
        if gen != rem                    // 出力のup/dowmnで駆動
        {
            pos = pos + dir * step;      // 位置加算
        }
    }
    rem = gen;                          // 次回のために記憶
    Dout( 0, 0, gen );                  // 速度パルス出力
    Dout( 1, 0, dir );                  // 方向パルス出力
    return pos;
}
// メイン処理:パルス駆動によるモータの位置制御
var pos;
var Vc;
var last;
proc 
{ 
    if currTime() > 0.1 { Pc = 1; }        // 0.1秒後に移動指令発生
    err = Pc - pos;                        // 誤差
    acc = Kp * err - Vc;                   // 加速度
    acc = limit( -sup, sup, acc );         // 加速度制限
    Vc = integral( acc, Vc, T, 1, -1 );    // 速度指令

    pos = genPulse( Vc, gain, step, pos, 10, last );  // パルス指令の発生
    dir  = auxfunc( dir );                            // 方向指令のモニタ
    rate = auxfunc( gen );                            // 速度パルス指令のモニタ
} 
説明

モータ角度制御のページと同じやりかたで速度指令 Vc を生成し、 ユーザ関数 genPulse により駆動信号 gen と方位信号 dir を生成します。 フィードバックは、角度信号の代わりに計算値 pos を使います。
ユーザ関数 genPilse ではステップモータのページと同じように 矩形波発生関数 w_sqr でパルス列を発生させています。

この例では以下の関数、信号、パラメータを使います。

関数
(予約語)
 w_sqr矩形の周期関数を発生します。
 integral出力リミット付き積分器です。
 auxfuncユーザ関数の内部信号を得ます。
 Doutデジタル信号を出力します。
信号 Pc単位角度指令信号です。
 Vc速度指令信号です。最大値は±1です。
 freq指令速度に比例した周波数の矩形波信号です。
 dir指令速度の符号を表わす1または-1の信号です。
 posgenとdirから計算した角度の推定値です。
パラメータ  Kp位置制御ゲインです。
 sup加速度を制限するリミット値です。
 T速度指令を生成する積分の時定数です。
 gain信号 gen の最大周波数[Hz]になります。
 step1ステップあたりの(単位指令角度に対する)回転角度です。

設定例
記録例


(2) 積分器を使ってパルスを発生させます。結果はほとんど同じになります。
プログラム
// ユーザ関数:パルス指令の発生
genPulse2( vc, stp, pos )
{
    pc = integral( vc, pc, 1, 1, -1 );	// 速度指令を積分して位置指令とする
    dir = 0;
    if    pc >  stp { dir= 1; }     // ステップ幅を超えたら正方向回転指令
    elsif pc < -stp { dir=-1; }     // ステップ幅を逆に超えたら負方向回転指令

    if dir != 0                     // 正または負方向に回転の場合は
    {
        gen = ! gen;                // High/Low切替 (0→1、1→0)
        pos = pos + dir * stp;      // 指令回転角度を位置に加算して
        pc = pc - dir * stp;        // 回転させる分 次回の指令を減らす
        Dout( 0, 0.5, gen );        // 速度パルス出力
        Dout( 1, 0,   dir );        // 方向パルス出力
    }
    return pos;
}
// メイン処理:パルス駆動によるモータの位置制御
var pos;
var Vc;
proc 
{ 
    if currTime() > 0.1 { Pc = 1; }     // 0.1秒後に移動指令発生
    err = Pc - pos;                     // 誤差
    acc = Kp * err - Vc;                // 加速度
    acc = limit( -sup, sup, acc );      // 加速度制限
    Vc = integral( acc, Vc, T, 1, -1 ); // 速度指令

    pos = genPulse2( Vc, step, pos );   // パルス指令の発生
    dir  = auxfunc( dir );              // 方向指令のモニタ
    rate = auxfunc( gen );              // 速度パルス指令のモニタ
} 

 

 

(3) 2相パルス信号でドライバを駆動する場合のプログラムです。
ブロック図
プログラム
// ユーザ関数:パルス指令の発生
genPulse3( vc, stp, pos, A, B )
{
	pc = integral( vc, pc, 1, 1, -1 );	// 速度指令を積分して位置指令とする
	dir = 0;
	if    pc > stp  { dir= 1;  if A^B { A=!A; } else { B=!B; } } // 正方向回転
	elsif pc <-stp  { dir=-1;  if A^B { B=!B; } else { A=!A; } } // 負方向回転

	if dir != 0			// 上記いずれかの場合は
	{
		pos = pos + dir * stp;	// 位置を加算
		pc = pc - dir * stp;	// 加算分を指令から減算
		Dout( 0, 0.5, A );	// A相信号出力
		Dout( 1, 0.5, B );	// B相信号出力
	}
	return pos;
}
// メイン処理:2相パルス駆動によるモータの位置制御
var pos;	// 位置フィードバック信号
var Vc;		// 速度指令信号
var A;		// 駆動指令信号 A相
var B;		// 駆動指令信号 B相
proc 
{ 
	if    currTime() > 0.6 { Pc = 0; }      // 0.6秒以降の指令
	elsif currTime() > 0.1 { Pc = 1; }      // 0.1〜0.6秒の指令
	err = Pc - pos;                         // 誤差
	acc = Kp * err - Vc;                    // 加速度
	acc = limit( -sup, sup, acc );          // 加速度制限
	Vc = integral( acc, Vc, T, 1, -1 );     // 速度指令

	pos = genPulse3( Vc, step, pos, A, B ); // 2相パルス指令の発生
} 
記録例

短時間で位置指令 Pc を0に戻し、速度を逆転させてみました。

拡大すると、速度指令 Vc の符号変化とともに、AとBの位相関係も逆転しています。