はじめに
前回の続きです。
前回の記事をまだ読まれていない方は、そちらを読んでから本稿をお読みいただけるとより楽しめます。
前回はRaspberry Pi Pico
(以下ラズパイピコ
)を用いて、パスワードを自動で入力するプログラムを製作しました。
ラズパイピコをHIDデバイス(キーボード)と認識させて、任意の文字列を打ち込むテスト pic.twitter.com/YbUPXdT0Yr
— Koushiro (@Koushiro_A) March 6, 2022
今回は新たなデバイスを使って、パスワード入力機を完成させます。
前回の課題点
前回明らかになった課題点が2つありました。
1つ目はセキュリティ面が弱いという点でした。
今回使うファームウェアのCircuitPython
は、PCに接続した際、ストレージとして認識されますが、
これだとソースコードが丸見えになってしまいます。
今回はこれを解決します。
2つ目はスタイリッシュではないという点でした。
前回はラズパイピコを使って実装しましたが、パスワードを自動で入力するだけのデバイスとしては大きすぎました。
特に、今回使っていないGPIOピンは必要ないですし、PCと接続するためにはmicroUSBケーブルを用意しなければなりません。
これを新たなデバイスを用意することで解決します。
今回使うデバイス
今回使うのが、Adafruit Trinkey QT2040
というデバイスです。
このデバイスはラズパイピコの心臓部であるチップRP2040
と同じものを積んでおり、ラズパイピコでのプログラム等をそのまま移植することができます。
そして見ての通り、GPIOピンが一切ありません!
これで小型化を実現できます。
さらに!
PCB上にUSB-A端子があり、直接USBポートに挿すことができます!
これで、接続のためのmicroUSBケーブルも必要ありません。
これで課題点の2つ目はクリアとなります。
CircuitPythonにおける起動手順
ここで、課題点1つ目を解決するために、CircuitPythonにおける起動手順、いわゆるブートシーケンスについて整理したいと思います。
以下のサイトを参考にさせていただきました。
こちらのサイトより、MicroPython及びCircuitPythonのブートシーケンスを引用させていただくと、
- MicroPython システム起動
- boot.py 実行
- REPL および USB ドライブ動作開始
- main.py 実行
- code.py 実行(CircuitPython のみ?)
このようになっているようです。
前回書いたプログラムは、code.py
だったので、上の手順によると一番最後に実行されることとなります。
一方上述のブートシーケンスによると、現在課題となっているUSBドライブが動作する前に、boot.py
というプログラムが実行されるようです。
つまり、ここでソースコードを見せないような処理を書けば良いということになります。
boot.pyで書く処理について
上で述べたように、boot.py
の中でストレージを無効化出来ればな~と思い、色々とリサーチしていました。
すると、Adafruit公式の以下のサイトを発見しました。
こちらに、以下のような記述がありました。
The CIRCUITPY drive is normally visible on the host computer. To disable it showing up as a USB device, use code like this in boot.py:
訳すと…
CIRCUITPYドライブは通常、ホストコンピュータ上に表示されます。USBデバイスとして表示されないようにするには、boot.pyで次のようなコードを使用します。
ということです。
そして、そのコードというのがこちらです。
import storage
storage.disable_usb_drive()
プログラムの意味としては、
-
storage
ライブラリをインポート - USBドライブを無効化する関数を実行
といった感じです。
storage
ライブラリについては、以下のリファレンスに詳しく書かれています。
これにより、ストレージが無効化→すなわちソースコードが見られる心配が(ほぼ)無いので、課題点1つ目もクリアとなります。
(実は抜け道はありますが、それはまたの機会に…)
ということでQT2040のストレージには、
- USBドライブを無効化する
boot.py
- メインプログラム用の
code.py
の2つのファイルを保存することとなります。
プログラムの修正
Adafruit Trinkey QT2040にはプログラマブルボタンが1つと、NeopixelのフルカラーLEDが搭載されていますので、これを使えるように少しだけプログラムを修正します。
↓参考にAdafruit Trinkey QT2040のピンアサイン(Adafruit公式ページより)
import usb_hid
from adafruit_hid.keyboard import Keyboard
from time import sleep
import board
import neopixel
import digitalio
keyboard = Keyboard(usb_hid.devices)
pixel_pin = board.NEOPIXEL
num_pixels = 1
pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.3, auto_write=False)
button = digitalio.DigitalInOut(board.BUTTON)
button.direction = digitalio.Direction.INPUT
RED = 0xFF0000
GREEN = 0x00FF00
BLUE = 0x0000FF
YELLOW = 0xFFFF00
#パスコード(例) : ABCDEfghij01234
pass_list = [4,5,6,7,8,9,10,11,12,13,39,30,31,32,33]
big_or_small = [1,1,1,1,1,0,0,0,0,0,0,0,0,0,0]
pixels[0] = YELLOW
pixels.show()
sleep(0.5)
while button.value==True:
sleep(0.01)
pixels[0] = GREEN
pixels.show()
for i in range(len(pass_list)):
if big_or_small[i]==1:
keyboard.press(225)
sleep(0.01)
keyboard.send(pass_list[i])
sleep(0.01)
keyboard.release(225)
keyboard.send(40)
pixels[0] = RED
pixels.show()
sleep(10)
ボタンについて
ボタンについての記述を抜粋します。
import board
import digitalio
button = digitalio.DigitalInOut(board.BUTTON)
button.direction = digitalio.Direction.INPUT
while button.value==True:
sleep(0.01)
ライブラリはboard
とdigitalio
の2つをインポートします。(1・2行目)
次に、button
という変数を用意し、これがボタンのIOであると定義します。(4行目)
さらに、IOをインプットであると認識させます。(5行目)
これにより、button.value
でボタンが押されているか(False
)、いないか(True
)を取得することができ、7行目のようにボタンが押されるまで待機といった処理が可能となります。
NeoPixel フルカラーLEDについて
先述の通り、Adafruit Trinkey QT2040にはAdafruitのNeoPixel規格のフルカラーLEDが1個搭載されています。
↓こんな感じ
これを制御するのが、以下のプログラムです。(上記プログラムより抜粋)
import board
import neopixel
pixel_pin = board.NEOPIXEL
num_pixels = 1
pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.3, auto_write=False)
RED = 0xFF0000
GREEN = 0x00FF00
BLUE = 0x0000FF
YELLOW = 0xFFFF00
pixels[0] = YELLOW
pixels.show()
ライブラリはboard
とneopixel
の2つをインポートします。(1・2行目)
なお、neopixel
ライブラリは前回のadafruit_hid
と同様に、ライブラリファイルをボード側に転送しておく必要があります。
やり方に関しては前回の記事のライブラリ導入手順を参考にしてください。
次に、変数pixel_pin
を用意し、board上のNEOPIXELを指定します。(4行目)
さらに、変数num_pixels
を用意し、LEDの数を指定します。(5行目)
今回は1つしかありませんが、数珠つなぎにして複数個操ることも可能です。
続いて新たに変数(正確にはリスト)pixels
を用意し、neopixel
の関数を用いて、LEDを定義します。(7行目)
ここまででLEDの設定は終わりましたが、光らせる色を簡単に指定するために、よく使う色を定義しておきます。
それぞれ、
【9行目】赤 #FF0000
【10行目】緑 #00FF00
【11行目】青 #0000FF
【12行目】黄 #FFFF00
となります。
これにより、14行目のように変数名(すなわち色の名前)を指定するだけで、光らせたい色を指定できます。
最後に15行目のpixels.show()
という関数により、LEDは点灯を始めます。
色の意味
フルカラーLEDは、今回のデバイスの唯一のインジケータとなります。
プログラム中の色の意味は、
黄 #FFFF00
→ 入力準備完了
緑 #00FF00
→ 入力中
赤 #FF0000
→ 入力完了・終了待機中
というようになっています。
実行映像
ここまでで大方のプログラムが出来上がったので、実際にテストしてみた映像を御覧いただきたいと思います。
ラズパイピコの互換機「Adafruit Trinkey QT2040」を使ってパスコード自動入力機を作ったので、Windowsへの自動ログインをデモ#Adafruit #RaspberryPi #RaspberryPiPico #CircuitPython pic.twitter.com/ePlKkB0n0R
— Koushiro (@Koushiro_A) March 22, 2022
本体保護について
今回使ったAdafruit Trinkey QT2040ですが、小さくてコンパクトなのはいいものの、PCBの上に素子が載っていて、それが剥き出しという状態なのはちょっと怖いですよね。
素子が載っている面に圧力がかかると、すぐに壊れてしまいそうです。
そこで、↓こちらの画像を参考にして、基盤を保護するための部品を製作することにしました。
3DPCBの取得
まず、Adafruit Trinkey QT2040の3DPCBが、Adafruit公式のGithubリポジトリにアップされているので、こちらよりダウンロードします。
ダウンロードできたら、boardファイルをAutodesk社のEAGLE
で開きます。
EAGLE
をAutodeskのアカウントと連携させておくと、EAGLE
上の3DPCBを3DCADソフトのFusion 360
に送ることができます。
↓矢印のところから
以下のようなダイアログが出てくるので、それに沿って進めていくと簡単にエクスポートすることができます。
3DCADでのデザイン
今度はこれをFusion 360
で開きます。
あとはこれを元に3DCAD上でデザインを進めて行きます。
出来上がったのが、以下のようなモデルです。
透けて見えているのがAdafruit Trinkey QT2040本体です。
上面に一枚、下面にもう一枚の覆いがあり、USBポート部分にもカバー(キャップ)があります。
上面のカバーとキャップにはストラップホルダーが用意されていて、キャップを無くさないようにしています。
完成へ
上記の3つのオブジェクトを3Dプリンタで印刷しました。
さらに↓これらの細かい部品を用意し、本体と組み合わせます。
(Φ2のビス・ナット・スペーサーとボールチェーン)
そして遂に、完成品がこちら!!
我ながら、非常に上手くできたと思っています👍
考察・感想
実際に何度か現場で使用してみましたが、めちゃくちゃ便利です!!
やはり長くてランダムで覚えられないようなパスワードにはとても有用だと思います。
前回のラズパイピコを使う方法も含め、非常に便利なデバイスだと思うので是非みなさんも作ってみて下さい!!