Program Resource

開発者向け各種コード、アルゴリズム、リソース情報ライブラリ もしくはねふぁの覚え書き

Arduinoの可能性をさらに広げるシールドの一つ、USB Hostシールド。

DSC03716

本シールドはAndroid端末と接続し、Android側のアプリとArduinoを組み合わせて使う為に良く利用されるが、ArduinoからUSBマウスやキーボード、PSコントローラーのBluetoothデバイスを使う用途にも使用出来る。

Arduinoでステッピングモーターやサーボモーターを使用し車やロボットを作成、PS3コントローラーで操作すると言った場面で活躍しそうだ。

今回はサンプルとしてUSBマウスとOLEDディスプレイで簡単なマウス操作UIを行ってみる。

まず、USBホストシールド用のライブラリをArduino IDEに取り込む。

https://github.com/felis/USB_Host_Shield_2.0

様々なUSBデバイス用のサンプルスケッチが含まれている。USBHIDBootMouseのサンプルを開いてビルドし、USBマウスを接続しシリアルコンソールを開けばUSBマウスの移動やクリック情報が見れる。後はそれら情報を自分好みに生かすだけである。

OLEDディスプレイはu8libを使えば簡単にピクセルや線、四角、テキスト等の描画が行えるので、マウスの情報を元にカーソルを描画し、クリック入力があればその下の四角を枠描画から塗りつぶし描画に変えるだけでマウス操作UIが出来る。コードは簡単だが、見た目が良くインパクトがあるものがすぐに組めてしまうのがArduinoのシールドとライブラリの豊富さから来る強みと言える。

DSC03708

DSC03709

DSC03710

マウスはBluetoothではなくただのワイヤレスマウスである。

動画を見て頂くとマイコン動作にしては結構ぐりぐり動作しているのが分かる。

コードは以下の通り。マウスのサンプルスケッチにOLEDの描画を少し足しただけである。

#include <hidboot.h>
#include <usbhub.h>

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <Wire.h>
#include <SPI.h>
#include "U8glib.h"

char oledstrbuff[6][16];
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);	// I2C / TWI
int mposx,mposy;
int mousepress;

void oled_drawstr(int line,char *text){
  strcpy(oledstrbuff[line],text);
  u8g.firstPage();
  do {
    u8g.setFont(u8g_font_6x10);
    u8g.setFontRefHeightExtendedText();
    u8g.setDefaultForegroundColor();
    u8g.setFontPosTop();
    for (int i=0;i<6;i++)
      u8g.drawStr(0,10*i,oledstrbuff[i]);
  } while (u8g.nextPage());
}

void oled_drawpixel(int ptx,int pty){
  u8g.firstPage();
  do {
    if (mousepress == 0)
      u8g.drawRBox(5,10,30,20,3);
    else
      u8g.drawRFrame(5,10,30,20,3);
    if (mousepress == 1)
      u8g.drawRBox(40,10,30,20,3);
    else
      u8g.drawRFrame(40,10,30,20,3);
    if (mousepress == 2)
      u8g.drawRBox(75,10,30,20,3);
    else
      u8g.drawRFrame(75,10,30,20,3);
    if (mousepress == 3)
      u8g.drawRBox(5,35,30,20,3);
    else
      u8g.drawRFrame(5,35,30,20,3);
    if (mousepress == 4)
      u8g.drawRBox(40,35,30,20,3);
    else
      u8g.drawRFrame(40,35,30,20,3);
    if (mousepress == 5)
      u8g.drawRBox(75,35,30,20,3);
    else
      u8g.drawRFrame(75,35,30,20,3);

    u8g.drawStr90(115,10, "Mouse");

    u8g.setRGB(255,255,255);
    mposx = min(125,max(0,mposx+ptx/10));
    mposy = min(57,max(0,mposy+pty/10));
    u8g.drawPixel(mposx,mposy);
    u8g.drawPixel(mposx,mposy+1);
    u8g.drawPixel(mposx,mposy+2);
    u8g.drawPixel(mposx,mposy+3);
    u8g.drawPixel(mposx,mposy+4);
    u8g.drawPixel(mposx+1,mposy+1);
    u8g.drawPixel(mposx+1,mposy+2);
    u8g.drawPixel(mposx+1,mposy+3);
    u8g.drawPixel(mposx+2,mposy+2);
    u8g.drawPixel(mposx+2,mposy+4);
    u8g.drawPixel(mposx+2,mposy+5);
  } while (u8g.nextPage());
}

class MouseRptParser : public MouseReportParser
{
protected:
	void OnMouseMove	(MOUSEINFO *mi);
	void OnLeftButtonUp	(MOUSEINFO *mi);
	void OnLeftButtonDown	(MOUSEINFO *mi);
	void OnRightButtonUp	(MOUSEINFO *mi);
	void OnRightButtonDown	(MOUSEINFO *mi);
	void OnMiddleButtonUp	(MOUSEINFO *mi);
	void OnMiddleButtonDown	(MOUSEINFO *mi);
};
void MouseRptParser::OnMouseMove(MOUSEINFO *mi)
{
    Serial.print("dx=");
    Serial.print(mi->dX, DEC);
    Serial.print(" dy=");
    Serial.println(mi->dY, DEC);
    oled_drawpixel(mi->dX,mi->dY);
};
void MouseRptParser::OnLeftButtonUp	(MOUSEINFO *mi)
{
    Serial.println("L Butt Up");
    mousepress = -1;
    oled_drawpixel(0,0);
};
void MouseRptParser::OnLeftButtonDown	(MOUSEINFO *mi)
{
    Serial.println("L Butt Dn");
    mousepress = -1;
    if (mposy > 10 && mposy < 30){
      if (mposx > 5 && mposx < 35)
        mousepress = 0;
      else if (mposx > 40 && mposx < 70)
        mousepress = 1;
      else if (mposx > 75 && mposx < 105)
        mousepress = 2;
    }
    else if (mposy > 35 && mposy < 55){
      if (mposx > 5 && mposx < 35)
        mousepress = 3;
      else if (mposx > 40 && mposx < 70)
        mousepress = 4;
      else if (mposx > 75 && mposx < 105)
        mousepress = 5;
    }
    oled_drawpixel(0,0);
};
void MouseRptParser::OnRightButtonUp	(MOUSEINFO *mi)
{
    Serial.println("R Butt Up");
};
void MouseRptParser::OnRightButtonDown	(MOUSEINFO *mi)
{
    Serial.println("R Butt Dn");
};
void MouseRptParser::OnMiddleButtonUp	(MOUSEINFO *mi)
{
    Serial.println("M Butt Up");
};
void MouseRptParser::OnMiddleButtonDown	(MOUSEINFO *mi)
{
    Serial.println("M Butt Dn");
};

USB     Usb;
USBHub     Hub(&Usb);
HIDBoot<HID_PROTOCOL_MOUSE>    HidMouse(&Usb);

uint32_t next_time;

MouseRptParser                               Prs;

void setup()
{
  mposx=64;
  mposy=32;
  mousepress = -1;
  Serial.begin( 115200 );
#if !defined(__MIPSEL__)
    while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
    Serial.println("Start");
    oled_drawstr(0,"Ok");

    if (Usb.Init() == -1)
        Serial.println("OSC did not start.");

    delay( 200 );

    next_time = millis() + 5000;

    HidMouse.SetReportParser(0,(HIDReportParser*)&Prs);
}

void loop()
{
  Usb.Task();
}

[2個セット] Arduino用 USB Hostシールド 2.0
[2個セット] Arduino用 USB Hostシールド 2.0
[GPG] 小型I2C 128x64 OLED ディスプレイ Arduino等の電子工作用 (ホワイト)
[GPG] 小型I2C 128×64 OLED ディスプレイ Arduino等の電子工作用 (ホワイト)


USB HostシールドでArduinoをマウス操作」 に2件のコメント

  1. タムラユウスケ より:

    夜分にスミマセン、タムラユウスケと申します。
    最近Arduinoを始めたばかりの初心者です。
    プログラムについて質問させてください。

    この記事に興味を惹かれて再現を試みたのですが、
    HID_PROTOCOL_MOUSEが定義されていないと警告が入りなかなかうまく行きません。
    プログラムは記事に載せていただいたものを使用しており、
    hidboot.hはUSB_Host_Shield_2.0ごとライブラリに追加済みです。

    正直かなりお手上げ状態です…
    もしよろしければ修正部分を教えていただけないでしょうか。
    以下にエラーメッセージを記載します。
    どうぞよろしくお願いします。

    __________________________________

    Arduino:1.6.7 (Windows 7), マイコンボード:”Arduino/Genuino Uno”

    OLED:143: error: ‘HID_PROTOCOL_MOUSE’ was not declared in this scope

    HIDBoot HidMouse(&Usb);

    ^

    OLED:143: error: template argument 1 is invalid

    HIDBoot HidMouse(&Usb);

    ^

    OLED:143: error: invalid type in declaration before ‘(‘ token

    HIDBoot HidMouse(&Usb);

    ^

    OLED:143: error: invalid conversion from ‘USB*’ to ‘int’ [-fpermissive]

    HIDBoot HidMouse(&Usb);

    ^

    C:\Users\Yusuke Tamura\Documents\Arduino\progaramresource\USBHost\OLED\OLED.ino: In function ‘void setup()’:

    C:\Users\Yusuke Tamura\Documents\Arduino\progaramresource\USBHost\OLED\OLED.ino:159:24: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]

    oled_drawstr(0,”Ok”);

    ^

    OLED:168: error: request for member ‘SetReportParser’ in ‘HidMouse’, which is of non-class type ‘int’

    HidMouse.SetReportParser(0,(HIDReportParser*)&Prs);

    ^

    exit status 1
    ‘HID_PROTOCOL_MOUSE’ was not declared in this scope

    This report would have more information with
    “コンパイル中の詳細な出力を表示する”
    enabled in File > Preferences.

    • ねふぁ より:

      最新のライブラリでは定義に一部修正が入っている様です

      HID_PROTOCOL_MOUSE

      USB_HID_PROTOCOL_MOUSE

      にしてみて下さい。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です


*