LEGO® MINDSTORMS™でつくるラジコンカー


専攻科 制御情報システム工学専攻 瀬川 博貴


1.作成方法

本体の作成

1. 本体の作り方はLEGO® MINDSTORMS™の付属マニュアルに記載されています。

2. 1.の通りに土台部分(RCXを取り付ける前まで)だけを作ります。--- 図1(高解像度)参照

図1

3. 次にRCXの首振り機構を作ります。--- 図2(高解像度)参照

図2

4. 首振り機構を別の角度から見るとこのような感じです。--- 図3(高解像度)参照, 図4(高解像度)参照

図3 図4

5. 首振り機構を本体に取り付けます。--- 図5(高解像度)参照

図5

6. RCXの方にこの軸受けを作ります。--- 図6(高解像度)参照, 図7(高解像度)参照

図6 図7

7. RCXに取り付けた軸受け部(緑)と本体から突き出ている軸を結合します。

8. ケーブルを垂らすための機構を先端に取り付けて完成です。--- 図8(高解像度)参照

図8

コントローラの作成

1. コントローラはNQCチュートリアル内の「赤外線通信その1」を参照してください。

3. 今回使用したコントローラはこんな感じです。--- 図9(高解像度)参照, 図10(高解像度)参照

図9 図10

2.配線方法

本体の場合

ポートA:右のモータ

ポートB:左のモータ

ポートC:RCX回転用モータ

ポート1:ロータリーセンサー

コントローラの場合

ポート1:左検出用タッチセンサ

ポート2:右検出用タッチセンサ

ポート3:ロータリーセンサー

3.プログラム

**ファームウェアはbrickos-0.9.0を使用しています。**

本体用プログラム --- rccar.c

/*戦車*/
#include<lnp/lnp.h>
#include<conio.h>
#include<unistd.h>
#include<dsensor.h>
#include<dmotor.h>

int stop();
int drive();
wakeup_t rt_dr_wakeup(wakeup_t data);
wakeup_t rs_r_wakeup(wakeup_t data);
wakeup_t rs_l_wakeup(wakeup_t data);
tid_t t_stop, t_drive;

int main(int argc, char *argv[]) {
    cputs("on");
    t_stop = execi(&stop, 0, NULL, 100, DEFAULT_STACK_SIZE); // make stop task
    t_drive = execi(&drive, 0, NULL, 50, DEFAULT_STACK_SIZE); // make drive task
    return 0;
}

int stop(){ // rcx stop function
    int stopchar;
    stopchar = getchar();
    if(stopchar == KEY_RUN || stopchar == KEY_ONOFF){
        cputs("stop");
        killall(100);
        msleep(5000);
    }
    else{}
    return 0;
}

int drive(){ // drive function
    char getmsg;
    int count = 0;
    int rotation = 0;
    
    ds_active(&SENSOR_1);
    ds_rotation_on(&SENSOR_1);
    ds_rotation_set(&SENSOR_1, 0);
    
    while(1){
        wait_event(&rt_dr_wakeup, 0); //wait for lnp_rcx_message
        getmsg = lnp_rcx_message;
        clear_msg();
        //motor a = right
        //motor b = -left
        rotation = ROTATION_1;
        if(getmsg == 'a'){ //fwd
            motor_a_speed(MAX_SPEED);
            motor_b_speed(MAX_SPEED);
            motor_a_dir(fwd);
            motor_b_dir(rev);
        }
        else if(getmsg == 'b'){ //back
            motor_a_speed(MAX_SPEED);
            motor_b_speed(MAX_SPEED);
            motor_a_dir(rev);
            motor_b_dir(fwd);
        }
        else if(getmsg == 'c'){ // left + fwd
            motor_a_speed(MAX_SPEED);
            motor_b_speed(0);
            motor_a_dir(fwd);
            motor_b_dir(rev);
        }
        else if(getmsg == 'd'){ // left + back
            motor_a_speed(MAX_SPEED);
            motor_b_speed(0);
            motor_a_dir(rev);
            motor_b_dir(fwd);
        }
        else if(getmsg == 'e'){ // left
            count++;
            motor_a_speed(MAX_SPEED);
            motor_b_speed(MAX_SPEED);
            motor_a_dir(fwd);
            motor_b_dir(fwd);
            /*************/
            if(count >= 5){
                motor_c_speed(MAX_SPEED);
                motor_c_dir(fwd);
                //rotation = ROTATION_1;
                //wait_event(&rs_l_wakeup, rotation);
                msleep(80);
                motor_c_dir(off);
                count = 0;
            }
            /*************/
        }
        else if(getmsg == 'f'){ // right + fwd
            motor_a_speed(0);
            motor_b_speed(MAX_SPEED);
            motor_a_dir(fwd);
            motor_b_dir(rev);
        }
        else if(getmsg == 'g'){ // right + back
            motor_a_speed(0);
            motor_b_speed(MAX_SPEED);
            motor_a_dir(rev);
            motor_b_dir(fwd);
        }
        else if(getmsg == 'h'){ // right
            count--;
            motor_a_speed(MAX_SPEED);
            motor_b_speed(MAX_SPEED);
            motor_a_dir(rev);
            motor_b_dir(rev);
            /*************/
            if(count <= -5){
                motor_c_speed(MAX_SPEED);
                motor_c_dir(rev);
                //rotation = ROTATION_1;
                //wait_event(&rs_r_wakeup, rotation);
                msleep(80);
                motor_c_dir(off);
                count = 0;
            }
            /*************/
        }
        else{
            motor_a_dir(off);
            motor_b_dir(off);
            motor_c_dir(off);
        }
        msleep(90);
        motor_a_dir(off);
        motor_b_dir(off);
        motor_c_dir(off);
    }
    return 0;
}

wakeup_t rt_dr_wakeup(wakeup_t data){ // lnp check for drive func
    return 'a' <= lnp_rcx_message && lnp_rcx_message <='h';
}

wakeup_t rs_r_wakeup(wakeup_t data){
    return ROTATION_1 < data;
}

wakeup_t rs_l_wakeup(wakeup_t data){
    return ROTATION_1 > data;
}

コントローラ用プログラム --- remocon.c

/*リモコン*/
#include<lnp/lnp.h>
#include<conio.h>
#include<unistd.h>
#include<dsensor.h>

int stop();
int send_mes();
tid_t t_stop, t_send;

int main(int argc, char **argv) {
    t_stop = execi(&stop, 0, NULL, 100, DEFAULT_STACK_SIZE);
    t_send = execi(&send_mes, 0, NULL, 50, DEFAULT_STACK_SIZE);
    return 0;
}

int stop(){ // rcx stop function
    int stopchar;

    stopchar = getchar();
    if(stopchar == KEY_RUN || stopchar == KEY_ONOFF){
        cputs("stop");
        killall(100);
        msleep(5000);
    }
    else{}
    return 0;
}

int send_mes(){
    char sendmsg = 'x';
    
    ds_active(&SENSOR_3);
    ds_rotation_on(&SENSOR_3);
    ds_rotation_set(&SENSOR_3, 0);

    while(1){
        if(ROTATION_3 >= 2){ // fwd
            cls();
            cputs("FFFF");
            sendmsg = 'a';
        }
        else if(ROTATION_3 <= -2){ // back
            cls();
            cputs("BBBB");
            sendmsg = 'b';
        }
        else{}
        if(SENSOR_2 < 0xf000 && ROTATION_3 >= 2){ // left + fwd
            cls();
            cputs("LFLF");
            sendmsg = 'c';
        }
        else if(SENSOR_2 < 0xf000 && ROTATION_3 <= -2){ // left + back
            cls();
            cputs("LBLB");
            sendmsg = 'd';
        }
        else if(SENSOR_2 < 0xf000){ // left
            cls();
            cputs("LLLL");
            sendmsg = 'e';
        }
        else{}
        if(SENSOR_1 < 0xf000 && ROTATION_3 >= 2){ // right + fwd
            cls();
            cputs("RFRF");
            sendmsg = 'f';
        }
        else if(SENSOR_1 < 0xf000 && ROTATION_3 <= -2){ // right + back
            cls();
            cputs("RBRB");
            sendmsg = 'g';
        }
        else if(SENSOR_1 < 0xf000){ // right
            cputs("RRRR");
            sendmsg = 'h';
        }
        else{}
        send_msg(sendmsg);
        cls();
        cputs("----");
        sendmsg = 'x';
    }
    return 0;
}

4.動作の様子

実際に動かしているときの様子です。
MVI_0784.avi