LoginSignup
1
0

More than 5 years have passed since last update.

後輩たちのためのEV3rt講座⑥(関数を使う)

Last updated at Posted at 2018-10-01

今回はソースコードをきれいに書くコツでもある『関数化』について紹介します。
教育版ソフトウェアでいうところのマイブロックですね
スクリーンショット 2018-10-01 22.00.06.png
基本的にはC言語と同じですが、一応紹介しておきます。

(注)今回の例ではコンフィグを省いています

関数でできること

まずは関数とはどういうものかを理解しておきましょう。
例えば、『ライントレースをタッチセンサーが押されるまで行う』という制御があるとします。

app.c
void main_task(intptr_t unused)
{
    float lasterror = 0, integral = 0;
    float midpoint = 30;

    while (ev3_touch_sensor_is_pressed(0) != true) {
        float error = midpoint - ev3_color_sensor_get_reflect(0);  //error  差分
        integral = error + integral * 0.5;  //integral  微分
        float steer = 0.07 * error + 0.3 * integral + 1 * (error - lasterror);  //steer  モーター設定

        ev3_motor_steer(EV3_MOTOR_A, EV3_MOTOR_D, 10, steer);

        lasterror = error;   //lasterror 積分

        tslp_tsk(1); //1mm秒休止
    }
}

これを何回もやりたいなと思ったとき、いちいち全部書いているとソースコードが見にくくなり、非効率です。
しかしこのプログラムを『関数化』してやると、11行が1行に短縮されるのです。
できるだけ見やすく、扱いやすいプログラムを書くのが重要です。

関数にも型がある

変数を宣言するときに、intchar boolなど、型を書きますよね。
関数も宣言するときに型を書きます。そもそも発想が逆なんですが、関数というのは別に簡略化の道具というわけではないんです。「ある作業をした結果を返す」というのが本来の役割で、そこを忘れてはいけません。
例えば、以下のような足し算をする関数があるとします。

int add(){
    return 1+2;  //3を返す
}

void main(){
    int answer=add();  //answer=3
}

これは1+2をする関数ですが、returnによって計算結果を返しています。
すなわち、answerに3が代入されることとなります。
今回、関数addは型がintですが、これはboolなどの他の型であっても問題ありません。(その型に沿った値を返す必要がありますが。)
又、返す値がない場合は、voidと書きます。この関数はreturnしても値を返しません。

引数(ひきすう)

いんすうではないですよ!! (数学的にいんすうは因数)
ひきすうです!!

さて、では引数とはなんなのか?
先程から提示している関数ですが、名前の横に()がありますね。
この()の中に任意の値を代入することができるのです。

y=f(a,b)\\
f(a,b)=a+b

この数式でいうところのabが引数です。
この引数も型を指定した上で値を代入させます。
では例として、先程の足し算関数をすこしいじってみましょう。

int add(int a , int b){
    return a + b;  //a+bを返す
}

void main(){
    int answer=add(3,5);  //answer=8
    int answer2=add(100,200);  //answer2=300
    int answer3=add(100,-200);  //answer3=-100
}

これでだいたいわかったと思います。(もう説明はいらないかな??)
引数の型も基本的に自由です。

では、実際にEV3rtで実装していきましょう。

EV3rtでの関数

上のライントレースの例をもとに関数化してみましょう。

app.c
void main_task(intptr_t unused)
{
    linetrace(0,0,30);  //(ⅲ)main_taskで使用
}

void linetrace(float LAST , float INTEG , float MID);  //(ⅰ)まずはこの一文を書く

void linetrace(float LAST , float INTEG , float MID){  //(ⅱ)そして本文
    while (ev3_touch_sensor_is_pressed(0) != true) {
        float lasterror = LAST, integral = INTEG;
        float midpoint = MID;

        float error = midpoint - ev3_color_sensor_get_reflect(0);  //error  差分
        integral = error + integral * 0.5;  //integral  微分
        float steer = 0.07 * error + 0.3 * integral + 1 * (error - lasterror);  //steer  モーター設定

        ev3_motor_steer(EV3_MOTOR_A, EV3_MOTOR_D, 10, steer);

        lasterror = error;   //lasterror 積分

        tslp_tsk(1); //1mm秒休止
    }
}

(ⅰ)まずはこの一文を書く

関数の本文を書く前にここで一文書きます。書かなくてもコンパイルは通りますが、書くことが推奨されているので、書いておきましょう。

(ⅱ)本文

実際の処理内容です。ここではfloat型の引数を3つ(LAST,INTEG,MID)を使用しています。
中身の処理はライントレースです。

(ⅲ)main_taskで使用

ソース上のあらゆる好きな場所で使うことができます。もちろん、何回でも使えます。

まとめ

  • 関数を使って効率よく書く
  • 関数にも型がある
  • いんすうではなくひきすう!!
  • 引数を使って関数を拡張

これでまた、プログラミングが上手くなったのではないでしょうか?
これを機に今までのプログラムも見直してみてみるのもいいでしょう。

次回:第7回
前回:第5回

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0