[[ファンアウト仙台]]

&ref(button1.jpg,zoom,250x200);
&ref(button2.jpg,zoom,250x200);
&ref(button3.jpg,zoom,250x200);

*概要 [#hdcecd2a]
Arduino 互換の Digispark という小型ボードを利用して Windows PC の USB 端子に接続する大きな電源ボタンを作りました。
接続すると「HID 準拠システムコントローラ」として認識されます。
ボタンを長押しすると、キーボードの SLEEP ボタンを押した時の信号が出力されて、PC がスリープ状態になります。ボタンを短く押すと、PC がスリープ状態から復帰します。

*原理 [#vaf903f5]
Windows PC の動作を調べたところ、USB 接続のキーボードからスリープさせる方法と、スリープからのウェイクアップをさせる方法は全く異なっていました。

**Windows PC をスリープさせる [#pd260cf8]
#ref(102key.jpg,zoom)
Windows7,8,10 では [Power][Sleep][Wake] のキーがあるキーボード(日本語112キーボード) の [Sleep] キーを押すとスリープ状態になります(この挙動はコントロールパネルの[電源オプション][電源ボタンの動作を選択する] から変更できます)。
#ref(dev.png,zoom,300x200)

通常の USB キーボードを Windows PC に接続すると、デバイスマネージャ上に [キーボード]-[HIDキーボードデバイス] として表示されますが、[Sleep] キーが付いているキーボードの場合は、これに加えて [ヒューマンインタフェースデバイス]-[HID 準拠システムコントローラ] という項目が追加されます。Windows はこのデバイスから [Sleep] キーのキーコードを受け取るとスリープ状態になります。

**Windows PC をスリープ状態からウェイクアップさせる [#u673b69e]
PC がスリープ状態になった後で、同じくキーボードの [Wake] キーを押すとウェイクアップします。ただしスリープ状態では OS 側からどのキーを押したかを判定できません。

そこで、キーボード側から USB の信号線の電圧レベルを一定のパターンで変化させることでウェイクアップさせるようになっているのですが、この手順がなかなか見つからずに苦労しました。

(参考) [[USB1.1仕様書:http://esd.cs.ucr.edu/webres/usb11.pdf]] の"7.1.7.5 Resume" に書いてありますが複雑です。また "Table 9-8. Standard Configuration Descriptor (Continued)" にある bmAttributes の "D5: Remote Wakeup" を有効にする必要がありました。今回は関係ありませんでしたが、[[HID 仕様書:http://www.usb.org/developers/hidpage/Hut1_12v2.pdf]] に出てくる "Boot Keyboard" とは BIOS 画面の操作に使えるキーボードのことだそうです。

最終的には [[PS2USB:https://github.com/robszy/ps2usb]] というプロジェクトの sendRemoteWakeUp() 関数内で実現できているのを見つけて、これを真似して実装しました。

**参考にしたツール [#ce0386eb]
-[[USBlyzer:http://www.usblyzer.com/download.htm]] : USB デバイスのディスクリプタやキーを押したときに発生するイベントを調べるためのツールです。有料ですが1ヶ月間の評価版もダウンロードできます。

*作り方 [#t88c1676]
**Digispark用ファームウェア [#xb86aef8]
-ZIP ファイル中の "DigiUSB.hex" というファイルがコンパイル後のバイナリファイルです。これを Digispark に書き込みます。
--&ref(Digispark_pwrbtn.zip); : デカスギ電源ボタン Digispark 用ファームウェア(ソース+コンパイル済みバイナリ)
-書き込み方
--RaspberryPi, Linux, FreeBSD の場合: [[Digispark+gcc Lチカチュートリアル(RaspberryPi, Linux, FreeBSD 版):http://milkandlait.blogspot.jp/2017/08/digisparkgcc-lfreebsd.html]] を参考に、書き込みツール micronucleus で書き込んで下さい。
--Windows の場合: [[DigiSpark に対応した Arduino の統合開発環境:https://sourceforge.net/projects/digistump/files/DigisparkArduino-Win32-1.0.4-May19.zip/download]] に含まれる micronucleus.exe を使えば、上と同じ手順で Windows PC からも書き込めます。



**回路 [#lbbf04d7]
-PB0 と GND の間にスイッチを1個付けるだけです。
-USB ケーブルが長いと不安定になることがあります。また USB ハブを通さないと認識されないことがあります。
#ref(sch.png);

**動作 [#d9388c23]
-まず下記の Windows の電源の設定を行う必要があります。
-スイッチを長押し(1秒以上)すると、PC がスリープ状態になります。
-PC がスリープ状態の時にスイッチを短く押すと、スリープから復帰します。

*Windows の電源の設定 [#ye71442c]
-COLOR(RED){Windows 側で下記の設定をしておかないと動作しません。}
**スリープさせる [#u3974888]
-電源オプション → 電源ボタンの動作を選択する → スリープボタンを押したときの動作」を「スリープ状態」にします。

#ref(setting1.png,zoom,300x200)

**スリープ状態からウェイクアップさせる [#uf2e3667]
-電源オプション → プラン変更の設定 → 詳細な電源設定の変更 → USB設定 → USBのセレクティブサスペンドの設定 を「無効」にします。

#ref(setting3.png,zoom,300x200)

-デカスギ電源ボタンが Windows に「HID 準拠システムコントローラ」として認識されてから、デバイスマネージャ → ヒューマンインタフェースデバイス → HID 準拠システムコントローラ の設定で、「このデバイスでコンピュータのスタンバイ状態を解除できるようにする」にチェックを入れます。

#ref(setting2.png,zoom,300x200)


*参考 [#a3f15429]
-ファームウェアのソースコードは C言語 で書いて avr-gcc-4.9.3 でコンパイルしました。[[USB HID keyboard with V-USB:http://codeandlife.com/2012/06/18/usb-hid-keyboard-with-v-usb/]] をベースにしていますが、キーボードではなく HID 準拠システムコントローラとして認識させるために main.c 中の HID ディスクリプタを次のように変更しています。

 [HID Report Descriptor]
 Usage Page (Generic Desktop) 	05 01 
 Usage (System Control) 	09 80 
 Collection (Application) 	A1 01 
    Report ID (1) 	85 01 
    Usage Minimum (System Power Down) 	19 81 
    Usage Maximum (System Wake Up) 	29 83 
    Logical Minimum (0) 	15 00 
    Logical Maximum (1) 	25 01 
    Report Count (3) 	95 03 
    Report Size (1) 	75 01 
    Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 	81 02 
    Report Count (1) 	95 01 
    Report Size (5) 	75 05 
    Input (Cnst,Ary,Abs) 	81 01 
 End Collection 	C0 
 Usage Page (Consumer Devices) 	05 0C 
 Usage (Consumer Control) 	09 01 
 Collection (Application) 	A1 01 
    Report ID (2) 	85 02 
    Logical Minimum (0) 	15 00 
    Logical Maximum (1) 	25 01 
    Usage (Volume Increment) 	09 E9 
    Usage (Volume Decrement) 	09 EA 
    Usage (Mute) 	09 E2 
    Usage (Play/Pause) 	09 CD 
    Usage Minimum (Scan Next Track) 	19 B5 
    Usage Maximum (Eject) 	29 B8 
    Report Size (1) 	75 01 
    Report Count (8) 	95 08 
    Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 	81 02 
    Usage (AL Email Reader) 	0A 8A 01 
    Usage (AC Search) 	0A 21 02 
    Usage (AC Bookmarks) 	0A 2A 02 
    Usage Minimum (AC Home) 	1A 23 02 
    Usage Maximum (AC Refresh) 	2A 27 02 
    Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 	81 02 
    Usage (AL Consumer Control Configuration) 	0A 83 01 
    Usage (AL Internet Browser) 	0A 96 01 
    Usage (AL Calculator) 	0A 92 01 
    Usage (AL Terminal Lock/Screensaver) 	0A 9E 01 
    Usage (AL Local Machine Browser) 	0A 94 01 
    Usage (AC Minimize) 	0A 06 02 
    Usage (Record) 	09 B2 
    Usage (Rewind) 	09 B4 
    Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 	81 02 
 End Collection 	C0 

-OS をウェイクアップ可能な USB デバイスにするために、usbdrv.c 中のコンフィグレーションのアトリビュート(bmAttributes) を変更する必要がありました。

 [usbdrv.c : ウェイクアップ可能デバイスにするための変更箇所]
 #if USB_CFG_IS_SELF_POWERED
 (1 << 5) | (1 << 7) | USBATTR_SELFPOWER, /* 変更後 */
  // (1 << 7) | USBATTR_SELFPOWER,        /* 変更前 */
 #else
 (1 << 5) | (1 << 7),                     /* 変更後 */
 // (1 << 7),                             /* 変更前 */
 #endif


----
#counter

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS