マルチタスク化

並列タスク化してみたが、並列タスクと関数化の違いがいまいちわからない
while true 文の中にPRECEDES TASKを入れることができないのも不明。
シングルタスクをWHILEの中に入れることができるか明日試す。
TASK先でWHILE TRUEするしか無いのか?

#define TIME 500

int status = 0;


task kount(){
NumOut(60,LCD_LINE3,status);
if(Sensor(IN_1)==1){

status = status + 1 ;

}
Wait(100);
}


task forward(){
if(status==1){
OnRev(OUT_C,40);

OnRev(OUT_A,40);
Wait(100);
}
else{
OnFwd(OUT_C,40);

OnFwd(OUT_A,40);
Wait(100);

}
}

task main()

{SetSensorColorRed(IN_2);

SetSensorTouch(IN_1);

SetSensorTouch(IN_4);


while(true){
Precedes(kount,forward);

}
}

NXCにおける関数化

いまさらながら各定義をタスクメイン内でやっていたなど
読みにくいコードで今までやっていたことに気がつく。
さらに高度なコードを書けるようになるべく関数化に挑戦。
inline void と頭につければよいらしい、
変数を内部で使用する際には宣言が必要とNXTチュートリアル和訳版には書いてあるが
そんな事しないでも手元のnxc1.2.1r2.0では何故か関数内でintが使えた。
あとinlineをつけないときの挙動は不明。

以下はセンサー1につけたタッチセンサーを押すと挙動が変わるトレースカー

#define TIME 500

int status = 0;


inline void kount(){
NumOut(60,LCD_LINE3,status);
if(Sensor(IN_1)==1){

status = status + 1 ;

}
Wait(100);
}


inline void forward(){
if(status==1){
OnRev(OUT_C,40);

OnRev(OUT_A,40);
Wait(100);
}
else{
OnFwd(OUT_C,40);

OnFwd(OUT_A,40);
Wait(100);

}
}

task main()

{SetSensorColorRed(IN_2);

SetSensorTouch(IN_1);

SetSensorTouch(IN_4);


while(true){
kount( );
forward( );

}
}

ライントレースとレゴpidについてまとめ。

今日までpid制御まとめて見たがこれでひと段落としたい。床にニチバン黒テープをはってライントレースして見たが、制度としては今ひとつなままで終わった。
ライントレーサーを単眼の光センサーで追う場合はこのへんが限界なのではないか。
pid制御で黒線を追う場合、やはりラインインのときとラインアウトの差が急激過ぎてほとんどオンオフ制御との差が見受けられなかった。むしろ急激なラインインらいんあうとのためD制御が邪魔になってるくさい。
ライントレースをpid制御でする際に有効であるためには条件がいると思う。
・線分はグラデーションのあるものであること。これはラインからどの程度離れているかが常時識別できないと比例成分をどの程度しゅっりょくしてよいかわからないためである。
ピーアイデイー制御は目標値と現在出力との差が常に明確でないとうまく機能しないのではないか。
黒線ライントレースのようなものが対象である場合は黒線を識別しなくなった時間からに対してステアリング角を比例させた法がいいのではないか?つまり黒線を見失う時間が長ければ長いほど急角度で線にもどろうとするような。

今日のPIDレシピ

今日のレシピ
スタンダード値28
P 1,8
I 0.5
D 0.01
が一番まとも
スタンダード値10から19程度で(つまり黒線とおなじ)で試してみたが
この程度を目標値とするとまっすぐの線にしか対応できない。右か左にしか片一方しか行かない、
臨機応変に対応できないマシーンになる。

PID値をめぐるはてしない物語 NXT 本体ボタン編 if(ButtonPressed(BTNRIGHT, false)){

PID値をいちいち入力してコンパイルしているのめんどくさいからNXT本体のボタンを押すと数値を追加するようにした。
buttonpressed文について説明しているページはグーグルが日本語でキャッシュしているページにはない。
nxc チュートリアルページをみて格闘40分出来ました。
いままでNXT本体のボタンを使った自販機のLEGOとかどのようにしていたのか気になっていたがコレでクローンコピーが出来る。なにより、タッチセンサーを新たに購入する必要が無くなったためコレは大きいと思う。

しかしボタンを押したときの構文をはっけんすることすらこんなにかかる!!
NXC職人は日本にはいないのか?

↓から類推するの大変だった。
Constants to specify which button to use with button module functions. More...

Defines

#define BTN1 0
#define BTN2 1
#define BTN3 2
#define BTN4 3
#define BTNEXIT BTN1
#define BTNRIGHT BTN2
#define BTNLEFT BTN3
#define BTNCENTER BTN4
#define NO_OF_BTNS 4

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@


task main()

{SetSensorColorRed(IN_2);

SetSensorTouch(IN_1);

SetSensorTouch(IN_4);

#define TIME 100

int standerd=20;//変数standerdに白黒の中点を入力するこれは以後の出力の基準点となる

float POW;

int currentsensor;

int previoussensor;

float kp=0.5;

float ki;

float kd=0;

float P;

float I;

float D;


previoussensor=Sensor(IN_2);//エラーを防ぐためセンサー値を初期化してからループ

while(true){


NumOut(60,LCD_LINE1,SENSOR_2);//ディスプレイにセンサー2の数値を表示
NumOut(60,LCD_LINE2,standerd);

NumOut(60,LCD_LINE3,kp);//ディスプレイにkpの数値を表示
NumOut(60,LCD_LINE4,ki);
NumOut(60,LCD_LINE5,kd);//ディスプレイにkdの数値を表示


if(ButtonPressed(BTNLEFT, false)){
standerd = standerd + 1 ;
}

if(ButtonPressed(BTNRIGHT, false)){
kp = kp + 0.1 ;
}


if(Sensor(IN_1)==1){

ki = ki + 0.1 ;

}

if(Sensor(IN_4)==1){

kd = kd + 0.01 ;

}


currentsensor=Sensor(IN_2);//現在の光量を計測する

P=(currentsensor-standerd)*kp;
I=*1/2*0.1;
D=*2/0.1*kd;

POW =P + I+ D;

OnFwd(OUT_C,40 - POW);

OnFwd(OUT_A,40 + POW);

Wait(TIME);

previoussensor=currentsensor;//モータ出力後現在の値を過去の値に代入し塗り替える

}}

*1:currentsensor-standerd)+ (previoussensor-standerd

*2:currentsensor-standerd)- (previoussensor-standerd

PID構文

エンデのはてしない物語みたいになってきた。
値が見つかりません。



task main()

{SetSensorColorRed(IN_2);

SetSensorTouch(IN_1);

SetSensorTouch(IN_4);

#define TIME 100

int standerd=27;//変数standerdに白黒の中点を入力するこれは以後の出力の基準点となる

float POW;

int currentsensor;

int previoussensor;

float kp=1.6;

float ki;

float kd=0;

float P;

float I;

float D;


previoussensor=Sensor(IN_2);//エラーを防ぐためセンサー値を初期化してからループ

while(true){


NumOut(60,LCD_LINE5,SENSOR_2);//ディスプレイにセンサー2の数値を表示

NumOut(60,LCD_LINE6,kp);//ディスプレイにkpの数値を表示
NumOut(60,LCD_LINE7,ki);
NumOut(60,LCD_LINE8,kd);//ディスプレイにkdの数値を表示

if(Sensor(IN_1)==1){

ki = ki + 0.1 ;

}

if(Sensor(IN_4)==1){

kd = kd + 0.01 ;

}


currentsensor=Sensor(IN_2);//現在の光量を計測する

P=(currentsensor-standerd)*kp;
I=*1/2*0.1;
D=*2/0.1*kd;

POW =P + I+ D;

OnFwd(OUT_C,40 - POW);

OnFwd(OUT_A,40 + POW);

Wait(TIME);

previoussensor=currentsensor;//モータ出力後現在の値を過去の値に代入し塗り替える

}}

*1:currentsensor-standerd)+ (previoussensor-standerd

*2:currentsensor-standerd)- (previoussensor-standerd

PD制御文

PD制御分のD値を前回の光センサー値と今回の光センサー値の差としてたところを
前回のP値と今回のP値の差とした。
公式上はこちらが正しいのである。
しかしD値は結局変化量であるから意味がそんなに変わっていると思えないが・・・挙動がどの程度変わるか不明。

目標値30
P値1.6〜2,2くらいでいい感じ

task main()

{SetSensorColorRed(IN_2);

SetSensorTouch(IN_1);

SetSensorTouch(IN_4);

#define TIME 50

int standerd=25;//変数standerdに白黒の中点を入力するこれは以後の出力の基準点となる

float POW;

int currentsensor;

int previoussensor;

float kp=1;

int ki;

float kd=0.5;

float P;

int I;

float D;


previoussensor=Sensor(IN_2);//エラーを防ぐためセンサー値を初期化してからループ

while(true){


NumOut(60,LCD_LINE6,SENSOR_2);//ディスプレイにセンサー2の数値を表示

NumOut(60,LCD_LINE7,kp);//ディスプレイにkpの数値を表示

NumOut(60,LCD_LINE8,kd);//ディスプレイにkdの数値を表示

if(Sensor(IN_1)==1){

kp = kp + 0.1 ;

}

if(Sensor(IN_4)==1){

kd = kd + 0.1 ;

}


currentsensor=Sensor(IN_2);//現在の光量を計測する

P=(currentsensor-standerd)*kp;

D=*1*
kd;

POW =P - D;

OnFwd(OUT_C,40 - POW);

OnFwd(OUT_A,40 + POW);

Wait(TIME);

previoussensor=currentsensor;//モータ出力後現在の値を過去の値に代入し塗り替える

}}

*1:currentsensor-standerd)- (previoussensor-standerd