iOSのアクセサビリティスイッチコントロール用のスイッチボックスの作成。

iOS機器との接続はBluetoothで行う

有線のが良い場合にはこちら

使うもの

Adafruit Feather nRF52840 Express
スイッチサイエンスとか秋月とかで買える
リチウムイオンポリマー電池かモバイルバッテリ
リチウムイオンポリマー電池は空になると使えなくなるらしいので要注意。モバイルバッテリを使うんだとオートパワーオフキャンセラーとか言われるものが必要。
スイッチ接続用の3.5mmモノラルジャック
3.5mmモノラルジャックなら何でもいいけど、安いの使うと何度も抜き差しする場合にはへたることもある
Arduinoとか
ここを見てAdafruit Feather nRF52840 Expressを使えるようにしておく。これを書いている時のバージョンは1.3。最初は0.14.1で書いていてそこから1.1にバージョンアップしたら動かなくて焦った。なのでもしかしたら1.3では不要になってるコードが入っているかもしれません。

配線図

配線図

工作的にはボードとモノラルジャックをつなぐだけなので簡単ですかね。

プログラム

Arudinoでボードに書き込み

/*********************************************************************
 This is an example for our nRF52 based Bluefruit LE modules

 Pick one up today in the adafruit shop!

 Adafruit invests time and resources providing this open source code,
 please support Adafruit and open-source hardware by purchasing
 products from Adafruit!

 MIT license, check LICENSE for more information
 All text above, and the splash screen below must be included in
 any redistribution
*********************************************************************/
#include <bluefruit.h>

BLEDis bledis;
BLEHidAdafruit blehid;

typedef volatile uint32_t REG32;
#define pREG32 (REG32 *)
//#define DEVICE_ID_HIGH    (*(pREG32 (0x10000060)))
#define DEVICE_ID_LOW     (*(pREG32 (0x10000064)))

//for hid_keyboard input pin
//user switch for test
//#define SW_PIN PIN_BUTTON1
//A0
#define SW_PIN A0
//output Key
#define SP_KEY ' '
bool volatile hasKeyPressed=true;          // Last set PIN val
bool volatile bleConnect = false;

void bleConn(uint16_t conn_handle)
{
  bleConnect = true;
}

void bleDisconn(uint16_t conn_handle,uint8_t reason)
{
  bleConnect = false;
}

bool pairing_passkey_callback(uint16_t conn_handle, uint8_t const passkey[6], bool match_request)
{
  return true;
}

void pairing_complete_callback(uint16_t conn_handle, uint8_t auth_status)
{
}

void connection_secured_callback(uint16_t conn_handle)
{
}

void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
}

void swPinCallback()
{
  unsigned int pinStatus = digitalRead(SW_PIN);
  if ( hasKeyPressed && pinStatus)
  {
    blehid.keyRelease();
    hasKeyPressed = false;
  }
  else if (pinStatus == LOW)
  {
    if(bleConnect)
      blehid.keyPress(SP_KEY);
    hasKeyPressed = true;
  }
  delay(5);
}

void setup()
{
  static char DevName[20];
  int id = DEVICE_ID_LOW & 0xfff;
  sprintf(DevName, "rescueICT %04d", id);


  Bluefruit.begin();
  Bluefruit.setTxPower(-12);    // Check bluefruit.h for supported values
  Bluefruit.setName(DevName);
  Bluefruit.autoConnLed(false);
  //Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);

  /* To use dynamic PassKey for pairing, we need to have
   * - IO capacities at least DISPPLAY
   *    - Display only: user have to enter 6-digit passkey on their phone
   *    - DIsplay + Yes/No: user ony need to press Accept on both central and device
   * - Register callback to display/print dynamic passkey for central
   *
   * For complete mapping of the IO Capabilities to Key Generation Method, check out this article
   * https://www.bluetooth.com/blog/bluetooth-pairing-part-2-key-generation-methods/
  */
  Bluefruit.Security.setIOCaps(false, false, false); // display = false, yes/no = false, keyboard = false
  Bluefruit.Security.setPairPasskeyCallback(pairing_passkey_callback);

  // Set complete callback to print the pairing result
  Bluefruit.Security.setPairCompleteCallback(pairing_complete_callback);

  // Set connection secured callback, invoked when connection is encrypted
  Bluefruit.Security.setSecuredCallback(connection_secured_callback);

  Bluefruit.Periph.setConnectCallback(bleConn);
  Bluefruit.Periph.setDisconnectCallback(bleDisconn);

  // Configure and Start Device Information Service
  bledis.setManufacturer("Adafruit Industries");
  bledis.setModel("Bluefruit Feather 52");
  bledis.begin();

  pinMode(SW_PIN, INPUT_PULLUP);
  hasKeyPressed = false;
  attachInterrupt(SW_PIN, swPinCallback, ISR_DEFERRED | CHANGE);

  /* Start BLE HID
     Note: Apple requires BLE device must have min connection interval >= 20m
     ( The smaller the connection interval the faster we could send data).
     However for HID and MIDI device, Apple could accept min connection interval
     up to 11.25 ms. Therefore BLEHidAdafruit::begin() will try to set the min and max
     connection interval to 11.25  ms and 15 ms respectively for best performance.
  */
  blehid.begin();

  // Set up and start advertising
  startAdv();
  suspendLoop();
}

void startAdv(void)
{
  // Advertising packet
  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  Bluefruit.Advertising.addTxPower();
  Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_KEYBOARD);

  //Include BLE HID
  Bluefruit.Advertising.addService(blehid);

  // There is enough room for the dev name in the advertising packet
  Bluefruit.Advertising.addName();

  /* Start Advertising
     - Enable auto advertising if disconnected
     - Interval:  fast mode = 20 ms, slow mode = 152.5 ms
     - Timeout for fast mode is 30 seconds
     - Start(timeout) with timeout = 0 will advertise forever (until connected)

     For recommended advertising interval
     https://developer.apple.com/library/content/qa/qa1931/_index.html
  */
  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setInterval(32, 244);    // in unit of 0.625 ms
  Bluefruit.Advertising.setFastTimeout(30);      // number of seconds in fast mode
  Bluefruit.Advertising.start(0);                // 0 = Don't stop advertising after n seconds
}

void loop()
{
}

※オートパワーオフキャンセラー

通常のモバイルバッテリーはつないでいる機器の消費電力が低いと自動的にパワーオフしてしまいます。ですので、今回の機器のように消費電力が低い機器の場合には通常は使えません。それに対応して自動的にオフにならないようなモバイルバッテリーも販売されています。

オートパワーオフ機能が無いモバイルバッテリーとしては以下のものとかあったりします。最近はイヤホンとか向けに低電流モードとかがあるモバイルバッテリーも出てきているようです。

cheero Canvas 3200mAh IoT 機器対応
もともとはほぼこれ一択でした
cheero Slim 5000mAh IoT機器対応
上の製品の容量大きくしたものなのかなぁ。使ってみたことはないのでよくわかりませんが

ただそれでも選択肢はそう多くないので、なんとか普通のモバイルバッテリーを使いたいなぁと思ったりもします。そこで考え出されたのがオートパワーオフキャンセラーです。製品として販売されていますが自作することも可能です。考え方としてはオートパワーオフ機能でオフになる前に抵抗などに電力を消費させてパワーオフを防ぐ。ということです。 難しいのはモバイルバッテリーによってオートパワーオフまでの時間やオートパワーオフがきいてパワーオフになるまでの消費電力が違うことです。使う機器に合わせて調整する必要があります。

USBload
モバイルバッテリーのオートパワーオフキャンセラー

などいくつか作例も紹介されています。Arduinoボードを使って作成することも可能です。自作するときには抵抗器の規格(特に定格電力)に気を付けて下さい。