Arduinoの可能性をさらに広げるシールドの一つ、USB Hostシールド。
本シールドは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のシールドとライブラリの豊富さから来る強みと言える。
マウスは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
[GPG] 小型I2C 128×64 OLED ディスプレイ Arduino等の電子工作用 (ホワイト)
夜分にスミマセン、タムラユウスケと申します。
最近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
にしてみて下さい。