115.PCD4511でステッピングモータ制御


2003/10/04 【ソフトウエア編TOPに戻る】

 

前回114.ステッピングモータを動かすのページでは、ユニポーラ型ステッピングモータを動かすための基本的な方法についてご紹介しました。今回は、日本パルスモータ製PCD4511というパルスコントロールLSIを使って、少しきめの細かい制御を行って見ましょう。きめの細かい制御といっても、CPUからPCD4511に対していくつかのパラメータを書き込んであげるだけで、あとのステッピングモータの制御はPCD4511が自分でやってくれるので、CPUの負担は軽くなります。

今回実験に使用するのは、14.PCD4511パルスモータ制御テストボード(ユニ)のページでご紹介している基板です。先ずはそちらからご覧下さい。また、日本パルスモータさんのホームページからマニュアルもダウンロードできますので、詳しくはそちらを参照して下さい。特に「初めてご検討、ご使用いただく方へ」と題された初心者向けマニュアルは、直感的に概要が分かるように説明されていますので、是非ご覧下さい。


115−1.PCD4511パルスコントロールLSIとは

 

PCD4511とは、CPUからのパラメータの書き込みによって、ステッピングモータを以下のように動作させるための制御パルス信号を発生します。

 

1.一定速動作

設定した速度で回転を続ける動作です。あらかじめ設定したパルス数で自動的に停止させることもできますし、ずっと回転させ続けることもできます。当然好きなタイミングでストップ制御を掛けることも可能です。

 

2.直線加減速動作

設定した初速度で回転を始めて、設定した時間で動作速度まで直線的に加速を行います。その後直線での減速を開始して初速度まで減速できたら自動的に停止させるというような一連の動作を行うことが可能です。一定時間内で任意の回転角度を得るような、ロボットの関節制御にピッタリです。

 

3.S字加減速動作

これは上記の直線加減速動作での加減速の仕方を、S字カーブ(2次曲線)で行う動作です。直線的な加減速よりも、より自然な加減速動作が可能です。

 

これらの基本動作に加え、加速途中で加速を止めて一定速動作に切り替えたり、任意のタイミングで減速を開始させたりといったイレギュラーな制御や、外部リミットスイッチや原点スイッチからの情報を取り込んで強制的に減速や停止を行うための制御などにも対応しています。

 

これらの動作を行わせるためのパラメータの書き込みは、以下の仕組みによります。

 

■アドレス

8BITのデータを読み書きするためのアドレスはA1A0の2ビットだけです。これにRD信号とWR信号が加わって、データの書き込みか、読み出しかを選択する仕組みです。これらの関係は以下の通りになります。

※CS端子がLOWの時に有効。

RD WR A1 A0 説 明
H L L L データバスはコマンドバッファへの書き込みバスとなる。
H L L H データバスはレジスタ下位7〜0BIT用の書き込みデータとなる。
H L H L データバスはレジスタ中位15〜8BIT用の書き込みデータとなる。
H L H H データバスはレジスタ上位23〜16BIT用の書き込みデータとなる。
L H L L データバスはコマンドバッファからの読み出しバスとなる。
L H L H データバスはレジスタ下位7〜0BIT用の読み出しデータとなる。
L H H L データバスはレジスタ中位15〜8BIT用の読み出しデータとなる。
L H H H データバスはレジスタ上位23〜16BIT用の読み出しデータとなる。

ここでコマンドバッファレジスタという言葉が新たに出てきました。コマンドバッファとはPCD4511様々な動作モードを決定付けるための設定を行うもので、レジスタとは動作を行う上での特性を決定する数値(パラメータ)を設定するためのものです。

レジスタは最長で24ビット幅あるため、上位/中位/下位に3分割して読み書きを行うことになります。

実は、PCD4511には動作の特性を決定するレジスタがR0からR6まで7個あり、読み書きの窓口は全て上記に示すアドレスのレジスタ(上位/中位/下位)を共通に使っています。この窓口に書き込んだデータを、R0からR6までの、どのレジスタにセットするのかについては、コマンドバッファに書き込むデータで選択させます。

つまり、PCD4511内でのアドレスに相当する部分は、上記のA1,A0だけではなく、コマンドバッファに書き込むデータにも、その意味合いがあるのです。ソフトウエア設計を行う上では、ちょっとだけ戸惑う部分かもしれません。

 

■コマンドバッファ

コマンドバッファは、様々な動作モードを決定するためのレジスタです。データ幅は8BITですが、上位2BITを使って、以下のようにコマンドバッファを大きく4種類に分けています

1.スタートモードコマンド

BIT 機 能 説 明
D7 0 D7とD6両方に0を書き込むと、そのコマンドはスタートモードコマンドであると認識されます。
D6 0
D5 停止時INT出力 0:INT出力しない  1:INT出力する
D4 スタート制御 0:スタートしない  1:スタートする
D3 ストップ制御 0:ストップしない  1:ストップする
D2 速度モード 0:一定速度動作  1:加減速動作
D1 外部スタート制御 0:STA端子を無効にする  1:STA端子がLになるまでスタートを保留する
D0 動作速度選択 0:FLを動作速度とする  1:FHを動作速度とする

スタートモードコマンドでは、上記のように主にスタート、ストップに関連する設定を行います。実際にモータを回転させたい時は、このD4のビットを1にすることで行ったりします。

 

2.制御モードコマンド

BIT 機 能 説 明
D7 0 D7に0、D6に1を書き込むと、そのコマンドは制御モードコマンドであると認識されます。
D6 1
D5 加減速特性選択 0:直線加減速動作  1:S字加減速動作
D4 OTS制御 0:OTS端子をLレベルにする  1:OTS端子をHレベルにする
D3 動作方向選択 0:プラス方向回転  1:マイナス方向回転
D2 プリセット動作選択 0:無効(ストップ制御するまで回転) 1:有効(セットしたパルス数で停止)
D1 SD信号制御 0:+SD,-SD入力を無効にする  1:+SD,-SD入力を有効にする
D0 ORG信号制御 0:ORG入力を無効にする  1:ORG入力を有効にする

制御モードコマンドでは、上記のように主に回転動作の特性に関する設定を行います。

 

3.レジスタセレクトコマンド

BIT 機 能 説 明
D7 1 D7に1、D6に0を書き込むと、そのコマンドはレジスタセレクトコマンドであると認識されます。
D6 0
D5 外部スタートINT 0:外部スタート時にINT出力しない  1:INT出力する
D4 SDポイントINT 0:スローダウンポイントでINT出力しない  1:INT出力する
D3 プリセットカウンタ 0:パルス出力ごとにカウントダウン動作をする  1:カウントダウンしない
D2 レジスタ選択BIT2 R0からR6のレジスタを選択するためのアドレスとして機能する。
D1 レジスタ選択BIT1
D0 レジスタ選択BIT0

レジスタセレクトコマンドでは、D2〜D0の3BIT分を使って、A1,A0のアドレスだけでは足りない、レジスタ選択のアドレス指定として機能します。ここで選択できる各種レジスタの説明は、この後すぐご紹介します。

 

4.出力モードコマンド

BIT 機 能 説 明
D7 1 D7とD6両方に1を書き込むと、そのコマンドは出力モードコマンドであると認識されます。
D6 1
D5 モニタモード選択 0:初期シリーズ互換  1:拡張新シリーズ対応
D4 信号入力感度 ORG/EL/STPの各信号入力に対して、0:高感度  1:低感度
D3 加減速途中停止 0:加減速動作可能  1:加減速動作停止(加速途中で一定速にする)
D2 励磁出力マスク φ1〜4の励磁パルス出力を、0:出力する  1:マスク(全Lレベル)する
D1 パルス出力制御 +PO,-PO出力を 0:停止する  1:出力する
D0 ±PO出力論理 +PO,-PO出力を 0:負論理にする  1:正論理にする

出力モードコマンドでは、上記のように主に出力信号に関連する動作を設定します。

 

■レジスタ (レジスタセレクト)

レジスタセレクトコマンドD2〜D0で選択できるレジスタには以下のものがあり、それぞれがモータ回転の動作や特性を設定するための数値(パラメータ)となります。

D2 D1 D0 レジスタ名 説 明 ビット幅
0 0 0 R0 プリセットカウンタデータ(動作カウント数設定) 24
0 0 1 R1 FL速度設定(初期速度設定) 13
0 1 0 R2 FH速度設定(動作速度設定) 13
0 1 1 R3 加速度レート(FLからFHに加減速する時間) 10
1 0 0 R4 倍率設定(動作速度設定の倍率) 10
1 0 1 R5 スローダウンポイント設定 16
1 1 0 R6 アイドリングパルス設定
1 1 1 R7 PCD4511では未使用

それぞれのレジスタに書き込むパラメータ値は、特定の計算式や約束ごとに基づいて決定します。この後のプログラムのご紹介で簡単にご説明しますが、詳細はPCD4511のマニュアルを参照して下さい。

それぞれのレジスタは、実際のステッピングモータの動作上、以下のような部分に影響します。事例はS字加減速のプリセット動作です。

パラメータ設定を行う上で考慮する点は以下の通りです。

 

1) R0でステッピングモータが始動してから自動で停止させるまでのパルス数を設定します。48ステップ/回転のモータの場合、480パルスに設定するとちょうど10回転する計算になります。このR0プリセットカウンタと呼んでおり、あらかじめ数字をセットしておき、回転を開始して1パルスもらうごとにダウンカウントし、0になったら停止するという仕組みです。

 

2) R1はステッピングモータを回転させる上での初速度で、徐々に加速してR2の速度に達します。ステッピングモータの特性上、いきなり高回転の自起動速度を超えるパルスを与えると追従しきれずに脱調が起き、正常に回転してくれませんが、加速動作によって自起動による脱調点を超える速度で回転させることが可能になります。ただしそれにも限界があり、あまりR2を高回転に設定しすぎると脱調がおきます。その見極めは実際に回して試してみるか、メーカから公開されている特性グラフを参考に決定します。

 初速度  FL=R1 x R4

 動作速度FH=R2 x R4

 倍率R4=基準クロック周波数/(設定したい倍率 x 8192)

 

3) R6アイドリングパルスといって、いきなり初速度で回転をはじめるのではなく、低速で数パルス分動かしてあげてから初速度運転へと引き継いであげるためのもので、加速動作でスタートする際に確実に回転させるためのものです。アイドリングパルスを設定すると、スタート時に極短時間だけ若干の振動が発生します

 

4) R3加速と減速時間を設定します。加速と減速の時間は別々の数値に設定できず、共通となります。R3の設定値を求める式があり、R2−R1(初速度と動作速度の差)が十分に大きくないとR3の時間は極短い時間になってしまい、直線加速かS字加速か分からないほどになります。ただし、それでも加減速動作をしない場合に比べると、始動時と停止時に発生する衝撃は随分と違います。

 R3=(基準クロック周波数 x 加減速時間)/(R2−R1)

 

5) R5スローダウンポイントを設定します。R0プリセットカウント値からR5の設定値を引いたカウント値が減速を開始するポイントとなります。例えば、R3で減速し終わったタイミングで、R0のカウントダウン値がちょうど0になるようにR5のスローダウンポイントを設定すれば、きれいに減速→停止といった動作になります。その場合、スローダウンポイントの算出は以下の計算式になります。

 R5=((R22−R12) x R3))/(R4 x 8192) [S字加減速用]

 

詳しくはユーザーズマニュアルを参照して下さい。

【先頭に戻る】


115−2.一定速動作ソフトウエア npmstep0.c

 

では、実際のプログラム例をご紹介しましょう。先ずは最も基本的な一定速での回転プログラムです。加減速動作はなく、いきなり動作速度で始動して、プログラム上のwait()関数で計測した時間ごとに回転方向の反転を繰り返すものです。

ここをクリックするとソースプログラムをダウンロードできます。npmstep0.c

なお、今回はベストテクノロジーのGDL(GCC Developer Lite版)で記述しています。

/***********************************************************
PCD4511ステッピングコントローラテスト       RIKIYA 2003.8.31 
                                             npmstep0.c(GDL) 
一定速回転の基本的な動作

Port A      Poer B
 0:CS        OUT 0:DATA0
 1:RD        OUT 1:DATA1
 2:WR        OUT 2:DATA2
 3:A0        OUT 3:DATA3
 4:A1        OUT 4:DATA4
 5:RST       OUT 5:DATA5
 6:BUSY      IN 6:DATA6
 7:NC        OUT 7:DATA7

************************************************************/

#include <3048.h>
#include <myfunc.h>

#define CS     PA.DR.BIT.B0
#define RD     PA.DR.BIT.B1
#define WR     PA.DR.BIT.B2
#define A0     PA.DR.BIT.B3
#define A1     PA.DR.BIT.B4
#define RST    PA.DR.BIT.B5
#define BUSY   PA.DR.BIT.B6
#define DATA   PB.DR.BYTE
#define CLK    4915200

int START_CMD;         // スタートモードコマンド
int CTRL_CMD;          // 制御モードコマンド
int REG_CMD;           // レジスタセレクトコマンド
int OUT_CMD;           // 出力モードコマンド

/* メイン関数 **********************************************/
int main(void){

    PA.DDR = 0xBF;     //portA制御ポート
    PB.DDR = 0xFF;     //portB出力に設定
    RST = 0;           //RESET信号出力

    timer_init();      //wait関数用初期化
    pcd_init();        //PCD4511の初期化

    while(1){
        pcd_cw(1);     //逆転
        wait(2000);    //2秒間回転を継続
        pcd_cw(0);     //正転
        wait(2000);    //2秒間回転を継続
    }
}
/* コントローラ初期化 **************************************
定速運転設定。1000pps
************************************************************/

pcd_init(){

    CS = 1;
    RD = 1;
    WR = 1;
    A0 = 1;
    A1 = 1;

// RESET 処理
    RST = 0;
    wait(1);
    RST = 1;

// CS(CHIP SELECT)処理
    CS = 0;

// 制御モードコマンドの設定
    pcd_cmdwr(0x50);            //直線加速,OTS=1,動作+方向,プリセット無効,SD/ORG無効
    CTRL_CMD = 0x50;            //制御モードコマンドの保存

// レジスタセレクトコマンドの設定
    pcd_cmdwr(0x8C);            //外部スタートINTなし,SD_INTなし,プリセットカウント停止
                                //レジスタはR4(倍率)にしておく
    REG_CMD = 0x8C;             //レジスタセレクトコマンドの保存

// R4レジスタ(倍率)設定→2倍(300 0x012C)
    pcd_datam(0x01);            //中位バイト書き込み
    pcd_datal(0x2c);            //下位バイト書き込み

// R1レジスタ(初速度FL)設定→500pps (250 0x00FA)
    pcd_reg(1);                 //R1レジスタ選択
    pcd_datam(0x00);            //中位バイト書き込み
    pcd_datal(0xFA);            //下位バイト書き込み

// R6レジスタ(アイドリングパルス)設定→7
    pcd_reg(6);                 //R6レジスタ選択
    pcd_datal(0x07);            //下位バイト書き込み

// 出力モードコマンドの設定
    pcd_cmdwr(0xF0);            //拡張モニタ,低感度,加減速動作,励磁出力,パルス出力
    OUT_CMD = 0xF0;             //出力モードコマンドの保存

// スタートコマンドの設定
    pcd_cmdwr(0x10);            //INTなし,定速モード,外部スタートなし,FL速度

}

/* コマンドバッファ書き込み *********************************/
// DATA : 書き込みデータ
pcd_cmdwr(int cmd_data){
    A0 = 0;                     //コマンドバッファ指定
    A1 = 0;
    DATA = cmd_data;
    pcd_wr();                   //書き込み信号出力
}

/* レジスタ選択 *********************************************/
// REG : レジスタ番号0〜7の指定
pcd_reg(int reg){

    DATA = REG_CMD;             //現在のレジスタセレクトコマンドをロード

    A0 = 0;                     //コマンドバッファ指定
    A1 = 0;
    PB.DR.BIT.B7 = 1;           //D7 レジスタセレクトコマンド選択
    PB.DR.BIT.B6 = 0;           //D6
    PB.DR.BIT.B3 = 0;           //D3

    switch(reg){
        case 0:                 //R0選択
            PB.DR.BIT.B0 = 0;
            PB.DR.BIT.B1 = 0;
            PB.DR.BIT.B2 = 0;
            break;
        case 1:                 //R1選択
            PB.DR.BIT.B0 = 1;
            PB.DR.BIT.B1 = 0;
            PB.DR.BIT.B2 = 0;
            break;
        case 2:                 //R2選択
            PB.DR.BIT.B0 = 0;
            PB.DR.BIT.B1 = 1;
            PB.DR.BIT.B2 = 0;
            break;
        case 3:                 //R3選択
            PB.DR.BIT.B0 = 1;
            PB.DR.BIT.B1 = 1;
            PB.DR.BIT.B2 = 0;
            break;
        case 4:                 //R4選択
            PB.DR.BIT.B0 = 0;
            PB.DR.BIT.B1 = 0;
            PB.DR.BIT.B2 = 1;
            break;
        case 5:                 //R5選択
            PB.DR.BIT.B0 = 1;
            PB.DR.BIT.B1 = 0;
            PB.DR.BIT.B2 = 1;
            break;
        case 6:                 //R6選択
            PB.DR.BIT.B0 = 0;
            PB.DR.BIT.B1 = 1;
            PB.DR.BIT.B2 = 1;
            break;
        case 7:                 //R7選択
            PB.DR.BIT.B0 = 1;
            PB.DR.BIT.B1 = 1;
            PB.DR.BIT.B2 = 1;
            break;
    }
    pcd_wr();                   //書き込み信号出力

    REG_CMD = DATA;             //変更後のレジスタセレクトコマンドの保存

}

/* 上位データ書き込み **************************************/
// data_h : 書き込みデータ
pcd_datah(int data_h){
    A0 = 1;                    //レジスタ上位バイトの指定
    A1 = 1;
    DATA = data_h;             //上位バイトの書き込み
    pcd_wr();                  //書き込み信号出力
}

/* 中位データ書き込み **************************************/
// data_m : 書き込みデータ
pcd_datam(int data_m){
    A0 = 0;                   //レジスタ中位バイトの指定
    A1 = 1;
    DATA = data_m;            //中位バイトの書き込み
    pcd_wr();                 //書き込み信号出力
}

/* 下位データ書き込み **************************************/
// data_l : 書き込みデータ
pcd_datal(int data_l){
    A0 = 1;                   //レジスタ下位バイトの指定
    A1 = 0;
    DATA = data_l;            //下位バイトの書き込み
    pcd_wr();                 //書き込み信号出力
}

/* 方向制御 ************************************************/
// rotate : 0 → 正転、1 → 逆転
pcd_cw(int rotate){

    DATA = CTRL_CMD;          //現在の制御モードコマンドのロード

    A0 = 0;                   //コマンドバッファ指定
    A1 = 0;
    PB.DR.BIT.B7 = 0;         //D7 スタートモードコマンド選択
    PB.DR.BIT.B6 = 1;         //D6
    PB.DR.BIT.B3 = rotate;    //D3 0:正転 1:逆転
    pcd_wr();                 //書き込み信号出力

 

    CTRL_CMD = DATA;          //変更後の制御モードコマンドの保存
}

/* WR信号出力 ********************************************/
pcd_wr(){
    WR = 0;
    wait(1);
    WR = 1;                   //コマンド書き込みタイミング
    wait(1);
}

大変申し訳ありませんが、今回はプログラム各所についての詳細な説明は省略させて頂きます。

基本的にはPCD4511の各レジスタへの書き込みを順番に行っているだけの処理です。プログラム中のコメントを参考にして頂きながら、PCD4511の各レジスタ、各コマンドバッファの意味付けと照らし合わせて見て頂ければ、きっとご理解頂けると思います。(手抜きですみません...)

ちなみに、PCD4511に対するデータや制御信号は、H8のPIOポートを使っているため、リセット信号WR信号などは、wait()関数によってパルス出力タイミングを作っています。wait()関数の引数は1にしているので、パルス幅1mSとなります。PCD4511にしてみれば大きすぎるパルス幅ですが、今回は既存の関数を利用するということで妥協しています。

また、コマンドバッファではそれぞれがbitごとに独立した意味を持つため、例えば回転方向制御の関数では、関連するbit(3,6,7)だけを操作してから書き込み制御をしています。これは例えば回転方向しか変化させたくないのに、同じコマンドバッファ内の関係ないbitの設定まで面倒を見たくないからです。ところが、データバスは各コマンドバッファで共通して使用しているため、操作しなかったbitは、すぐ前に設定した違うコマンドバッファの状態が残ってしまったりしています。なので、そのままコマンドバッファに書き込むと、全く予期せぬ設定が書き込まれ、誤動作の原因となるのです。(分かりますか???)

そこで、

int START_CMD;      // スタートモードコマンド
int CTRL_CMD;       // 制御モードコマンド
int REG_CMD;        // レジスタセレクトコマンド
int OUT_CMD;        // 出力モードコマンド

というグローバル変数を設けておき、それぞれのコマンドバッファを操作する際にロードし、ロードしたデータに対して必要なbitだけの操作を行います。そして、操作して書き込みを行ったあと、セーブを行ってコマンドバッファごとに最新の状態を保存しておきます。これで汎用性の高い関数が出来ます。

 

【先頭に戻る】


115−3.S字加減速動作ソフトウエア npmstep1.c

 

次に、S字加減速を行うプログラム例をご紹介しましょう。S字加減速動作で、プリセットしたパルス数だけ回転して自動停止し、次に逆回転するという動作を5回繰り返します。ステッピングモータが自動停止したことはBSY信号の監視で検知します。プログラム自体はちょっと長めですが、イニシャル設定部分がちょっと長いだけですので、全然難しいことはありません。

ここをクリックするとソースプログラムをダウンロードできます。npmstep1.c

なお、今回もベストテクノロジーのGDL(GCC Developer Lite版)で記述しています。

/********************************************************
PCD4511ステッピングコントローラテスト    RIKIYA 2003.9.12 
                                          npmstep1.c(GDL) 
S字加減速の基本的動作

Port A        Port B
 0:CS          OUT 0:DATA0
 1:RD          OUT 1:DATA1
 2:WR          OUT 2:DATA2
 3:A0          OUT 3:DATA3
 4:A1          OUT 4:DATA4
 5:RST         OUT 5:DATA5
 6:BUSY        IN 6:DATA6
 7:NC          OUT 7:DATA7

**********************************************************/

#include <3048.h>
#include <myfunc.h>

#define CS       PA.DR.BIT.B0
#define RD       PA.DR.BIT.B1
#define WR       PA.DR.BIT.B2
#define A0       PA.DR.BIT.B3
#define A1       PA.DR.BIT.B4
#define RST      PA.DR.BIT.B5
#define BUSY     PA.DR.BIT.B6
#define DATA     PB.DR.BYTE
#define CLK      4915200

int START_CMD;                // スタートモードコマンド
int CTRL_CMD;                 // 制御モードコマンド
int REG_CMD;                  // レジスタセレクトコマンド
int OUT_CMD;                  // 出力モードコマンド

/* メイン関数 **********************************************/
int main(void){

int i;

    PA.DDR = 0xBF;            //portA制御ポート
    PB.DDR = 0xFF;            //portB出力に設定
    RST = 0;                  //RESET信号出力

    timer_init();             //wait関数用初期化
    pcd_init();               //PCD4511の初期化

    for(i=0;i<5;i++){
        while(BUSY == 0){}    //動作中次の処理を待機
        wait(500);            //500mS待機
        pcd_cw(0);            //正転
        pcd_precnt(480);      //カウント数480にセット
        pcd_start();          //スタート

        while(BUSY == 0){}    //動作中次の処理を待機
        wait(500);            //500mS待機
        pcd_cw(1);            //逆転
        pcd_precnt(960);      //カウント数960にセット
        pcd_start();          //スタート
    }
    pcd_stop();               //ストップ
    while(1){}
}

/* コントローラ初期化 ***************************************

S字加減速用の設定

*************************************************************/
pcd_init(){

    CS = 1;
    RD = 1;
    WR = 1;
    A0 = 1;
    A1 = 1;

// RESET 処理
    RST = 0;
    wait(1);
    RST = 1;

// CS(CHIP SELECT)処理
    CS = 0;

// 制御モードコマンドの設定
    pcd_cmdwr(0x74);                //S字加速,OTS=1,動作+方向,プリセット有効,SD/ORG無効
    CTRL_CMD = 0x74;                //制御モードコマンドの保存

// レジスタセレクトコマンドの設定
    pcd_cmdwr(0x80);                //外部スタートINTなし,SD_INTなし,プリセットカウント動作
//レジスタはR0にしておく
    REG_CMD = 0x80;                 //レジスタセレクトコマンドの保存

// R4レジスタ(倍率)設定→2倍(300 0x012C)
    pcd_reg(4);                     //R4レジスタ選択
    pcd_datam(0x01);                //中位バイト書き込み
    pcd_datal(0x2c);                //下位バイト書き込み

// R1レジスタ(初速度FL)設定→50pps (25 0x0019)
    pcd_reg(1);                     //R1レジスタ選択
    pcd_datam(0x00);                //中位バイト書き込み
    pcd_datal(0x19);                //下位バイト書き込み

// R6レジスタ(アイドリングパルス)設定→0
    pcd_reg(6);                     //R6レジスタ選択
    pcd_datal(0x00);                //下位バイト書き込み

// 出力モードコマンドの設定
    pcd_cmdwr(0xF0);                //拡張モニタ,低感度,加減速動作,励磁出力,パルス出力
    OUT_CMD = 0xF0;                 //出力モードコマンドの保存

/* S字加減速パラメータの設定 *************************/

// R2レジスタ(動作速度FH)設定→500pps (250 0x00FA)
    pcd_reg(2);                     //R2レジスタ選択
    pcd_datam(0x00);                //中位バイト書き込み
    pcd_datal(0xFA);                //下位バイト書き込み

// R3レジスタ(加減速レート)設定→0.468s (1023 0x03FF)
    pcd_reg(3);                     //R3レジスタ選択
    pcd_datam(0x03);                //中位バイト書き込み
    pcd_datal(0xFF);                //下位バイト書き込み

// R5レジスタ(スローダウンポイント)設定→25パルス (0x0019)
    pcd_reg(5);                     //R5レジスタ選択
    pcd_datam(0x00);                //中位バイト書き込み
    pcd_datal(0x19);                //下位バイト書き込み


// スタートコマンドの設定
    pcd_cmdwr(0x05);                //INTなし,高速モード,外部スタートなし,FH速度
    START_CMD = 0x05;               //スタートモードコマンドの保存

}

/* コマンドバッファ書き込み ****************************/
// DATA : 書き込みデータ
pcd_cmdwr(int cmd_data){
    A0 = 0;                         //コマンドバッファ指定
    A1 = 0;
    DATA = cmd_data;
    pcd_wr();                       //書き込み信号出力
}

/* レジスタ選択 ****************************************/
// REG : レジスタ番号0〜7の指定
pcd_reg(int reg){

    DATA = REG_CMD;                 //現在のレジスタセレクトコマンドをロード

    A0 = 0;                         //コマンドバッファ指定
    A1 = 0;
    PB.DR.BIT.B7 = 1;               //D7 レジスタセレクトコマンド選択
    PB.DR.BIT.B6 = 0;               //D6 
    PB.DR.BIT.B3 = 0;               //D3

    switch(reg){
        case 0:                     //R0選択
            PB.DR.BIT.B0 = 0;
            PB.DR.BIT.B1 = 0;
            PB.DR.BIT.B2 = 0;
            break;
        case 1:                     //R1選択
            PB.DR.BIT.B0 = 1;
            PB.DR.BIT.B1 = 0;
            PB.DR.BIT.B2 = 0;
            break;
        case 2:                     //R2選択
            PB.DR.BIT.B0 = 0;
            PB.DR.BIT.B1 = 1;
            PB.DR.BIT.B2 = 0;
            break;
        case 3:                     //R3選択
            PB.DR.BIT.B0 = 1;
            PB.DR.BIT.B1 = 1;
            PB.DR.BIT.B2 = 0;
            break;
        case 4:                     //R4選択
            PB.DR.BIT.B0 = 0;
            PB.DR.BIT.B1 = 0;
            PB.DR.BIT.B2 = 1;
            break;
        case 5:                     //R5選択
            PB.DR.BIT.B0 = 1;
            PB.DR.BIT.B1 = 0;
            PB.DR.BIT.B2 = 1;
            break;
        case 6:                     //R6選択
            PB.DR.BIT.B0 = 0;
            PB.DR.BIT.B1 = 1;
            PB.DR.BIT.B2 = 1;
            break;
        case 7:                     //R7選択
            PB.DR.BIT.B0 = 1;
            PB.DR.BIT.B1 = 1;
            PB.DR.BIT.B2 = 1;
            break;
    }
    pcd_wr();                       //書き込み信号出力

    REG_CMD = DATA;                 //変更後のレジスタセレクトコマンドの保存
}

/* 上位データ書き込み **************************/
// data_h : 書き込みデータ
pcd_datah(int data_h){
    A0 = 1;                        //レジスタ上位バイトの指定
    A1 = 1;
    DATA = data_h;                 //上位バイトの書き込み
    pcd_wr();                      //書き込み信号出力
}

/* 中位データ書き込み **************************/
// data_m : 書き込みデータ
pcd_datam(int data_m){
    A0 = 0;                       //レジスタ中位バイトの指定
    A1 = 1;
    DATA = data_m;                //中位バイトの書き込み
    pcd_wr();                     //書き込み信号出力
}

/* 下位データ書き込み **************************/
// data_l : 書き込みデータ
pcd_datal(int data_l){
    A0 = 1;                       //レジスタ下位バイトの指定
    A1 = 0;
    DATA = data_l;                //下位バイトの書き込み
    pcd_wr();                     //書き込み信号出力
}

/* R0 プリセットカウンタ設定 ********************************/
// precnt : long型プリセットカウント値
pcd_precnt(long precnt){
long dummy;

    pcd_reg(0);                          //R0レジスタ選択

    pcd_datah(0);                        //上位バイト書き込み 強制0固定

    dummy = (precnt >> 8) & 0x000000FF;  //中位データの抽出
    pcd_datam((int)dummy);               //中位バイト書き込み

    dummy = precnt & 0x000000FF;         //下位データの抽出
    pcd_datal((int)dummy);               //下位バイト書き込み
}

/* スタート制御 ********************************************/
// 
pcd_start(){

    DATA = START_CMD;              //現在のスタートモードコマンドのロード

    A0 = 0;                        //コマンドバッファ指定
    A1 = 0;
    PB.DR.BIT.B7 = 0;              //D7 スタートモードコマンド選択
    PB.DR.BIT.B6 = 0;              //D6
    PB.DR.BIT.B3 = 0;              //D3 ストップ制御 OFF
    PB.DR.BIT.B4 = 1;              //D4 スタート制御 ON
    pcd_wr();                      //書き込み信号出力

    START_CMD = DATA;              //変更後のスタートモードコマンドの保存
}

/* ストップ制御 ********************************************/
// 
pcd_stop(){

    DATA = START_CMD;              //現在のスタートモードコマンドのロード

    A0 = 0;                        //コマンドバッファ指定
    A1 = 0;
    PB.DR.BIT.B7 = 0;              //D7 スタートモードコマンド選択
    PB.DR.BIT.B6 = 0;              //D6
    PB.DR.BIT.B3 = 1;              //D3 ストップ制御 ON
    PB.DR.BIT.B4 = 0;              //D4 スタート制御 OFF
    pcd_wr();                      //書き込み信号出力

    START_CMD = DATA;              //変更後のスタートモードコマンドの保存
}

/* 方向制御 ********************************************/
// rotate : 0 → 正転、1 → 逆転
pcd_cw(int rotate){

    DATA = CTRL_CMD;               //現在の制御モードコマンドのロード

    A0 = 0;                        //コマンドバッファ指定
    A1 = 0;
    PB.DR.BIT.B7 = 0;              //D7 制御モードコマンド選択
    PB.DR.BIT.B6 = 1;              //D6
    PB.DR.BIT.B3 = rotate;         //D3 0:正転 1:逆転
    pcd_wr();                      //書き込み信号出力

    CTRL_CMD = DATA;               //変更後の制御モードコマンドの保存
}

/* WR信号出力 ********************************************/
pcd_wr(){
    WR = 0;
    wait(1);
    WR = 1;                        //コマンド書き込みタイミング
    wait(1);
}


大変申し訳ありませんが、これもプログラム各所についての詳細な説明は省略させて頂きます。

ひとつ前にご紹介している一定速度回転用のプログラムをS字加減速用の設定に追加変更し、制御用の関数をいくつか追加したものです。PCD4511のパラメータを設定するための関数は、全てこのプログラム後半に記載されていますので、内容についてはコメントを参考にしながらご覧下さい。

プログラムの内容的には大した事は無いのですが、PCD4511の各コマンドバッファや各レジスタへの設定(イニシャル処理)部分が少し煩雑になってしまいました。LSIのパッケージ自体を小さくしていることもあり、データバスにアドレス選択的な要素も含ませている点や、最大24ビット幅のデータを3分割して書き込むなどの処理が必要になっているためです。

ただし、これらの設定を行うための環境(関数類)を整備してしまえば、あとのメインとなる処理は、簡単なものだと思います。

【先頭に戻る】


115−4.実験風景

左の写真は実験風景です。PCD4511パルスモータ制御ボードAKI-H8小型マザーボードでコントロールしています。

114.ステッピングモータを動かすの実験回路で駆動している時よりも、安定して振動も少ない気がします。

加減速制御なしで反復動作を行うよりも、加減速動作ありで反復動作を行ったほうが、発生する反動が小さくなる様子が良く分かります。

 

【先頭に戻る】


今回の実験では、PCD4511からデータを読み出す動作までは行いませんでした。なにか高度な処理が必要な場合にはトライしようと思いますが、当面はデータの書き込みだけで十分そうです。

これで一応、ユニポーラ型ステッピングモータをまともに動かす環境が整いましたが、知れば知るほど、ステッピングモータ自体の選定の難しさを感じています。それは、もともと高回転が不得意で、発生トルクの小さなステッピングモータから、いかに高トルク、高レスポンスを引き出すか、という点に尽きます。更に出来るだけ小型であるという条件が入りますので、なかなか難題です。

しかし、ステッピングモータというアクチュエータにどこか魅力を感じます。もう少し突っ込んで検討し、ロボット駆動のためにモノにしたいと思っています。(^^;

 

【ソフトウエア編TOPに戻る】


【表紙に戻る】