2025年1月26日日曜日

USBでHIDでロータリーエンコーダ

左手デバイスって言って、少しのボタンやスライドつまみや回転つまみなどがあるUSBデバイスっていうものがある。
これを試作してみた。

昔はアルドゥイーノのUSBHID対応機種(レオナルドとかマイクロ)を使うのが最有力候補だったけど、
今だとラズベリーパイピコ2の方が安くて普通にUSBHID対応しているので今回はこちらで作ってみた。

まずは、配線はこんな感じ。

スイッチ8個の片側をGPIO~GPIO7に、もう一方をGNDに接続。 ロータリーエンコーダ1の1,GND,2をGPIO14, GND, GPIO15に接続。 ロータリーエンコーダ2の1,GND,2をGPIO12, GND, GPIO13に接続。 ラズベリーパイピコ2の方は、ボタンを押しながらusbに接続し、 共有ドライブ直下に、circuitpythonのページでダウンロードした.uf2ファイルを格納してcircuitpythonを使えるようにして、 https://circuitpython.org/libraries から対応するadafruit-circuitpyhton-bundleをダウンロード/展開し、その中の"adafruit_hid"ディレクトリを circuitpythonの共有ドライブのlibフォルダにコピーしてadafruit_hidを使えるようにして、 以下の内容を共有フォルダ上のcode.pyファイルを上書きした後、一旦PCから外してもう一度つなげて入力ができることを確認。 import digitalio from board import * import time import usb_hid from adafruit_hid.keyboard import Keyboard from adafruit_hid.keyboard import Keycode from adafruit_hid.consumer_control import ConsumerControl from adafruit_hid.consumer_control_code import ConsumerControlCode s1 = digitalio.DigitalInOut(GP14) s1.direction = digitalio.Direction.INPUT s1.pull = digitalio.Pull.UP s2 = digitalio.DigitalInOut(GP15) s2.direction = digitalio.Direction.INPUT s2.pull = digitalio.Pull.UP n_s1=o_s1=s1.value n_s2=o_s2=s2.value s3 = digitalio.DigitalInOut(GP12) s3.direction = digitalio.Direction.INPUT s3.pull = digitalio.Pull.UP s4 = digitalio.DigitalInOut(GP13) s4.direction = digitalio.Direction.INPUT s4.pull = digitalio.Pull.UP n_s3=o_s3=s3.value n_s4=o_s4=s4.value sw=[] n_sws=[True,True,True,True,True,True,True,True] o_sws=[True,True,True,True,True,True,True,True] vol1map=[ConsumerControlCode.VOLUME_DECREMENT, ConsumerControlCode.VOLUME_INCREMENT] vol2map=[ConsumerControlCode.BRIGHTNESS_DECREMENT, ConsumerControlCode.BRIGHTNESS_INCREMENT] keymap=[Keycode.ONE, Keycode.TWO, Keycode.THREE, Keycode.FOUR, Keycode.FIVE, Keycode.SIX, Keycode.SEVEN, Keycode.EIGHT] for _gpio in GP0,GP1,GP2,GP3,GP4,GP5,GP6,GP7: s = digitalio.DigitalInOut(_gpio) s.direction = digitalio.Direction.INPUT s.pull = digitalio.Pull.UP sw.append(s) cc = ConsumerControl(usb_hid.devices) keyboard = Keyboard(usb_hid.devices) while True: n_s1 , n_s2= s1.value , s2.value if(n_s1 != o_s1 or n_s2 != o_s2) : if n_s1 ^ o_s2 == 0 : cc.send(vol1map[1]) else: cc.send(vol1map[0]) o_s1,o_s2=n_s1,n_s2 n_s3 , n_s4= s3.value , s4.value if(n_s3 != o_s3 or n_s4 != o_s4) : if n_s3 ^ o_s4 == 0 : cc.send(vol2map[1]) else: cc.send(vol2map[0]) o_s3,o_s4=n_s3,n_s4 for i in range(8): n_sws[i] = sw[i].value if ((o_sws[i]==True) and (n_sws[i]==False)): keyboard.send(keymap[i]) o_sws[i]=n_sws[i] time.sleep(0.001) ボタンの方は、多数のボタンの場合、普通はポート数を少なくするため以下のページのように入力と出力をグリッド上にするのですが、 https://www.elec-hobbyist.com/MicomMemo/Pgm_Method/Pgm_method_3.html 手元にダイオードがないため、各ボタン独立でポートを使いました。 ロータリーエンコーダの方は、切り替えのタイミングで短時間でON/OFFを繰り返すため、普通はセラミックコンデンサを入れて高周波成分を取り除くのですが、 https://sheep-me.me/2019/12/05/geidai_21/ 手元にセラミックコンデンサがないため、バタつきが収まるであろう時間を開けてスキャンするだけにしました。

0 件のコメント: