「パソコンの消し忘れて布団に入っちゃったので、リモートでSleepさせたい」という家族の要望を受けて開発しました。
ちょっと、できてないこともあるんですが、一旦報告です。
要件
-
左のボタンを押すとスリープ
-
右のボタンを押すとスリープ解除
-
スリープはWindows専用で、Win + X → U → S を押します。
-
スリープ解除はスペースキーを押します。
実はできてないことは解除なんです。詳細後述・・
Arduino
今回 XIAO BLE nRF52840 を利用したんですが、理由はArduinoでコードを書けるからでした。
でも、少しハマりました。詳細後述。
回路図(構成図)
準備した部品
- BLEモジュール → XIAO BLE nRF52840 (Seeed Studio) (電子工作ステーションで購入)
- リチウムポリマーバッテリー → 102025 リチウムポリマー電池 3.7V 400mAh (Amazonで購入)
→ nRF52840には充電回路が入っているっていうので、これを採用。 - 上記が入っていたケース(ちょうどよかったので再利用)
- セラミックコンデンサー 0.1μF → ストック品 (電子工作ステーションで以前購入)
- スライドスイッチ → CR02032電池ケースを壊して利用 (電子工作ステーションで以前購入)
- ジャンパー線 → ストック品 (Amazonで以前購入)
- CherryMX PCB基盤 → ストック品(Amazonで以前購入)
- CherryMX 銀軸 → ストック品(Amazonで以前購入)
- キーキャップ (Amazonで購入)
- ネジ → ストック品(ホームセンターで購入:M2、長さはいろいろ)
組み立て
ここで、できた気分になります!!
プログラミング
まずは、ソースをご紹介。
#include <bluefruit.h>
const int PIN_SW1 = A0; // スリープ実行 (Windows用)
const int PIN_SW2 = A1; // スリープ解除 (Windows用)
BLEDis bledis;
BLEHidAdafruit blehid;
void setup() {
Serial.begin(115200);
pinMode(PIN_SW1, INPUT_PULLUP);
pinMode(PIN_SW2, INPUT_PULLUP);
// 省電力設定(電池駆動時の内部DCDC有効化)
NRF_POWER->DCDCEN = 1;
Bluefruit.begin();
Bluefruit.setTxPower(4); // 安定通信のため+4dBmにしてみた
Bluefruit.setName("BLE Sleep Switch");
bledis.setManufacturer("Seeed Studio");
bledis.setModel("XIAO nRF52840");
bledis.begin();
blehid.begin();
// Windows向け最適化アドバタイズ設定
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_KEYBOARD);
Bluefruit.Advertising.addService(blehid);
Bluefruit.Advertising.addName();
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244);
Bluefruit.Advertising.setFastTimeout(30);
Bluefruit.Advertising.start(0);
Serial.println("-> Windows BLE Sleep Switch Ready.");
}
void loop() {
// -------------------------------------------------------------
// SW1 (A0): Windowsを確実にスリープ (Win + X -> U -> S)
// -------------------------------------------------------------
if (digitalRead(PIN_SW1) == LOW) {
Serial.println("\n[SW1 Detected] Executing Sleep Sequence...");
if (Bluefruit.connected()) {
// Step 1: Win + X を送信(アドバンスドメニュー展開)
uint8_t keycode_x[6] = { HID_KEY_X, 0, 0, 0, 0, 0 };
blehid.keyboardReport(KEYBOARD_MODIFIER_LEFTGUI, keycode_x);
delay(150);
blehid.keyRelease();
delay(600); // メニュー展開待ち
// Step 2: 'u' キー送信(シャットダウン/サインアウトメニュー選択)
uint8_t keycode_u[6] = { HID_KEY_U, 0, 0, 0, 0, 0 };
blehid.keyboardReport(0, keycode_u);
delay(150);
blehid.keyRelease();
delay(600); // サブメニュー展開待ち
// Step 3: 's' キー送信(スリープ実行)
uint8_t keycode_s[6] = { HID_KEY_S, 0, 0, 0, 0, 0 };
blehid.keyboardReport(0, keycode_s);
delay(150);
blehid.keyRelease();
Serial.println("-> Sleep Sequence Sent Successfully.");
} else {
Serial.println("-> Status: NOT Connected via BLE!");
}
while (digitalRead(PIN_SW1) == LOW) delay(10);
Serial.println("[SW1 Released]");
}
// -------------------------------------------------------------
// SW2 (A1): スリープ解除 (Spaceキー送信)
// -------------------------------------------------------------
if (digitalRead(PIN_SW2) == LOW) {
Serial.println("\n[SW2 Detected] Sending Space Key for Wake Up...");
if (Bluefruit.connected()) {
// Space キーを送信
uint8_t keycode_space[6] = { HID_KEY_SPACE, 0, 0, 0, 0, 0 };
blehid.keyboardReport(0, keycode_space);
delay(150);
blehid.keyRelease();
Serial.println("-> Sent Space Key successfully.");
} else {
Serial.println("-> Status: NOT Connected via BLE!");
}
while (digitalRead(PIN_SW2) == LOW) delay(10);
Serial.println("[SW2 Released]");
}
delay(20);
}
書き込み
ここでハマりました。
ハマったのは、Arduinoのボード選択。
お試し実行
どうなってるかわかんないので、シリアルに情報を出すコードにしてますので、ますは、ArduinoIDE上で実行してみます。
Windowsマシンで、Bluetooth認識できました。
やったー!!
## 動くかな??
-
メモ帳を開いて、スペースキーが押せるか試します。
→OK! やったー。 -
スリープを試します。
→OK! やったー。
ところが・・
スリープしたあと、起きません。
どうも、自分のパソコンはスリープするとBluetoothを認識しないようです。
さて、困った。
ぐぐってみたら、BIOSの設定を変えろとのこと。
→今、ここで挫折中。 今、USBキーボードがなくてBIOS画面を開けません・・・
ということで、もうちょっと頑張ります。
以上。








