JoyConでLチカしてみた!

この記事は, Muroran Institute of Technology Advent Calendar 2019 - Adventar 18日目の記事です.

 はじめに

はてなブログ始めちゃいました!ぷりんです。大学のアドカレを見つけたら後輩に圧をかけられたので自分の誕生日分を担当することにしました。とても遅れちゃってごめんなさいm(__)m。

ニンテンドーswitchのJoyConで遊んでみたので紹介します。

120文字を超える文章を書くのは苦手なのですが最後まで読んでくれると嬉しいです。

 環境

Joyconの規格

Joyconの通信はNintendo Switch|任天堂にも書かれている通りBluetooth 3.0です。 なのでPython3 からLEDを光らせたり、センサーから入力を取得できそうです。

また、Switchを解析している以下のリポジトリを参考にしました。 https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering

早速通信してみる

入力レポートの設定を参考にシンプルHIDモードで入力を受け取ってみます。

import hid
import time

VENDOR_ID = 0x057E
L_PRODUCT_ID = 0x2006
R_PRODUCT_ID = 0x2007

joycon_device = hid.device()
joycon_device.open(VENDOR_ID, R_PRODUCT_ID)

joycon_device.write(b'\x01'+b'\x00'+b'\x00\x01\x40\x40\x00\x01\x40\x40'+b'\x03'+b'\x3f')
while True:
    print(joycon_device.read(12))

f:id:nep_pudding:20191224233504p:plain

なんか通信できてそうですね!

 Lチカ

subcommand0x30によると、player番号を表してるLEDやHomeボタンも光らせることが出来るので光らせます。 Playerライトは引数の上位ニブルで点滅、下位ニブルで点灯を制御できるそうです。 また、Homeボタンはフェージングとか出来るので楽しいです。詳しくは ここ を読んでください。

def player_light(joycon_device, flush, light):
    write_output(joycon_device, 0, b'\x01', b'\x30', ((flush << 4) + light).to_bytes(1,byteorder='big'))

def home_lamp(joycon_device, cycle_number, pattern, cycle_duration, LED_start_power):
    argument = ((len(pattern) & 0xf) << 12) + ((cycle_duration & 0xf) << 8)\
             + ((LED_start_power & 0xf) << 4) + (cycle_number & 0xf)
    pattern = (pattern + [[0,0,0] for i in range(15)])[:15]
    for i in range(7):
        argument <<= 24
        argument += ((pattern[i*2][0] & 0xf)<<20) + ((pattern[i*2+1][0] & 0xf)<<16)\
             + ((pattern[i*2][1] & 0xf)<<12) + ((pattern[i*2][2] & 0xf)<<8)\
             + ((pattern[i*2+1][1] & 0xf)<<4) + ((pattern[i*2+1][2] & 0xf)<<0)
    argument <<= 16
    argument += ((pattern[14][0] & 0xf)<<12)\
              + ((pattern[14][1] & 0xf)<<4)\
              + ((pattern[14][2] & 0xf)<<0)
    write_output(joycon_device, 0, b'\x01', b'\x38',argument.to_bytes(25,byteorder='big'))

def write_output(joycon_device, packet_number, command, subcommand, argument):
    order = (command # 1Byte
                + packet_number.to_bytes(1,byteorder='big') # 1Byte
                + b'\x00\x01\x40\x40\x00\x01\x40\x40' # 8Byte
                + subcommand # 1Byte
                + argument) # 引数
    joycon_device.write(order)

home_lampのpatternは[LED光度,PWMの何か(これを大きくするとゆっくり遷移する),遷移にかける時間]*15です。実際に動かしてみました。

import joycon
import time

joycon.home_lamp(joycon.get_joyconR(),0x0,[[0xf*(i%2),abs(15-i*2),abs(15-i*2)]for i in range(14)],1,0xf)
count = 0
signal = [1,3,7,15,14,12,8,0]
while 1:
    joycon.player_light(joycon.get_joyconR(), 0,signal[count])
    count = (count+1) % 8
    time.sleep(0.5)

光った!!!!

きれいですね!皆さんもJoyconでクリスマスツリーを作ってみてはどうですか?

他の機能

Joyconには他にもHD振動(閃乱カグラの乳を表現した機能)やARカメラ(透視とかできるのかな?)があるのでそれも遊んでみたいです。

 最後に

www.youtube.com

いまプリパラ2期がYoutubeで無料公開されています。ぜひ見てください(唐突なダイマ)

おしまい