1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

後輩たちのためのEV3rt講座⑦(ファイルを扱う-fprintf)

Last updated at Posted at 2018-10-25

#はじめに…#
ev3rtにてセンサーの値を取りたい時、よくやる手法はLCDに値を書く方法かと思いますが、これってあの小さい液晶を覗き込まなければならなく、見にくいですよね。
教育版ソフトウエアでは「データロギング」というモードがあり、モーター・センサーの値の動きを連続してみることができます。これに近いものをev3rtで実現できれば、ログ取りには困りませんよね。

ちなみにこれ↓がデータロギング
スクリーンショット 2018-10-25 20.38.20.png

#標準Cライブラリを使用する#
ev3rtで使える標準Cライブラリには、ファイルを扱う機能があり、Windowsでいうメモ帳で読み書きできる.txtファイルも作成できます。よって今回は.txtファイルに値を書き込んでいくとします。

#書き方#
まずはサンプルコードを見てみましょう。

app.c
void main_task(intptr_t unused)
{
    int i=100;

    FILE *file;//ファイルポインタを宣言
    file=fopen("/test.txt","a");//ファイルをオープン(名前の指定)
    fprintf(file,"Hello %d\n",i);//書き込み
    fclose(file);//ファイルを閉じる
}

fileというのはただの名前なので、別のファイルを作りたければfile2などとすれば複数個同時に作ることも可能です。その際は、上記例に示されているfileはすべてfile2に置き換えることになります。
(例)

FILE *file;                      FILE *file2;
file=fopen("/test.txt","a");     file2=fopen("/test.txt","a");
fprintf(file,"Hello %d\n",i);  → fprintf(file2,"Hello %d\n",i);
fclose(file);                    fclose(file2);

#テキストを確認#
プログラム終了後、ロボットとPCをUSBケーブルで繋ぐと、SDカード領域がマウントされるはずです。そしてその中に、先程指定した名前のファイルが作成されているはずです。無い場合はプログラムが正常に動いていません。もう一度やってみると作成される場合もあります。それでもなお作られない場合はプログラムミスを疑ってください。
今回の場合は「Hello 100」と書かれているはずです。

#fopenの書式#
上記例の"a"と書かれている部分ですが、これはテキストの処理方法を宣言していて、以下の表の様に様々な記述方法があります。ロボットの場合、値を随時書き足していくという使い方が多いと思いますので、オススメは"a"です。

モード 動作 ファイルがあるとき ファイルが無いとき
"r" 読み込み専用 正常 エラー(NULL)
"w" 書き込み専用 サイズを0にする(上書き) 新規作成
"a" 追加書き込み専用 最後に追加 新規作成
"r+" 読み込み(主)と書き込み 正常 エラー(NULL)
"w+" 書き込み(主)と読み込み サイズを0にする(上書き) 新規作成
"a+" 読み込みと追加書き込み 最後に追加 新規作成

#fprintfの書式#
##引数を用いる##
fprintfでは引数として任意の値を代入することができます。例えば、上記例ではint型変数testを%dの部分に動的に代入しています。この書式法を使えば、任意のタイミングの値を記録することが可能なのです。なお、値の型によって書式が異なります。

変換指定子 意味
d , i int 型の引数を 10 進符号付き整数に変換する
u unsigned int 型の引数を 10 進符号無し整数に変換する
o unsigned int 型の引数を 8 進符号無し整数に変換する
x , X unsigned int 型の引数を 16 進符号無し整数に変換する
f , F double 型の引数を小数形式浮動小数点数に変換する
e , E double 型の引数を指数形式浮動小数点数に変換する
g , G f か e のどちらかに変換する (変換の結果として得られる指数が -4 より小さいか,精度以上の場合は e 形式になる)
a , A double 型の引数を 16 進浮動小数点に変換する
c int 型の引数を 一端 unsigned char 型に変換し,変換結果の文字を書き込む
s 文字配列の先頭要素へのポインタを文字列に変換する
p void 型へのポインタを処理系定義の方法で表示文字の並びに変換する
n 整数変数に出力済み文字数を格納する (引数は符号付き整数型へのポインタ)

又、場合によっては長さ修飾子を付ける必要があります。

長さ修飾子 意味
hh 対応する実引数の型が char 型であることを指定する
h 対応する実引数の型が short 型であることを指定する
l 対応する実引数の型が long 型, wchar_t 型であることを指定する
ll 対応する実引数の型が long long 型であることを指定する
j 対応する実引数の型が intmax_t 型であることを指定する
z 対応する実引数の型が size_t 型であることを指定する
t 対応する実引数の型が ptrdiff_t 型であることを指定する
L 対応する実引数の型が long double 型であることを指定する

さらに、フラグというものを使うとさらに文字の表現が広がります。

フラグ 意味
- 変換結果をフィールド内に左詰めにする (デフォルトは右詰め)
+ 変換結果が正,負に関わらず符号を出力する (デフォルトは負の場合のみ出力)
空白 変換結果の最初の文字が符号でない場合か,符号付き変換の結果が 0 の場合に空白を結果の前に付ける
# 結果を "代替形式"※ に変換する
0 出力文字数が最小フィールド幅未満の場合は 0 を埋める

これだけ説明しといてなんですが、EV3rtで扱うような値(センサー値など)はint型が多く、計算でもしない限り%dだけで書き出せちゃうのです。(もちろん、私のように複数個の値でパーセンテージなどをだすとfloatもしくはdoubleになりますが…)

あ、そうそう。printfとかfprintf、あるいはsprintfなどはすべて仲間みたいなもんなので書式もほぼ共通です。

ちなみに、この引数は複数個も可能です。

app.c
void main_task(intptr_t unused)
{
    int i[10]={10,20,30,40,50,60,70,80,90,100};

    FILE *file;//ファイルポインタを宣言
    file=fopen("/test.txt","a");//ファイルをオープン(名前の指定)
    fprintf(file,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n"
,i[0],i[1],i[2],i[3],i[4],i[5],i[6],i[7],i[8],i[9]);//書き込み
    fclose(file);//ファイルを閉じる
}

この場合、出力は10,20,30,40,50,60,70,80,90,100になります。

###センサー値も代入可能###
以下のようにすれば、センサーの値も引数として代入可能です。(今回はライトセンサーをポート1、2に繋いでいます。)

app.c
void main_task(intptr_t unused)
{
    int i=100;

    FILE *file;//ファイルポインタを宣言
    file=fopen("/test.txt","a");//ファイルをオープン(名前の指定)
    fprintf(file,"Port1:%d,Port2:%d\n",ev3_color_sensor_get_reflect(0),ev3_color_sensor_get_reflect(1));//書き込み
    fclose(file);//ファイルを閉じる
}

##改行する##
ファイルを作成するとき、書き出せたは良いものの、改行されていないと非常に見にくいです…
そこで「改行コード」を入力することで、文字列を次の行に移すことが可能です。
LINUX系(EV3rt含む)の場合は\nです。

#おまけ#
この作成したファイルですが、そのままメモ帳で見るとなかなか見にくいです。そこで、ファイルをexcelで開きましょう。その時ポイントとなるのが、値と値の間に「,」などの印をつけることです。excelでは指定した文字で文字列を分解する機能があります。そうすれば、とても簡単にデータが見れますし、グラフを作ることも容易です。
スクリーンショット 2018-10-25 20.15.17.png
スクリーンショット 2018-10-25 20.16.55.png

#最後に#
今回はファイルの扱い方について紹介しました。printf系統は非常によく使うので、覚えておいた方が良いでしょう。
さて、次回はいよいよタスク・周期ハンドラに入っていきたいと思います。僕は理解するのに1年かかりました…

次回:第8回
前回:第6回

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?