MagicMirror2用タブレットにたぶん便利! 人が近づいたらキー入力して、PC画面が復帰するUSBデバイスを作りました。

# これって何？
人が近づいたら、USB経由でキー入力を送信するデバイスです。Digispark ATtiny85とPIRセンサ(人感センサー)をつないだだけです。プログラムは[Arduino IDE](https://www.arduino.cc/en/software)で作ります。

# はじめに 
先日 [古いWindows10タブレットを再活用！MagicMirror2を稼働してGoogleフォトフレームを作ろう！](https://qiita.com/tonasuzuki/items/ce4e075904170e7d71b7)の記事を書きました。最近、少し前のタブレットPCが中古屋さんなどに安く出回っています。[MagicMirror2](https://magicmirror.builders/)など、ちょっとした情報を常時出力する端末として活用すると便利です。
ただ、普通に設定すると、画面は常時点灯することになるので、ちょっとうるさい…。画面を見ていないときは、自動的に画面が消えたりするとよさそうです。PIRセンサ(人感センサー)を使って、近くに誰かいるときキーを押すことで、PCが復帰するデバイスを作りました。
具体的には、以下のような動作をします。USBキーボードとして認識しますので、PC側は無改造、PC側に特別なドライバも不要です。
- PCは、指定時間でディスプレイを消灯するよう設定しておきます。
- PIRセンサ(人感センサー)をつないで、人が近づいたらテキトウなキーボード信号([WAKE UP]キー)を送って、PCを復帰します。(Windowsでは、[WAKE UP]キーを押しても何も起こらないようです。ただ、キー入力することで画面OFFは復帰します。)
- 人がいる間は、テキトウな間隔で(作例では1分間隔)キーボード信号を送ります。

世の中にはちょうど良いことに、Atmel ATtiny85と呼ばれる、USBデバイスを容易に作れるマイコンがあります。開発はArduino互換ですのでとても楽です。
ATtiny85が載っている「Digispark ATtiny85」互換のボードは、USBコネクタも付いているので便利です。例えば[Shigezone](https://www.shigezone.com/product/digispark_usb-micro1/)で入手できます。
PIRセンサは、秋月電子で薄型の[焦電型赤外線センサーモジュール](https://akizukidenshi.com/catalog/g/gM-11233/)を利用しました。
![usb-sensor_devices.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679798/3967c859-e4e7-91d7-ced8-968341cc3581.jpeg)
※写真左:焦電型赤外線センサーモジュール 右:Digispark ATtiny85

# 組み立てる
Digispark ATtiny85に、PIRセンサをつなぐだけです。上記センサの場合、センサのVCC(赤色)を「5V」(AtTiny85の8ピン)、GND(黒)を「GND」(4ピン)、センサ出力(黄)を「P0」(5ピン)につなぎます。
ATtiny85互換のボードには、動作確認用のLEDとして、P1にLEDが実装されています。ただ、モノによってP0につながっているボードもあるらしいので、その場合は「P1」(6ピン)か「P2」(7ピン)につなぎます(ソースコードの PIN_SENSOR をP1の場合は1、P2の場合は2に変更します)。

![usb-sensor.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679798/79a71bfe-02e7-e2b3-a2e2-fa17659df023.jpeg)

# プログラムを作って書き込む
プログラムは[Arduino IDE](https://www.arduino.cc/en/software)で作ります。あらかじめ、ボードマネージャーとして[ATTinyCore](https://github.com/SpenceKonde/ATTinyCore)を入れておきます。(この記事作成時点では1.5.2が最新です。なお1.5.2は、最新のArduino2.xでは上手く動かないかもしれませんので、その場合はArduino 1.8.xを入れて下さい。)
ボード設定は、以下を設定しました。
- Board: ATTinyCore -> ATTiny 45/85(OptiBoot)
- Chip : ATTiny 85
- Clock source:16MHz
- millis()/micros() : Enabled
※ Digisparkに使われている[Micronucleus](https://github.com/micronucleus/micronucleus)ブートローダーを使う場合は、Boardを「Digispark Pro (Default 16mhz)」に変更すれば動くと思います(未確認です)。

また、ライブラリとして、USBキーボードライブラリ[Adafruit-Trinket-USB](https://github.com/adafruit/Adafruit-Trinket-USB/)を事前に入れて下さい。
今回は、ブートローダーを変更して(「ツール」→「ブートローダーを書き込む」)、[Arduino as ISP](https://ht-deko.com/arduino/bootloader.html)経由でバイナリを書き込んでいます。

# プログラムについて
見ての通り、超短いです。コピーしてArduinoの新規スケッチに貼り付けてビルドしてみて下さい。人が近づいたら押すキーは[WAKE UP]キー( SYSCTRLKEY_WAKE ) を設定しました。他のキーに変えたい場合は、 libraries/TrinketHidCombo/TrinketHidCombo.h を参考にして、 PIR_PRESS_KEY を変更してください。また、手元のDigispark ATtiny85互換ボードは、P1にLEDが実装されていましたので、PIRセンサが感知したときに点灯するようにしています。

```
#include <TrinketHidCombo.h>
#include <TrinketHidComboC.h>
#include <cmdline_defs.h>
#include <usbconfig.h>

// PIN assign
#define PIN_SENSOR  0
#define PIN_LED     1

// PIR SENSOR
#define PIR_SENSOR_ON  LOW
#define PIR_SENSOR_OFF HIGH

// PRESS KEYBOARD
#define PIR_PRESS_KEY  SYSCTRLKEY_WAKE

// SLEEP time (60 seconds)
#define KEY_PRESS_ROUND_TIME (60 * 1000L)

// SENSOR debounce delay
#define SENSOR_DELAY_TIME 1000L


unsigned long lRoundTime;
unsigned long lNowTime;
bool          bPressKey;

void setup()
{
  // button pins as inputs
  pinMode(PIN_SENSOR,INPUT_PULLUP);
  pinMode(PIN_LED   ,OUTPUT);    // LED pins as output

  // start USB stuff
  TrinketHidCombo.begin();
  //
  lRoundTime = 0;
  bPressKey = false;
}

void loop()
{
  lNowTime = millis();

  if (digitalRead(PIN_SENSOR) == PIR_SENSOR_ON)
  {
    digitalWrite(PIN_LED, HIGH);
    if ( lRoundTime < lNowTime )
    {
      lRoundTime = lNowTime + KEY_PRESS_ROUND_TIME;
      bPressKey = true;
    }
  }
  else
  {
    digitalWrite(PIN_LED, LOW);
    if ( lRoundTime < lNowTime )
    {
      lRoundTime = lNowTime + SENSOR_DELAY_TIME  ;
    }
  }
  if (bPressKey)
  {
    TrinketHidCombo.pressSystemCtrlKey(PIR_PRESS_KEY);
    delay(5); // debounce delay
    // this releases the key (otherwise it is held down!)
    TrinketHidCombo.pressKey(0, 0);
    bPressKey = false;
  }
  TrinketHidCombo.poll();
  delay(10); // keystroke delay
}
```

# 完成例
![windows-mm2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679798/9f727d4a-b60e-ecde-1882-75b1a6805b52.jpeg)

PIRセンサをPCの前面に張り付ければ完成です(写真では、左下に張り付けてあります。)。自分は、タブレットPCを机の横の壁に貼り付けました。机に座っている時だけ、画面が表示されます。