RaspberryPiをUSB接続のSSDから起動する

今回はRaspberryPiをUSB接続のSSDから起動してみたいと思います。

※失敗しても責任は持てませんので自己責任でお願いいたします。

RaspberryPi 3 B+モデルからはUSB起動はデフォルトで有効になっていますが、RaspberryPi 3 BまでではUSB起動自体ができない状態でした。

ですが、以下の情報を読むと…

www.raspberrypi.org

USB boot is available on the Raspberry Pi 3B, 3B+, 3A+ and Raspberry Pi 2B v1.2 models only.

RaspberryPi 2Bでも行けるとのこと。これは試してみたいですね。

ブートモードはワンタイムプログラマブルメモリ(OTP(One-Time Programmable) memory)を変更することで、 有効化されます。そこでまずはRaspberryPi3でブートモードを有効化にする必要があります。具体的には/boot/config.txtにパラメーター設定をします。

では、設定をしてみましょう!

今回使用したRaspberryPiについて

今回しようしたのはRaspberryPi3ですが以下のものを使用しています。 ちなみにB+では初期状態からUSBのストレージからの起動にはデフォルトで対応しているので 作業不要です。

【ハードウエア】

$ cat /proc/device-tree/model 
Raspberry Pi 3 Model B Rev 1.2

【OS】

$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 9.8 (stretch)
Release:        9.8
Codename:       stretch

今回使用したデバイスは以下になります。SSDはかなり古めのデバイスですが、SDカードよりは十分早いので効果は現れるかなと思います。

USB起動の設定

通常起動したら、OTPメモリの状況を確認します。

$ vcgencmd otp_dump | grep 17:
17:1020000a

この値が状態がデフォルトになので、ここを書き換えていきます。 まずはaptでパッケージを更新して、そのあとrpi-updateコマンドでRaspberryPiもアップデートしておきます。一応、念の為の作業になりますが、やっておきましょう。

$ sudo apt update
$ sudo apt upgrade
$ sudo rpi-update
$ sudo reboot

下の再起動が終わったら、以下のコマンドを入力してOTPメモリに書き込みをする準備をします。 以下のコマンドで/boot/config.txtの末尾に追記します。

$ echo program_usb_boot_mode=1 | sudo tee -a /boot/config.txt

これらの作業が終わったら、一応再起動を行います。この再起動によってOTPメモリが書き換えられます。

$ sudo reboot

起動後に再度OTPメモリの状態を確認すると以下のように変更されていることがわかります。

$ vcgencmd otp_dump | grep 17:
17:3020000a

(旧)17:1020000a → (新)17:3020000a

これで作業完了です。 あとは、この状態でインストールイメージを書き込んだストレージをUSBに挿入すれば起動できます。

起動用のSDカードを作成するEtcherではUSBメモリSSDも初期化できるのでお手軽です。(確認のダイアログが何回か表示されますが問題ありません)

www.balena.io

USBで起動する

自分の手持ちのUSBストレージ環境でいくつかのを試しましたが、USBメモリ、SSDHハードディスクでは問題なさそうですが、USB-USBメモリの変換コネクタでは失敗することもありました。

ちなみにUSBメモリとSDカードメモリを両方挿した状態はSDカードの起動が優先されるようです。

250GのSSDで起動し、Raspbianをインストールしたときのディスクの状態はこんな感じになりました。

SSD起動時の状態】

$ sudo fdisk -l

…(略)…

Disk /dev/sda: 238.5 GiB, 256060514304 bytes, 500118192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x679a8aa9

Device     Boot Start       End   Sectors   Size Id Type
/dev/sda1        8192     96042     87851  42.9M  c W95 FAT32 (LBA)
/dev/sda2       98304 500118191 500019888 238.4G 83 Linux

ちゃんと起動されていることがわかります。

【比較:SDカード起動時の状態】

$ sudo fdisk -l

…(略)…

Disk /dev/mmcblk0: 29.6 GiB, 31765561344 bytes, 62042112 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x8e8f7bbf

Device         Boot Start      End  Sectors  Size Id Type
/dev/mmcblk0p1       8192    96042    87851 42.9M  c W95 FAT32 (LBA)
/dev/mmcblk0p2      98304 62042111 61943808 29.6G 83 Linux

【比較:USBメモリ起動時の状態】

$ sudo fdisk -l

…(略)…

Disk /dev/sda: 28.7 GiB, 30752000000 bytes, 60062500 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xd92665a9

Device     Boot Start      End  Sectors  Size Id Type
/dev/sda1        8192    96042    87851 42.9M  c W95 FAT32 (LBA)
/dev/sda2       98304 60062499 59964196 28.6G 83 Linux

sysbenchのインストールとベンチマークテスト

今回はベンチマークのアプリケーションとしてsysbenchを使用します。 Unixbenchでも良かったのですが、今回はbuildの必要がないsysbenchとしました。

以下を参考にインストールをします。

github.com

RasbianはDebian/Ubuntuと同様で大丈夫なので以下でOKです。

$ sudo apt install sysbench

Optionなしでsysbenchを起動すると、以下のようにOption一覧が表示されます。

$ sysbench 
Missing required command argument.
Usage:
  sysbench [general-options]... --test=<test-name> [test-options]... command

General options:
  --num-threads=N            number of threads to use [1]
  --max-requests=N           limit for total number of requests [10000]
  --max-time=N               limit for total execution time in seconds [0]
  --forced-shutdown=STRING   amount of time to wait after --max-time before forcing shutdown [off]
  --thread-stack-size=SIZE   size of stack per thread [32K]
  --init-rng=[on|off]        initialize random number generator [off]
  --test=STRING              test to run
  --debug=[on|off]           print more debugging info [off]
  --validate=[on|off]        perform validation checks where possible [off]
  --help=[on|off]            print help and exit
  --version=[on|off]         print version and exit

Compiled-in tests:
  fileio - File I/O test
  cpu - CPU performance test
  memory - Memory functions speed test
  threads - Threads subsystem performance test
  mutex - Mutex performance test
  oltp - OLTP test

Commands: prepare run cleanup help version

See 'sysbench --test=<name> help' for a list of options for each test.

今回はファイルIOのベンチマークを取りたいので--test=fileioのオプションをつけることになりますが、さらにサブオプション(--file-test-mode)をつけることができます。サブオプションは以下の通りです。

モード 説明
seqwr シーケンシャル書き込み
seqrewr シーケンシャル読み書き
seqrd シーケンシャル読み出し
rndrd ランダム読み出し
rndwr ランダム書き込み
rndrw ランダム読み書き

今回はシーケンシャルの読み書きをテストしてみるので--file-test-mode=seqrewrを指定しています。

$ sysbench --test=fileio --file-test-mode=seqrewr run
sysbench 0.4.12:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 1

Extra file open flags: 0
128 files, 16Mb each
2Gb total file size
Block size 16Kb
Periodic FSYNC enabled, calling fsync() each 100 requests.
Calling fsync() at the end of test, Enabled.
Using synchronous I/O mode
Doing sequential rewrite test
Threads started!
Done.

Operations performed:  0 Read, 131072 Write, 128 Other = 131200 Total
Read 0b  Written 2Gb  Total transferred 2Gb  (32.635Mb/sec)
 2088.66 Requests/sec executed

Test execution summary:
    total time:                          62.7540s
    total number of events:              131072
    total time taken by event execution: 58.4210
    per-request statistics:
         min:                                  0.04ms
         avg:                                  0.45ms
         max:                                713.06ms
         approx.  95 percentile:               0.15ms

Threads fairness:
    events (avg/stddev):           131072.0000/0.00
    execution time (avg/stddev):   58.4210/0.00

ベンチマークで使用されたファイルは残ってしまうので、以下のコマンドでクリーンにして置きましょう。

$ sysbench --test=fileio cleanup

結果は

32.635Mb/sec

すごい!このSSDは4年ぐらい前に購入したのですが、Windowsでは全く使い物にならなかった(プチフリが原因?)感じでしたが、RaspberryPiであればそこまでのパフォーマンスの低下は感じなさそうなのでいい感じかなと思います。USB2.0転送速度の限界のこともあるので、少し古めでお安いSSDでもいい効果が見られるのかなと思いますよ。

【比較:SDカードでのベンチマーク

$ sysbench --test=fileio --file-test-mode=seqrewr run
sysbench 0.4.12:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 1

Extra file open flags: 0
128 files, 16Mb each
2Gb total file size
Block size 16Kb
Periodic FSYNC enabled, calling fsync() each 100 requests.
Calling fsync() at the end of test, Enabled.
Using synchronous I/O mode
Doing sequential rewrite test
Threads started!
Done.

Operations performed:  0 Read, 131072 Write, 128 Other = 131200 Total
Read 0b  Written 2Gb  Total transferred 2Gb  (11.802Mb/sec)
  755.35 Requests/sec executed

Test execution summary:
    total time:                          173.5244s
    total number of events:              131072
    total time taken by event execution: 168.8663
    per-request statistics:
         min:                                  0.04ms
         avg:                                  1.29ms
         max:                               6575.40ms
         approx.  95 percentile:               0.16ms

Threads fairness:
    events (avg/stddev):           131072.0000/0.00
    execution time (avg/stddev):   168.8663/0.00

【比較:USBメモリでのベンチマーク

$ sysbench --test=fileio --file-test-mode=seqrewr run
sysbench 0.4.12:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 1

Extra file open flags: 0
128 files, 16Mb each
2Gb total file size
Block size 16Kb
Periodic FSYNC enabled, calling fsync() each 100 requests.
Calling fsync() at the end of test, Enabled.
Using synchronous I/O mode
Doing sequential rewrite test
Threads started!
Done.

Operations performed:  0 Read, 131072 Write, 128 Other = 131200 Total
Read 0b  Written 2Gb  Total transferred 2Gb  (17.081Mb/sec)
 1093.16 Requests/sec executed

Test execution summary:
    total time:                          119.9023s
    total number of events:              131072
    total time taken by event execution: 109.9788
    per-request statistics:
         min:                                  0.04ms
         avg:                                  0.84ms
         max:                               1930.89ms
         approx.  95 percentile:               0.15ms

Threads fairness:
    events (avg/stddev):           131072.0000/0.00
    execution time (avg/stddev):   109.9788/0.00
ストレージ 転送速度
SDカード 11.802Mb/sec
USBメモリ 17.081Mb/sec
SSD HDD 32.635Mb/sec

おわりに

予想以上のパフォーマンスなので、ファイルIOを多用する場合にはUSB経由の起動にしたほうが良さそうです。 ただ、RaspberryPiからUSB給電する場合には電源には気をつけたほうがいいかもしれません。

体感もかなり高速だなと思いました。特にパッケージのインストールなどではそれが顕著に感じました。SDカードの挿入も面倒なので今後はUSBの運用にしちゃうかもしれません。

Pixelaを使ってはてなブログにPV数の草を生やしてみた

今回のエントリの内容はメモレベルです。

去年のMashupAwards2018で出た作品でFesta(最後のイベント)に参加したときに、githubのような感じででコミットの状態を出すサービスでPixelaというものがあるということを知りました。そのときはおもしろいなと思ってましたが、自分にはあんまり関係ないのかな~という感じでみていました。

ただ、少し前まで使用していた、ブログのPV数をTwitterでつぶやいてくれるサービスがうまく動作してない(多分https化したときに設定が変わったから?)という状況と、最近はTwitterのタイムラインを見る機会がそれほど多くなくなってきたということもあるので、別の手段でなんか見れないかなと思っていました。

んで、ググってみたところPixelaの作者さんのエントリーに当たりました。

pixe.la

blog.a-know.me

このやり方をそのまま進めれば問題ないのですが、設定していたところちょっと躓いたのでメモ。 上記の2つのエントリーを読んでについて書いています。

  1. ユーザの登録
  2. グラフデータの作成の仕方
  3. はてなブログへの貼付け方法

ただ、設定してブログに貼り付けたあとPV数の更新(カウントアップ)がされない状況になります。これだけではなにかが足りないような感じです。グラフの生成はされているので、外部にカウント機能を持った何かが必要なのかなと思っていたのですが、以下のエントリを読み込んでみてわかりました。

blog.a-know.me

ここで、これまでの Pixela を知っている人向けの説明として、今回のバージョンアップで selfSufficient というフィールドが指定できるようになっています。直訳すると自給自足。これはつまり、グラフが見られるごとに自分自身を加算(もしくは減算)していく、ということを指定するための属性になります。

グラフの生成時のJSON"selfSufficient":"increment"のフィールドを追加することでグラフへアクセスするたびにカウントできるということです。これを指定すれば問題は解決します。

ただサンプルにあるコマンド例がcurlのため、Windowsではかなり不安ですw。

そこで作者の方が別途作成されたpiというCLIツールを使用することにします。ここまでやると別途curlをインストールしてもいいんですけどね。

blog.a-know.me

まずはこちらからダウンロードします。 Windows処理系なのでリスト中からpi_v1.0.1_windows_amd64.zipを選んでダウンロードします。 Windows処理系なのでリスト中からpi_v1.0.2_windows_amd64.zipを選んでダウンロードします。 アーカイブを展開するとこんな感じになるので、テキトーな場所に展開します。

f:id:ueponx:20190421182625p:plain

実はこのままだとうまくいかないです。 実行ファイルのpiに拡張子がないので実行しようとしても失敗します。リネームしてpi.exeにします。 念の為githubで作者の方にissueを投げたところ、version 1.0.2にバージョンアップして対応していただきました。超感謝! これで準備完了です。

あとは事前に以下を決めておきます。

  • ユーザーネーム
  • アクセスに必要なAPIトーク
  • グラフ名(URLで使用)
  • グラフ名(人間識別用)

この実行ファイルはAPIトークンを環境変数で使用するのでユーザー登録をしたときのトークンは登録が成功したら環境変数PIXELA_USER_TOKENに登録しておきましょう。

今回は以下の様に決める前提としようと思います。

設定項目 設定値
ユーザーネーム hogepon
APIトーク fuga2019
グラフ名(URLで使用) hatena-pv
グラフ名(人間識別用) "HatenaPV graph"

これを使って実行していきます。

> pi users create --username hogepon --token fuga2019 --agree-terms-of-service yes --not-minor yes
> set PIXELA_USER_TOKEN=fuga2019
> pi graphs create -u hogepon -g hatena-pv -n "HatenaPV graph" -i view -t int -c shibafu -z "Asia/Tokyo" -s increment

f:id:ueponx:20190421143451p:plain

piコマンドは成功すると以下の様なJSONが帰ってくるので判断に使用します。

{"message":"Success.","isSuccess":true}

上記のコマンドが成功すると以下のURLでグラフの状況を見ることができます。 ユーザー名、グラフ名が自分のものになっているかを確認しましょう!

https://pixe.la/v1/users/hogepon/graphs/hatena-pv.html

f:id:ueponx:20190421143749p:plain

これでOKです。

リロードするとちゃんとカウントアップできました。

f:id:ueponx:20190421144231p:plain

あとは

blog.a-know.me

上記のブログ通りに設定すれば問題ありません。あとは引っかかるところはほとんどありませんが、 テストで使用しているURLは作者さんのページなので自分のグラフのURLに書き換えましょう。

おわりに

今回はちょっと引っかかった部分があったのでやってみましたが、REST API経由でこういうグラフが出せるのは便利かも。あとカウンタの値がページ描画完了してからのカウントになっているのではてなブログのアクセスカウンターよりも少なく表示されています。多分、ちゃんとページロードが走った部分だけがカウントされているからだと推測。はてなさんのアクセス数はGoogleさんのBots経由のアクセスも含まれているのかもしれませんね。

以下が設定して配置した結果です。

f:id:ueponx:20190421145502p:plain

これからの草生え具合を楽しみにします。

RaspberryPi3にWindows10 ARM版をインストールする【インストール編】(2019/04/12現在)

前回のエントリに引き続きRaspberryPi3にWindows10 ARM版をインストールするということでやっていこうと思います。 前回のエントリではMicroSDカードメモリにインストールイメージを作成するところまでを行いました。

【前回のエントリ】

uepon.hatenadiary.com

今回のエントリではそのMicroSDカードメモリをRaspberryPi3に挿して起動し、Windows10のARM版を立ち上げる部分となります。 わりとバギーなものなので、なぜそうなるのかということよりも、うまく行った方法みたいなことになりますので、ご注意ください。 うまく行かなかった点もそのうち治ると思いますよw

起動→UEFIっぽい部分

MicroSDカードメモリをRaspberryPi3に挿入します。今回使用したのはRaspberryPi3 Bになります。最近はB+も出ていますが、多分どちらでも大きくは変わらないのではと思います。

起動するとRaspberryPiのロゴが大きくでプログレスバーがその下に出てきます。

f:id:ueponx:20190414080121j:plain

そのままにしているとUEFIのシェルモード画面になってしまいます。

f:id:ueponx:20190414080129j:plain

ロゴが出ているうちに【ESC】キーを押してメニューモードに入りましょう。2019/04/17追記:UEFIのシェルモード画面になった場合にはexitと入力すればメニューモードに行けるようです。このような画面になります。BIOSのような画面のような感じです。

f:id:ueponx:20190414080137j:plain

ここまで来たらBootの順番などの設定を行っていきます。まずは【Boot Maintenance Manager】にカーソルをあわせて【Enter】キーを押して設定を行っていきます。

f:id:ueponx:20190414080145j:plain

Boot Maintenance Managerの画面になったら【Boot Options】を選択し、【Enter】キーを押して進みます。

f:id:ueponx:20190414080154j:plain

Boot Optionsの画面になったら【Change Boot Order】を選択し、【Enter】キーを押して進みます。

f:id:ueponx:20190414080201j:plain

Change Boot Orderの画面にくると【Change the order】で<UEFI Shell>`<SD/MMC on Broadcom SDHOST>にカーソルが来ていると思うので、そのまま【Enter】キーを押します。

f:id:ueponx:20190414080210j:plain

以下のような画面になったら、【UEFI Shell】にカーソルが当たっている状況で【-(マイナス)】キーを押して

f:id:ueponx:20190414080218j:plain

以下のように【SD/MMC on Broadcom SDHOST】(上)と【UEFI Shell】(下)に変化させます。

f:id:ueponx:20190414080237j:plain

設定が終わったら【ESC】キーを押してメニューに戻ります。

f:id:ueponx:20190414080244j:plain

設定を変更したので【Commit Changes and Exit】にカーソルを移動させて【Enter】キーを押します。

f:id:ueponx:20190414080252j:plain

すると、Boot Optionsの画面に戻ります。そのまま、【Go Back To Main Page】にカーソルを合わせて、【Enter】キーを押します。

f:id:ueponx:20190414080302j:plain

Boot Maintenance Managerの画面に戻ります。そのまま、【ESC】キーを押してメインメニューに戻ります。

f:id:ueponx:20190414080310j:plain

メインメニューに来たら今度はカーソルを【Boot Manager】に合わせて【Enter】キーを押します。

f:id:ueponx:20190414080328j:plain

※注意この操作をするとSDカードから起動を行います。

Boot Managerの画面に遷移したら、【SD/MMC on Broadcom SDHOST】にカーソルを合わせて【Enter】キーを押します。これでRaspberryPiは再起動され、Windows10のインストール処理を開始しますので注意してください。

f:id:ueponx:20190414080343j:plain

Windows10のインストール処理

再起動が行われるとWindows10のロゴが表示されインストール処理が開始されます。ここからも時間がかかる処理が多いので30分ぐらいかかると思っていてください。

f:id:ueponx:20190414080353j:plain

時間が経つと以下のような画面になります。住んでいる地域の設定になります。今回はデフォルトだった【日本】にカーソルを合わせて【はい】ボタンをクリックします。(ここからはマウス操作はできます。)

まずはWindows10のインストール作業が進んだということで一安心となるのですが…

f:id:ueponx:20190414080519j:plain

問題が発生しましたと表示されます。画面上にはやり直すことも、今はスキップすることもできます。という優しい言葉が表示されますが、何度【やり直す」ボタンをクリックしても同じ画面にいきつきます。ですので、【スキップ】ボタンをクリックして処理を進めていきます。

OOBEKEYBOARDと表示されているのでキーボードの認識関連でコケているのだと推測。その後の設定でもキーボードが英語キーボードの配列になっているので注意です。

ここで脱落する人もいるかもという罠その1

f:id:ueponx:20190414080528j:plain

そのあと、ネットワークに接続していなければ有線ネットワークの設定などを行う画面が入ったりしますが、事前にEthernetケーブルを指しておけば、セットアップは何もしなくても継続してくれます。

f:id:ueponx:20190414080536j:plain

処理中に、またもや問題が発生しましたと表示されます。OOBEEULAとかかれていますが、こちらは内容がよくわかりませんが、やり直すことができます。と書かれていますというか【やり直す】ボタンしかないので、これをクリックして進めていきます。

f:id:ueponx:20190414080545j:plain

そのまま処理は進めていけました。

f:id:ueponx:20190414080600j:plain

少し時間が経つとWindows10の使用許諾契約の画面が表示されます。【同意】ボタンをクリックします。

f:id:ueponx:20190414080608j:plain

設定する方法を指定してください。と画面に出るので今回は個人用に設定を選び

f:id:ueponx:20190414080615j:plain

【次へ】ボタンをクリックしました。

f:id:ueponx:20190414080624j:plain

Microsoftアカウントでサインインという画面に来ます。 もうこれで大丈夫そうだなという空気が漂います。 アカウントのメールアドレスを入力します。先程もいいましたがキーボードの配列がJISではないので気をつけて入力してください。入力が終わったら【次へ】ボタンをクリックします。

f:id:ueponx:20190414081205j:plain

続いてはパスワードを入力します。入力後に【次へ】ボタンをクリックします。

f:id:ueponx:20190414081251j:plain

するとまたインストール処理が進みます。

f:id:ueponx:20190414081334j:plain

少しすると今度はPINの設定処理になります。ここはスキップはできないようですね…

f:id:ueponx:20190414081359j:plain

好きなものをPINにして処理を進めましょう。入力できたら【OK】ボタンをクリックします。

f:id:ueponx:20190414081421j:plain

アクティビティの履歴を利用してデバイス感でより多くのことを行うという画面が表示されます。ここでは【いいえ】を選択しました。

f:id:ueponx:20190414081453j:plain

AndroidまたはiPhoneをこのPCにリンクするという画面になります。ここは画面左下の【後で処理する】をクリックしてスキップを行います。

f:id:ueponx:20190414081501j:plain

OneDriveの設定になりますが、SDカードの容量などもあるのでこのあたりはやめて画面左下の【このPCにのみファイルを保存する】をクリックしてスキップをしました。

f:id:ueponx:20190414081511j:plain

デジタルアシスタントを利用する画面が表示されます。もうそろそろ完了しそうな雰囲気ですね! 基本的にはデジタルアシスタントはスキップする項目なので【拒否】をクリックして選択するのですが、

f:id:ueponx:20190414081525j:plain

問題が発生しました。(エラーはOOBESETTINGS)となります。やり直すことができますと表示されますが、何度やってもこの画面に戻ってきます。(※でも何度かやることが重要のようです)しかたないので、画面犠打理上の【←(左矢印)】ボタンをクリックして一手順戻します。

f:id:ueponx:20190414081533j:plain

するとデジタルアシスタントを利用する画面に戻ります。今度は【同意】ボタンをクリックします。

f:id:ueponx:20190414081542j:plain

すると、デバイスのプライバシー設定の選択に画面が遷移します。 初回から【同意】ボタンをクリックして進めても実は問題が発生しました。(エラーはOOBESETTINGS)が表示されます。何回か、このエラー画面を表示させて、その後手順を戻さないと何故か進められなかったようです。

ここが結構わかりにくいハマりポイントでした。

ここでは適切に設定して貰もらって、【同意】ボタンをクリックします。(結局同意にしないと進められないということです)

f:id:ueponx:20190414081550j:plain

クリックすると処理が進みます。

f:id:ueponx:20190414081557j:plain

そして、画面の解像度がアップして全画面モードになります!漸くWindowsの設定が完了した様子です。

f:id:ueponx:20190414081605j:plain

数分かかるらしい…

f:id:ueponx:20190414081614j:plain

いよいよインストールが終わりそうです!

f:id:ueponx:20190414081622j:plain

予想より長いらしい…こんな表示初めてみました!

f:id:ueponx:20190414081632j:plain

やっと起動しました!(45分弱経っていたようです)

f:id:ueponx:20190414081640j:plain

Edgeの画面がでるのですが、真っ白。ネットワークの設定が画面右からニューっと出てくるのでその設定をしたら

f:id:ueponx:20190414081650j:plain

Edge言語設定ダイアログが表示されました。

f:id:ueponx:20190414081700j:plain

プルダウンから【日本語】の設定にして、【Get Start】ボタンをクリックします。

f:id:ueponx:20190414081709j:plain

無事に起動できたようです。

f:id:ueponx:20190414081717j:plain

インストールの情報に関して

画面のキャプチャなども通常のWindows同様にできるようなのでやってみました。スピードに関しては全く実用的ではありませんが、Webの閲覧もかなり我慢すればできなくはないと行ったところです。

f:id:ueponx:20190414081924p:plain

コンピュータの情報のキャプチャもとってみました。

f:id:ueponx:20190414081939p:plain

ちゃんとARMベースのプロセッサになっています!

おわりに

なんとかRaspberryPi3にWindows10のARM版をインストールできました。 動作が遅いのはPC資源としては非力なので致し方ないです。ですが、この大きさのものでWindows10も動くのだな~という点では関心しました。

パフォーマンスのチェックはしませんでしたが、一番のネックはストレージでしょうか。 CPUのパワーも100%に近い状態ではありましたが、クロックを600MHzからもう少し上げることができるので、熱対策を行ってそれを行えば割とまだありかな? ストレージに関してはもう100%から下がることはほとんどなかったです。

RaspberryPi 3B+モデルではUSBストレージからの起動もデフォルトで可能なのでSSDUSBメモリなどを接続(電源的な辛さもありそう)すればもう少し動作の改善がみられるかなと思いました。

残りの課題としてはノートPCのVisual Studioで作成したARM処理系のプログラムが動くのかに関しては後日調べてみたいです。

でも最後のトラップは普通だとあきらめるよなあ…

RaspberryPi3にWindows10 ARM版をインストールする【準備編】(2019/04/12現在)

RaspberryPiにWindows10 ARM版がインストールできたという話題が2019年の2月頃にネットに出ていました。

gigazine.net

いよいよ、IoTCoreではなく、通常のWindows10も動作するようになったのか!ということで自分も以前から何回か試していたのですが、 全くインストーラーがブルースクリーンから進行せず。SDカードの相性のことも聞こえてきたのでそのときは諦めることにしました。

最近、Facebookのコミュニティでうまくインストールできた方がいらっしゃってうまく行ったMicroSDカードメモリを教えていただいたので再度チャレンジを行いました。 自分みたいに知りたい方もいるかなと思いますので、自分がうまく行った方法論を記録します。この他の方法で成功するかはわかりませんが自分の成功した 手順だけを記録しておきます。自分も5回ぐらい失敗してわかった感じなので。うまく行かなくても責任は持てません。

あと、全部やろうとすると3-4時間ぐらいかかると思いますのでご注意ください。

自分は以下のエントリーを参考にしています。(最初の記事が出た2月の時点からツールなどの情報が変わっているので注意

【参考】 qiita.com

qiita.com

【2019/04/17追記】 ツールがバージョンアップしたので以下からダウンロードすると以下の手順がほぼなくなるようです github.com


MicroSDカードメモリにインストールイメージを生成する

準備編ではMicroSDカードメモリにインストールイメージを生成するところを行います。この時点ではSDカードの相性などは存在しません。

Facebookで紹介されたMicroSDカードメモリを使用しています。A1仕様のカードでないとインストーラーが起動した段階でブルースクリーンが連発すると思います(多分リードのタイムアウトが原因だと思います。)インストール後はサイズとしては16Gぐらい必要なるようなので、32Gぐらいのサイズでもいいと思いますが、今回は64Gのものを使用しています。SDカードメモリの規格もうすこし少なくならんものなんでしょうかね…

必要になるものとしては

【ハードウエア】

  • RaspberryPi 3B/B+
  • MicroSDカードメモリ

【ソフトウエア】

となります。

Windows on Raspberry imagerのダウンロード

MicroSDカードメモリに、インストールイメージを作成するのがWindows on Raspberry imagerになります。以下のページからダウンロードをします。

https://www.worproject.ml/

ダウンロードページはこちら

こちらのページにも必要なものはかいてありますのでチェックしましょう。 Windows on Raspberry imagerの実行にはbuild 15063以降が必要のようです。

ダウンロードが終わったら、展開しておきます。

f:id:ueponx:20190414135259p:plain

Windows 10 ARM64イメージの取得

つづいては使用するWindows10 のARM64イメージをダウンロードします。以下のサイトから選択すると、ISOイメージを取得するcmdファイルがダウンロードできます。 このcmdファイルを実行することになります。

uup.rg-adguard.net

リンクを開くと以下のような画面になります。

f:id:ueponx:20190414142333p:plain

今回は以下のパラメータで設定しました。

  • Select type: Cumulative Update for Windows 10
  • Select version: [18362.53]2019-04 Cumulative Update for Windows 10 Version 1903 for arm64-based System[arm64]
  • Select language: ja-jp: Japanese
  • Select edition: Windows 10 Professional
  • Select type download: Download ISO complier in OneClick!(run downloaded CMD-file)

パラメーターが設定されると画面の右にダウンロードリンクが表示されるのでそれをクリックします。

f:id:ueponx:20190414144840p:plain

今回はこんな感じのファイル名がでててくるのでこれをダウンロードします。ダウンロードしたらイメージ作成用のフォルダに保存します。

creatingISO_18362.53_ja-jp_arm64_professional.cmd

このcmdファイルを実行するとcmdウインドウが開きます。

f:id:ueponx:20190414150026p:plain

f:id:ueponx:20190414154916p:plain

実行が完了するとPress any key to exit.が表示されるのでウインドウが閉じます。(40分ぐらいかかります) cmdファイルの保存されているフォルダにISOファイルができていると思います。(他にもフォルダができていると思いますが問題有りません)

f:id:ueponx:20190414155033p:plain

これでWindows 10 ARM64イメージの準備はOKです。

Raspberry Pi用のTiano Core UEFIファームウェアの取得

以下のGithubリンクからダウンロードをします。(gitコマンドからも取得できます)

github.com

f:id:ueponx:20190414153704p:plain

こんな感じでZipファイル展開しましょう。実際に使用するのはこのアーカイブ内の RaspberryPiPkg-master\RaspberryPiPkg-master\Binary\prebuilt\2019Feb18-GCC5\DEBUG\RPI_EFI.fdファイルになります。(2019/04/12現在)

また後ほどツールから場所を指定することになります。

f:id:ueponx:20190414154429p:plain

これでRaspberry Pi用のTiano Core UEFIファームウェアの準備はOKです。

デバイスドライバを含むZIPアーカイブの取得

以下のリンクにドライバのアーカイブがあるのでダウンロードします。

https://www.worproject.ml/downloads

f:id:ueponx:20190414154806p:plain

このファイルはZIPファイルのままで大丈夫です。

f:id:ueponx:20190414155431p:plain


インストールイメージをMicroSDカードメモリに書き込む

イメージは先程準備したWindows on Raspberry imagerを使用して行います。 WoR.exeを起動します。

f:id:ueponx:20190414164027p:plain

起動すると以下ウインドウが開きます。言語設定もできるのですが、変えてもほとんどメッセージの内容が変わらないのでEnglishのままで進めます。 【Next】ボタンをクリックしてすすめます。

f:id:ueponx:20190413093904p:plain

【Select device】タブに移動します。ここでは書き込み先のMicroUSBカードメモリのドライブをしていします。予めPCに挿しておいてください。 選択して問題なければ、ウインドウの下部にチェックマークが付きます。【Next】ボタンをクリックしてすすめます。

f:id:ueponx:20190413093909p:plain

【Select image】タブに処理が移ります。ここでは使用するISOイメージを選択することになります。ここで先程ダウンロードしたISOファイル、 今回は18362.53.190401-1814.19H1_RELEASE_SVC_PROD1_CLIENTPRO_OEMRET_A64FRE_JA-JP.ISOが今回使用したISOファイルになります。(2019/04/12現在) 選択し、ウインドウ内にチェックマークがでたら【Next】ボタンをクリックしてすすめます。

f:id:ueponx:20190413093930p:plain

つづいて【Select drivers】タブに処理が移ります。ここではドライバがファイルを選択することになります。先程ダウンロードしたWoA64_Drivers_RPi3_20Feb19.zip(2019/04/12現在)を選択します。ウインドウ内にチェックマークがでたら【Next】ボタンをクリックしてすすめます。

f:id:ueponx:20190413093937p:plain

UEFI Firmware】タブに処理が移ります。ここでは先程準備したUEFIのファームウエアファイルを選択します。今回はアーカイブを展開した中からRaspberryPiPkg-master\RaspberryPiPkg-master\Binary\prebuilt\2019Feb18-GCC5\DEBUG\RPI_EFI.fd(2019/04/12現在)を選択します。この処理ではウインドウ内にチェックマークは 出てなかった感じです。【Next】ボタンをクリックしてすすめます。

f:id:ueponx:20190413093943p:plain

つづいては【Configuration】タブに処理が移ります。開始時点では以下のような画面になっています。ここは選択がいくつかあります細かく説明していきます。

f:id:ueponx:20190413093954p:plain

設定する項目は以下となります。

  • 【Install options】→【Partition scheme】:Master Boot Record(MBR)
  • 【Install options】→【Install image with】:Wimlib
  • 【Install options】→【Enable LZX install compression】:チェックを外す
  • 【WoR options】→【Save this configuration on exit】:ON

ここまで設定したら【Next】ボタンをクリックします。

f:id:ueponx:20190413094003p:plain

【Install】タブに処理が移り、最終確認の画面になります。再度、設定値の確認ができたら【Install】ボタンをクリックします。

f:id:ueponx:20190413094015p:plain

Install処理のプログレスバーが進んでいきます。完了するのに30分程度はかかると思います。

f:id:ueponx:20190413094024p:plain

終了するとThis installation has been finished!と表示されるので、

f:id:ueponx:20190413094044p:plain

【Finish】ボタンをクリックします。これでMicroSDカードメモリにインストーラーのイメージが書き込まれています。

おわりに

続いて実際にRaspberryPiにMicroSDカードメモリを挿入してWindows10をインストールさせていきます。これ以降が割とハマりポイントがあるので注意が必要です。

WebブラウザのGamepadAPIをつかってみる

前々から気になっていたのですが、最近あんまりネットで効かなくなったGamepadAPIを試してみます。

【公式情報】 w3c.github.io

公式のW3Cな情報でもいいのですが、Mozillaのサイトのほうが情報がわかりやすいので以下を参照しながらコーディングをしてみようと思います。

【参考】

developer.mozilla.org

参考をみるとこの様に書かれています。

Gamepad API は開発者とデザイナーに Gamepad やコントローラーへのアクセスを提供するものです。Gamepad API は Window オブジェクトにGamepadとコントローラー(以下、Gamepad)の状態を読み取る新しいイベントをいくつか追加します。

ではこれを見ながら最小限のコーディングをしていきます。

Webに公開できるようにGithubにUPしてみました。ここでもソースコードおいてみますのでご利用ください。

github.com

ソースコード

【index.html】

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">

<style>
.buttons, .axes {
  padding: 1em;
}

.axis {
  min-width: 400px;
  margin: 1em;
}

.button {
  padding: 1em;
  border: 2px solid black;
  background-color: rgb(255, 255, 128);
}

.pressed {
  border: 2px solid black;
  background-color: red;
}
</style>
</head>
<body>
<h2 id="start">Gamepadを接続してなにかボタンを押すとスタートします。</h2>
<script type="text/javascript" src="gamepad.js"></script>
</body>
</html>

【gamepad.js】

var haveEvents = 'GamepadEvent' in window;
var controllers = {};
var rAF = window.requestAnimationFrame;

function connectHandler(e) {
    addGamepad(e.gamepad);
}
function addGamepad(gamepad) {
    // gamepadのArrayを作成
    controllers[gamepad.index] = gamepad;
    // HTMLへ接続されたGamepad毎の要素を追加(複数のgamepadにも対応)
    var d = document.createElement("div");
    d.setAttribute("id", "controller" + gamepad.index);//idはpadの番号がついた形式
    var t = document.createElement("h2");
    t.appendChild(document.createTextNode("接続Gamepad情報: "));
    d.appendChild(t);
    var info = document.createElement("h1");
    info.appendChild(document.createTextNode(gamepad.id));
    d.appendChild(info);

    //Gamepadコントロール要素(ボタンなど)表示部分
    var b = document.createElement("div");
    b.className = "buttons";
    var t = document.createElement("h2");
    t.appendChild(document.createTextNode("ボタンコントロール情報: "));
    b.appendChild(t);
    for (var i = 0; i < gamepad.buttons.length; i++) {
        var e = document.createElement("span");
        e.className = "button";
        //e.id = "b" + i;
        e.innerHTML = i;
        b.appendChild(e);
    }
    d.appendChild(b);

    //Gamepadコントロール要素(アナログジョイなど)表示部分
    var a = document.createElement("div");
    a.className = "axes";
    var t = document.createElement("h2");
    t.appendChild(document.createTextNode("アナログコントロール情報: "));
    a.appendChild(t);
    for (i = 0; i < gamepad.axes.length; i++) {
        c = document.createElement("h3");
        c.appendChild(document.createTextNode("axis" + i));
        a.appendChild(c);
        e = document.createElement("meter");
        e.className = "axis";
        //e.id = "a" + i;
        e.setAttribute("min", "-1");
        e.setAttribute("max", "1");
        e.setAttribute("value", "0");
        e.innerHTML = i;
        a.appendChild(e);
    }
    d.appendChild(a);
    document.getElementById("start").style.display = "none";
    document.body.appendChild(d);
    rAF(updateStatus);
}

function disconnectHandler(e) {
    removeGamepad(e.gamepad);
}

function removeGamepad(gamepad) {
    var d = document.getElementById("controller" + gamepad.index);
    document.body.removeChild(d);
    delete controllers[gamepad.index];
}

function updateStatus() {
    scanGamepads();
    for (j in controllers) {
        var controller = controllers[j];
        var d = document.getElementById("controller" + j);
        var buttons = d.getElementsByClassName("button");

        //ボタン情報の状態取得
        for (var i = 0; i < controller.buttons.length; i++) {
            var b = buttons[i];
            var val = controller.buttons[i];
            var pressed = val == 1.0;
            if (typeof (val) == "object") {
                pressed = val.pressed;
                val = val.value;
            }
            var pct = Math.round(val * 100) + "%";
            b.style.backgroundSize = pct + " " + pct;
            if (pressed) {
                b.className = "button pressed";
            } else {
                b.className = "button";
            }
        }

        //アナログコントロール情報の状態取得
        var axes = d.getElementsByClassName("axis");
        for (var i = 0; i < controller.axes.length; i++) {
            var a = axes[i];
            a.innerHTML = i + ": " + controller.axes[i].toFixed(4);
            a.setAttribute("value", controller.axes[i]);
        }
    }
    rAF(updateStatus);
}

function scanGamepads() {
    var gamepads = navigator.getGamepads ? navigator.getGamepads() : [];
    for (var i = 0; i < gamepads.length; i++) {
        if (gamepads[i]) {
            if (!(gamepads[i].index in controllers)) {
                addGamepad(gamepads[i]);
                console.log("a");
            } else {
                controllers[gamepads[i].index] = gamepads[i];
                //console.log("b");
            }
        }
    }
}

if (haveEvents) {
    window.addEventListener("gamepadconnected", connectHandler);
    window.addEventListener("gamepaddisconnected", disconnectHandler);
} else {
    setInterval(scanGamepads, 500);
}

実行させてみる

GithubリポジトリをWeb公開状態に以下においてありますのでそのまま動作させてみてください。

https://ueponx.github.io/gamepadapi/

2つのファイル(index.htmlgamepad.js)をローカルPCの同じディレクトリにおいても同じ様に使用できます。

index.htmlの開くと以下のように表示されますので、

f:id:ueponx:20190330221428p:plain

Gamepadを接続するか、Gamepadのいずれかのボタンを押すと表示が変更されます。

f:id:ueponx:20190330223116p:plain

今回接続したのは以下のUSB接続をゲームパッドを接続していますが、ちゃんと認識してくれているようです。

buffalo.jp

ボタンは物理的には10あるのですが、認識されているのは連射機能とそのOFFを除く8つのボタンでした。 また、方向ボタン(十字ボタン)はアナログスティックとして認識されているようです。ただ動かすとわかるのですが、デジタル的な動きをしているようです。

また複数のゲームパッドを接続しても認識してくれます。

f:id:ueponx:20190330222810p:plain

2つ目に接続したのはXBOX Oneの無線コントローラになります。

詳細は以下の通りです。

f:id:ueponx:20190330222636p:plain

おわりに

Gamepad APIを使ってみました。まだDraft状態のAPIではありますが、現行のモダンブラウザであれば比較的対応しているのでわりといい感じです。 ネットの情報ではブラウザ毎の挙動が微妙に違っているという話もありますが…。そのうち正式な対応されるでしょう。

各ブラウザの対応状況

対応状況をみると、IEは兎も角としてSafari

あと、パッドのおすすめはXBOXなコントローラーをデフォルト扱いとして開発されているようなので、今後コントローラーを購入するのであればXBOX用のものを おすすめします。

できれば、現在あるWebアプリなどにJoy2Keyみたいな感じでこの機能を簡単でアタッチする方法とかがあるといいなあとか思いました。 なにかつかえますかねえ。IotデバイスでWebインターフェースを作るようなパターンであれば行けそうな気もしますが。

今回やってて痛感しましたが、Javascriptスクリプト書くのは問題ないんですけど、HTMLを書くのがもう面倒で厳しいかも。JQueryとかBootstrapにシフトして行きたいです…その他のフレームワークに行ってもいいのかも。

/* -----codeの行番号----- */