C++
ARM
mbed

mbedを用いたUSBエアマウスの作成

More than 1 year has passed since last update.

はじめに

この記事では、mbedを使ってUSBエアマウスの簡単なプロトタイプを作成する方法を説明します。

mbedとは

mbedとは、mbed対応ボード(ARM Cortex-Mベース)のための開発フレームワークのことです。オンラインIDE、OS、mbed対応ボードなどを含めたエコシステム全体のことをmbedと呼びます。mbedを使うことで、プロトタイプ開発を迅速に進めることができます。詳細については、公式ページなどを参照してください。

作成したUSBエアマウスの使い方

以下に、作成したUSBエアマウスの使い方を説明します。

マウスカーソルの水平移動

ボードを横方向に傾けると水平方向にマウスカーソルが移動します。また、傾きを検出している間は、LEDが青色に点灯します。

mouse_move_horizontal.gif

マウスカーソルの垂直移動

ボードを縦方向に傾けると垂直方向にマウスカーソルが移動します。傾きを検出している間は、LEDが青色に点灯します。

mouse_move_vertical.gif

マウスの右クリック

タッチセンサの右半分をタッチすることで、マウスの右クリックができます。同時にLEDが緑色に点灯します。

mouse_right_click.gif

マウスの左クリック

タッチセンサの左半分をタッチすることで、マウスの左クリックができます。同時にLEDが赤色に点灯します。

mouse_left_click.gif

USBエアマウスの作成方法

USBエアマウスは、以下の流れで作成しました。

  1. FRDM-KL25Zのファームウェアの更新
  2. 必要なライブラリのインポート
  3. コーディング
  4. コンパイル

FRDM-KL25Z

今回は、mbed対応ボードとして、FRDM-KL25Zを採用しました。FRDM-KL25Zは、以下のような機能を備えています。

  • ARM Cortex-M0+
  • 3軸加速度センサ
  • 静電容量タッチセンサ

mbed FRDM KL25Z 諸元
https://os.mbed.com/users/okini3939/notebook/mbed_frdm_kl25z_jp/

ファームウェアの更新

FRDM-KL25Z上でmbedを使うために、ファームウェアを更新する必要があります。更新方法については、以下のWebページなど参照してください。

mbed FRDM KL25Z ゲッティングスターテッド
https://os.mbed.com/users/Norisuke/notebook/mbed-frdm-kl25z-Getting-started-jp/

コーディング

続いて、mbedのオンラインIDE上でC/C++を使って実装を行っていきます。

mbedのオンラインIDEの使い方

mbedのオンラインIDEの使い方については、以下のWebページなどを参照してください。

mbed入門
https://os.mbed.com/users/RyoheiHagimoto/notebook/mbed_introduction/

ライブラリのインポート

今回は以下の3つのライブラリを使いました。

  1. USBMouse
  2. タッチセンサ(Touch Sensor)
  3. 加速度センサ(Accelerometer)

それぞれのWebページで「Import program」のボタンをクリックします。

import_program.png

インポートする際は、Libraryとしてインポートしてください。

import_library.png

ライブラリとしてインポートした場合、ライブラリ内のmain.cppは不要ですので削除してください。

コード

今回実装したコードは以下のとおりです。main.cppに以下のコードを記述してください。

main.cpp
#include "mbed.h"
#include "MMA8451Q.h"
#include "TSISensor.h"
#include "USBMouse.h"

class LED {
public:
    LED() : _rled(LED_RED), 
            _gled(LED_GREEN), 
            _bled(LED_BLUE) {}

    void turnOn(PinName pin) {
        turnOffAll();
        if (pin == LED_RED) {
            _rled = 0;
            _timeout_rled.attach(this, &LED::turnOffAll, 0.01);
        } else if (pin == LED_GREEN) {
            _gled = 0;
            _timeout_gled.attach(this, &LED::turnOffAll, 0.01);
        } else {
            _bled = 0;
            _timeout_bled.attach(this, &LED::turnOffAll, 0.01);
        }
    }

private:
    DigitalOut _rled;
    DigitalOut _gled;
    DigitalOut _bled;

    Timeout _timeout_rled;
    Timeout _timeout_gled;
    Timeout _timeout_bled;

    void turnOffAll(void) {
        _rled = 1;
        _gled = 1;
        _bled = 1;
    }
};

class TouchSensor {
public:
    TouchSensor() {}

    bool isLeftClick(void) {
        float tsi_val = _tsi.readPercentage();
        return tsi_val > 0.0 && tsi_val < 0.5;
    }

    bool isRightClick(void) {
        float tsi_val = _tsi.readPercentage();
        return tsi_val >= 0.5 && tsi_val < 1.0;
    }

private:
    TSISensor _tsi;
};

class Accelerometer {
public:
    Accelerometer() : _acc(PTE25, PTE24, MMA8451_I2C_ADDRESS) {}

    int getMouseCursorXDist(void) {
        return (int)(10.0 * _acc.getAccY());
    }

    int getMouseCursorYDist(void) {
        return (int)(10.0 * _acc.getAccX());
    }

    bool isMouseCursorMoved(void) {
        return getMouseCursorXDist() != 0 || getMouseCursorYDist() != 0;
    }            

private:
    static const int MMA8451_I2C_ADDRESS = 0x1d << 1;
    MMA8451Q _acc;
};

class Mouse {
public:              
    Mouse() {}

    void handle(void) {
        while (true) {
            handleClick();
            handleMove();
            wait(0.01);
        }
    }

private:
    LED _led;
    USBMouse _mouse;
    TouchSensor _ts;
    Accelerometer _acc;

    void handleClick(void) {        
        if (_ts.isLeftClick()) {
            _mouse.click(MOUSE_LEFT);
            _led.turnOn(LED_RED);
        } else if (_ts.isRightClick()) {
            _mouse.click(MOUSE_RIGHT);
            _led.turnOn(LED_GREEN);
        }
    }

    void handleMove(void) {
        if (_acc.isMouseCursorMoved()) {
            _mouse.move(_acc.getMouseCursorXDist(), _acc.getMouseCursorYDist());
            _led.turnOn(LED_BLUE);
        }
    }
};

int main(void) {
    Mouse mouse;
    mouse.handle();    
}

コンパイル

以下の画像のとおり、FRDM-KL25Zにある2つのUSBのうち、「OpenSDA」の方にUSBケーブルを接続すると、「MBED」という名前のUSBメモリとして認識されます。

openSDA.png

続いて、オンラインIDE上で「コンパイル」ボタンをクリックすると、.binファイルが作成されるので、それを先ほどの「MBED」にコピーしてください。自動的に.binファイルがインストールされます。

USBエアマウスとして使用する

USBエアマウスとして使用する場合は、以下の画像のとおり、2つのUSBのうち、「KL25Z USB」の方にUSBケーブルを接続します。

KL25Z_USB.png

補足)
Windows、Macの双方でUSBエアマウスとして使用することができます。

参考文献

ほとんどコピペで作るコピペ専用USBデバイス
http://www.dm9records.com/index.php/tips/elec/mbedadvent2014/