Edited at

TOPPERS/EV3RTでEV3のタッチセンサーを使ってみる

More than 1 year has passed since last update.

TOPPERS/EV3RT環境でC言語を使って、タッチセンサーを使ってみます。

環境開発の記事はこちら


タッチセンサーを本体につなぐ

touch_sensor.png

上の画像のように接続しました。ポート1にタッチセンサーを、ポートAにLモーターを接続しました。


アプリケーションを作成する

タッチセンサーの動きが確認できればいいので、押している間モーターが回転するものを作ります。名前はtouch-testにするとして、前回のプログラムから、本体のエンターボタンの代わりにタッチセンサーを用いるだけで出来上がってしまうので、cp -r motor-test touch-testで、motor-testの中身を丸ごとコピーします。

cpapp.png

さて、今度は中身の編集です。main.cの中身を、以下のように書き換えます。


main.c


/**
******************************************************************************
** ファイル名 : app.c
** 説明 : タッチセンサーを押してる間モーターが回る
******************************************************************************
**/

#include "ev3api.h"
#include "app.h"

#if defined(BUILD_MODULE)
#include "module_cfg.h"
#else
#include "kernel_cfg.h"
#endif

#define DEBUG

#ifdef DEBUG
#define _debug(x) (x)
#else
#define _debug(x)
#endif

/* モーターポートの設定 */
static const motor_port_t
L_motor = EV3_PORT_A;

/* センサーの設定 */
static const sensor_port_t
touch_sensor = EV3_PORT_1;

/* メインタスク */
void main_task(intptr_t unused)
{
/* ループに入ってしまう前にモーターとモーターポートを接続する */
ev3_motor_config (L_motor, LARGE_MOTOR);
/* 同じくセンサーとセンサーポートを接続する */
ev3_sensor_config (touch_sensor, TOUCH_SENSOR);
ev3_led_set_color(LED_ORANGE);
/* ループの中に入る */
while(1)
{ /* タッチセンサーが押されている間とそうでないときで処理を分ける */
if(ev3_touch_sensor_is_pressed(touch_sensor) == true){
/* Lモーターを最大パワーで回す */
ev3_motor_set_power(L_motor,100);
}else{
/* Lモーターを止める */
ev3_motor_stop(L_motor, false);
}
}
ev3_motor_stop(L_motor, false);
ext_tsk();
}


タッチセンサーが押されている間モーターが回転し、離すと止まるという内容です。

この他にも、書き方次第でトグル操作に切り替えたりすることも可能です。


タッチセンサーを使ったトグル操作

トグル操作とは:

家電製品の電源ボタンをイメージしてください。

ボタンを押すと起動し、次に押すと動作が終了します。

このように、同一の操作により内部の状態を切り替える操作をトグル操作といいます。

On/Offの切り替えが最も多いですね。先ほどのプログラムを改良し、トグル操作を実装します。


main.c


/**
******************************************************************************
** ファイル名 : app.c
** 説明 : タッチセンサーを使いトグル操作でモーターが回る
******************************************************************************
**/

#include "ev3api.h"
#include "app.h"

#if defined(BUILD_MODULE)
#include "module_cfg.h"
#else
#include "kernel_cfg.h"
#endif

#define DEBUG

#ifdef DEBUG
#define _debug(x) (x)
#else
#define _debug(x)
#endif
/* フラグONとOFFのマクロ定義 */
#define ON 1
#define OFF 0
/* モーターポートの設定 */
static const motor_port_t
L_motor = EV3_PORT_A;

/* センサーの設定 */
static const sensor_port_t
touch_sensor = EV3_PORT_1;

/* 関数のプロトタイプ宣言 */
void toggle_control(void);

/* 大域変数でフラグを定義 */
static int flag = 0;
/* メインタスク */
void main_task(intptr_t unused)
{
/* ループに入ってしまう前にモーターとモーターポートを接続する */
ev3_motor_config (L_motor, LARGE_MOTOR);
/* 同じくセンサーとセンサーポートを接続する */
ev3_sensor_config (touch_sensor, TOUCH_SENSOR);
ev3_led_set_color(LED_ORANGE);
/* ループの中に入る */
while(1)
{ /* トグル関数を呼び出す */
toggle_control();
/* タッチセンサーが押されている間とそうでないときで処理を分ける */
/* フラグONでモーター駆動、OFFで動作停止 */
if(flag == OFF){
ev3_motor_set_power(L_motor, 0);
}else{
ev3_motor_set_power(L_motor, 100);
}
}
ev3_motor_stop(L_motor, false);
ext_tsk();
}

/* トグル操作の関数 */
void toggle_control()
{
/* ボタンの現在と直前の状態を保持する変数 */
static int now = 0;
static int before = 0;

/* ボタンの現在値を記録する */
now = ev3_touch_sensor_is_pressed(touch_sensor);
/* 直前のボタンの状態と現在のボタンの状態を比較し、ボタンが押された瞬間に条件のなかに入る */
if(now == 1 && before == 0){ /*前回のタスク周期でボタンが押されておらず、今回のタスク周期でボタンが押されたとき(立ち上がり判定) */
/* フラグ変数の状態に応じてフラグ変数のONとOFFを切り替える */
if(flag == OFF){
flag = ON;
}else{
flag = OFF;
}
}
/* 関数の終わりに現在値を過去値変数に代入する */
before = now;
}


これでトグル操作が実装されました。タッチセンサーを押すと動作と停止の切り替えができます。

toggle_control()のif文のあたりがミソです。EV3は、定められたタスク周期に従って繰り返し処理をしています。1周期あたりは人間にとっては一瞬ですが、EV3の中ではしっかりとその時間の中で処理を行えます。(LCD表示などの重い処理を繰り返させる場合は例外ですが)その超高速な周期で動いている間で、人間にとっての感覚で一瞬だけ、タッチボタンを押したとしましょう。周期回数を横軸、タッチセンサの返り値を縦軸とすると、以下のグラフのようになります。

toggle-graph.png

タッチセンサーが押されてから離されるまでの間にも周期は何周かするため、グラフは0が続く区間、0から1になる瞬間、1が続く区間、1から0になる瞬間に分けられます。if文の条件では、赤い丸で囲った、"0から1に変わる瞬間"をとらえて、モーターのON/OFFを切り替えています。この0から1になった瞬間を判定することを立ち上がり判定といい、逆に1から0になった瞬間を判定することは立下り判定といいます。if文の条件を、now == 0 && before == 1にするだけで立下り判定にもできるので、試してみてください。