USB Host Shield 2.0 for Arduino を使ってみた時の色々 メモとして残します。 ※追記:2018/03/27:下のほうに Bluetooth ゲームコントローラ を接続してみた経緯を追加。 ※追記:2018/07/--:さらに下に Arduino Pro Mini と USB Host Shield for Arduino Pro Mini (ミニUSBホストシールド 2.0) を組み合わせた、ラジコン戦車製作用のハードを組んだ経緯を書いてる途中(調べたこと、やってみたことをまとめながら、随時更新してます) ※追記:2018/12/09:さらにさらに下に、Logicool(Logitech)社製ワイヤレスゲームパッド F710 + 専用USB無線アダプタ を、製作したラジコン戦車用ハードで、動かすことが出来た経緯と結果を追加しました。プログラムソースも公開。
・Arduino pro mini や Arduino pro micro などの、小さな Arduino と、ミニUSBホストシールド2.0 を購入して、小型化 ・DCモータードライバの基板を購入して、DCモーターを無線制御 ・これらでラジコン戦車っぽいのを作ってみる ・USB Bluetooth アダプタ の Class1 を購入してみて、野外での電波到達距離を実際に測ってみる(結果を見てClass2でいいやになる可能性大) ・Bluetooth アダプタ ではなく、専用の無線ドングルを使うタイプのPC用ゲームパッドを試してみる(結果が Bluetooth と変わらないのなら、いっそこっちにするかも)
・ミニUSBホストシールドは、Arduino Pro Mini (3.3V版) の上にスタックして(積み重ねて)の使用を想定した小型版。 ・但し、スタックで使用する場合は、ホストシールド基板上のMAX3421EからのGPIOの端子へのアクセスが上面から出来なくなるのと、 INT と SS で使用する D9 と D10 をほかのピンに変更する際に注意が必要になる。
(最初、このブログ記事の上にある Arduino Micro + 通常サイズのUSBホストシールド上で、LED点滅プログラムを作っていて、その時は Arduino Micro の基板上に最初から乗っている LED を使用することにして "LED_BUILTIN" を指定していたのですが、作り終わって、いざ Pro Mini に書き込んだら、動かなくて焦ってしまいました。Arduino Micro だと、基板上の LED は、未使用の D13 に繋がっているので問題はなかったのですが、普通の Arduino では、"LED_BUILTIN" は "PIN_SPI_SCK" と同じピンになっています。(\Arduino\hardware\arduino\avr\variants\standard\pins_arduino.h) そのため、今回のホストシールドの制御に使われている SPI の SCK を、作ったLED点滅プログラムが邪魔をする形になってしまいました。最初からこれに気が付かなかった、気が回らなかった、気付けなかった自分が不甲斐ないです。)
・Arduino Pro Mini + ミニUSBホストシールド2.0 + USB Bluetooth アダプタ + USB Host
Library Rev.2.0(書き代え) + Android/PC用のBluetooth ゲームコントローラ + 秋月のDCモータードライバ + マブチモーター2個制御の、Bluetooth ラジコン戦車用ハードウェア、完成(FIX)
・Arduino Pro Mini + USB Host Shield for Arduino Pro Mini (ミニUSBホストシールド2.0) + USB Host
Library Rev.2.0 + Logicool(Logitech)社製ワイヤレスゲームパッド F710 + 専用USB無線アダプタ
/* f710dinputparser.cpp USB Host Shield Library 2.0 で、 Logicool(Logitech)社製、ワイヤレスゲームパッド【F710】を動作させるための、Parser です。 "f710dinputparser.h" と "f710dinputparser.cpp" のセットで使用します。 "USB Host Shield Library 2.0" の "examples" にある "USBHIDJoystick" を元にしています。 https://github.com/felis/USB_Host_Shield_2.0*/#include"f710dinputparser.h"JoystickReportParser::JoystickReportParser(JoystickEvents*evt):joyEvents(evt),oldHat(0x08),oldButtons(0){for(uint8_ti=0;i<RPT_GEMEPAD_LEN;i++)oldPad[i]=0x7F;}voidJoystickReportParser::Parse(USBHID*hid,boolis_rpt_id,uint8_tlen,uint8_t*buf){boolmatch=true;// Checking if there are changes in report since the method was last calledfor(uint8_ti=0;i<RPT_GEMEPAD_LEN;i++){if(buf[i]!=oldPad[i]){match=false;break;}}// Calling Game Pad event handlerif(!match&&joyEvents){joyEvents->OnGamePadChanged((constGamePadEventData*)buf);for(uint8_ti=0;i<RPT_GEMEPAD_LEN;i++){oldPad[i]=buf[i];padData[i]=oldPad[i];}}uint8_that=(buf[5]&0x0F);// Calling Hat Switch event handlerif(hat!=oldHat&&joyEvents){joyEvents->OnHatSwitch(hat);oldHat=hat;hatData=oldHat;}uint16_tbuttons=(0x0000|buf[6]);buttons<<=4;buttons|=(buf[5]>>4);uint16_tchanges=(buttons^oldButtons);// Calling Button Event Handler for every button changedif(changes){for(uint8_ti=0;i<0x0C;i++){uint16_tmask=(0x0001<<i);if(((mask&changes)>0)&&joyEvents){if((buttons&mask)>0){joyEvents->OnButtonDn(i+1);buttonsData[i]=1;}else{joyEvents->OnButtonUp(i+1);buttonsData[i]=0;}}}oldButtons=buttons;}}voidJoystickEvents::OnGamePadChanged(constGamePadEventData*evt){/* Serial.print("Re: "); PrintHex<uint8_t > (evt->Re, 0x80); Serial.print("\tX1: "); PrintHex<uint8_t > (evt->X, 0x80); Serial.print("\tY1: "); PrintHex<uint8_t > (evt->Y, 0x80); Serial.print("\tX2: "); PrintHex<uint8_t > (evt->Z1, 0x80); Serial.print("\tY2: "); PrintHex<uint8_t > (evt->Z2, 0x80); Serial.println("");*/}voidJoystickEvents::OnHatSwitch(uint8_that){/* Serial.print("Hat Switch: "); PrintHex<uint8_t > (hat, 0x80); Serial.println("");*/}voidJoystickEvents::OnButtonUp(uint8_tbut_id){/* Serial.print("Up: "); Serial.println(but_id, DEC);*/}voidJoystickEvents::OnButtonDn(uint8_tbut_id){/* Serial.print("Dn: "); Serial.println(but_id, DEC);*/}
<F710-D_RC_Test.ino>
/* F710-D_RC_Test.ino Arduino Pro Mini + ミニUSBホストシールド2.0 + USB Host Shield Library 2.0 の組み合わせに、 Logicool(Logitech)社製、ワイヤレスゲームパッド【F710】 +専用USB無線アダプタ を接続して、 秋月のDCモータードライバ + マブチモーター2個制御の、ラジコン戦車を動かすためのテストプログラムです。 "f710dinputparser.h" と "f710dinputparser.cpp" を使用します。 詳細は下記のブログ記事を参照してください。 http://kato-h.cocolog-nifty.com/khweblog/2018/07/usb-host-shield.html ※注意点 このテストプログラムとハードでは、Arduino Pro Mini が ミニUSBホストシールド2.0 の MAX3421E を制御するための、 INT と SS のピンを移動しています。 そのために "USB Host Shield Library 2.0"ライブラリ の "UsbCore.h" の該当箇所を書き変えます。 INT 9 -> 4 SS 10 -> 2 typedef MAX3421e<P10, P9> MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560, Leonardo, Due etc.), Intel Edison, Intel Galileo 2 or Teensy 2.0 and 3.x を、 typedef MAX3421e<P2, P4> MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560, Leonardo, Due etc.), Intel Edison, Intel Galileo 2 or Teensy 2.0 and 3.x と書き換えて保存。 I/O は以下のようになってます。 MAX3421Eとの通信用 INT D4 SS D2 モータードライバ制御用 motor_L1 D3(PWM) motor_L2 D5(PWM) motor_R1 D9(PWM) motor_R2 D6(PWM) 外付けLED externalLed D10 操作方法 Rスティック上下:前進後退(アクセル) Lスティック左右:旋回(ステアリング) 十字キー左右:信地旋回 Aボタンを押しながらLスティック左右:超信地旋回*/#include<usbhid.h>#include<hiduniversal.h>#include<usbhub.h>// Satisfy IDE, which only needs to see the include statment in the ino.#ifdefdobogusinclude#include<spi4teensy3.h>#endif#include<SPI.h>#include"f710dinputparser.h"USBUsb;USBHubHub(&Usb);HIDUniversalHid(&Usb);JoystickEventsJoyEvents;JoystickReportParserJoyPrs(&JoyEvents);// settings// I/Oconstintmotor_L1=3;constintmotor_L2=5;constintmotor_R1=9;constintmotor_R2=6;constintexternalLed=10;// joystickconstintstickCenter=0x7F;// inputintstick_1x;intstick_1y;intstick_2x;intstick_2y;inthatSwitch;intbuttons[12];// outputconstintstop=0;// Stopconstintforward=1;// Forwardconstintreverse=2;// ReverseconstintpwmHigh=255;// motor driver HconstintpwmLow=0;// motor driver Lintdirection;// 0:Stop(Brake) 1:Forward 2:Backintspeed;// 0 << 255intsteering;// L -127 << 0 << 127 R intspeedLeft=0;intspeedRight=0;intL1,L2,R1,R2;voidsetup(){// I/O pin settingspinMode(motor_L1,OUTPUT);pinMode(motor_L2,OUTPUT);pinMode(motor_R1,OUTPUT);pinMode(motor_R2,OUTPUT);pinMode(externalLed,OUTPUT);// initializefor(inti=1;i<5;i++){JoyPrs.padData[i]=stickCenter;}JoyPrs.hatData=0x08;for(inti=0;i<12;i++){JoyPrs.buttonsData[i]=0;} // USB SetupSerial.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");if(Usb.Init()==-1){// Serial.println("OSC did not start.");}delay(200);if(!Hid.SetReportParser(0,&JoyPrs)) {// ErrorMessage<uint8_t > (PSTR("SetReportParser"), 1); }}voidloop(){Usb.Task();// input from Joystick.stick_1x=stickCenterThreshold(JoyPrs.padData[1]);stick_1y=stickCenterThreshold(JoyPrs.padData[2]);stick_2x=stickCenterThreshold(JoyPrs.padData[3]);stick_2y=stickCenterThreshold(JoyPrs.padData[4]);hatSwitch=JoyPrs.hatData;for(inti=0;i<12;i++){buttons[i]=JoyPrs.buttonsData[i];}// direction: 進行方向if(stick_2y<stickCenter){direction=forward;}elseif(stick_2y>stickCenter){direction=reverse;}else{direction=stop;}// speed: 速度speed=constrain(((abs(stick_2y-stickCenter)*2)+1),0,255);//steering: 旋回量steering=constrain((stick_1x-stickCenter),-127,127);// spin turn: (超信地旋回)if(buttons[1]==1){speedLeft=((255*(abs(steering)))/127);speedRight=speedLeft;// LEDdigitalWrite(externalLed,HIGH);// motor controlif(steering<0){//Lefy turn L1=speedLeft;L2=pwmLow;R1=pwmLow;R2=speedRight;}elseif(steering>0){//Right turnL1=pwmLow;L2=speedLeft;R1=speedRight;R2=pwmLow;}else{L1=pwmHigh;L2=pwmHigh;R1=pwmHigh;R2=pwmHigh;}}else{// LEDdigitalWrite(externalLed,LOW);if(hatSwitch!=0x08){// hat Switch:// pivot turn: (信地旋回)if(hatSwitch==6){//Left turnspeedLeft=0;speedRight=speed;}elseif(hatSwitch==2){//Right turnspeedLeft=speed;speedRight=0;}else{speedLeft=speed;speedRight=speed;}}else{// power turn: (緩旋回)if(steering<0){//Left turnspeedLeft=((speed*(127-abs(steering)))/127);speedRight=speed;}elseif(steering>0){//Right turnspeedLeft=speed;speedRight=((speed*(127-abs(steering)))/127);}else{speedLeft=speed;speedRight=speed;}}// motor controlif(direction==forward){L1=speedLeft;L2=pwmLow;R1=speedRight;R2=pwmLow;}elseif(direction==reverse){L1=pwmLow;L2=speedLeft;R1=pwmLow;R2=speedRight;}else{//stop:L1=pwmHigh;L2=pwmHigh;R1=pwmHigh;R2=pwmHigh;}}// output to motor driver.// Left motor:analogWrite(motor_L1,L1);analogWrite(motor_L2,L2);// Right motor:analogWrite(motor_R1,R1);analogWrite(motor_R2,R2);/* Serial.print("\n"); Serial.print("motor_L1 = "); Serial.print(L1); Serial.print("\t"); Serial.print("motor_L2 = "); Serial.print(L2); Serial.print("\t"); Serial.print("motor_R1 = "); Serial.print(R1); Serial.print("\t"); Serial.print("motor_R2 = "); Serial.print(R2); */}/* Stick Center Threshold */intstickCenterThreshold(ints){if((s>(stickCenter-40))&&(s<(stickCenter+40))){s=stickCenter;}returns;}
/* USBAPI.h Copyright (c) 2005-2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
typedef unsigned char u8; typedef unsigned short u16; typedef unsigned long u32;
#include "Arduino.h"
#if defined(USBCON)
#include "USBDesc.h" #include "USBCore.h"
//================================================================================ //================================================================================ // USB
class USBDevice_ { public: USBDevice_(); bool configured();
void attach(); void detach(); // Serial port goes down too... void poll(); }; extern USBDevice_ USBDevice;
//================================================================================ //================================================================================ // Serial over CDC (Serial1 is the physical port)
class Serial_ : public Stream { private: int peek_buffer; public: Serial_() { peek_buffer = -1; }; void begin(unsigned long); void begin(unsigned long, uint8_t); void end(void);
virtual int available(void); virtual int peek(void); virtual int read(void); virtual void flush(void); virtual size_t write(uint8_t); virtual size_t write(const uint8_t*, size_t); using Print::write; // pull in write(str) and write(buf, size) from Print operator bool();
class Mouse_ { private: uint8_t _buttons; void buttons(uint8_t b); public: Mouse_(void); void begin(void); void end(void); void click(uint8_t b = MOUSE_LEFT); void move(signed char x, signed char y, signed char wheel = 0); void press(uint8_t b = MOUSE_LEFT); // press LEFT by default void release(uint8_t b = MOUSE_LEFT); // release LEFT by default bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default }; extern Mouse_ Mouse;
int USB_SendControl(uint8_t flags, const void* d, int len); int USB_RecvControl(void* d, int len);
uint8_t USB_Available(uint8_t ep); int USB_Send(uint8_t ep, const void* data, int len); // blocking int USB_Recv(uint8_t ep, void* data, int len); // non-blocking int USB_Recv(uint8_t ep); // non-blocking void USB_Flush(uint8_t ep);
#endif
#endif /* if defined(USBCON) */
HID.cpp(機能追加)
/* Copyright (c) 2011, Peter Barrett ** ** Permission to use, copy, modify, and/or distribute this software for ** any purpose with or without fee is hereby granted, provided that the ** above copyright notice and this permission notice appear in all copies. ** ** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL ** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED ** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR ** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES ** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ** SOFTWARE. */
0x2c, //' ' //ASCII 32 0x1e|SHIFT, // ! 0x34|SHIFT, // " 0x20|SHIFT, // # 0x21|SHIFT, // $ 0x22|SHIFT, // % 0x24|SHIFT, // & 0x34, // ' 0x26|SHIFT, // ( 0x27|SHIFT, // ) 0x25|SHIFT, // * 0x2e|SHIFT, // + 0x36, // , 0x2d, // - 0x37, // . 0x38, // / 0x27, // 0 0x1e, // 1 0x1f, // 2 0x20, // 3 0x21, // 4 0x22, // 5 0x23, // 6 0x24, // 7 0x25, // 8 0x26, // 9 0x33|SHIFT, // : 0x33, // ; 0x36|SHIFT, // < 0x2e, // = 0x37|SHIFT, // > 0x38|SHIFT, // ? 0x1f|SHIFT, // @ 0x04|SHIFT, // A 0x05|SHIFT, // B 0x06|SHIFT, // C 0x07|SHIFT, // D 0x08|SHIFT, // E 0x09|SHIFT, // F 0x0a|SHIFT, // G 0x0b|SHIFT, // H 0x0c|SHIFT, // I 0x0d|SHIFT, // J 0x0e|SHIFT, // K 0x0f|SHIFT, // L 0x10|SHIFT, // M 0x11|SHIFT, // N 0x12|SHIFT, // O 0x13|SHIFT, // P 0x14|SHIFT, // Q 0x15|SHIFT, // R 0x16|SHIFT, // S 0x17|SHIFT, // T 0x18|SHIFT, // U 0x19|SHIFT, // V 0x1a|SHIFT, // W 0x1b|SHIFT, // X 0x1c|SHIFT, // Y 0x1d|SHIFT, // Z 0x2f, // [ 0x31, // bslash 0x30, // ] 0x23|SHIFT, // ^ 0x2d|SHIFT, // _ 0x35, // ` 0x04, // a 0x05, // b 0x06, // c 0x07, // d 0x08, // e 0x09, // f 0x0a, // g 0x0b, // h 0x0c, // i 0x0d, // j 0x0e, // k 0x0f, // l 0x10, // m 0x11, // n 0x12, // o 0x13, // p 0x14, // q 0x15, // r 0x16, // s 0x17, // t 0x18, // u 0x19, // v 0x1a, // w 0x1b, // x 0x1c, // y 0x1d, // z 0x2f|SHIFT, // { 0x31|SHIFT, // | 0x30|SHIFT, // } 0x35|SHIFT, // ~ //ASCII 126 0 // DEL };
uint8_t USBPutChar(uint8_t c);
// press() adds the specified key (printing, non-printing, or modifier) // to the persistent key report and sends the report. Because of the way // USB HID works, the host acts like the key remains pressed until we // call release(), releaseAll(), or otherwise clear the report and resend. size_t Keyboard_::press(uint8_t k) { uint8_t i; if (k >= 136) { // it's a non-printing key (not a modifier) k = k - 136; } else if (k >= 128) { // it's a modifier key _keyReport.modifiers |= (1<<(k-128)); k = 0; } else { // it's a printing key k = pgm_read_byte(_asciimap + k); if (!k) { setWriteError(); return 0; } if (k & 0x80) { // it's a capital letter or other character reached with shift _keyReport.modifiers |= 0x02; // the left shift modifier k &= 0x7F; } }
// Add k to the key report only if it's not already present // and if there is an empty slot. if (_keyReport.keys[0] != k && _keyReport.keys[1] != k && _keyReport.keys[2] != k && _keyReport.keys[3] != k && _keyReport.keys[4] != k && _keyReport.keys[5] != k) {
for (i=0; i<6; i++) { if (_keyReport.keys[i] == 0x00) { _keyReport.keys[i] = k; break; } } if (i == 6) { setWriteError(); return 0; } } sendReport(&_keyReport); return 1; }
// release() takes the specified key out of the persistent key report and // sends the report. This tells the OS the key is no longer pressed and that // it shouldn't be repeated any more. size_t Keyboard_::release(uint8_t k) { uint8_t i; if (k >= 136) { // it's a non-printing key (not a modifier) k = k - 136; } else if (k >= 128) { // it's a modifier key _keyReport.modifiers &= ~(1<<(k-128)); k = 0; } else { // it's a printing key k = pgm_read_byte(_asciimap + k); if (!k) { return 0; } if (k & 0x80) { // it's a capital letter or other character reached with shift _keyReport.modifiers &= ~(0x02); // the left shift modifier k &= 0x7F; } }
// Test the key report to see if k is present. Clear it if it exists. // Check all positions in case the key is present more than once (which it shouldn't be) for (i=0; i<6; i++) { if (0 != k && _keyReport.keys[i] == k) { _keyReport.keys[i] = 0x00; } }
size_t Keyboard_::write(uint8_t c) { uint8_t p = press(c); // Keydown release(c); // Keyup return (p); // just return the result of press() since release() almost always returns 1 }
constint analogInPinX = A0; // Analog input pin that the potentiometer is attached toconstint analogInPinY = A1; // Analog input pin that the potentiometer is attached toint sensorValueX = 0; // value read from the portint sensorValueY = 0; // value read from the portint outputValueX = 0; // value outputint outputValueY = 0; // value outputvoidsetup() {
// initialize serial communications at 9600 bps:Serial.begin(9600);
}
voidloop() {
// read the analog in value:
sensorValueX = analogRead(analogInPinX);
sensorValueY = analogRead(analogInPinY);
// map it to the range of the analog out:
outputValueX = map(sensorValueX, 0, 1023, 0, 255);
outputValueY = map(sensorValueY, 0, 1023, 0, 255);
// change the analog out value:// analogWrite(analogOutPin, outputValue);// print the results to the serial monitor:Serial.print("sensor X = " );
Serial.print(sensorValueX);
Serial.print("\t outputX = ");
Serial.print(outputValueX);
Serial.print("\t sensor Y = " );
Serial.print(sensorValueY);
Serial.print("\t outputY = ");
Serial.print(outputValueY);
Serial.print("\n");
// wait 2 milliseconds before the next loop// for the analog-to-digital converter to settle// after the last reading:delay(2);
}
Arduino IDE のエディタにソースをコピペして「検証」して「マイコンボードに書き込む」を行えば、書き込み終了後に Arduino にリセットがかかって書き込んだプログラムが動き出します。
ソースコードは Examples の JoystickMouseControl のソースを元にして、今回スイッチをプルアップで使っているのでそこだけ書き換えれば(スイッチ関係の INPUT → INPUT_PULLUP、 HIGH → LOW、LOW → HIGH )、あとはそのままで動きます。
/* JoystickMouseControl Controls the mouse from a joystick on an Arduino Leonardo or Micro. Uses a pushbutton to turn on and off mouse control, and a second pushbutton to click the left mouse button Hardware: * 2-axis joystick connected to pins A0 and A1 * pushbuttons connected to pin D2 and D3 The mouse movement is always relative. This sketch reads two analog inputs that range from 0 to 1023 (or less on either end) and translates them into ranges of -6 to 6. The sketch assumes that the joystick resting values are around the middle of the range, but that they vary within a threshold. WARNING: When you use the Mouse.move() command, the Arduino takes over your mouse! Make sure you have control before you use the command. This sketch includes a pushbutton to toggle the mouse control state, so you can turn on and off mouse control. created 15 Sept 2011 updated 28 Mar 2012 by Tom Igoe this code is in the public domain */// set pin numbers for switch, joystick axes, and LED:constint switchPin = 2; // switch to turn on and off mouse controlconstint mouseButton = 3; // input pin for the mouse pushButtonconstint xAxis = A0; // joystick X axis constint yAxis = A1; // joystick Y axisconstint ledPin = 13; // Mouse control LED// parameters for reading the joystick:int range = 12; // output range of X or Y movementint responseDelay = 5; // response delay of the mouse, in msint threshold = range/4; // resting thresholdint center = range/2; // resting position valueboolean mouseIsActive = false; // whether or not to control the mouseint lastSwitchState = HIGH; // previous switch state (PULL_UP)voidsetup() {
pinMode(switchPin, INPUT_PULLUP); // the switch pinpinMode(ledPin, OUTPUT); // the LED pin pinMode(mouseButton, INPUT_PULLUP); // the mouseButton pin// take control of the mouse:Mouse.begin();
}
voidloop() {
// read the switch:int switchState = digitalRead(switchPin);
// if it's changed and it's low, toggle the mouse state:if (switchState != lastSwitchState) {
if (switchState == LOW) {
mouseIsActive = !mouseIsActive;
// turn on LED to indicate mouse state:digitalWrite(ledPin, mouseIsActive);
}
}
// save switch state for next comparison:
lastSwitchState = switchState;
// read and scale the two axes:int xReading = readAxis(A0);
int yReading = readAxis(A1);
// if the mouse control state is active, move the mouse:if (mouseIsActive) {
Mouse.move(xReading, yReading, 0);
}
// read the mouse button and click or not click:// if the mouse button is pressed:if (digitalRead(mouseButton) == LOW) {
// if the mouse is not pressed, press it:if (!Mouse.isPressed(MOUSE_LEFT)) {
Mouse.press(MOUSE_LEFT);
}
}
// else the mouse button is not pressed:else {
// if the mouse is pressed, release it:if (Mouse.isPressed(MOUSE_LEFT)) {
Mouse.release(MOUSE_LEFT);
}
}
delay(responseDelay);
}
/* reads an axis (0 or 1 for x or y) and scales the analog input range to a range from 0 to <range> */int readAxis(int thisAxis) {
// read the analog input:int reading = analogRead(thisAxis);
// map the reading from the analog input range to the output range:
reading = map(reading, 0, 1023, 0, range);
// if the output reading is outside from the// rest position threshold, use it:int distance = reading - center;
if (abs(distance) < threshold) {
distance = 0;
}
// return the distance for this axis:return distance;
}
/* JoystickMouseControl Controls the mouse from a joystick on an Arduino Leonardo or Micro. Uses a pushbutton to turn on and off mouse control, and a second pushbutton to click the left mouse button Hardware: * 2-axis joystick connected to pins A0 and A1 * pushbuttons connected to pin D2 and D3 The mouse movement is always relative. This sketch reads two analog inputs that range from 0 to 1023 (or less on either end) and translates them into ranges of -6 to 6. The sketch assumes that the joystick resting values are around the middle of the range, but that they vary within a threshold. WARNING: When you use the Mouse.move() command, the Arduino takes over your mouse! Make sure you have control before you use the command. This sketch includes a pushbutton to toggle the mouse control state, so you can turn on and off mouse control. created 15 Sept 2011 updated 28 Mar 2012 by Tom Igoe modified August 2015 by HisashiKato this code is in the public domain */// set pin numbers for switch, joystick axes, and LED:constint switchPin = 2; // switch to turn on and off mouse controlconstint mouseButton = 3; // input pin for the mouse pushButtonconstint xAxis = A0; // joystick X axis constint yAxis = A1; // joystick Y axisconstint ledPin = 13; // Mouse control LED// parameters for reading the joystick:int analogInMin = 0;
int analogInMax = 1023;
int analogInRange = analogInMax - analogInMin;
int center = (analogInRange / 2) + analogInMin; // resting position valueint mouseMoveMaxValue = 6; // int range = mouseMoveMaxValue * 2; // output range of X or Y movementint threshold = analogInRange / range; // resting thresholdint responseDelay = 5; // response delay of the mouse, in msboolean mouseIsActive = false; // whether or not to control the mouseint lastSwitchState = HIGH; // previous switch statevoidsetup() {
pinMode(switchPin, INPUT_PULLUP); // the switch pinpinMode(ledPin, OUTPUT); // the LED pin pinMode(mouseButton, INPUT_PULLUP); // the mousButton pin/* // initialize serial communications at 9600 bps: Serial.begin(9600); */// take control of the mouse:Mouse.begin();
}
voidloop() {
// read the switch:int switchState = digitalRead(switchPin);
// if it's changed and it's low, toggle the mouse state:if (switchState != lastSwitchState) {
if (switchState == LOW) {
mouseIsActive = !mouseIsActive;
// turn on LED to indicate mouse state:digitalWrite(ledPin, mouseIsActive);
}
}
// save switch state for next comparison:
lastSwitchState = switchState;
// read and scale the two axes:int xReading = readAxis(A0);
int yReading = readAxis(A1);
// if the mouse control state is active, move the mouse:if (mouseIsActive) {
Mouse.move(xReading, yReading, 0);
/* // print the results to the serial monitor: Serial.print("outputX = "); Serial.print(xReading); Serial.print("\t outputY = "); Serial.print(yReading); Serial.print("\t MouseButton = "); Serial.print(digitalRead(mouseButton)); Serial.print("\n"); */
}
// read the mouse button and click or not click:// if the mouse button is pressed:if (digitalRead(mouseButton) == LOW) {
// if the mouse is not pressed, press it:if (!Mouse.isPressed(MOUSE_LEFT)) {
Mouse.press(MOUSE_LEFT);
}
}
// else the mouse button is not pressed:else {
// if the mouse is pressed, release it:if (Mouse.isPressed(MOUSE_LEFT)) {
Mouse.release(MOUSE_LEFT);
}
}
delay(responseDelay);
}
/* reads an axis (0 or 1 for x or y) and scales the analog input range to a range from 0 to <range> */int readAxis(int thisAxis) {
int reading = analogRead(thisAxis); // read the analog input:int distance = reading - center;
// if the output reading is outside from the rest position threshold, use it:if (abs(distance) < threshold) {
distance = 0;
} else {
// map the reading from the analog input range to the output range:
distance = map(reading, analogInMin, analogInMax, 0, range) - (range/2);
}
return distance; // return the distance for this axis:
}
/* JoystickMouseControl Controls the mouse from a joystick on an Arduino Leonardo or Micro. Uses a pushbutton to turn on and off mouse control, and a second pushbutton to click the left mouse button Hardware: * 2-axis joystick connected to pins A0 and A1 * pushbuttons connected to pin D2 and D3 The mouse movement is always relative. This sketch reads two analog inputs that range from 0 to 1023 (or less on either end) and translates them into ranges of -6 to 6. The sketch assumes that the joystick resting values are around the middle of the range, but that they vary within a threshold. WARNING: When you use the Mouse.move() command, the Arduino takes over your mouse! Make sure you have control before you use the command. This sketch includes a pushbutton to toggle the mouse control state, so you can turn on and off mouse control. created 15 Sept 2011 updated 28 Mar 2012 by Tom Igoe https://www.arduino.cc/en/Tutorial/JoystickMouseControl modified August 2015 by HisashiKato http://kato-h.cocolog-nifty.com/khweblog/ this code is in the public domain */// set pin numbers for switch, joystick axes, and LED:constint switchPin = 2; // switch to turn on and off mouse controlconstint mouseLeftButton = 3; // input pin for the mouse LEFT pushButtonconstint mouseRightButton = 4; // input pin for the mouse RIGHT pushButtonconstint mouseMiddleButton = 5; // input pin for the mouse MIDDLE pushButtonconstint xAxis = A0; // joystick X axis constint yAxis = A1; // joystick Y axisconstint ledPin = 13; // Mouse control LED// parameters for reading the joystick:int analogInMin = 0;
int analogInMax = 1023;
int analogInRange = analogInMax - analogInMin;
int center = (analogInRange / 2) + analogInMin; // resting position valueint mouseMoveMaxValue = 6; // int range = mouseMoveMaxValue * 2; // output range of X or Y movementint threshold = analogInRange / range; // resting thresholdint responseDelay = 6; // response delay of the mouse, in msboolean mouseIsActive = false; // whether or not to control the mouseint lastSwitchState = HIGH; // previous switch statevoidsetup() {
pinMode(switchPin, INPUT_PULLUP); // the switch pinpinMode(ledPin, OUTPUT); // the LED pinpinMode(mouseLeftButton, INPUT_PULLUP); // the mouse Left Button pinpinMode(mouseRightButton, INPUT_PULLUP); // the mouse Right Button pinpinMode(mouseMiddleButton, INPUT_PULLUP); // the mouse Middle Button pin/* // initialize serial communications at 9600 bps: Serial.begin(9600); */// take control of the mouse:Mouse.begin();
}
voidloop() {
// read the switch:int switchState = digitalRead(switchPin);
// if it's changed and it's low, toggle the mouse state:if (switchState != lastSwitchState) {
if (switchState == LOW) {
mouseIsActive = !mouseIsActive;
// turn on LED to indicate mouse state:digitalWrite(ledPin, mouseIsActive);
}
}
// save switch state for next comparison:
lastSwitchState = switchState;
// read and scale the two axes:int xReading = readAxis(xAxis);
int yReading = readAxis(yAxis);
// if the mouse control state is active, move the mouse:if (mouseIsActive) {
Mouse.move(xReading, yReading, 0);
/* // print the results to the serial monitor: Serial.print("outputX = "); Serial.print(xReading); Serial.print("\t outputY = "); Serial.print(yReading); Serial.print("\n"); */
}
// read the mouse button and click or not click:
readMouseButton(mouseLeftButton, MOUSE_LEFT);
readMouseButton(mouseRightButton, MOUSE_RIGHT);
readMouseButton(mouseMiddleButton, MOUSE_MIDDLE);
delay(responseDelay);
}
/* reads an axis (0 or 1 for x or y) and scales the analog input range to a range from 0 to <range> */int readAxis(int thisAxis) {
// read the analog input:int reading = analogRead(thisAxis);
int distance = reading - center;
// if the output reading is outside from the rest position threshold, use it:if (abs(distance) < threshold) {
distance = 0;
} else {
// map the reading from the analog input range to the output range:
distance = map(reading, analogInMin, analogInMax, 0, range) - (range / 2);
}
// the Y axis needs to be inverted in order to// map the movemment correctly:if (thisAxis == yAxis) {
distance = -distance;
}
return distance; // return the distance for this axis:
}
/* read the mouse button and click or not click: */int readMouseButton(int mouseInputPin, int mouseButton) {
// if the mouse button is pressed:if (digitalRead(mouseInputPin) == LOW) {
// if the mouse is not pressed, press it:if (!Mouse.isPressed(mouseButton)) {
Mouse.press(mouseButton);
}
}
// else the mouse button is not pressed:else {
// if the mouse is pressed, release it:if (Mouse.isPressed(mouseButton)) {
Mouse.release(mouseButton);
}
}
}
// set pin numbers for switch, joystick axes, and LED:constint switchPin = 2; // switch to turn on and off mouse controlconstint mouseLeftButton = 3; // input pin for the mouse LEFT pushButtonconstint mouseRightButton = 4; // input pin for the mouse RIGHT pushButtonconstint mouseMiddleButton = 5; // input pin for the mouse MIDDLE pushButtonconstint xAxis = A0; // joystick X axis constint yAxis = A1; // joystick Y axisconstint ledPin = 13; // Mouse control LED// interval time for slow move:constint pointerMoveInterval = 60;
constint scrollInterval = 0;
// parameters for reading the joystick:int xAnalogInMin = 160;
int xAnalogInMax = 890;
int yAnalogInMin = 140;
int yAnalogInMax = 860;
int xPointerMoveDirection = 0;
int yPointerMoveDirection = 0;
int mouseMoveMaxValue = 6; // int range = mouseMoveMaxValue * 2; // output range of X or Y movementint responseDelay = 6; // response delay of the mouse, in msint xSendAxisData = 0;
int ySendAxisData = 0;
int sendWeelData = 0;
// timer:// unsigned long currentMillis;unsignedlong CurrentMillis;
unsignedlong xPreviousMillis = 0; // will store last time mouse move data was updatedunsignedlong yPreviousMillis = 0; // will store last time mouse move data was updated// mouse active switch:boolean mouseIsActive = false; // whether or not to control the mouseint lastSwitchState = HIGH; // previous switch statevoidsetup() {
pinMode(switchPin, INPUT_PULLUP); // the switch pinpinMode(ledPin, OUTPUT); // the LED pinpinMode(mouseLeftButton, INPUT_PULLUP); // the mouse Left Button pinpinMode(mouseRightButton, INPUT_PULLUP); // the mouse Right Button pinpinMode(mouseMiddleButton, INPUT_PULLUP); // the mouse mode change Button pin// initialize serial communications at 9600 bps:Serial.begin(9600);
// take control of the mouse:Mouse.begin();
}
voidloop(){
// read the switch:int switchState = digitalRead(switchPin);
// if it's changed and it's high, toggle the mouse state:if (switchState != lastSwitchState) {
if (switchState == LOW) {
mouseIsActive = !mouseIsActive;
// turn on LED to indicate mouse state:digitalWrite(ledPin, mouseIsActive);
}
}
// save switch state for next comparison:
lastSwitchState = switchState;
// read for I/O:int xReading = readAxis(xAxis, xAnalogInMin, xAnalogInMax);
int yReading = readAxis(yAxis, yAnalogInMin, yAnalogInMax);
// pointer move slow:
CurrentMillis = millis();
xSendAxisData = pointerSlowMove(xReading, xPreviousMillis);
if(xSendAxisData != 0) {
xPreviousMillis = CurrentMillis;
}
ySendAxisData = pointerSlowMove(yReading, yPreviousMillis);
if(ySendAxisData != 0) {
yPreviousMillis = CurrentMillis;
}
// set mouse data for sending to USB:// if the mouse control state is active, move the mouse:if (mouseIsActive) {
Mouse.move(xSendAxisData, ySendAxisData, 0);
// read the mouse button and click or not click:
readMouseButton(mouseLeftButton, MOUSE_LEFT);
readMouseButton(mouseRightButton, MOUSE_RIGHT);
readMouseButton(mouseMiddleButton, MOUSE_MIDDLE);
// print the results to the serial monitor:Serial.print("inputX = ");
Serial.print(xReading);
Serial.print("\t inputY = ");
Serial.print(yReading);
Serial.print("\t outputX = ");
Serial.print(xSendAxisData);
Serial.print("\t outputY = ");
Serial.print(ySendAxisData);
Serial.print("\n");
}
delay(responseDelay);
}
/* read axis data: */int readAxis(int thisAxis, int analogInMin, int analogInMax) {
// read the analog input:int analogInRange = analogInMax - analogInMin;
int center = (analogInRange / 2) + analogInMin;
int reading = analogRead(thisAxis);
reading = constrain(reading, analogInMin, analogInMax);
int distance = reading - center;
int threshold = analogInRange / range; // resting threshold// if the output reading is outside from the rest position threshold, use it:if (abs(distance) < threshold) {
distance = 0;
} else {
// map the reading from the analog input range to the output range:
distance = map(reading, analogInMin, analogInMax, 0, range) - (range / 2);
}
// the Y axis needs to be inverted in order to// map the movemment correctly:if (thisAxis == yAxis) {
distance = -distance;
}
return distance; // return the distance for this axis:
}
/* cursor move low speed: */int pointerSlowMove(int reading, unsignedlong previousMillis) {
unsignedlong currentMillis = millis();
if (reading == 0) {
return 0;
} else {
int interval = pointerMoveInterval / abs(reading);
int pointerMoveDirection = reading / abs(reading);
if (currentMillis - previousMillis < interval) {
return 0;
} else {
return pointerMoveDirection;
}
}
}
/* read the mouse button and click or not click: */int readMouseButton(int mouseInputPin, int mouseButton) {
// if the mouse button is pressed:if (digitalRead(mouseInputPin) == LOW) {
// if the mouse is not pressed, press it:if (!Mouse.isPressed(mouseButton)) {
Mouse.press(mouseButton);
}
}
// else the mouse button is not pressed:else {
// if the mouse is pressed, release it:if (Mouse.isPressed(mouseButton)) {
Mouse.release(mouseButton);
}
}
}
// set pin numbers for switch, joystick axes, and LED:constint switchPin = 2; // switch to turn on and off mouse controlconstint mouseLeftButton = 3; // input pin for the mouse LEFT pushButtonconstint mouseRightButton = 4; // input pin for the mouse RIGHT pushButtonconstint mouseMiddleButton = 5; // input pin for the mouse MIDDLE pushButtonconstint xAxis = A0; // joystick X axis constint yAxis = A1; // joystick Y axisconstint ledPin = 13; // Mouse control LED// interval time for slow move:constint pointerMoveInterval = 60;
constint scrollInterval = 0;
// parameters for reading the joystick:int xAnalogInMin = 160;
int xAnalogInMax = 890;
int yAnalogInMin = 140;
int yAnalogInMax = 860;
int xPointerMoveDirection = 0;
int yPointerMoveDirection = 0;
int pointerMoveMaxValue = 5; // -5 < send data < 5int pointerSlowMoveRange = 3;
int range = (pointerMoveMaxValue + pointerSlowMoveRange) * 2; // output range of X or Y movementint responseDelay = 5; // response delay of the mouse, in msint xSendAxisData = 0;
int ySendAxisData = 0;
int sendWeelData = 0;
// timer:// unsigned long currentMillis;unsignedlong CurrentMillis;
unsignedlong xPreviousMillis = 0; // will store last time mouse move data was updatedunsignedlong yPreviousMillis = 0; // will store last time mouse move data was updated// mouse active switch:boolean mouseIsActive = false; // whether or not to control the mouseint lastSwitchState = HIGH; // previous switch statevoidsetup() {
pinMode(switchPin, INPUT_PULLUP); // the switch pinpinMode(ledPin, OUTPUT); // the LED pinpinMode(mouseLeftButton, INPUT_PULLUP); // the mouse Left Button pinpinMode(mouseRightButton, INPUT_PULLUP); // the mouse Right Button pinpinMode(mouseMiddleButton, INPUT_PULLUP); // the mouse Middle Button pin// initialize serial communications at 9600 bps:Serial.begin(9600);
// take control of the mouse:Mouse.begin();
}
voidloop(){
// read the switch:int switchState = digitalRead(switchPin);
// if it's changed and it's high, toggle the mouse state:if (switchState != lastSwitchState) {
if (switchState == LOW) {
mouseIsActive = !mouseIsActive;
// turn on LED to indicate mouse state:digitalWrite(ledPin, mouseIsActive);
}
}
// save switch state for next comparison:
lastSwitchState = switchState;
// read for I/O:int xReading = readAxis(xAxis, xAnalogInMin, xAnalogInMax);
int yReading = readAxis(yAxis, yAnalogInMin, yAnalogInMax);
// set xAxis data for send:if (xReading == 0) {
// center:
xSendAxisData = 0;
} elseif (abs(xReading) <= pointerSlowMoveRange) {
// slow:
CurrentMillis = millis();
xSendAxisData = pointerSlowMove(xReading, xPreviousMillis);
if(xSendAxisData != 0) {
xPreviousMillis = CurrentMillis;
}
} else {
xSendAxisData = (xReading / abs(xReading)) * (abs(xReading) - pointerSlowMoveRange);
}
// set yAxis data for send:if (yReading == 0) {
// center:
ySendAxisData = 0;
} elseif (abs(yReading) <= pointerSlowMoveRange) {
// slow:
CurrentMillis = millis();
ySendAxisData = pointerSlowMove(yReading, yPreviousMillis);
if(ySendAxisData != 0) {
yPreviousMillis = CurrentMillis;
}
} else {
ySendAxisData = (yReading / abs(yReading)) * (abs(yReading) - pointerSlowMoveRange);
}
// set mouse data for sending to USB:// if the mouse control state is active, move the mouse:if (mouseIsActive) {
Mouse.move(xSendAxisData, ySendAxisData, 0);
// read the mouse button and click or not click:
readMouseButton(mouseLeftButton, MOUSE_LEFT);
readMouseButton(mouseRightButton, MOUSE_RIGHT);
readMouseButton(mouseMiddleButton, MOUSE_MIDDLE);
// print the results to the serial monitor:Serial.print("inputX = ");
Serial.print(xReading);
Serial.print("\t inputY = ");
Serial.print(yReading);
Serial.print("\t outputX = ");
Serial.print(xSendAxisData);
Serial.print("\t outputY = ");
Serial.print(ySendAxisData);
Serial.print("\n");
}
delay(responseDelay);
}
/* read axis data: */int readAxis(int thisAxis, int analogInMin, int analogInMax) {
// read the analog input:int analogInRange = analogInMax - analogInMin;
int center = (analogInRange / 2) + analogInMin;
int reading = analogRead(thisAxis);
reading = constrain(reading, analogInMin, analogInMax);
int distance = reading - center;
int threshold = analogInRange / range; // resting threshold// if the output reading is outside from the rest position threshold, use it:if (abs(distance) < threshold) {
distance = 0;
} else {
// map the reading from the analog input range to the output range:
distance = map(reading, analogInMin, analogInMax, 0, range) - (range / 2);
}
// the Y axis needs to be inverted in order to// map the movemment correctly:if (thisAxis == yAxis) {
distance = -distance;
}
return distance; // return the distance for this axis:
}
/* cursor move low speed: */int pointerSlowMove(int reading, unsignedlong previousMillis) {
unsignedlong currentMillis = millis();
if (reading == 0) {
return 0;
} else {
int interval = pointerMoveInterval / abs(reading);
int pointerMoveDirection = reading / abs(reading);
if (currentMillis - previousMillis < interval) {
return 0;
} else {
return pointerMoveDirection;
}
}
}
/* read the mouse button and click or not click: */int readMouseButton(int mouseInputPin, int mouseButton) {
// if the mouse button is pressed:if (digitalRead(mouseInputPin) == LOW) {
// if the mouse is not pressed, press it:if (!Mouse.isPressed(mouseButton)) {
Mouse.press(mouseButton);
}
}
// else the mouse button is not pressed:else {
// if the mouse is pressed, release it:if (Mouse.isPressed(mouseButton)) {
Mouse.release(mouseButton);
}
}
}
/*2017/02/07 by HisashiKato */#include"Mouse.h"// set pin numbers for switch, joystick axes, and LED:constintswitchPin=2;// switch to turn on and off mouse controlconstintmouseLeftButton=3;// input pin for the mouse LEFT pushButtonconstintmouseRightButton=4;// input pin for the mouse RIGHT pushButton//const int mouseMiddleButton = 5; // input pin for the mouse MIDDLE pushButtonconstintmouseScrollModeButton=5;// input pin for the mouse mode change pushButtonconstintxAxis=A0;// joystick X axis constintyAxis=A1;// joystick Y axisconstintledPin=13;// Mouse control LED// send data when mouse wheel is move:constintscrollWheelStop=0x00;constintscrollWheelUp=0x01;constintscrollWheelDown=0xFF;// interval time for slow move:constintpointerMoveInterval=20;constintscrollInterval=500;// parameters for reading the joystick:intxAnalogInCenter=520;intyAnalogInCenter=505;intxAnalogMaxRange=240;intyAnalogMaxRange=240;intthreshold=30;// resting thresholdintxPointerMoveDirection=0;intyPointerMoveDirection=0;intpointerMoveMaxValue=2;intpointerSlowMoveRange=8;intdivision=(pointerMoveMaxValue+pointerSlowMoveRange)*2;// division numberintresponseDelay=5;// response delay of the mouse, in msintxSendAxisData=0;intySendAxisData=0;intsendWheelData=0;// timer:// unsigned long currentMillis;unsignedlongCurrentMillis;unsignedlongxPreviousMillis=0;// will store last time mouse move data was updatedunsignedlongyPreviousMillis=0;// will store last time mouse move data was updatedunsignedlongwheelPreviousMillis=0;// mouse active switch:booleanmouseIsActive=false;// whether or not to control the mouseintlastSwitchState=HIGH;// previous switch state// mouse mode change switch:booleanscrollMode=false;intlastModeSwitchState=HIGH;// previous switch statevoidsetup(){pinMode(switchPin,INPUT_PULLUP);// the switch pinpinMode(ledPin,OUTPUT);// the LED pinpinMode(mouseLeftButton,INPUT_PULLUP);// the mouse Left Button pinpinMode(mouseRightButton,INPUT_PULLUP);// the mouse Right Button pin//pinMode(mouseMiddleButton, INPUT_PULLUP); // the mouse Middle Button pinpinMode(mouseScrollModeButton,INPUT_PULLUP);// the mouse mode change Button pin// take control of the mouse:Mouse.begin();// initialize serial communications at 9600 bps://Serial.begin(9600);}voidloop(){// read the switch:intswitchState=digitalRead(switchPin);// if it's changed and it's high, toggle the mouse state:if(switchState!=lastSwitchState){if(switchState==LOW){mouseIsActive=!mouseIsActive;// turn on LED to indicate mouse state:digitalWrite(ledPin,mouseIsActive);}}// save switch state for next comparison:lastSwitchState=switchState;// read for I/O:intxReading=readAxis(xAxis,xAnalogInCenter,xAnalogMaxRange);intyReading=readAxis(yAxis,yAnalogInCenter,yAnalogMaxRange);// read the mouseModeSwitch:intmodeSwitchState=digitalRead(mouseScrollModeButton);if(modeSwitchState==LOW){scrollMode=true;}else{scrollMode=false;}if(scrollMode==false){// pointer mode:sendWheelData=scrollWheelStop;// set xAxis data for send:if(xReading==0){// center:xSendAxisData=0;}elseif(abs(xReading)<=pointerSlowMoveRange){// slow:CurrentMillis=millis();xSendAxisData=pointerSlowMove(xReading,xPreviousMillis);if(xSendAxisData!=0){xPreviousMillis=CurrentMillis;}}else{xSendAxisData=(xReading/abs(xReading))*(abs(xReading)-pointerSlowMoveRange);}// set yAxis data for send:if(yReading==0){// center:ySendAxisData=0;}elseif(abs(yReading)<=pointerSlowMoveRange){// slow:CurrentMillis=millis();ySendAxisData=pointerSlowMove(yReading,yPreviousMillis);if(ySendAxisData!=0){yPreviousMillis=CurrentMillis;}}else{ySendAxisData=(yReading/abs(yReading))*(abs(yReading)-pointerSlowMoveRange);}}else{// scroll mode:xSendAxisData=0;ySendAxisData=0;if(yReading==0){// center:sendWheelData=0;}else{// scroll up and down:CurrentMillis=millis();intwheelMoveDirection=yReading/abs(yReading);if(CurrentMillis-wheelPreviousMillis<(scrollInterval/abs(yReading))){sendWheelData=0;}else{if(wheelMoveDirection<0){// scroll up:sendWheelData=scrollWheelUp;}else{// scroll down:sendWheelData=scrollWheelDown;}}if(sendWheelData!=0){wheelPreviousMillis=CurrentMillis;}}}// set mouse data for sending to USB:// if the mouse control state is active, move the mouse:if(mouseIsActive){Mouse.move(xSendAxisData,ySendAxisData,sendWheelData);// read the mouse button and click or not click:readMouseButton(mouseLeftButton,MOUSE_LEFT);readMouseButton(mouseRightButton,MOUSE_RIGHT);// readMouseButton(mouseMiddleButton, MOUSE_MIDDLE);/* // print the results to the serial monitor: Serial.print("inputX = "); Serial.print(xReading); Serial.print("\t inputY = "); Serial.print(yReading); Serial.print("\t outputX = "); Serial.print(xSendAxisData); Serial.print("\t outputY = "); Serial.print(ySendAxisData); Serial.print("\t outputWheel = "); Serial.print(sendWheelData); Serial.print("\n"); */}//delay(responseDelay);}/* read axis data: */intreadAxis(intthisAxis,intcenter,intmaxRange){// read the analog input:intanalogInMin=center-maxRange;intanalogInMax=center+maxRange;intreading=analogRead(thisAxis);reading=constrain(reading,analogInMin,analogInMax);intdistance=reading-center;// if the output reading is outside from the rest position threshold, use it:if(abs(distance)<threshold){distance=0;}else{// map the reading from the analog input range to the output range:distance=map(reading,analogInMin,analogInMax,0,division)-(division/2);}// the Y axis needs to be inverted in order to// map the movemment correctly:if(thisAxis==yAxis){distance=-distance;}returndistance;// return the distance for this axis:}/* cursor move low speed: */intpointerSlowMove(intreading,unsignedlongpreviousMillis){unsignedlongcurrentMillis=millis();if(reading==0){return0;}else{intinterval=pointerMoveInterval/abs(reading);intpointerMoveDirection=reading/abs(reading);if(currentMillis-previousMillis<interval){return0;}else{returnpointerMoveDirection;}}}/* read the mouse button and click or not click: */intreadMouseButton(intmouseInputPin,intmouseButton){// if the mouse button is pressed:if(digitalRead(mouseInputPin)==LOW){// if the mouse is not pressed, press it:if(!Mouse.isPressed(mouseButton)){Mouse.press(mouseButton);}}// else the mouse button is not pressed:else{// if the mouse is pressed, release it:if(Mouse.isPressed(mouseButton)){Mouse.release(mouseButton);}}}
こんな感じで。
おまけ:Arduino IDE で困った話
今まで Arduino IDE の 1.7.x を使っていたのですが、Arduino 分裂解消ということで、せっかくなので、最新の 1.8.1 に上げてみました。 そしたら、コンパイル時に、「 error: 'USB_EP_SIZE' was not declared in this scope 」とエラーが出て、なんじゃこりゃ!?に。 USBAPI.h を覗いてみたら、ちゃんと宣言されてるし。いろいろ試して以下のようなことに。 ・USB HID とかかんけーない、スケッチ例の Blink でさえ、コンパイルエラーが出る。 ・ボードで、チップ本体にUSBを積んでない UNO を選ぶとエラーは出ない、Leonardo,Micro でエラー出る。 ・1.7.x をインストールしなおすと、エラーは出ない、1.8.1 と 1.6.x をインストールすると駄目。 ・別のPCに、1.8.1 を入れてみたら、そっちではエラーは出ずに正常にコンパイル終了した。 てな感じ。 テンポラリとか探しまくって消してみたけど解決せず。 こりゃアンインストールしても、どっかに何かが残留してて、何か悪さしてるのかなー、最悪、メインPCの Windows10 をクリーンインストールかぁ・・・? などと思っていたのですが、ふと、Arduino の Wiki に書かれていた、「Arduino IDE は Javaアプリケーションだよ」というのを思い出しまして、うちのメインPCでJava関係だと、Java本体と、AndroidStudio が入れてあったなーと。 試しに、Java と AndroidStudio をアンインストールして、再インストール。 そして、 Arduino IDE 1.8.1 をインストールしてみたところ、エラー出なくなりました!!! 何が起きてたんでしょうねぇ何かが不具合を起こしてたんでしょうね、とにかく正常になって良かった。
※これに記載されているキーボードマトリクスなのですが、私の手元にあって分解した無名メーカー製のUSBキーボードのキーマトリクスとかなり似通っていました。全く異なる2個をバラしたのですがその2個が全く同一のマトリクスで驚きました(但しメンブレンシートの配線のパターン図は異なってました) もしかしたらですが、今出回っているUSBキーボードに使われているいくつかのマイコンチップとそれのファームウェアは、このリファレンスの68HC08とソースを使っているか、またはセカンドソースか、互換品か、または他のチップに置き換えたコピーだったりするのかもしれませんね。あくまで想像ですけれど。 今のほとんどのUSBキーボードの中の制御チップは、チップ表面の刻印が無くて不明だったり、COB実装(Chip on board、半導体チップをそのまま基板に載せて配線して上から黒い樹脂をかぶせちゃう)なので、中身までは分からないのですよね。
最近のコメント