[PYTHON] Verbinden Sie die Maus mit dem Kreisel des Nintendo Switch Procon

zunaechst

Ich wollte Splatoon 2 von Nintendo Switch mit einer Maus bedienen. Auf der Straße sind bereits Konverter auf dem Markt, die Nintendo-Schalter mit einer Maus bewegen können. Kommerzielle Konverter ersetzten jedoch nur die Bewegung des Sticks des Gamecontrollers durch die Bewegung der Maus (soweit ich sehen konnte). Ich dachte, dass es mit dieser Methode nicht gut funktionieren würde. Deshalb habe ich ein Gerät hergestellt, das die Bewegung des Kreisels des professionellen Controllers durch die Bewegung der Maus ersetzt.

Es wurde jedoch etwas, das ich mit meinen technischen Fähigkeiten nicht gut bedienen konnte. Ich denke, dass die Methode, die Bewegung des Kreisels durch die Bewegung der Maus zu ersetzen, praktisch ist, wenn sie gut gemacht wird. Ich werde hier veröffentlichen, was ich bisher gemacht habe.

Das ist gemacht

Das Video kann nicht geöffnet werden

Wie benutzt man

Artikel, der sehr hilfreich war

Dinge vorzubereiten

Die Maus, die ich benutze https://www.elecom.co.jp/products/M-Y8UBXBK.html Ich denke, das ist wahrscheinlich der Fall. Wenn das von der Maus gesendete Datenformat mit dem meiner Maus übereinstimmt, wird dies meiner Meinung nach die Probleme beim Umschreiben des Python-Codes verringern, der später veröffentlicht wird.

Verfahren

Bitte richten Sie Rasppie ein (diesmal habe ich Raspbian als Betriebssystem gewählt). Schalten Sie die Kabelverbindung in den Nintendo Switch-Controller-Einstellungen ein. Schalten Sie den Kreisel in den Splatoon 2-Einstellungen ein. Finden Sie die Vendor ID (VID) Ihrer Maus heraus. Die VID meiner ELECOM-Maus war "04F3" Schließen Sie Ihre Maus, Tastatur und Ihren Pro-Controller an den Raspeye USB Type-A-Anschluss an. Verbinden Sie den HDMI-Anschluss 0 von Raspeye mit dem Display. Das angeschlossene Display dient zur Anzeige des Bildschirms von Raspeye. Das Display, auf dem der Spielbildschirm angezeigt wird, wird mit dem HDMI-Anschluss am Dock des Nintendo Switch verbunden. Nachdem Sie bestätigt haben, dass der Nintendo-Schalter aktiviert ist, Schließen Sie den Nintendo-Switch an den Typ-C-Anschluss an (ich habe ihn an den USB-Anschluss am Nintendo-Switch-Dock angeschlossen). Dann startet Razzpie. Fügen Sie in Raspbian dtoverlay = dwc2 zu /boot/config.txt und dwc2 und libcomposite zu / etc / modules hinzu, um das dwc2-Modul zu laden.

Seien Sie in der Lage, ein Superuser mit "su" in der Befehlszeile zu werden Erstellen Sie eine Datei mit dem Namen add_procon_gadget.sh (siehe unten) Geben Sie in der Befehlszeile "source add_procon_gadget.sh" ein

add_procon_gadget.sh


#!/bin/bash

cd /sys/kernel/config/usb_gadget/
mkdir -p procon
cd procon
echo 0x057e > idVendor
echo 0x2009 > idProduct
echo 0x0200 > bcdDevice
echo 0x0200 > bcdUSB
echo 0x00 > bDeviceClass
echo 0x00 > bDeviceSubClass
echo 0x00 > bDeviceProtocol

mkdir -p strings/0x409
echo "000000000001" > strings/0x409/serialnumber
echo "Nintendo Co., Ltd." > strings/0x409/manufacturer
echo "Pro Controller" > strings/0x409/product

mkdir -p configs/c.1/strings/0x409
echo "Nintendo Switch Pro Controller" > configs/c.1/strings/0x409/configuration
echo 500 > configs/c.1/MaxPower
echo 0xa0 > configs/c.1/bmAttributes

mkdir -p functions/hid.usb0
echo 0 > functions/hid.usb0/protocol
echo 0 > functions/hid.usb0/subclass
echo 64 > functions/hid.usb0/report_length
echo 050115000904A1018530050105091901290A150025017501950A5500650081020509190B290E150025017501950481027501950281030B01000100A1000B300001000B310001000B320001000B35000100150027FFFF0000751095048102C00B39000100150025073500463B0165147504950181020509190F2912150025017501950481027508953481030600FF852109017508953F8103858109027508953F8103850109037508953F9183851009047508953F9183858009057508953F9183858209067508953F9183C0 | xxd -r -ps > functions/hid.usb0/report_desc

ln -s functions/hid.usb0 configs/c.1/

ls /sys/class/udc > UDC

Geben Sie in der Befehlszeile exit ein, um zu einem normalen Benutzer zurückzukehren. Geben Sie in der Befehlszeile "sudo dmesg | grep -A7 057e" ein.

pi@raspberrypi:~ $ sudo dmesg | grep -A7 057e
[ 7201.091044] usb 1-1.3: New USB device found, idVendor=057e, idProduct=2009, bcdDevice= 2.00
[ 7201.091060] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 7201.091074] usb 1-1.3: Product: Pro Controller
[ 7201.091087] usb 1-1.3: Manufacturer: Nintendo Co., Ltd.
[ 7201.091099] usb 1-1.3: SerialNumber: 000000000001
[ 7201.112454] input: Nintendo Co., Ltd. Pro Controller as /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.3/1-1.3:1.0/0003:057E:2009.0002/input/input1
[ 7201.114447] hid-generic 0003:057E:2009.0002: input,hidraw0: USB HID v1.11 Joystick [Nintendo Co., Ltd. Pro Controller] on usb-0000:01:00.0-1.3/input0

Es gibt einen Ort, an dem hidraw0 steht. Dies ist wie eine Datei, die einen Pro-Controller darstellt. Die Zahlen unter "Hidraw" können je nach Umgebung variieren. Überprüfen Sie daher die Nummer "Hidraw".

Als nächstes findet die Maus in der Befehlszeile heraus, um welche Zahl es sich handelt sudo dmesg | grep -A7 Ersetzen Sie den" Maus-VID "-Teil der Maus-VID durch die Maus-VID und drücken Sie. Die VID meiner ELECOM-Maus war "04F3". Überprüfen Sie, welche Nummer die Maus versteckt.

Erstellen Sie ein Programm, das Mausbetriebsdaten zwischen der Kommunikation zwischen dem Nintendo-Switch und dem Pro-Controller unterbricht. Erstellen Sie die unten gezeigte Python-Codedatei. (Entschuldigung für den sehr schmutzigen Code).

mouse_gyro.py


#!/usr/bin/env python3

import os
import threading
import time
import random

# Re-connect USB Gadget device
os.system('echo > /sys/kernel/config/usb_gadget/procon/UDC')
os.system('ls /sys/class/udc > /sys/kernel/config/usb_gadget/procon/UDC')

time.sleep(0.5)

gadget = os.open('/dev/hidg0', os.O_RDWR | os.O_NONBLOCK)
procon = os.open('/dev/hidraw3', os.O_RDWR | os.O_NONBLOCK)
mouse  = os.open('/dev/hidraw2', os.O_RDWR | os.O_NONBLOCK)
mouse_int = bytes([0,0,0,0])
def mouse_input():
    global mouse_int
    while True:
        try:
            mouse_int = os.read(mouse, 128)
            #print('<<<', output_data.hex())
            #print(output_mouse.hex())
            #os.write(gadget, output_mouse)
        except BlockingIOError:
            pass
        except:
            os._exit(1)



def procon_input():
    while True:
        try:
            input_data = os.read(gadget, 128)
            #print('>>>', input_data.hex())
            os.write(procon, input_data)
        except BlockingIOError:
            pass
        except:
            os._exit(1)

def convert(ou_dt_i, mo_in_i, weight, reflect):
    mo_in_i = int.from_bytes(mo_in_i, byteorder='little', signed=True)
    ou_dt_i = int.from_bytes(ou_dt_i, byteorder='little', signed=True)
    if reflect == True:
        mo_in_i = mo_in_i * -1
        ou_dt_i = ou_dt_i * -1
    merged_gy = ou_dt_i + mo_in_i * weight
    if merged_gy > 32767:
        merged_gy = 32767
    elif merged_gy < -32768:
        merged_gy = -32768
    else:
        pass
    merged_gy = merged_gy.to_bytes(2, byteorder='little', signed=True)

    return merged_gy

def replace_mouse(output_data, mouse_int):
    #a = output_data[0:13]

    #mouse no click wo migi no button ni henkan
    ri_btn = 0
    if mouse_int[0] == 1:#hidari click
        ri_btn = 0x80#ZR button
    elif mouse_int[0] == 2:#migi click
        ri_btn = 0x40#R button
    elif mouse_int[0] == 4:#chuu click
        ri_btn = 0x08#A button
    ri_btn = (output_data[3] + ri_btn).to_bytes(1, byteorder='little')
    a = output_data[0:3] + ri_btn + output_data[4:13]

    #kasokudo sensor ni tekitou ni atai wo ire naito setsuzoku ga kireru
    if mouse_int[1] != 0:
        b = 127
    else:
        b=0
    if mouse_int[2] != 0:
        b = 127
    else:
        b = 0
    d = bytes([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
    ac0 = bytes([255]) if output_data[14] + b > 255 else bytes([output_data[14] + b])
    ac1 = bytes([255]) if output_data[16] + b > 255 else bytes([output_data[16] + b])
    ac2 = bytes([255]) if output_data[18] + b > 255 else bytes([output_data[18] + b])
    ac0_1 = bytes([255]) if output_data[26] + b > 255 else bytes([output_data[26] + b])
    ac1_1 = bytes([255]) if output_data[28] + b > 255 else bytes([output_data[28] + b])
    ac2_1 = bytes([255]) if output_data[30] + b > 255 else bytes([output_data[30] + b])
    ac0_2 = bytes([255]) if output_data[38] + b > 255 else bytes([output_data[38] + b])
    ac1_2 = bytes([255]) if output_data[40] + b > 255 else bytes([output_data[40] + b])
    ac2_2 = bytes([255]) if output_data[42] + b > 255 else bytes([output_data[42] + b])

    #mouse no ugoki wo gyro no ugoki ni henkan
    gy0_0 = convert(output_data[19:21], mouse_int[1:2], 250, False)#
    gy1_0 = convert(output_data[21:23], mouse_int[2:3], 250, False)#
    gy2_0 = convert(output_data[23:25], mouse_int[2:3], 0, False)#

    gy0_1 = convert(output_data[31:33], mouse_int[1:2], 250, False)#
    gy1_1 = convert(output_data[33:35], mouse_int[2:3], 250, False)#
    gy2_1 = convert(output_data[35:37], mouse_int[2:3], 0, False)#

    gy0_2 = convert(output_data[43:45], mouse_int[1:2], 250, False)#
    gy1_2 = convert(output_data[45:47], mouse_int[2:3], 250, False)#
    gy2_2 = convert(output_data[47:49], mouse_int[2:3], 0, False)#

    e = a+output_data[13:14]+ac0+output_data[15:16]+ac1+output_data[17:18]+ac2 \
        +gy0_0+gy1_0+gy2_0 \
        +output_data[25:26]+ac0_1+output_data[27:28]+ac1_1+output_data[29:30]+ac2_1 \
        +gy0_1+gy1_1+gy2_1 \
        +output_data[37:38]+ac0_2+output_data[39:40]+ac1_2+output_data[41:42]+ac2_2 \
        +gy0_2+gy1_2+gy2_2 \
        +d

    print(int.from_bytes(gy1_0, byteorder='little'))
    #print(mouse_int[1])
    return e

def procon_output():
    global mouse_int
    while True:
        try:
            output_data = os.read(procon, 128)
            #output_mouse = os.read(mouse, 128)
            #print('<<<', output_data.hex())
            #print(output_data)
            e = replace_mouse(output_data, mouse_int)
            #print(e.hex())
            os.write(gadget, e)#output_data
            mouse_int = bytes([0,0,0,0])
        except BlockingIOError:
            pass
        except Exception as g:
            print(type(g))
            print(g)
            os._exit(1)

threading.Thread(target=procon_input).start()
threading.Thread(target=procon_output).start()
threading.Thread(target=mouse_input).start()

Schreiben Sie die nächste Anzahl von Hidraws, die den Variablen "procon" und "mouse" zugewiesen sind, auf die zuvor bestätigte Nummer um. Als nächstes schreibe ich den Python-Code neu, um den Python-Code mit dem von der Maus gesendeten Signal abzugleichen. Die Maus, die ich benutze https://www.elecom.co.jp/products/M-Y8UBXBK.html Ich denke, dass dies wahrscheinlich der Fall ist, aber damit müssen Sie Ihren Code möglicherweise nicht neu schreiben. Um herauszufinden, welche Daten Ihre Maus sendet, kommentieren Sie "#print (output_mouse.hex ())" in der Funktion "mouse_input ()" aus. Stattdessen ist es einfacher zu erkennen, ob Sie den print () - Teil an anderer Stelle auskommentieren. Um diesen Python-Code auszuführen, geben Sie in der Befehlszeile "sudo python3 mouse_gyro.py" ein.

Wenn alles gut geht, können Sie den Kreisel mit der Maus unbeholfen bewegen, wie im obigen Video.

Es kommt häufig vor, dass der Pro-Controller in der Mitte getrennt wird. Befolgen Sie die Anweisungen auf dem Schalterbildschirm oder halten Sie die kleine runde Taste an der Seite des Controllers gedrückt, um den Controller neu zu registrieren. Zu diesem Zeitpunkt kann sich die nächste Anzahl von Hidraws ändern. Schreiben Sie in diesem Fall den Zuweisungsteil der Variablen "procon" des Python-Codes neu, indem Sie auf den Befehl klicken, um die oben geschriebene Hidraw-Nummer erneut zu überprüfen.

Am Ende

Wenn Sie das obige Video gesehen oder die Operation ausprobiert haben, werden Sie verstehen. Selbst wenn ich die Maus bewege, bewegt sich der Kreisel nicht richtig. Ich möchte um Ihre Hilfe bitten. Der Python-Code ist auf GitHub verfügbar und es gibt keine Lizenz. Sie können ihn also jederzeit ändern. Ich wäre Ihnen sehr dankbar, wenn Sie zusammenarbeiten könnten.

Danke fürs Lesen.

https://github.com/Bokuchin/SwitchProconGyroMouse

Artikel-Link, auf den ich verweisen durfte

Recommended Posts

Verbinden Sie die Maus mit dem Kreisel des Nintendo Switch Procon
Ändern Sie den Einstellungswert von settings.py entsprechend der Entwicklungsumgebung
Ergänzung zur Erklärung von vscode
Die Geschichte des Versuchs, den Client wieder zu verbinden
Skript zum Ändern der Beschreibung von Fasta
10 Methoden zur Verbesserung der Genauigkeit von BERT
So überprüfen Sie die Version von Django
Die Geschichte, MeCab in Ubuntu 16.04 zu setzen
Die Geschichte von pep8 wechselt zu pycodestyle
Link zu den Datenpunkten des von jupyterlab & matplotlib erstellten Diagramms
Wenn Sie mit der Maus über Matplotlib fahren, wird das entsprechende Bild angezeigt.
So finden Sie den Bereich des Boronoi-Diagramms
Die Hand von "Millijan" durch Kombinationsoptimierung finden
Die Ungenauigkeit von Tensorflow war auf log (0) zurückzuführen.
Ich habe versucht, die Trapezform des Bildes zu korrigieren
Ändern Sie den Dezimalpunkt der Protokollierung von, nach.
Ich möchte das Erscheinungsbild von zabbix anpassen
Von der Einführung von Pyethapp bis zur Vertragsabwicklung
Versuchen Sie, die Bewegung des Sonnensystems zu simulieren
[Java] So wechseln Sie zwischen mehreren Java-Versionen
Die Geschichte vom Umzug von Pipenv zur Poesie
Ich habe versucht, die Texte von Hinatazaka 46 zu vektorisieren!