« 2015年6月 | トップページ | 2016年2月 »

2015年10月の1件の記事

2015年10月10日 (土)

Arduino Micro を使って、試しに USB スライドパッド マウスを作ってみた(小型USBキーボード自作のための準備色々)

※2017/02/06:更新、追加しました。

※注意!:私、はっきり言って、ほぼ素人です!!!、電子工作をちょろっとと、無印 C言語を少しかじったことがあるだけです。間違い等がある可能性が十分にありますので、ここはあくまで参考程度として、みなさん各自で試行錯誤してくださいませ。ここの間違い指摘は大歓迎です。

小型USBキーボードを自作してみたいと考え始めたわけですが、そのための情報収集や自分の経験値を積み重ねる必要があると思ったので、段階的に色々と作っていこうと思っています。

まずはマイコンを実際に使ってみないと。という目的と、キーボードにポインティングデバイスを付けたいという理由から、USBマウスっぽいものを作ってみる事にしました。

使用するマイコンは、前のブログ記事「USBキーボードは自作できるのか下調べをしてみる」で検討した結果から、
Arduino Micro」に決めました。

ポインティングデバイスは、小型のトラックボールが魅力的だったのですが、部品の入手先が少なくなってるのと、お値段がちょいお高いので今回はやめて、
3DSやPSPなどで使用されている、スライドさせるタイプのアナログジョイスティックを使ってみることにしました。

部品の購入は、今回、初めて秋月電子通商さんの通販を利用させて頂きました。
東京で働いていた頃、秋葉原で、まだLaOX ザ・コンピューター館が健在でその裏の通りでT-ZONEもあった頃に、店舗にはちょくちょく寄らさせて頂いてました。

通販で注文した部品は、

Arduino Micro 本体
アナログジョイスティックのパーツ
・仮組み実験用のブレッドボード
・ブレッドボード用のワイヤー
などなど

ネットで注文して数日で到着。
こんな感じで部品ごとにジップ袋に入れられてました。

Pict002

 

これが Arduino Micro

Pict0008

想像していたより小っさかったです。

こちらはアナログジョイスティックのパーツ

Pict0004

レバーを倒す(傾ける)タイプではなくて、平面的にスライドさせるタイプです。
外形は1.75cm角、厚さ5.5mm(レバー含まず)中に可変抵抗がXY軸でふたつ入っています。
100円

Arduino Micro を早速動かしてみます。
Arduino 入門」などで検索をかけて、まずは基本の「Lチカ」LEDの点滅あたりから初めて、色々と試してみます。

PCに Arduino IDE(統合開発環境、Arduinoに書き込むプログラムを開発するためのソフトウェア)をインストール。(1.6.x はこちら1.7.x はこちらから)
PCと Arduino Micro は、microUSBケーブルで繋ぎます。
microUSBのB端子ケーブルは、Androidスマートフォンなどで使っているもので良いですが、充電専用のケーブルはデータ線が繋がっていなくて使えませんので、データ通信対応のケーブルを用意してください。

プログラムの記述、コンパイル、Arduino Micro 本体へのプログラム書き込みの方法などは、入門サイトを見て回ってくださいな。
Arduino Leonard 、Arduino Micro などのUSB内蔵タイプでは従来のArduinoシリーズとは書き込みの仕様が異なるとのことですので、スイッチサイエンスさんが日本語に翻訳をしてくださった「Arduino Leonardoへのガイド」をお読みください。
あとArduino のプログラム言語のリファレンスの日本語訳が「Arduino 日本語リファレンス」にあります。

「Lチカ」等で使用するLEDですが、Arduinoでは13番ピンにLEDが繋がっていて基板上に実装されていますので、それを使用しました。

スイッチの入力は、内部プルアップ抵抗を有効にして、スイッチだけ繋ぎました。外部抵抗省略。
プルアップの場合はスイッチの片側はグランドに繋ぎます。
LOWアクティブの動作になります(スイッチを押すとHIGHからLOWに変わります)

この辺りを変更している場合は、スケッチ(プログラム)を記述する時に注意です。

ソースコードは Arduino 本家のページにある Leaning > Examples を参考にします(ほぼ丸写し)
例題が色々そろってて有り難いです。

Arduino Micro のピン配置

Arduinomicro_pinout

Arduino Micro と一緒に購入したアナログジョイスティックの入力を試してみます。
基本は可変抵抗の入力なので Arduino 公式の Examples のアナログ入力と JoystickMouseControl を読んでいきます。

Examples の JoystickMouseControl を読みながら、Arduino Micro とアナログジョイスティックのパーツを結線していきます。

ここで注意、この JoystickMouseControl の解説ページですが、上の結線図や回路図と、下のソースコードで食い違いがあったりします。

下のソースコードでは、マウスのクリック用のプッシュスイッチに加えて、Arduino がマウスとして動作するのを ON/OFF するためのプッシュスイッチが追加になっています。
これは Arduino がUSBマウスとして動作している間はPCにマウスが追加で接続されている状態になるために、もし Arduino が意図しないマウスの移動信号を出し続けてしまうと、PCに繋いである普段使いのマウスの動作を邪魔してしまって、マウスでの操作が出来なくなる恐れがあるためです。
まぁ、そうなったら Arduino 側のUSBケーブルを引っこ抜いちゃえば嫌でも止まるんですけれどね。
それではスマートでは無いので Examples のソースコードでは ON/OFF のスイッチが追加になってます。

ジョイスティックのパーツはテスターなどでパーツの中の配線を確認しておきます。

購入したパーツは下図のようになってました。

Analogjoystick

片側3本の端子のうち左右が抵抗の両端で真ん中が可変部分、端子の間隔は2.54mmではなくて2mm間隔です。

抵抗の両端を GND と 5V に繋げて、可変する端子を Arduino のアナログ入力に繋げます。
今回は X軸方向は A0、Y軸方向は A1。

ここでの注意は、アナログ入力の X-Y の向き。
USB HIDの規格では、左上が原点になっていて、右方向にX軸、下方向(手前側方向)にY軸です。
Hid1_11_30p

アナログ出力の上下がこれに合うようにジョイスティックパーツの5VとGNDを配線してください。

ジョイスティックパーツの端子の両端を5VとGNDに。真ん中の出力をアナログ入力の A0 と A1 に繋ぎます。(なぜこのように繋ぐとアナログの可変値が読み取れるのかは「可変抵抗 分圧回路」で検索してみてくださいな)
デジタル入出力の2番にマウスON/OFF用のタクトスイッチ、3番にマウスクリック。
内部プルアップを使うことにするので、片側は GND に落とします。

Pict0012

Arduino Micro (及び Arduino Leonardo 等も含めたUSB内蔵タイプ)は、これ単体で、それまでのUSBのシリアル入出力と、USB HID での入出力を混在させることが出来るようになっています。

なので、USBシリアル出力で生データをPCに送りつつ USB HID の出力も行う、といったことが可能です。
これがけっこう助かります。

手始めに、ジョイスティックから入力される生のデータをシリアルで出力させてみます。
ついでに map 関数を試しに使ってみたり。
Examples のアナログ入力のソースを切り貼り。
ここから先のソースコードには
#include "Keyboard.h"
#include "Mouse.h"

の記載がありません。
Arduino IDE 1.7.x を使用しているためです。
理由は後述します。

 

const int analogInPinX = A0;  // Analog input pin that the potentiometer is attached to
const int analogInPinY = A1;  // Analog input pin that the potentiometer is attached to

int sensorValueX = 0;        // value read from the port
int sensorValueY = 0;        // value read from the port
int outputValueX = 0;        // value output
int outputValueY = 0;        // value output

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
}

void loop() {
  // 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 にリセットがかかって書き込んだプログラムが動き出します。

シリアルモニタを開くと Arduino から送られてくるデータが表示されます(COMポートを合わせてくださいね)
ジョイスティックをスライドさせると数値の変化が分かります。

動かした時の数値を見てお気づきかと思いますが、スティックに触っていない中立の時の値が、1024 / 2 の 512ぴったりにはなりません(Arduino Micro のアナログ入力は 0 - 1023 の10bit)
ズレます。そして一定の値を取りません。
バネの力で中立位置に戻るので、上に上げてからスティックを離した時とか下に下げたあとスティックを離した時などでも中立時の数値が変わります。
これは部品や構造の個体差なので、ぴったりにはどうしてもなりません。
そこでソフト側で補正をしてやらないといけないのですが、それは後述します。

続いて、Examples の JoystickMouseControl のソースを使って、USBマウスとして動かしてみます。

結線は配線図ではなくソースコードに書かれている通りに、このブログの画像のように繋げます。

ソースコードは 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:
const int switchPin = 2;      // switch to turn on and off mouse control
const int mouseButton = 3;    // input pin for the mouse pushButton
const int xAxis = A0;         // joystick X axis  
const int yAxis = A1;         // joystick Y axis
const int ledPin = 13;        // Mouse control LED

// parameters for reading the joystick:
int range = 12;               // output range of X or Y movement
int responseDelay = 5;        // response delay of the mouse, in ms
int threshold = range/4;      // resting threshold
int center = range/2;         // resting position value

boolean mouseIsActive = false;    // whether or not to control the mouse
int lastSwitchState = HIGH;       // previous switch state (PULL_UP)

void setup() {
  pinMode(switchPin, INPUT_PULLUP);   // the switch pin
  pinMode(ledPin, OUTPUT);            // the LED pin  
  pinMode(mouseButton, INPUT_PULLUP); // the mouseButton pin
 // take control of the mouse:
  Mouse.begin();
}

void loop() {
  // 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;
}

動かしてみると、確かに動くのですが、操作感がよろしくないです。

reading = map(reading, 0, 1023, 0, range);

で reading の値を[ 0 < 1023 ]→ [ 0 < 12 ] に変換しています(詳しくは map関数の説明を読んで下さい)

distance(移動量)は、

int distance = reading - center;

で、[ -6 < 0(中立) < 6 ] 0 ~ ±6 となります。

その後で、中立位置のブレを吸収する処理をしています。
threshold(しきい値)を range/4 = 3 として、


if (abs(distance) < threshold) {
    distance = 0;
  }

で、移動量の絶対値が 3 より小さい場合は、0(中立)と見なします。
このために、移動量は[ -6,-5,-4,-3,0,3,4,5,6 ]となり、3以下の移動量(1,2)が出力されることが無くなるため、移動量が3以下の細かな操作が出来なくなっています。
ポインタの動きがかなりおおざっぱになっていて、動かしづらいです。

そこで、変更してみました。
先に、しきい値を適用して中立位置のブレを吸収しておき、そのあとで map関数で移動量に最適化します。
これなら、移動量は[,,,-3,-2,-1,0,1,2,3,,,]となります。

書いてみたのが以下のソースです。
しきい値(threshold)を設定する計算式は、てきとーで雰囲気で、なんとなく。多分大丈夫。

チェック用にシリアル出力を入れてあります(コメントアウトしてあります)
シリアル出力で数値を確認する場合は、マウスON/OFFスイッチでONにする前に、シリアルモニタを開いておいてください。


/*
  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:
const int switchPin = 2;      // switch to turn on and off mouse control
const int mouseButton = 3;    // input pin for the mouse pushButton
const int xAxis = A0;         // joystick X axis  
const int yAxis = A1;         // joystick Y axis
const int 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 value
int mouseMoveMaxValue = 6;                      // 
int range = mouseMoveMaxValue * 2;              // output range of X or Y movement
int threshold = analogInRange / range;          // resting threshold
int responseDelay = 5;                          // response delay of the mouse, in ms

boolean mouseIsActive = false;    // whether or not to control the mouse
int lastSwitchState = HIGH;       // previous switch state

void setup() {
  pinMode(switchPin, INPUT_PULLUP);       // the switch pin
  pinMode(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();

}

void loop() {
  // 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:
}

まだいまいち。

今回ポインティングデバイスとして、スライドするタイプのアナログジョイスティックのパーツを購入したのですが、同じタイプのジョイスティックを、3DSやPSP等で使用しているのを知りました(私、携帯型ゲーム機を持っていないので知らなかったのです)

ネットを色々見ていたら、どうやら同じような部品っぽいので、使ってみようと思いつきまして、中古で300円だった「ニンテンドー3DS専用拡張スライドパッド」というオプションを購入しました。

Img_3ds_slidepad

「3DS専用拡張スライドパッド」は、3DSの右側にもスライドパッドを、そして、Lボタンx1、Rボタンx2、を3DSに増設するオプションで、3DSとは赤外線経由で接続されます。

これを分解して、中の基板を取り払って、配線を引き出して、Arduino に繋いでみることにしました。

「3DS用拡張スライドパッド」の分解方法を調べると、専用のY字頭のドライバーが必要ということで、送料を合わせても格安のをネット通販で購入。数回しか使いませんしね、使えれば安物で十分。けれど安いせいか握り部分に成形のバリがあって回すと手が痛かったのでバリを削りました。

早速分解、を始めたのですが、ネットの分解の解説をチラ見していただけだったので、スライドパッドの部品からのフレキケーブルを基板に繋ぐラッチ付きコネクタを壊してしまいました、やっちまった・・・
仕方が無いので、スライドパッドの部品を加工してフレキケーブルを取っ払って端子を露出させて、ケーブルで直結しました。
何とか復旧。

各スイッチ等は、こんな感じの配線になってました。
Sp
これをそのまま外に引き出して、ブレッドボードに刺さるようにしました。
あとは結線するだけ。

Rボタン:左クリック
ZRボタン:右クリック
ZLボタン:センタークリック

に、とりあえず割り当てて配線。

Pict0007

ソフトウェアでのスクロールホイール機能の実装は後日にすることにしました。

試しに最初の生データをシリアルで出力させるプログラムを書き込んで、スライドパッドから出力されるデータを見てみます。

このスライドパッドでは、今度は出力の最小値と最大値が 0 と 1023 になりません。
このようにアナログの部品はそれぞれ違いが出るので、補正のプログラムを組まなければなりません。キャリブレーションというやつです。
が、後回し。今回は手を付けてません。

スライドパッドの部品の内部の配線の都合上、Y軸の値の増加は上方向になります。
送られてくる Y軸のデータをそのまま使うとパッドを上に動かした時にカーソルが下に動いてしまうので、反転させます。

そして色々いじくってみたのが以下のソースです。

/*
  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:
const int switchPin = 2;      // switch to turn on and off mouse control

const int mouseLeftButton   = 3;    // input pin for the mouse LEFT pushButton
const int mouseRightButton  = 4;    // input pin for the mouse RIGHT pushButton
const int mouseMiddleButton = 5;    // input pin for the mouse MIDDLE pushButton

const int xAxis = A0;         // joystick X axis  
const int yAxis = A1;         // joystick Y axis

const int 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 value
int mouseMoveMaxValue = 6;                      // 
int range = mouseMoveMaxValue * 2;              // output range of X or Y movement
int threshold = analogInRange / range;          // resting threshold
int responseDelay = 6;                          // response delay of the mouse, in ms

boolean mouseIsActive = false;    // whether or not to control the mouse
int lastSwitchState = HIGH;       // previous switch state

void setup() {
  pinMode(switchPin, INPUT_PULLUP);            // the switch pin
  pinMode(ledPin, OUTPUT);                     // the LED pin
  pinMode(mouseLeftButton, INPUT_PULLUP);      // the mouse Left Button pin
  pinMode(mouseRightButton, INPUT_PULLUP);     // the mouse Right Button pin
  pinMode(mouseMiddleButton, INPUT_PULLUP);    // the mouse Middle Button pin
  
/*
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
 */
  
  // take control of the mouse:
  Mouse.begin();
  
  
}

void loop() {
  // 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);
    }
  }
}


これで一応、USBマウスとして使えます、が、快適とは言えません。

マウスホイール機能の実装も含めて、次回。
(つづく)

追記:2015/09/18
先日、Arduino Micro の製品ページを見たら「Arduino/Genuino MICRO」と表記が変わってて「?」と思っていたのですよ。
あと、上記のソースの元になったサンプルコードが、最近、若干書き換えられてさらに「???」に。
サンプルコードにヘッダファイルのインクルードが追加されたけれど、そのヘッダファイルうちのIDEの中になくなくない???って。

実は、、Arduino の組織が内部分裂をしているのは知っていたのですが、WEBページまで分かれていることを、今さらですが知りました。

ずっと見ていた Arduino のWEBページは、https://www.arduino.cc/ で、ここのダウンロードのページで配布されている Arduino IDE は、
Arduino 1.6.x なのですが、

今、私が使っている Arduino IDE は、http://www.arduino.org/ からダウンロードした、
Arduino 1.7.6 だったのでした。

あれ?どーゆー経緯で自分は 1.7.x の方を落として使ってたんだろ?覚えてない・・・
とりあえず、私のソースは、1.7.x を前提としているということで、よろしくお願いします。

 

追記:2015/10/10
ソフトウェア追加です。

キャリブレーション(Calibration 較正)

今回使用した3DS用拡張スライドパッドのアナログスライドパッドの部品からの出力のことなのですが、
シリアルモニタで生データを見るとお分かりでしょうが、出力の最小値と最大値が、0 - 1023 にならずに、0より大きな値から1023より小さな値の範囲になります。
これは多分、部品のばらつきの問題や、スライドパッドの部品に余計な負荷が掛からないようにするために、あえてスライドパッド部品の最小と最大に行かないように、パッド部分が動く範囲を成形品の方で制限しているでしょう。

プログラム側では、今使用しているスライドパッドの出力値の最小と最大が必要になるので(ソース内のアナログ入力の analogInMin と analogInMax)、これを調べておかなければなりません。
そこで、Example の Calibration を元にして、
スライドパッドの出力データの最小と最大を表示させるプログラムを書いてみました。

// set pin numbers for switch, joystick axes, and LED:
const int switchPin = 2;      // switch to turn on and off mouse control
const int ledPin = 13;        // Mouse control LED

const int xAxis = A0;         // joystick X axis  
const int yAxis = A1;         // joystick Y axis

// variables:
int xSensorValue = 0;         // the sensor value
int xSensorMin = 1023;        // minimum sensor value
int xSensorMax = 0;           // maximum sensor value
int ySensorValue = 0;         // the sensor value
int ySensorMin = 1023;        // minimum sensor value
int ySensorMax = 0;           // maximum sensor value

int xCenter;
int yCenter;

boolean valueReset = true;
int stopCount= 0;

int xMinTotal = 0;
int xMaxTotal = 0;
int yMinTotal = 0;
int yMaxTotal = 0;

int xMinAverage;
int xMaxAverage;
int yMinAverage;
int yMaxAverage;

int responseDelay = 5;        // response delay of the mouse, in ms

// mouse active switch:
boolean mouseIsActive = false;    // whether or not to control the mouse
int lastSwitchState = HIGH;       // previous switch state


void setup() {
  // turn on LED to signal the start of the calibration period:
  pinMode(switchPin, INPUT_PULLUP);            // the switch pin
  pinMode(ledPin, OUTPUT);                     // the LED pin
  
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
}

void loop() {
  // 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;

  // if the mouse control state is active, move the mouse:
  if (mouseIsActive) {
    valueReset = false;
    
    // read the sensor:
    xSensorValue = analogRead(xAxis);
    ySensorValue = analogRead(yAxis);

    // record the maximum sensor value
    if (xSensorValue > xSensorMax) {
      xSensorMax = xSensorValue;
    }
    if (ySensorValue > ySensorMax) {
      ySensorMax = ySensorValue;
    }
    // record the minimum sensor value
    if (xSensorValue < xSensorMin) {
      xSensorMin = xSensorValue;
    }
    if (ySensorValue < ySensorMin) {
      ySensorMin = ySensorValue;
    }

    xCenter = ((xSensorMax - xSensorMin) / 2) + xSensorMin;
    yCenter = ((ySensorMax - ySensorMin) / 2) + ySensorMin;

    // print the results to the serial monitor:
    Serial.print("input_X = ");
    Serial.print(xSensorValue);
    Serial.print("\t input_Y = ");
    Serial.print(ySensorValue);

    Serial.print("\t X_Min = ");
    Serial.print(xSensorMin);
    Serial.print("\t X_Max = ");
    Serial.print(xSensorMax);
    Serial.print("\t Y_Min = ");
    Serial.print(ySensorMin);
    Serial.print("\t Y_Max = ");
    Serial.print(ySensorMax);

    Serial.print("\t X_Center = ");
    Serial.print(xCenter);
    Serial.print("\t Y_Center = ");
    Serial.print(yCenter);

    Serial.print("\n");
  
  } else {
    if (!valueReset) {
      stopCount += 1;

      xMinTotal += xSensorMin;
      xMaxTotal += xSensorMax;
      yMinTotal += ySensorMin;
      yMaxTotal += ySensorMax;

      xMinAverage = xMinTotal / stopCount;
      xMaxAverage = xMaxTotal / stopCount;
      yMinAverage = yMinTotal / stopCount;
      yMaxAverage = yMaxTotal / stopCount;

      Serial.print("\n");
      Serial.print("X_Min_ave = ");
      Serial.print(xMinAverage);
      Serial.print("\t X_Max_ave = ");
      Serial.print(xMaxAverage);
      Serial.print("\t Y_Min_ave = ");
      Serial.print(yMinAverage);
      Serial.print("\t Y_Max_ave = ");
      Serial.print(yMaxAverage);

      Serial.print("\t stop = ");
      Serial.print(stopCount);

      Serial.print("\n");

      //reset min max value:
      xSensorMin = 1023;
      xSensorMax = 0;
      ySensorMin = 1023;
      ySensorMax = 0;

      valueReset = true;
    }
  }
  
  delay(responseDelay);
}

これを書き込んで、シリアルモニタを起動して、マウス起動スイッチを押すと、シリアルに生データを吐き出します。
スライドパッドをぐーるぐーると縁に沿って回してやると、Min と Max に最小値と最大値が残るようになっています。
マウス起動スイッチを押して停止させると、最小値と最大値、停止した回数が表示されるように書き加えてあります。
そしておまけ要素として、
動かして最小と最大を計測する>止める>また動かして計測する、
を繰り返すと、止めた回数を元にした、最小値と最大値の平均値(Max_ave)を表示するようにしてあります。あんまし意味ないですが目安程度にはなるかと。

この値を見ながら、アナログ入力の最小値と最大値 analogInMin と analogInMax を決めると良いと思います。
(平均値から少し内側の数値にするとよろしいかもです)



マウスポインタの移動速度

PC等に渡される、マウスの移動量の数値ですが、Example を始め、今回のプログラム群では、[-6 < 0 < 6]に指定しています。
移動量の最小の値は [ ±1 ] なのですが、移動量が[ 1 ]になっても、下記のような感じでデータが渡されるので、出力された回数の分だけ、ポインタが動いてしまいます。

こんな感じというか雰囲気
...333333222222111111000000111111000000000000111111111111222222...

プログラムの周回ディレイを長めにとることで対応することが可能だと思います。ですが、それをするとプログラム全体の動作が遅くなるのでデータの取りこぼしや遅延が起きてしまいます。

そこで、今回は、以下のような方法を試してみました。
移動量[ 1 ]を渡したあとに、一定時間[ 0 ]を挟み、その後再び[ 1 ]を渡すを繰り返します。
こうすると、ちょっと動いては止まる、ちょっと動いては止まる、となって見かけ上はゆっくり移動することになります。
そして[ 0 ]を挟む時間を変えることで移動速度の調整が出来ます。こんな感じで

...11111111111001001001001000001000001000001000001000000000000000....

空ける間隔(0を挟む時間)は内蔵のタイマーを元にします。
このあたりは Example の Blink Without Delay を参考にしました。

そしてとりあえず作ってみたのが、移動量は[ 1 ]のみで、それを出力する間隔だけ可変させるテストプログラムです。

マウスカーソルがスライドパッドを動かした量に合わせて、ゆぅーっくり動きます。

// set pin numbers for switch, joystick axes, and LED:
const int switchPin = 2;      // switch to turn on and off mouse control

const int mouseLeftButton   = 3;    // input pin for the mouse LEFT pushButton
const int mouseRightButton  = 4;    // input pin for the mouse RIGHT pushButton
const int mouseMiddleButton = 5;    // input pin for the mouse MIDDLE pushButton

const int xAxis = A0;         // joystick X axis  
const int yAxis = A1;         // joystick Y axis

const int ledPin = 13;        // Mouse control LED

// interval time for slow move:
const int pointerMoveInterval = 60;
const int 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 movement

int responseDelay = 6;                          // response delay of the mouse, in ms

int xSendAxisData = 0;
int ySendAxisData = 0;
int sendWeelData = 0;

// timer:
// unsigned long currentMillis;
unsigned long CurrentMillis;
unsigned long xPreviousMillis = 0;        // will store last time mouse move data was updated
unsigned long yPreviousMillis = 0;        // will store last time mouse move data was updated

// mouse active switch:
boolean mouseIsActive = false;    // whether or not to control the mouse
int lastSwitchState = HIGH;       // previous switch state


void setup() {
  pinMode(switchPin, INPUT_PULLUP);            // the switch pin
  pinMode(ledPin, OUTPUT);                     // the LED pin
  pinMode(mouseLeftButton, INPUT_PULLUP);      // the mouse Left Button pin
  pinMode(mouseRightButton, INPUT_PULLUP);     // the mouse Right Button pin
  pinMode(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();

}

void loop(){
  // 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, unsigned long previousMillis) {
  unsigned long 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);
    }
  }
}

このゆっくり移動と、通常移動を合わせます。

 

これまでのマウスのプログラムではスライドパッドの移動量と出力する移動量をそのまま map 関数で対比させていましたが、それを低速移動の領域と通常移動の領域に分割してみました。
以下の図のようにしてみました。(クリックで拡大します、が、この図は間違ってるかも???)
Analog_1
作ってみたのが以下のテストプログラムです。

// set pin numbers for switch, joystick axes, and LED:
const int switchPin = 2;      // switch to turn on and off mouse control

const int mouseLeftButton   = 3;    // input pin for the mouse LEFT pushButton
const int mouseRightButton  = 4;    // input pin for the mouse RIGHT pushButton
const int mouseMiddleButton = 5;    // input pin for the mouse MIDDLE pushButton

const int xAxis = A0;         // joystick X axis  
const int yAxis = A1;         // joystick Y axis

const int ledPin = 13;        // Mouse control LED

// interval time for slow move:
const int pointerMoveInterval = 60;
const int 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 < 5
int pointerSlowMoveRange = 3;
int range = (pointerMoveMaxValue + pointerSlowMoveRange) * 2;  // output range of X or Y movement

int responseDelay = 5;                          // response delay of the mouse, in ms

int xSendAxisData = 0;
int ySendAxisData = 0;
int sendWeelData = 0;

// timer:
// unsigned long currentMillis;
unsigned long CurrentMillis;
unsigned long xPreviousMillis = 0;        // will store last time mouse move data was updated
unsigned long yPreviousMillis = 0;        // will store last time mouse move data was updated

// mouse active switch:
boolean mouseIsActive = false;    // whether or not to control the mouse
int lastSwitchState = HIGH;       // previous switch state


void setup() {
  pinMode(switchPin, INPUT_PULLUP);            // the switch pin
  pinMode(ledPin, OUTPUT);                     // the LED pin
  pinMode(mouseLeftButton, INPUT_PULLUP);      // the mouse Left Button pin
  pinMode(mouseRightButton, INPUT_PULLUP);     // the mouse Right Button pin
  pinMode(mouseMiddleButton, INPUT_PULLUP);    // the mouse Middle Button pin

  
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
  
  // take control of the mouse:
  Mouse.begin();

}

void loop(){
  // 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;
  } else if (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;
  } else if (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, unsigned long previousMillis) {
  unsigned long 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);
    }
  }
}

これでマウスカーソルを動かすと、かなり自然に移動させられると自分では感じたのですがどうでしょうか?

 

スクロールホイール

続いてマウスのスクロールホイールの機能の実装です。
Arduino IDE のUSBマウスの関数 Mouse.move() には、スクロールホイールのパラメータも設定出来るようになっています。https://www.arduino.cc/en/Reference/MouseMove

Mouse.move(xVal, yPos, wheel) <?(yPosは本当はyVal?)

但し、この wheel の変数に、具体的に、いったい何を入れればいいかは、リファレンスに書かれていません。
(私が見つけられなかっただけ?)

とにかくググって探してみたところ、以下のような感じの文章が、USBマウス関連のとあるデータシートにあるのを見つけました。

以下では、USBレポートプロトコルのフォーマットで、4番目のバイトにホイールの動きの情報を追加することが可能であることを説明します。
ホイールを前方に移動すると4番目のバイトに「0x01」を報告し、
後方に移動したときは4番目のバイトに「0xFF」を報告します。
ホイールが停止状態のときには、このバイトには「0x00」が割り当てられます。

つまり、ホイールを回して1回カコンと動くたびに、前方の時は「0x01(+1)」を、後方の時は「0xFF(-1)」をデータとして渡して、動いていない時は「0x00」を入れておく、ということらしいです。

というわけで、Mouse.move(xVal, yPos, wheel) 関数の wheel 変数に、この値を入れてみることにしました。
但しホイールを回すスピード、つまりはクリック感(カコカコ)の時間の間隔を変えることでスクロールのスピードが変わるっぽいので、上で使った、マウスポインタのゆっくり移動の方法をそのまま使ってみることにしました。カコカコの間隔をスライドパッドを動かした量に比例させます。

そしで出来たのがスクロールホイールの機能も使えるようにしたプログラム。
ZLボタン(デジタルインプットの5番ピン)をスクロールの切替にしてあります。押すとスクロールホイールモードになり、もう一度押すとマウスモードになるという、トグルにしてあります。
これは以前購入した小型のトラックボールの仕様にあわせてみました。
これ。(これ、どっかから再販売されないかな…)
400ma018_ma

// set pin numbers for switch, joystick axes, and LED:
const int switchPin = 2;      // switch to turn on and off mouse control

const int mouseLeftButton   = 3;    // input pin for the mouse LEFT pushButton
const int mouseRightButton  = 4;    // input pin for the mouse RIGHT pushButton
//const int mouseMiddleButton = 5;    // input pin for the mouse MIDDLE pushButton
const int mouseScrollModeButton = 5;    // input pin for the mouse mode change pushButton

const int xAxis = A0;         // joystick X axis  
const int yAxis = A1;         // joystick Y axis

const int ledPin = 13;        // Mouse control LED

// send data when mouse wheel is move:
const int scrollWheelStop = 0x00;
const int scrollWheelUp   = 0x01;
const int scrollWheelDown = 0xFF;

// interval time for slow move:
const int pointerMoveInterval = 50;
const int scrollInterval = 500;

// parameters for reading the joystick:

int xAnalogInMin = 160;
int xAnalogInMax = 890;
int yAnalogInMin = 140;
int yAnalogInMax = 860;
int threshold = 30;          // resting threshold

int xPointerMoveDirection = 0;
int yPointerMoveDirection = 0;

int pointerMoveMaxValue = 5;
int pointerSlowMoveRange = 3;
int range = (pointerMoveMaxValue + pointerSlowMoveRange) * 2;  // output range of X or Y movement

int responseDelay = 5;                    // response delay of the mouse, in ms

int xSendAxisData = 0;
int ySendAxisData = 0;
int sendWheelData = 0;

// timer:
// unsigned long currentMillis;
unsigned long CurrentMillis;
unsigned long xPreviousMillis = 0;        // will store last time mouse move data was updated
unsigned long yPreviousMillis = 0;        // will store last time mouse move data was updated
unsigned long wheelPreviousMillis = 0;

// mouse active switch:
boolean mouseIsActive = false;    // whether or not to control the mouse
int lastSwitchState = HIGH;       // previous switch state
// mouse mode change switch:
boolean scrollMode = false;       // whether or not to control the mouse
int lastModeSwitchState = HIGH;   // previous switch state


void setup() {
  pinMode(switchPin, INPUT_PULLUP);            // the switch pin
  pinMode(ledPin, OUTPUT);                     // the LED pin
  pinMode(mouseLeftButton, INPUT_PULLUP);      // the mouse Left Button pin
  pinMode(mouseRightButton, INPUT_PULLUP);     // the mouse Right Button pin
//pinMode(mouseMiddleButton, INPUT_PULLUP);    // the mouse Middle Button pin
  pinMode(mouseScrollModeButton, INPUT_PULLUP);     // the mouse mode change Button pin

/*
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
 */
  
  // take control of the mouse:
  Mouse.begin();

}

void loop(){
  // 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);

  // read the mouseModeSwitch:
  int modeSwitchState = digitalRead(mouseScrollModeButton);
  if (modeSwitchState != lastModeSwitchState) {
    if (modeSwitchState == LOW) {
      scrollMode = !scrollMode;
    }
  }
  // save switch state for next comparison:
  lastModeSwitchState = modeSwitchState;

  if (scrollMode == false) {
    // pointer mode:
    sendWheelData = scrollWheelStop;
    
    // set xAxis data for send:
    if (xReading == 0) {
      // center:
      xSendAxisData = 0;
    } else if (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;
    } else if (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();
      int wheelMoveDirection = 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:
 */

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, unsigned long previousMillis) {
  unsigned long 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);
    }
  }
}

 

いざ使ってみたら、ちょっと違和感があったので、もうひとつ、ZLボタンを押している間はスクロール、ボタンを離すとマウスというのも作ってみました。

// set pin numbers for switch, joystick axes, and LED:
const int switchPin = 2;      // switch to turn on and off mouse control

const int mouseLeftButton   = 3;      // input pin for the mouse LEFT pushButton
const int mouseRightButton  = 4;      // input pin for the mouse RIGHT pushButton
//const int mouseMiddleButton = 5;    // input pin for the mouse MIDDLE pushButton
const int mouseScrollModeButton = 5;  // input pin for the mouse mode change pushButton

const int xAxis = A0;         // joystick X axis  
const int yAxis = A1;         // joystick Y axis

const int ledPin = 13;        // Mouse control LED

// send data when mouse wheel is move:
const int scrollWheelStop = 0x00;
const int scrollWheelUp   = 0x01;
const int scrollWheelDown = 0xFF;

// interval time for slow move:
const int pointerMoveInterval = 50;
const int scrollInterval = 500;

// parameters for reading the joystick:

int xAnalogInMin = 160;
int xAnalogInMax = 890;
int yAnalogInMin = 140;
int yAnalogInMax = 860;
int threshold = 30;          // resting threshold


int xPointerMoveDirection = 0;
int yPointerMoveDirection = 0;

int pointerMoveMaxValue = 5;
int pointerSlowMoveRange = 3;
int range = (pointerMoveMaxValue + pointerSlowMoveRange) * 2;  // output range of X or Y movement

int responseDelay = 5;                    // response delay of the mouse, in ms

int xSendAxisData = 0;
int ySendAxisData = 0;
int sendWheelData = 0;

// timer:
// unsigned long currentMillis;
unsigned long CurrentMillis;
unsigned long xPreviousMillis = 0;        // will store last time mouse move data was updated
unsigned long yPreviousMillis = 0;        // will store last time mouse move data was updated
unsigned long wheelPreviousMillis = 0;

// mouse active switch:
boolean mouseIsActive = false;    // whether or not to control the mouse
int lastSwitchState = HIGH;       // previous switch state
// mouse mode change switch:
boolean scrollMode = false;
int lastModeSwitchState = HIGH;   // previous switch state


void setup() {
  pinMode(switchPin, INPUT_PULLUP);            // the switch pin
  pinMode(ledPin, OUTPUT);                     // the LED pin
  pinMode(mouseLeftButton, INPUT_PULLUP);      // the mouse Left Button pin
  pinMode(mouseRightButton, INPUT_PULLUP);     // the mouse Right Button pin
//pinMode(mouseMiddleButton, INPUT_PULLUP);    // the mouse Middle Button pin
  pinMode(mouseScrollModeButton, INPUT_PULLUP);     // the mouse mode change Button pin

/*
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
 */
  
  // take control of the mouse:
  Mouse.begin();

}

void loop(){
  // 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);

  // read the mouseModeSwitch:
  int modeSwitchState = 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;
    } else if (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;
    } else if (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();
      int wheelMoveDirection = 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:
 */

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, unsigned long previousMillis) {
  unsigned long 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);
    }
  }
}

こちらのほうが、使いやすいですかね。

 

というわけで、とりあえず、Arduino Micro と、スライド式のジョイスティックパーツを使っての、USBスライドパッドマウス(スクロールホイール機能付き)が出来上がりました。
動作させるソフトを自分で自由にいじれるので、こんな具合に自分が使いやすい、またはみんなが使いやすいデバイスに仕立てることが出来るところが、自作の良いところですね。

各パラメータ類は、できる限り変数にしてありますので、使いやすいように、数値を色々変えてみてください。
また、プログラムの改造も自由に行っていただいて結構です。
なにせ、ほぼ素人の私が組んだプログラムなので、改良して、どんどん使いやすくしてやってください。(Arduinoのライセンスは遵守してくださいね)

あと「ここ変だよ」とか「こうするといいよ」とかありましたら、お気楽にコメントお願いします。

※追記
threshold の値を計算で出すのではなく、決め打ちして初期設定で定義するように、上のスケッチ変更しました。

int threshold = 30;

としてみましたが、これは私の手持ちの部品に合わせた値なので、使っている部品によって、指を離しても動いてしまうようなら値をより大きく、中立位置から指を動かしていって動き出しが遅いようなら値を小さくしてみてください。


さて、では次は、キーボード部分です。

追記:2017/02/06
Arduinoの団体がふたつに分裂していたことを以前書きましたが、この2団体が和解して統合するそうです。
それに伴ってか、https://www.arduino.cc/http://www.arduino.org/ の両サイトで配布されているArduino IDE が、共に 1.8.x に統一?されました。

そこで、1.8.x に合わせるのと同時に若干の変更をして、スケッチを書き直してみました。
1.8.x は 1.6.x の後半のバージョンと同じく、USB HID のライブラリの分離、具体的には、Keyboard.h Mouse.h を必要な時にインクルードするようになっています。

これまでのスケッチから変更して、スライドパッドの中心と、そこからの最大距離を、変数に指定します。あと変数の名前をいくつか変えました。
変数の初期値は各自で変更してください。

/*
2017/02/07 by HisashiKato 
 */

#include "Mouse.h"

// set pin numbers for switch, joystick axes, and LED:
const int switchPin = 2;      // switch to turn on and off mouse control

const int mouseLeftButton   = 3;      // input pin for the mouse LEFT pushButton
const int mouseRightButton  = 4;      // input pin for the mouse RIGHT pushButton
//const int mouseMiddleButton = 5;    // input pin for the mouse MIDDLE pushButton
const int mouseScrollModeButton = 5;  // input pin for the mouse mode change pushButton

const int xAxis = A0;         // joystick X axis  
const int yAxis = A1;         // joystick Y axis

const int ledPin = 13;        // Mouse control LED

// send data when mouse wheel is move:
const int scrollWheelStop = 0x00;
const int scrollWheelUp   = 0x01;
const int scrollWheelDown = 0xFF;

// interval time for slow move:
const int pointerMoveInterval = 20;
const int scrollInterval = 500;

// parameters for reading the joystick:

int xAnalogInCenter = 520;
int yAnalogInCenter = 505;
int xAnalogMaxRange = 240;
int yAnalogMaxRange = 240;

int threshold = 30;          // resting threshold


int xPointerMoveDirection = 0;
int yPointerMoveDirection = 0;

int pointerMoveMaxValue = 2;
int pointerSlowMoveRange = 8;
int division = (pointerMoveMaxValue + pointerSlowMoveRange) * 2;  // division number

int responseDelay = 5;                    // response delay of the mouse, in ms

int xSendAxisData = 0;
int ySendAxisData = 0;
int sendWheelData = 0;

// timer:
// unsigned long currentMillis;
unsigned long CurrentMillis;
unsigned long xPreviousMillis = 0;        // will store last time mouse move data was updated
unsigned long yPreviousMillis = 0;        // will store last time mouse move data was updated
unsigned long wheelPreviousMillis = 0;

// mouse active switch:
boolean mouseIsActive = false;    // whether or not to control the mouse
int lastSwitchState = HIGH;       // previous switch state
// mouse mode change switch:
boolean scrollMode = false;
int lastModeSwitchState = HIGH;   // previous switch state


void setup() {
  pinMode(switchPin, INPUT_PULLUP);            // the switch pin
  pinMode(ledPin, OUTPUT);                     // the LED pin
  pinMode(mouseLeftButton, INPUT_PULLUP);      // the mouse Left Button pin
  pinMode(mouseRightButton, INPUT_PULLUP);     // the mouse Right Button pin
//pinMode(mouseMiddleButton, INPUT_PULLUP);    // the mouse Middle Button pin
  pinMode(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);

}

void loop(){
  // 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, xAnalogInCenter, xAnalogMaxRange);
  int yReading = readAxis(yAxis, yAnalogInCenter, yAnalogMaxRange);

  // read the mouseModeSwitch:
  int modeSwitchState = 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;
    } else if (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;
    } else if (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();
      int wheelMoveDirection = 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:
 */

int readAxis(int thisAxis, int center, int maxRange) {
  // read the analog input:
  int analogInMin = center - maxRange;
  int analogInMax = center + maxRange;
  int reading = analogRead(thisAxis);
  reading = constrain(reading, analogInMin, analogInMax);
  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, division) - (division / 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, unsigned long previousMillis) {
  unsigned long 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);
    }
  }
}

 

こんな感じで。

 

おまけ: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 をインストールしてみたところ、エラー出なくなりました!!!
何が起きてたんでしょうねぇ何かが不具合を起こしてたんでしょうね、とにかく正常になって良かった。

おしまい 

| | コメント (1) | トラックバック (0)

« 2015年6月 | トップページ | 2016年2月 »