今回はロボットの中枢ともいえるインテリジェントブロックの機能の紹介です。
インテリジェントブロックはプログラムを実行するためだけの物ではなく、液晶ディスプレイに文字を表示したり、サウンドを鳴らしたりすることができます。
一つ一つ紹介していきます。
例のごとく、詳しいことはAPIを見て確認しましょう。
#①LEDライト#
ボタンの周りで光るLEDを制御します。
void main_task(intptr_t unused)
{
ev3_led_set_color(LED_OFF);//OFFにする
ev3_led_set_color(LED_RED);//赤色にする
ev3_led_set_color(LED_GREEN);//緑色にする
ev3_led_set_color(LED_ORANGE);//オレンジ色にする
}
#②ボタン#
メニュー画面でボタンをよく使用しますが、プログラム実行中も使用することができます。
列挙型は以下の通りです。
##(i)ボタンが押されているか##
指定したボタンが押されているかどうかをbool型で判断します。基本的にはif文でボタンの処理を書くのが王道かと思われます。
今回は「真ん中ボタンが押されているか」を判断する制御を例に挙げます。
void main_task(intptr_t unused)
{
while(1){
if(ev3_button_is_pressed(ENTER_BUTTON)==true){
ev3_led_set_color(LED_GREEN);//緑色にする
}
else{
ev3_led_set_color(LED_RED);//赤色にする
}
}
}
又、指定のボタンが押されるまで待機という制御も可能です。
「真ん中のボタンが押されたら処理を実行する」という制御を例に示します。
void main_task(intptr_t unused)
{
while(ev3_button_is_pressed(ENTER_BUTTON)==false){
//押されていない間待機
}
//処理
}
WROではスタート時、真ん中ボタンでロボットを発進させなければならない
というルールがあるので(2018年ルール)、このような制御が必要になるかと思います。
##(ⅱ)クリックイベントハンドラを設定する方法について##
これについては、EV3rt/TOPPERS hrp2における『タスク』の扱い方を理解しておく必要があります。しかしながら現時点ではまだタスク分岐や周期ハンドラについて説明していません。よってこの場で理解していただくのは困難かと思いますので今回は省略させていただきます。
近い内にタスク分岐・周期ハンドラについてのページを投稿いたしますので、その際に記載する予定です。
#③スピーカー#
EV3の側面についているスピーカーから音を鳴らす機能です。
##(ⅰ)音量の設定##
鳴らす前に音量を設定しておきましょう。
音量は0〜+100までで設定してください。
void main_task(intptr_t unused)
{
ev3_speaker_set_volume(0);//音量0に設定
ev3_speaker_set_volume(10);//音量10に設定
ev3_speaker_set_volume(50);//音量50に設定
ev3_speaker_set_volume(100);//音量100に設定
}
##(ⅱ)指定周波数でトーン出力##
指定した周波数で音を鳴らすことができます。
引数の1つ目に周波数、2つ目に鳴らす時間の長さ(ミリ秒)を指定します。
ここでは261.63で1秒間鳴らす例を示します。
void main_task(intptr_t unused)
{
ev3_speaker_play_tone(261.63,1000);
}
さて、ここでなぜ私が261.63
などという絶妙な周波数を指定したのか?
鳴らしてみると「なるほど」と思うかもしれませんが、実はこれはC4(ド)の音なんです。
これらの主要な音は既にdefineされているので、周波数を数字で設定しなくても、APIの表を見ればすぐに鳴らしたい音が鳴らせます。http://www.toppers.jp/ev3pf/EV3RT_C_API_Reference/group__ev3api-speaker.html
つまり、
void main_task(intptr_t unused)
{
ev3_speaker_play_tone(NOTE_C4,1000);
}
こんな風にプログラムしても全く同じように鳴ります。
##(ⅲ)音を停止する##
再生したら停止しなければいけませんね。ということで停止の方法です。
void main_task(intptr_t unused)
{
ev3_speaker_stop();
}
##(ⅳ)WAVファイルを鳴らす(高難易度)##
EV3rtではSDカードに保存したWAVファイルを再生することができます。
しかし、そのファイルは 8bit 8kHz モノラル で作成されてなければならず、この作業がうまくいかないこともよくあります。
今回はそれに成功した体で話をすすめます。
(今回のはsdcard/ev3rt/resの中のtest.wav
を使用します。)
void main_task(intptr_t unused)
{
memfile_t memfile;//ファイル構造体を作成
ev3_memfile_load("/test.wav", &memfile);//SDカード内の"test.wav"を紐づけ
ev3_speaker_set_volume(100);//ボリュームを100に設定
ev3_speaker_play_file(&memfile,SOUND_MANUAL_STOP);//音声を再生
}
理論上はこれで鳴ります。しかしながら前述の通り8bit 8kHz モノラル という音声の条件が容易では無く、作成できていたつもりでもうまくいかない場合が多々あります。よって、あまりオススメしません。
以上、スピーカーの紹介でした。
#④LCD(液晶ディスプレイ)#
センサーの値などを表示するときなどによく使います。文字や絵、図形等描くことが可能です。
##(ⅰ)フォントの大きさを設定##
まずは文字の書き方から紹介しようと思うのですが、その前に描く文字の大きさを指定しておきましょう。
void main_task(intptr_t unused)
{
ev3_lcd_set_font(EV3_FONT_SMALL);//文字の大きさを小さく
ev3_lcd_set_font(EV3_FONT_MEDIUM);//文字の大きさを大きく
}
個人的にはEV3_FONT_MEDIUMに設定したほうが見やすいです。しかし、文字が大きいため情報量は少なくなってしまいます。
##(ⅱ)文字を書く##
ではいよいよ文字を書き込んでいきましょう。
まずは、定番のHello EV3
を書いてみましょう。
void main_task(intptr_t unused)
{
ev3_lcd_draw_string("Hello EV3",0,0);
}
ここで、末尾に0,0
と書かれていますが、これはLCD上の座標を指しており、左上隅を原点として右方向にx軸、下方向にy軸が伸びています。
例えば、今の位置より少し下に書きたいなと思ったら0,20
とする、今の位置より少し右に書きたいなと思ったら50,0
とする、などといったような形です。
さて、今の例では"Hello EV3"を書いてみましたが、実際に使用するときは変数を表示させたかったりしますよね。センサーの値や変数などだとintやdoubleだったりします。そんなときは、一度char配列
に代入しなおしてやる必要があります。その流れを紹介します。
void main_task(intptr_t unused)
{
int reflect_value=ev3_color_sensor_get_reflect(0);//ライトセンサーの値を変数に代入
char str[20];//配列を宣言
sprintf(str,"Value:%d",reflect_value);//配列strにreflect_valueの値を書き込む
ev3_lcd_draw_string(str,0,0);//LCDにstrの内容を書き込む
}
char str[20]
というのは20文字まで入力可能なchar型の配列を宣言しています。
配列の一つ一つの箱に文字が一個ずつ入っていくイメージです。
そしてsprintf
ですが、これはC言語標準の関数で、変数名・入力する文字を引数に渡すことで、書き込むことができるのです。
また%dですが、%dの部分にはreflect_valueの値が入ります。
どちらもC言語の共通の機能なので、よくわからなければ、ググってみましょう。
【追記18/10/25】第7回にてprintf系統の説明を詳しく行っています。合わせて御覧ください。
第7回 ファイルを扱う-fprintf
##(ⅲ)図形を描く##
文字だけでなく、簡単な図形もかけちゃいます。
void main_task(intptr_t unused)
{
ev3_lcd_draw_line(0,0,50,50);//線を引く
ev3_lcd_fill_rect(50,50,30,30,EV3_LCD_BLACK);//四角形を黒色で描く
}
まずは上の線を書く方から。最初の0,0
は始点の座標、後ろの50,50
は終点の座標を指しています。つまりこれは、(0,0)から(50,50)まで右斜め下に直線が引かれることになります。
続いて下の四角形を描く方。最初の50,50
は描く四角形の左上隅の座標を指しています。真ん中の30,30
は各辺の長さで、順番に幅・高さです。
最後のEV3_LCD_BLACK
ですが、塗り潰すときに白か黒かを指定できます。白く塗り潰したい場合はEV3_LCD_WHITE
とするとできます。
##(ⅳ)任意の画像を表示する(高難易度)##
実は任意の画像をSDカード内に保存し、表示させることもできるのですが、その画像はBMP形式のモノクロ画像しかサポートしておらず、何でもかんでも表示できるわけではありません。今回は画像の作成に成功した体で話をすすめます。(以下例のテストではsdcard/ev3rt/resの中のtest.bmpを使用します。)
void main_task(intptr_t unused)
{
memfile_t memfile;//ファイル構造体を作成
ev3_memfile_load("/test.bmp", &memfile);//SDカード内の"test.bpm"を紐づけ
image_t image;//イメージ構造体を作成
ev3_image_load(&memfile, &image);//イメージ構造体にファイル構造体を紐づけてろロード
ev3_lcd_draw_image(&image,0,0);//座標0,0に画像を表示
ev3_image_free(&image)//イメージ構造体を解放
}
以上の流れで任意の画像を表示させることができます。
##(ⅴ)残り物##
実は…
ev3_font_get_size(lcdfont_t font , int32_t * p_width , int32_t * p_height);
こんなのが残ってます。しかし「よくわからない」「使ったこと無い」「多分今後も使わない」ということで、これの紹介は省略します。ゴメンね……
#⑤バッテリー#
EV3rtではバッテリーに関する情報も取得することができます。
void main_task(intptr_t unused)
{
char str[20];
sprintf(str,"%d",ev3_battery_current_mA());//バッテリー残量
ev3_lcd_draw_string(str,0,0);
sprintf(str,"%d",ev3_battery_current_mV());//現出力電圧
ev3_lcd_draw_string(str,0,20);
}
上はバッテリーの残り残量、下は今の出力電圧です。
バッテリー残量のmax値はだいたい8300〜8400です。これが徐々に低下していくので、バッテリー交換の目安にはなるでしょう。
出力電圧はだいたい50前後です。何に使うかは未だによくわかりません…
#まとめ#
いかがでしたでしょうか?これでできることもかなり多くなったはずです。
しかし、まだまだ紹介しないといけないことがいっぱいあります…
徐々に紹介していきますね。
次回は関数の使い方について紹介します。EV3rtの独自的要素は減ると思いますが、かなり重要ですよ。