0.はじめに
この記事では、SPIKE-RTの文法を一部抜粋して取り上げます。
以下のようなレイアウトで行きます。(一部例外あり)
①見出し
②文法(syntax.c)
③説明、使い方
④例文(example.c)
⑤説明
環境構築については以下の記事を参照ください。
1. モーター
デバイスポインタの宣言
pup_motor_t *motorポート;
デバイスポインタを設定します(void Main(intptr_t exinf){} の前に置きます)。
pup_motor_t *motorA;
Aポートのモーター用デバイスポインタを宣言しています。
モーターを宣言
motorポート = pup_motor_get_device(PBIO_PORT_ID_ポート);
指定したポートと PUP モータデバイスポインタを結びつけます。
motorA = pup_motor_get_device(PBIO_PORT_ID_A);
Aポートに接続されたモーターを取得して motorA にセットしています。
モーターを反時計回りに初期化
pup_motor_setup(motorポート, PUP_DIRECTION_COUNTERCLOCKWISE, true);
モーターを反時計回りでセットアップします。
pup_motor_setup(motorA, PUP_DIRECTION_COUNTERCLOCKWISE, true);
Aモーターを反時計回りに初期化しています。
モーターを時計回りにセットアップ
pup_motor_setup(motorポート, PUP_DIRECTION_CLOCKWISE, true);
pup_motor_setup(motorA, PUP_DIRECTION_CLOCKWISE, true);
Aモーターを時計回りに初期化しています。
モーターを回転
pup_motor_set_speed(motorポート, 一秒あたりの回転度);
モーターの回転速度を度/秒で指定します(0で停止します)。
pup_motor_set_speed(motorA, 1000);
Aモーターを 1000度/秒 で回転させています。
モーターをストップ
pup_motor_stop(motorポート);
pup_motor_stop(motorA);
Aモーターを停止しています。
モーターを角度維持させる
pup_motor_hold(motorポート);
モーターの角度を維持します(動かしても元の位置に戻ります)。
pup_motor_hold(motorA);
Aモーターが現在の角度を維持しています。
モーターの角度をリセット
pup_motor_reset_count(motorポート);
pup_motor_reset_count(motorA);
Aモーターの角度を0にリセットしています。
モーターの角度を取得
int angleポート = pup_motor_get_count(motorポート);
int angleA = pup_motor_get_count(motorA);
Aモーターの角度を angleA に取得しています。
角度を指定して回転
角度を指定して回転させる方法と、mmや角度で旋回、直進する車用のプログラムについては以下を参照してください。
2. カラーセンサー
デバイスポインタの宣言
pup_device_t *colorポート;
PUPデバイスポインタを宣言します(void Main(intptr_t exinf){} の前に置きます)。
pup_device_t *colorA;
AポートのPUPデバイスポインタを宣言しています。
カラーセンサーを宣言
colorポート = pup_color_sensor_get_device('ポート');
指定したポートをカラーセンサーとして取得します。
colorA = pup_color_sensor_get_device('A');
Aポートをカラーセンサーとして取得しています。
反射光の測定
pup_color_sensor_reflection(colorポート);
ポートの反射光を測定します(if、while、for の条件に使えます)。
int reflect_A = pup_color_sensor_reflection(colorA);
Aポートの反射光を reflect_A に代入しています。
周辺光の測定
pup_color_sensor_ambient(colorポート);
ポートの周辺光を測定します。
int ambient_A = pup_color_sensor_ambient(colorA);
Aポートの周辺光を ambient_A に代入しています。
RGB値の測定
pup_color_rgb_t rgb = pup_color_sensor_rgb(colorポート);
RGB値を取得します。
pup_color_rgb_t rgb = pup_color_sensor_rgb(colorA);
char rgb_str[32];
sprintf(rgb_str, "R:%d G:%d B:%d", rgb.r, rgb.g, rgb.b);
AポートのRGB値を取得し、文字列に整形しています。
カラーセンサーのLEDを点灯
pup_color_sensor_light_set(colorポート, 明るさ1, 明るさ2, 明るさ3);
カラーセンサーの3つのLEDを個別に明るさ設定します(0で消灯します)。
pup_color_sensor_light_set(colorA, 100, 100, 100);
AポートのカラーセンサーLEDを最大明るさで全灯しています。
色の実際の取得について
RGB値の扱い方や色判定の実例は上記資料を参照ください。
3. 距離センサー
デバイスポインタの宣言
pup_device_t *ultrasonicポート;
PUPデバイスポインタを宣言します(void Main(intptr_t exinf){} の前に置きます)。
pup_device_t *ultrasonicA;
AポートのPUPデバイスポインタを宣言しています。
距離センサーの宣言
ultrasonicポート = pup_ultrasonic_sensor_get_device('ポート');
指定したポートを距離センサーとして取得します。
ultrasonicA = pup_ultrasonic_sensor_get_device('A');
Aポートを距離センサーとして取得しています。
距離を測定
pup_ultrasonic_sensor_distance(ultrasonicポート);
ポートの距離を測定します(if、while、for の条件に使えます)。
int distance = pup_ultrasonic_sensor_distance(ultrasonicA);
Aポートの距離を distance に代入しています。
距離センサーのLEDを点灯
pup_ultrasonic_sensor_light_set(ultrasonicポート, 左上, 右上, 左下, 右下);
距離センサーの4つのLEDを個別に明るさ設定します(0で消灯します)。
pup_ultrasonic_sensor_light_set(ultrasonicA, 100, 100, 100, 100);
Aポートの距離センサーLEDを最大明るさで全灯しています。
4. フォースセンサー
デバイスポインタの宣言
pup_device_t *forceポート;
PUPデバイスポインタを宣言します(void Main(intptr_t exinf){} の前に置きます)。
pup_device_t *forceA;
AポートのPUPデバイスポインタを宣言しています。
フォースセンサーを宣言
forceポート = pup_force_sensor_get_device('ポート');
指定したポートをフォースセンサーとして取得します。
forceA = pup_force_sensor_get_device('A');
Aポートをフォースセンサーとして取得しています。
押し込み具合を測定
(int)pup_force_sensor_force(forceポート);
押し込み具合を取得します(小数が返るため int にキャストします)。
int force = (int)pup_force_sensor_force(forceA);
Aポートの押し込み具合を force に代入しています。
触れられているか測定
pup_force_sensor_touched(forceポート);
フォースセンサーが触れられているかを判定します。
pup_force_sensor_touched(forceA);
Aポートのフォースセンサーが触れられているかを判定しています。
5. ハブ
電流の測定
hub_battery_get_current();
ハブの電流(mA)を取得します(if、while、for の条件に使えます)。
int current = hub_battery_get_current();
電流を変数 current に代入しています。
電圧の測定
hub_battery_get_voltage();
ハブの電圧(mV)を取得します。
int voltage = hub_battery_get_voltage();
電圧を変数 voltage に代入しています。
センターボタンを光らせる
hub_light_on_color(PBIO_COLOR_カラー);
ハブのセンターボタンを指定した色で光らせます
(使える色:PBIO_COLOR_NONE, PBIO_COLOR_BLACK, PBIO_COLOR_BLUE, PBIO_COLOR_GREEN,
PBIO_COLOR_YELLOW, PBIO_COLOR_RED, PBIO_COLOR_WHITE, PBIO_COLOR_BROWN,
PBIO_COLOR_ORANGE, PBIO_COLOR_PURPLE, PBIO_COLOR_CYAN, PBIO_COLOR_LIGHT_GRAY,
PBIO_COLOR_DARK_GRAY)。
hub_light_on_color(PBIO_COLOR_RED);
センターボタンを赤色で光らせています。
数を表示
hub_display_number(数);
指定した数値を表示します。
hub_display_number(1);
1 を表示しています。
文字列を表示
hub_display_text_scroll("文字列", 速さ);
文字列を指定した速さでスクロール表示します。
hub_display_text_scroll("hello", 100);
"hello" を速さ 100 でスクロール表示しています。
指定したピクセルを点灯
hub_display_pixel(行, 列, 明るさ);
指定したピクセルを点灯します(明るさ 0 で消灯します)。
行は上から 0、列は左から 0 です。
hub_display_pixel(0, 0, 100);
左上のピクセルを明るさ 100 で点灯しています。
全てのピクセルを消灯
hub_display_off();
ディスプレイの全てのピクセルを消灯します。
hub_display_off();
全てのピクセルを消灯しています。
センターライトを HSV で光らせる
hub_light_on_hsv(h, s, v);
HSV 形式でセンターライトを光らせます。
hub_light_on_hsv(0, 100, 100);
赤色で光らせています。
ボタン
hub_button_is_pressed((hub_button_t *)&press);
どのボタンが押されたかを判定します
(press & HUB_BUTTON_CENTER / LEFT / RIGHT を if などに使います)。
int press;
hub_button_is_pressed((hub_button_t *)&press);
if (press & HUB_BUTTON_CENTER) {
hub_display_text_scroll("CENTER", 100);
}
センターボタンが押されたときに "CENTER" と表示しています。
IMU の初期化
hub_imu_init();
IMU を初期化します(IMU を使う場合は最初に必ず呼びます)。
hub_imu_init();
IMU を初期化しています。
IMU で加速度を取得
hub_imu_get_acceleration(accel);
加速度を取得します(accel[0] が X、accel[1] が Y、accel[2] が Z)。
float accel[3];
hub_imu_get_acceleration(accel);
if (accel[0] <= 100) {
hub_display_text_scroll("x is shaking.", 100);
}
X軸の加速度が 100 以下のときにメッセージを表示しています。
IMU で角速度を取得
hub_imu_get_angular_velocity(angv);
角速度を取得します(angv[0] が X、angv[1] が Y、angv[2] が Z)。
float angv[3];
hub_imu_get_angular_velocity(angv);
if (angv[0] <= 100) {
hub_display_text_scroll("x is shaking.", 100);
}
X軸の角速度が 100 以下のときにメッセージを表示しています。
IMU で温度を測定
hub_imu_get_temperature();
温度(℃)を取得します。
if (hub_imu_get_temperature() <= 25) {
hub_display_text_scroll("it is cold!", 100);
}
25℃ 以下のときに「寒い」と表示しています。
スピーカーのボリュームを設定
hub_speaker_set_volume(ボリューム);
スピーカーの音量を設定します。
hub_speaker_set_volume(100);
音量を最大に設定しています。
指定した周波数で音を鳴らす
hub_speaker_play_tone(周波数, 秒数 * 1000 * 1000);
指定した周波数の音を、指定した秒数だけ鳴らします。
hub_speaker_play_tone(260, 1 * 1000 * 1000);
ドの音(260Hz)を 1 秒鳴らしています。
6. C言語基本文法
〇秒待つ
dly_tsk(秒数 * 1000 * 1000);
指定した秒数だけ待ちます。
dly_tsk(1 * 1000 * 1000);
1秒待っています。
if文
if (条件) {
処理;
}
条件が真のときに処理を実行します。
if (x > 10) {
hub_display_number(1);
}
x が 10 より大きいときに 1 を表示しています。
if / else 文
if (条件) {
処理1;
} else {
処理2;
}
条件が真なら処理1、偽なら処理2を実行します。
if (x == 0) {
hub_display_text_scroll("ZERO", 100);
} else {
hub_display_text_scroll("NOT ZERO", 100);
}
x が 0 のときとそれ以外で表示を切り替えています。
AND(&&)・OR(||)
条件1 && 条件2
条件1 || 条件2
AND は両方真のとき、OR はどちらかが真のときに成立します。
if (x > 10 && y < 5) { ... }
if (x == 0 || y == 0) { ... }
複数条件を組み合わせています。
比較演算子(==, !=, >=, <=)
a == b
a != b
a >= b
a <= b
値を比較します。
if (temp <= 25) { ... }
温度が25以下かどうかを判定しています。
while文
while (条件) {
処理;
}
条件が真の間、処理を繰り返します。
while(1){
処理
}
で「ずっと」を作ることが出来ます。
while (hub_button_is_pressed(&press) == 0) {
dly_tsk(1000);
}
ボタンが押されるまで待っています。
for文
for (初期化; 条件; 更新) {
処理;
}
決まった回数だけ処理を繰り返します。
for (int i = 0; i < 5; i++) {
hub_display_number(i);
}
0〜4 を順番に表示しています。
int(整数)
int 変数名;
整数を扱います。
int count = 10;
count に 10 を代入しています。
static int = 変数
で、何回呼び出しても、前回の値を記憶する変数を作ることが出来ます。
float(小数)
float 変数名;
小数を扱います。
float speed = 1.5;
speed に 1.5 を代入しています。
変数の値を変える
x = x + 1
x += 1
//どちらもxに1を足す。
くわしい四則計算については、これの3つ下に書いてあります。
配列(リスト)を作る文法
型名 配列名[要素数];
配列は、同じ型の値をまとめて扱うための仕組みです。複数の値をひとつの名前で管理でき、インデックス(0から始まる番号)を使って個々の要素にアクセスします。
以下の例では、3つの角度をまとめて配列として定義し、順番に読み出しています。
int angles[3] = {90, 180, 360};
for(int i = 0; i < 3; i++) {
printf("角度%d: %d\n", i, angles[i]);
}
配列の要素を取得する文法
配列名[インデックス];
配列の要素は、インデックス(0から始まる番号)を使って取得します。
インデックスを指定することで、特定の位置にある値を読み出したり、書き換えたりできます。
以下の例では、3つの角度を保存した配列から、2番目の値を取得しています。
int angles[3] = {90, 180, 360};
int second = angles[1]; // 2番目の要素を取得(180)
sprintf(文字列の整形)
sprintf(バッファ, "書式", 値);
数値を文字列に変換してバッファに入れます。
char buf[32];
sprintf(buf, "X:%d", x);
x の値を文字列に変換しています。
四則計算(+ - * /)
a + b
a - b
a * b
a / b
基本的な計算を行います。
int total = a + b;
a と b を足した結果を total に代入しています。
定義(#define)
#define 名前 値
定数を定義します。
#define MAX_SPEED 1000
MAX_SPEED を 1000 として定義しています。
複数の命令を同時に実行する(見た目上の同時実行)
#define 名前 do { 処理1; 処理2; ... } while(0)
複数の命令を 1 つの定義にまとめて、連続して実行します。
この方法は、実際には順番に実行されますが、処理が高速なため同時に動いているように見えます。
定義は通常、#include の後、void Main(intptr_t exinf){} より前に書きます。
#define MOVE_AND_BEEP() do { pup_motor_set_speed(motorA, 500); hub_speaker_play_tone(440, 500000); } while(0)
MOVE_AND_BEEP() を呼び出すと、Aモーターを回転させ、同時に音を鳴らしているように見えます。
void 名前() {
処理1;
処理2;
...
}
複数の命令をまとめる
複数の命令を 1 つのブロックとしてまとめます。
関数は void Main(intptr_t exinf){} より前に書きます。
void move_and_beep() {
pup_motor_set_speed(motorA, 500);
hub_speaker_play_tone(440, 500000);
}
move_and_beep() を呼び出すと、モーターを回し、音を鳴らします。
void関数に引数を入れる文法
void 関数名(引数の型 引数名) {
// 引数を使った処理
}
voidは「戻り値がない」という意味であり、引数を入れられないという意味ではありません。
void関数でも、通常の関数と同じように引数を受け取り、その値を計算に利用できます。
以下の例では、角度(angle)を引数として受け取り、関数内で計算に使用しています。
void move_and_beep(int angle) {
pup_motor_set_speed(motorA, 500);
// angleを使って音の長さを計算
int duration = angle * 10000;
hub_speaker_play_tone(440, duration);
}
7.終わりに
ここまで、SPIKE-RTの基本の文法をまとめてきました。ここで紹介している物は一部ですが、これだけで、かなり書けるようになるはずです。SPIKE-RTのAPIがのっている
を参考にしました。こちらにはもっとくわしく文法がのっていますので、是非参考にしてみてはいかがでしょうか。