制御工学 I 前期中間試験問題 June2005 担当小坂 次のプログラムは,H8 モータ実験装置で位置フィードバック + 速度フィードバックを使って, モータ軸をある角度だけ回転させて止めようとするプログラムである 後の問いに答えなさい 001 /********************************************************** 002 プログラムの説明 003 位置フィードバックと速度フィードバックを使ったモータ制御 by Kosaka 13Feb2005 004 **********************************************************/ 005 #include "h8-01.h" 006 #include "motorsys.h" 007 008 #define PWM_MAX 00 009 #define RBUFFSIZE 16 /*0x=16*/ 0 #define RBUFFMASK 0xf /*0x0f=15*/ 011 012 volatile int x; /* 割り込み時位置 */ 013 volatile int v; /* 位置差分 ( 速度 )*/ 014 volatile int pwmvalue; /* モータ PWM 指令値 */ 015 volatile int requestdisplaydata; /* 表示要求 0: 表示要求なし 1: あり */ 016 volatile int timecounter; /* 制御開始時刻からの時間 [msec]*/ 017 int tick; /* 表示を msec ごとにするための変数 */ 018 int ringbuffer[rbuffsize]; /* 速度測定のための割り込み時位置の履歴 */ 019 int currentpointer; /* リングバッファで現時点を指すポインタ */ 020 int previouspointer; /* リングバッファで 周期前を指すポインタ */ 021 022 int theposition; /* モータを停止する位置 */ 023 /*( ロータリエンコーダのカウンタ値 )*/ 024 int kpro_8; /* 位置フィードバック係数 8 倍値 */ 025 int kvel_8; /* 速度フィードバック係数 8 倍値 */ 026 027 /* ほかに必要なグローバル変数があったらこの位置に追加すること */ 028 029 void setdefaultconstants(void) 030 /* ここではあらかじめ決めておかなければならない値を規定値に設定する */ 031 { 032 theposition=500; 033 kpro_8=80; 034 kvel_8=32; 035 SCI1_printf("\n"); 036 SCI1_printf("the Position that motor should stop =%5d\n",thePosition); 037 SCI1_printf("Proportional Feedback Coefficient (*8) =%5d\n",kpro_8); 038 SCI1_printf("Velocity Feedback Coefficient (*8) =%5d\n",kvel_8); 039 /* ほかに必要な設定があったらこの位置に追加すること */ 040 } 041 042 void setconstants(void) 043 /* ここではあらかじめ決めておかなければならない値を設定する */ 044 { 045 SCI1_printf("\n"); 046 SCI1_printf("the Position that motor will stop =%5d\n",thePosition); 047 SCI1_printf("Proportional Feedback Coefficient (*8) =%5d\n",kpro_8); 048 SCI1_printf("Velocity Feedback Coefficient (*8) =%5d\n",kvel_8); 049 theposition=getintsci1("input theposition (-500..500)--> "); 050 kpro_8= getintsci1("input Prop F. C. *8 ( 0..0)--> "); 051 kvel_8= getintsci1("input Velc F. C. *8 ( 0..0)--> "); 052 /* ほかに必要な設定があったらこの位置に追加すること */ 053 } 054 055 void initvariable(void) 056 /* ここで変数を初期化する */ 1/5
057 { 058 int i; 059 timecounter=0; 060 pwmvalue=0;x=0;v=0; 061 requestdisplaydata=1; 062 tick=1; 063 for (i=0; i<rbuffsize; i++) { 064 ringbuffer[i]=0; 065 } 066 currentpointer=; 067 previouspointer=0; 068 /* ほかに必要な設定があったらこの位置に追加すること */ 069 } 070 071 void controlmotor(void) 072 /* モータ駆動を行い, シリアル通信で駆動状況を表示する */ 073 { 074 SCI1_printf("\n"); 075 SCI1_printf("the Position that motor should stop =%5d\n",thePosition); 076 SCI1_printf("Proportional Feedback Coefficient (*8) =%5d\n",kpro_8); 077 SCI1_printf("Velocity Feedback Coefficient (*8) =%5d\n",kvel_8); 078 initvariable(); 079 clearphasecounter(); /* counter(ituch2) クリア */ 080 SCI1_printf("Time(msec), PWMvalue, Position, Velocity(per5[ms])\n"); 081 E_INT(); /* CPU 割り込み許可 */ 082 starttimer1(); /* 割り込みカウンタスタート */ 083 do { 084 if (requestdisplaydata) { 085 SCI1_printf("%3d,%4d,%4d,%3d\n",timecounter,pwmvalue,x,v); 086 requestdisplaydata=0; /* 表示要求の解除 */ 087 } 088 } while(timecounter<=00); 089 stoptimer1(); /* 割り込タイマストップ */ 090 D_INT(); /* 割り込み禁止 */ 091 drivemotor(0); 092 } 093 094 main() 095 { 096 int key=-1; 097 initsci1(); /*SCI1 初期化 */ 098 initphasecounter(); /*Rotaryencoder counter ITUch2 初期化 */ 099 init_pwm3(pwm_max); /*PWM の初期設定 */ 0 inittimer1int(500); /* 500μsec ごとの割り込み関数起動を設定 */ 1 setdefaultconstants(); 2 while (1) { 3 SCI1_printf("\n\n*** "); 4 SCI1_printf("Motor Driving with step response"); 5 SCI1_printf(" ***\n"); 6 SCI1_printf("1 set constants\n"); 7 SCI1_printf("2 execute!!\n"); 8 do {key=getcharsci1();} while(key<'1' '2'<key); 9 if (key=='1') setconstants(); /*PWM 値と駆動時間の設定 */ 1 else if (key=='2') controlmotor(); /* モータ制御動作実行 */ 111 } 112 } 113 114 void interrupt_cfunc() /* 割り込みルーチンこの関数名は固定 */ 115 { 116 long int value; 117 x=getphasecounter(); /* 位相カウンタ ( ロータリエンコーダ ) の読み出し */ 2/5
118 ringbuffer[currentpointer]=x; 119 v=x-ringbuffer[previouspointer];/* 位置の 5ms 間の増分 ( 速度に対応 ) を求める */ 120 121 /* モータへの PWM 指令値の送出 */ 122 /* この位置で pwmvalue の値を決める */ 123 /*pwmvalue の値を決めるのに考慮するものは, 現時刻の変位 x と速度 v とする */ 124 value=((long)kpro_8*(long)(theposition-x)-(long)kvel_8*(long)v)>>3; 125 if (PWM_MAX<value) pwmvalue=pwm_max; 126 else if (value<-pwm_max) pwmvalue=-pwm_max; 127 else pwmvalue=value; 128 drivemotor(pwmvalue); /* モータ指令値出力 */ 129 130 currentpointer=(currentpointer+1)&rbuffmask; 131 previouspointer=(previouspointer+1)&rbuffmask; 132 tick++; 133 if (tick==20) { 134 timecounter+=; /*500μsec の割り込み周期なので 20 周期で msec*/ 135 requestdisplaydata=1;/* 表示要求 */ 136 tick=0; 137 } 138 } 1. このプログラムで PWM 周期は何 ms に設定されているか 2. このプログラムで割り込み周期は何秒か また,1 秒間に, 何回割り込み関数が起動していると考えられるか 3.085 行ではロータリエンコーダのカウント値などの表示を行なっているが, 表示の周期は何秒か 4.085 行によるロータリエンコーダのカウント値などの 1 行分の表示では, 何バイトのデータが送信されているか ただし改行には 2 バイトが必要である またこの 1 行分データの送信にかかる時間は,38400baud の通信速度 (3840byte/sec) で,CPU が通信に専念しているとすると, 何秒ほどになると推定されるか 通信時間以外は時間はかからないと仮定しなさい 5. もし,main() 中の割り込み周期の設定部分 (0 行 ) を inittimer1int(200); /* 200μsec ごとの割り込み関数起動を設定 */ と変更し, さらに割り込み関数中の tick に関する if 文 (133 行 ) if (tick==20) { を if (tick==0) { と変更したら, ロータリエンコーダのカウント値などの表示の周期は何秒になるか 6. タイマ割り込み関数内で次の作業を行うと, 変数の値はどのように変化するか説明しなさいただし, 変数 myvar はグローバルの int 型変数で初期値は 0 とする 解答では要点をはずさず, 採点者に自分は理解できていることを示しなさい myvar=(myvar+1)&15; 7. タイマ割り込み関数内で次の作業を行うと, 変数の値はどのように変化するか説明しなさい ただし, 変数 myvar はグローバルの int 型変数で初期値は 0 とする 解答では要点をはずさず, 採点者に自分は理解できていることを示しなさい myvar=(myvar+1)&127; 3/5
8. タイマ割り込み関数内で次の作業を行うと, 変数の値はどのように変化するか説明しなさい ただし, 変数 myvar はグローバルの int 型変数で初期値は 0 とする 解答では要点をはずさず, 採点者に自分は理解できていることを示しなさい myvar=(myvar+1)&99; 9. タイマ割り込み関数内で v=x-ringbuffer[previouspointer]; を使って,5msec 間のカウンタ値の増分を求めているが,20msec 間のカウンタ値の増分を求めるように変更したい どの行をどのように変更すればよいか答えなさい ただし, 割り込み周期を変更せずに, 次のような変更を行う (a)#define を 2 行変更 (b) 関数 void initvariable(void) を 1 箇所変更 (c) このままでは速度表示にうそが表示されてしまうので, 関数 void controlmotor(void) 内でもう一箇所変更. モータの位置決め制御で次の問いに答えなさい ただし, x は角度の現在位置で, モータへの指令値 y は M y M ( 0 M ) で 0 y の時モータは正回転, y 0 の時は逆回転し, 絶対値が大きいほどモータへの供給電圧を上げることに対応することとする k は正の定数である また各式はある時刻のモータ軸の角度と指令値の関係を示すものとする また関数 clip( x, A), (0 A) は次式の関数とする A A clip( x, A) x A A A x A 制御則は次の 8 種類を考えることとし, 時刻 0 において初期角度は x l, 目標値 ( 目標角度 ) は x l, (0 l) の時, 次の 8 つの制御則で起動すると, それぞれどのような動作となるか すべての制御則が正しい制御を保証しているわけではない M l M l 1) y 2) y M l M ) l l ), M ) l 3) y 4) y M ) l l ), M ) l 5) y 6) y l ), M ) l M ) l 7) y clip( l ), M ) 8) y clip( M ) 11. 位置フィードバック係数 kp と速度フィードバック係数 kv の役割を次の中から選びなさい ただしモータ指令値制御規則は次のようになっているものとする y clip( k p ( l ) kv x, M ) x は速度を表す (1) 位置フィードバック係数 kp (2) 速度フィードバック係数 kv (a) 速度の絶対値を大きくする役割 (b) 目標値に向けて動くように指令を与える役割 (c) 速度の絶対値を小さくする役割 (d) 速度を絶えず負に保つ役割 (e) 目標値が正なら正方向に,, 負なら負方向に動くように指令を与える役割 (f) 速度を常に正に保つ役割 4/5
1 0.0625ms 制御工学 I 前期中間試験 制御工学 I 前期中間試験解答用紙 (4J )( ) 2 0.0005s 2000 回 / 秒 3 0.01s 4 19 バイト 0.00495s 5 0.02s 6. myvar は 0 から始まり,1,2,3,...,15 まで増加し, 再び 0 に戻る この動作を繰り返す 7. myvar は 0 から始まり,1,2,3,...,127 まで増加し, 再び 0 に戻る この動作を繰り返す 8. myvar は 0 から始まり,1,2,3 まで増加し, 再び 0 に戻る この動作を繰り返す 9. #define RBUFFSIZE 64 #define RBUFFMASK 0x3f currentpointer=40 per20ms (1) 目標値に向けて全力で進む 目標値を行き過ぎたら全力で戻る 再び目標値を行き過ぎたら全力で戻る という動作を繰り返し, 振動を続ける (2) 目標値に向けて全力で進む 目標値を行き過ぎたら, 指令値は0になり惰性でそのまま同方向に回転し, そのうち目標値から離れたところで止まる 逆向きに加速し, そのまま全力で目標値と反対方向に離れていく 止まらない (3) (4) 目標値に向けて最初は全力で進む 目標値に近づくにつれて, 指令値は弱まり, 目標値を過ぎると指令値は0になり惰性でそのまま同方向に回転し, そのうち目標値から離れて止まる (3) と同じ (5) (4) と同じ (6) (7) 目標値に向けて最初は全力で進む 目標値に近づくにつれて, 指令値は弱まり, 目標値を過ぎると逆向きに動く 指令値は目標値からの距離に比例しているので, 目標値の直近で停止 (3) と同じ (8) 11 (1) b (2) c 5/5