見出し画像

ArduinoでHID ver.2(割り当て変更可能版)

少し前にArduinoProMicro(Leonardo)を使ってHID機能を持つスイッチBOXを考えたが、この仕様で割り当てられる機能は8つまで(外部スイッチ用ジャックの数)である。
あるアプリは「 Space、Enter 、Tab 、BackSpace、→、 ←、 ↑、 ↓  」、別のアプリは「h、k、l、→、←  」、このゲームは「 w、a、s、d、r、Space  」、別のゲームでは「マウスポインタの移動とクリック」...と割り当てが異なり、それぞれに対応したスイッチBOXが必要である。
そこでスイッチの割り当てが変更可能な仕様を考えてみた。


仕様

電源投入(USB接続)時にスイッチ1を押している状態か否かで割り当てモード操作モードの2つのモードで起動する
各スイッチの割り当てには、設定を確認する画面が必要である。 JoyToKeyREVIVE USBなんでもスイッチUSB ではPCにアプリをインストールして設定しているが、PCに慣れない人にはハードルが高い。LCDを使うのも面倒である。そこでPCやタブレットのエディタ(メモ帳やワープロなど)に設定内容を表示することにした。

割り当てモード

1 エディタを立ち上げる
 (動画ではiライターズを立ち上げている)
  ※ i ライターズはピンチイン、アウトで文字サイズが変わるだけでなく
   自動改行するのでオススメのアプリである
2 スイッチ1を押しながらPCやタブレットとUSB接続する
 (動画ではスイッチ1に並列接続したクマスイッチを押している)
3 スイッチ2を押すと現在の各スイッチの割り当てがエディタに出力される

スイッチ1~8の割り当てが表示される

4 割り当てを変更したいスイッチを押すと割り当てが変更される

スイッチ1を押すとa→b→c→d→..と下の表の順に送られる(長押しでスキャン)
割り当ての一覧

5 すべての割り当てが終了したらUSBを抜く
 (変更結果はマイコンの不揮発メモリに記録されている)

操作モード

1 PCやタブレットとUSB接続する(スイッチは押さない)
  不揮発メモリの情報に基づいて各スイッチに機能が割り当てられる
2 各スイッチを押して操作する

スケッチ

各スイッチを表わす変数(SW_1..)を for文で上手く処理できずに不細工な sketchになった。(特にvoid control() )今後の課題とする。
割り当てモードで、起動時に Keybord.print を実行したら Windows に介入されて制御が効かなくなった。sketch を書き直そうとすると今度は arduino IDE の編集画面が荒らされて書き込みが出来ない。(arduinoISP を書き込んだUNOからSCLK、MISO、MOSI、RESET経由でやっと書き直すことが出来た。やれやれ) というわけで、Keybord.print(各スイッチの割り当ての出力)は起動後スイッチ2を押してから実行するようにした。
マウスポインタの移動速度はノートPCや iPad では丁度よいぐらいだが、解像度の高いディスプレイでは遅い可能性がある。速度を変更するメニューを作ることも考えたが、ユーザーにとって面倒な作業になると思われる。Windowsのアクセシビリティで対応してもらうこととする。( → 参考サイト )
この sketch はスイッチの2重押しには対応していない。ctrl+r などのショートカットは出来ない。技術的には可能だが、ctrl、shift、alt ..と a、b、c..の組合せを考えると恐ろしい数になる。わたしの書いたsketchとは別のエレガントな方法があるはずだが、今のわたしにそのスキルはない。今後の課題とする。ちなみにネットで調べたところ市販のキーボードは6重押しまで対応しているらしい。

/* HID_for_Pro_Micro_09.ino

        Arduino Pro Micro     *PWM
                    J1・
                  TX/1・     ・RAW
                  RX/0・     ・GND
                   GND・     ・Reset
                   GND・     ・VCC
                 SDA/2・     ・21/A3
                 SCL/3*      ・20/A2 <-- SW_5
        SW_1 -->  A6/4・     ・19/A1 <-- SW_6
                     5*     ・18/A0 <-- SW_7
        SW_2 -->  A7/6*     ・15/SCLK
                     7・     ・14/MISO <-- LED
        SW_3 -->  A8/8・     ・16/MOSI
        SW_4 -->  A9/9*     *10/A10  <-- SW_8
*/

#include <Keyboard.h>
#include <Mouse.h>
#include <EEPROM.h>

#define ON LOW
#define OFF HIGH

const int SW_1 = A6;  const int SW_2 = A7;  const int SW_3 = A8;  const int SW_4 = A9;
const int SW_5 = A2;  const int SW_6 = A1;  const int SW_7 = A0;  const int SW_8 = A10;
const int LED = 14;

int sw_num = 100;
int responseDelay = 10;  // response delay 10msec
int SW_task_num[8];
int num_of_task = 54;

char* task_list[] = {
  /*  0-12 */ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
  /* 13-25 */ "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
  /* 26-35 */ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
  /* 36-42 */ "Space", "Enter", "BackSpace", "Tab", "Esc", "PageUp", "PageDown",
  /* 43-46 */ "up-arrow", "down-arrow", "left-arrow", "right-arrow",  // keyboard
  /* 47-50 */ "mouse-up", "mouse-down", "mouse-left", "mouse-right",  // mouse pointer move
  /* 51-53 */ "left click", "left double click", "right click",       // mouse click
};

void setup() {
  Serial.begin(9600);
  delay(0);
  Keyboard.begin();
  Mouse.begin();
  read_from_EEPROM();  // read form EEPROM
  set_pinMode();
  //  Serial_print_task_list();
  Serial_print_SW_task();
  if (digitalRead(SW_1) == ON) set_mode(true);  // set_mode(bool is_keyboard_print)  true or false
}

void loop() {
  control();
  delay(responseDelay); //  10msec
}
void read_from_EEPROM() { // called from setup()
  for (int i = 0; i < 8; i++) {       // read from EEPROM
    SW_task_num[i] = EEPROM.read(i);  // (address, value)
    Serial.print(SW_task_num[i]); Serial.print(", ");
  }
  Serial.println();
}

void set_pinMode() {  // called from setup()
  pinMode(SW_1, INPUT_PULLUP);  pinMode(SW_2, INPUT_PULLUP);  pinMode(SW_3, INPUT_PULLUP);  pinMode(SW_4, INPUT_PULLUP);
  pinMode(SW_5, INPUT_PULLUP);  pinMode(SW_6, INPUT_PULLUP);  pinMode(SW_7, INPUT_PULLUP);  pinMode(SW_8, INPUT_PULLUP);
}

void Serial_print_task_list() {   // called from setup()
  Serial.println("task list -------");
  for (int i = 0; i < num_of_task; i++) {
    Serial.print(i);  Serial.print(": "); Serial.print(task_list[i]); Serial.println("");
  }
  Serial.println("-----------------");
}

void Serial_print_SW_task() {  // called from setup()
  //    Serial.println("now SW task ----  ");
  for (int i = 0; i < 8; i++) {
    Serial.print(" ");  Serial.print(i + 1);  Serial.print(":");  Serial.print(task_list[SW_task_num[i]]);
    Serial.print("   ");
  }
  Serial.println("");
  // Serial.println("Serial_print_SW_task() is end. ------");
}

void set_mode(bool is_keyboard_print) { // called from setup()
  while (true) {                        // is_keyboard_print( true or false )
    if (digitalRead(SW_2) == ON) {
      Serial.println("set mode --- Press the switch you want to change!");
      Serial_print_SW_task();
      if (is_keyboard_print == true) {
        Keyboard.println("set mode --- Press the switch you want to change!");
        Keyboad_print_SW_task();
      }
      break;
    }
  }
  while (true) {
    if (digitalRead(SW_2) == OFF) break;  // when SW_* is released, go to next.
  }
  while (true) {
    which_sw_ON();  // input switch number to sw_num
    // Serial.print("SW_");  Serial.println(sw_num + 1);
    SW_task_num[sw_num] = (SW_task_num[sw_num] + 1) % num_of_task;
    EEPROM.write(sw_num, SW_task_num[sw_num]);
    Serial_print_SW_task();
    if (is_keyboard_print == true) {
      Keyboad_print_SW_task();
    }
    delay(500);
  }
}

void Keyboad_print_SW_task() {  // called from set_mode()
  for (int i = 0; i < 7; i++) {
    Keyboard.print(i + 1);  Keyboard.print("'");   // ":"-->"'"
    Keyboard.print(task_list[SW_task_num[i]]);  Keyboard.print("   ");
  }
  Keyboard.print(8);  Keyboard.print(" ");  Keyboard.println(task_list[SW_task_num[7]]);
}

bool which_sw_ON() {  // called from set_mode() and control()
  while (true) {      // input switch number to sw_num
    if (digitalRead(SW_1) == ON) {        sw_num = 0; break;
    } else if (digitalRead(SW_2) == ON) { sw_num = 1; break;
    } else if (digitalRead(SW_3) == ON) { sw_num = 2; break;
    } else if (digitalRead(SW_4) == ON) { sw_num = 3; break;
    } else if (digitalRead(SW_5) == ON) { sw_num = 4; break;
    } else if (digitalRead(SW_6) == ON) { sw_num = 5; break;
    } else if (digitalRead(SW_7) == ON) { sw_num = 6; break;
    } else if (digitalRead(SW_8) == ON) { sw_num = 7; break;
    } else {      // non
    }
  }
}

void control() {  // called from loop()
  which_sw_ON();  // input switch number to sw_num
  Serial.print(SW_task_num[sw_num]);  Serial.print(": ");  Serial.println(task_list[SW_task_num[sw_num]]);
  int task_num = SW_task_num[sw_num];

  if (digitalRead(SW_1) == ON) {  // for SW_1
    if ((task_num >= 0) * (task_num <= 46)) {  //  key press
      Serial.println("key press");  digitalWrite(LED, HIGH);
      press_key();
      while (digitalRead(SW_1) == ON) {}; // while switch on, press key.
      Keyboard.releaseAll();              // switch off, then release key.
      digitalWrite(LED, LOW);
    }
    if ((task_num >= 47) * (task_num <= 50)) {  //  mouse pointer move
      while (digitalRead(SW_1) == ON) {
        mouse_pointer_move(task_num);
      }
    }
    if (task_num == 51) {  //  mouse left click(51)
      while (digitalRead(SW_1) == ON) {
        Serial.println("left click");
        Mouse.press(MOUSE_LEFT);  digitalWrite(LED, HIGH);
      }
      Mouse.release(MOUSE_LEFT);  digitalWrite(LED, LOW);
    }
    if (task_num == 52) { //  mouse double click (52)
      if (digitalRead(SW_1) == ON) {
        double_click();
      }
    }
    if (task_num == 53) {  //  mouse right click(53)
      while (digitalRead(SW_1) == ON) {
        Serial.println("right click");
        Mouse.press(MOUSE_RIGHT); digitalWrite(LED, HIGH);
      }
      Mouse.release(MOUSE_RIGHT); digitalWrite(LED, LOW);
    }
  }
  if (digitalRead(SW_2) == ON) {  // for SW_2
    if ((task_num >= 0) * (task_num <= 46)) {  //  key press
      Serial.println("key press");  digitalWrite(LED, HIGH);
      press_key();
      while (digitalRead(SW_2) == ON) {}; // while switch on, press key.
      Keyboard.releaseAll();              // switch off, then release key.
      digitalWrite(LED, LOW);
    }
    if ((task_num >= 47) * (task_num <= 50)) {  //  mouse pointer move
      while (digitalRead(SW_2) == ON) {
        mouse_pointer_move(task_num);
      }
    }
    if (task_num == 51) {  //  mouse left click(51)
      while (digitalRead(SW_2) == ON) {
        Serial.println("left click");
        Mouse.press(MOUSE_LEFT);  digitalWrite(LED, HIGH);
      }
      Mouse.release(MOUSE_LEFT);  digitalWrite(LED, LOW);
    }
    if (task_num == 52) { //  mouse double click (52)
      if (digitalRead(SW_2) == ON) {
        double_click();
      }
    }
    if (task_num == 53) {  //  mouse right click(53)
      while (digitalRead(SW_2) == ON) {
        Serial.println("right click");
        Mouse.press(MOUSE_RIGHT); digitalWrite(LED, HIGH);
      }
      Mouse.release(MOUSE_RIGHT); digitalWrite(LED, LOW);
    }
  }
  if (digitalRead(SW_3) == ON) {  // for SW_3
    if ((task_num >= 0) * (task_num <= 46)) {  //  key press
      Serial.println("key press");  digitalWrite(LED, HIGH);
      press_key();
      while (digitalRead(SW_3) == ON) {}; // while switch on, press key.
      Keyboard.releaseAll();              // switch off, then release key.
      digitalWrite(LED, LOW);
    }
    if ((task_num >= 47) * (task_num <= 50)) {  //  mouse pointer move
      while (digitalRead(SW_3) == ON) {
        mouse_pointer_move(task_num);
      }
    }
    if (task_num == 51) {  //  mouse left click(51)
      while (digitalRead(SW_3) == ON) {
        Serial.println("left click");
        Mouse.press(MOUSE_LEFT);  digitalWrite(LED, HIGH);
      }
      Mouse.release(MOUSE_LEFT);  digitalWrite(LED, LOW);
    }
    if (task_num == 52) { //  mouse double click (52)
      if (digitalRead(SW_3) == ON) {
        double_click();
      }
    }
    if (task_num == 53) {  //  mouse right click(53)
      while (digitalRead(SW_3) == ON) {
        Serial.println("right click");
        Mouse.press(MOUSE_RIGHT); digitalWrite(LED, HIGH);
      }
      Mouse.release(MOUSE_RIGHT); digitalWrite(LED, LOW);
    }
  }
  if (digitalRead(SW_4) == ON) {  // for SW_4
    if ((task_num >= 0) * (task_num <= 46)) {  //  key press
      Serial.println("key press");  digitalWrite(LED, HIGH);
      press_key();
      while (digitalRead(SW_4) == ON) {}; // while switch on, press key.
      Keyboard.releaseAll();              // switch off, then release key.
      digitalWrite(LED, LOW);
    }
    if ((task_num >= 47) * (task_num <= 50)) {  //  mouse pointer move
      while (digitalRead(SW_4) == ON) {
        mouse_pointer_move(task_num);
      }
    }
    if (task_num == 51) {  //  mouse left click(51)
      while (digitalRead(SW_4) == ON) {
        Serial.println("left click");
        Mouse.press(MOUSE_LEFT);  digitalWrite(LED, HIGH);
      }
      Mouse.release(MOUSE_LEFT);  digitalWrite(LED, LOW);
    }
    if (task_num == 52) { //  mouse double click (52)
      if (digitalRead(SW_4) == ON) {
        double_click();
      }
    }
    if (task_num == 53) {  //  mouse right click(53)
      while (digitalRead(SW_4) == ON) {
        Serial.println("right click");
        Mouse.press(MOUSE_RIGHT); digitalWrite(LED, HIGH);
      }
      Mouse.release(MOUSE_RIGHT); digitalWrite(LED, LOW);
    }
  }
  if (digitalRead(SW_5) == ON) {  // for SW_5
    if ((task_num >= 0) * (task_num <= 46)) {  //  key press
      Serial.println("key press");  digitalWrite(LED, HIGH);
      press_key();
      while (digitalRead(SW_5) == ON) {}; // while switch on, press key.
      Keyboard.releaseAll();              // switch off, then release key.
      digitalWrite(LED, LOW);
    }
    if ((task_num >= 47) * (task_num <= 50)) {  //  mouse pointer move
      while (digitalRead(SW_5) == ON) {
        mouse_pointer_move(task_num);
      }
    }
    if (task_num == 51) {  //  mouse left click(51)
      while (digitalRead(SW_5) == ON) {
        Serial.println("left click");
        Mouse.press(MOUSE_LEFT);  digitalWrite(LED, HIGH);
      }
      Mouse.release(MOUSE_LEFT);  digitalWrite(LED, LOW);
    }
    if (task_num == 52) { //  mouse double click (52)
      if (digitalRead(SW_5) == ON) {
        double_click();
      }
    }
    if (task_num == 53) {  //  mouse right click(53)
      while (digitalRead(SW_5) == ON) {
        Serial.println("right click");
        Mouse.press(MOUSE_RIGHT); digitalWrite(LED, HIGH);
      }
      Mouse.release(MOUSE_RIGHT); digitalWrite(LED, LOW);
    }
  }
  if (digitalRead(SW_6) == ON) {  // for SW_6
    if ((task_num >= 0) * (task_num <= 46)) {  //  key press
      Serial.println("key press");  digitalWrite(LED, HIGH);
      press_key();
      while (digitalRead(SW_6) == ON) {}; // while switch on, press key.
      Keyboard.releaseAll();              // switch off, then release key.
      digitalWrite(LED, LOW);
    }
    if ((task_num >= 47) * (task_num <= 50)) {  //  mouse pointer move
      while (digitalRead(SW_6) == ON) {
        mouse_pointer_move(task_num);
      }
    }
    if (task_num == 51) {  //  mouse left click(51)
      while (digitalRead(SW_6) == ON) {
        Serial.println("left click");
        Mouse.press(MOUSE_LEFT);  digitalWrite(LED, HIGH);
      }
      Mouse.release(MOUSE_LEFT);  digitalWrite(LED, LOW);
    }
    if (task_num == 52) { //  mouse double click (52)
      if (digitalRead(SW_6) == ON) {
        double_click();
      }
    }
    if (task_num == 53) {  //  mouse right click(53)
      while (digitalRead(SW_6) == ON) {
        Serial.println("right click");
        Mouse.press(MOUSE_RIGHT); digitalWrite(LED, HIGH);
      }
      Mouse.release(MOUSE_RIGHT); digitalWrite(LED, LOW);
    }
  }
  if (digitalRead(SW_7) == ON) {  // for SW_7
    if ((task_num >= 0) * (task_num <= 46)) {  //  key press
      Serial.println("key press");  digitalWrite(LED, HIGH);
      press_key();
      while (digitalRead(SW_7) == ON) {}; // while switch on, press key.
      Keyboard.releaseAll();              // switch off, then release key.
      digitalWrite(LED, LOW);
    }
    if ((task_num >= 47) * (task_num <= 50)) {  //  mouse pointer move
      while (digitalRead(SW_7) == ON) {
        mouse_pointer_move(task_num);
      }
    }
    if (task_num == 51) {  //  mouse left click(51)
      while (digitalRead(SW_7) == ON) {
        Serial.println("left click");
        Mouse.press(MOUSE_LEFT);  digitalWrite(LED, HIGH);
      }
      Mouse.release(MOUSE_LEFT);  digitalWrite(LED, LOW);
    }
    if (task_num == 52) { //  mouse double click (52)
      if (digitalRead(SW_7) == ON) {
        double_click();
      }
    }
    if (task_num == 53) {  //  mouse right click(53)
      while (digitalRead(SW_7) == ON) {
        Serial.println("right click");
        Mouse.press(MOUSE_RIGHT); digitalWrite(LED, HIGH);
      }
      Mouse.release(MOUSE_RIGHT); digitalWrite(LED, LOW);
    }
  }
  if (digitalRead(SW_8) == ON) {  // for SW_8
    if ((task_num >= 0) * (task_num <= 46)) {  //  key press
      Serial.println("key press");  digitalWrite(LED, HIGH);
      press_key();
      while (digitalRead(SW_8) == ON) {}; // while switch on, press key.
      Keyboard.releaseAll();              // switch off, then release key.
      digitalWrite(LED, LOW);
    }
    if ((task_num >= 47) * (task_num <= 50)) {  //  mouse pointer move
      while (digitalRead(SW_8) == ON) {
        mouse_pointer_move(task_num);
      }
    }
    if (task_num == 51) {  //  mouse left click(51)
      while (digitalRead(SW_8) == ON) {
        Serial.println("left click");
        Mouse.press(MOUSE_LEFT);  digitalWrite(LED, HIGH);
      }
      Mouse.release(MOUSE_LEFT);  digitalWrite(LED, LOW);
    }
    if (task_num == 52) { //  mouse double click (52)
      if (digitalRead(SW_8) == ON) {
        double_click();
      }
    }
    if (task_num == 53) {  //  mouse right click(53)
      while (digitalRead(SW_8) == ON) {
        Serial.println("right click");
        Mouse.press(MOUSE_RIGHT); digitalWrite(LED, HIGH);
      }
      Mouse.release(MOUSE_RIGHT);
      digitalWrite(LED, LOW);
    }
  }
}

void press_key() {  // called from control()
  switch (SW_task_num[sw_num]) {
    case 0: Keyboard.press('a'); break;    case 1: Keyboard.press('b'); break;
    case 2: Keyboard.press('c'); break;    case 3: Keyboard.press('d'); break;
    case 4: Keyboard.press('e'); break;    case 5: Keyboard.press('f'); break;
    case 6: Keyboard.press('g'); break;    case 7: Keyboard.press('h'); break;
    case 8: Keyboard.press('i'); break;    case 9: Keyboard.press('j'); break;
    case 10: Keyboard.press('k'); break;   case 11: Keyboard.press('l'); break;
    case 12: Keyboard.press('m'); break;   case 13: Keyboard.press('n'); break;
    case 14: Keyboard.press('o'); break;   case 15: Keyboard.press('p'); break;
    case 16: Keyboard.press('q'); break;   case 17: Keyboard.press('r'); break;
    case 18: Keyboard.press('s'); break;   case 19: Keyboard.press('t'); break;
    case 20: Keyboard.press('u'); break;   case 21: Keyboard.press('v'); break;
    case 22: Keyboard.press('w'); break;   case 23: Keyboard.press('x'); break;
    case 24: Keyboard.press('y'); break;   case 25: Keyboard.press('z'); break;
    case 26: Keyboard.press('0'); break;   case 27: Keyboard.press('1'); break;
    case 28: Keyboard.press('2'); break;   case 29: Keyboard.press('3'); break;
    case 30: Keyboard.press('4'); break;   case 31: Keyboard.press('5'); break;
    case 32: Keyboard.press('6'); break;   case 33: Keyboard.press('7'); break;
    case 34: Keyboard.press('8'); break;   case 35: Keyboard.press('9'); break;
    case 36: Keyboard.press(0x20); break;  // space
    case 37: Keyboard.press(KEY_RETURN); break;
    case 38: Keyboard.press(KEY_BACKSPACE); break;
    case 39: Keyboard.press(KEY_TAB); break;
    case 40: Keyboard.press(KEY_ESC); break;
    case 41: Keyboard.press(KEY_PAGE_UP); break;
    case 42: Keyboard.press(KEY_PAGE_DOWN); break;

    case 43: Keyboard.press(KEY_UP_ARROW); break;
    case 44: Keyboard.press(KEY_DOWN_ARROW); break;
    case 45: Keyboard.press(KEY_LEFT_ARROW); break;
    case 46: Keyboard.press(KEY_RIGHT_ARROW); break;
  }
}

void mouse_pointer_move(int task_num) { // called from control()
  Serial.println("mouse pointer move");
  switch (task_num) {
    case 47:  Mouse.move(0, -1, 0); break;  //  up
    case 48:  Mouse.move(0, 1, 0); break;   //  down
    case 49:  Mouse.move(-1, 0, 0); break;  //  left
    case 50:  Mouse.move(1, 0, 0); break;   //  right
  }
  delay(5);
} 

void double_click() { // called from control()  // double click
  Mouse.press(MOUSE_LEFT);    digitalWrite(LED, HIGH);  delay(50);
  Mouse.release(MOUSE_LEFT);  digitalWrite(LED, LOW);   delay(50);
  Mouse.press(MOUSE_LEFT);    digitalWrite(LED, HIGH);  delay(50);
  Mouse.release(MOUSE_LEFT);  digitalWrite(LED, LOW);
}

この記事が気に入ったらサポートをしてみませんか?