Categoria: Python

  • Connessione Joystick DB9 (C64) su Windows tramite Arduino e Python

    Con un modulo Arduino e qualche riga di Python รจ possibile utilizzare un Joystick del Commodore come periferica di input.

    Nel test ho utilizzato un Joystick Alberici Albatros.

    Materiale occorrente:

    • Joystick con connessione DB9
    • Connettore DB9 Maschio da collegare ad Arduino
    • Arduino
    • Python
    • Software Vjoy

    Ecco lo schema generale di funzionamento: Arduino legge l’input grezzo proveniente dal joystick e lo converte in un messaggio inviato tramite porta seriale, python processa questo messaggio e governa il virtual Joystick (che viene visto da Windows come una periferica di gioco fisica).

    Sketch Arduino:

    const int pinUp    = 2;
    const int pinDown  = 3;
    const int pinLeft  = 4;
    const int pinRight = 5;
    const int pinFire  = 6;
    
    unsigned long lastSend = 0;
    const unsigned long interval = 20; // ms (50 Hz)
    
    void setup() {
      pinMode(pinUp,    INPUT_PULLUP);
      pinMode(pinDown,  INPUT_PULLUP);
      pinMode(pinLeft,  INPUT_PULLUP);
      pinMode(pinRight, INPUT_PULLUP);
      pinMode(pinFire,  INPUT_PULLUP);
    
      Serial.begin(115200);
    }
    
    void loop() {
      if (millis() - lastSend >= interval) {
        lastSend = millis();
    
        int up    = !digitalRead(pinUp);
        int down  = !digitalRead(pinDown);
        int left  = !digitalRead(pinLeft);
        int right = !digitalRead(pinRight);
        int fire  = !digitalRead(pinFire);
    
        Serial.print("U:");
        Serial.print(up);
        Serial.print(" D:");
        Serial.print(down);
        Serial.print(" L:");
        Serial.print(left);
        Serial.print(" R:");
        Serial.print(right);
        Serial.print(" F:");
        Serial.println(fire);
      }
    }
    

    Programma python per processare i dati provenienti dalla seriale:

    import re
    import serial
    import pyvjoy
    
    # --- CONFIG ---
    PORT = "COM7"      # <-- cambia qui
    BAUD = 115200
    VJOY_ID = 1
    # --------------
    
    LINE_RE = re.compile(r"U:(\d)\s+D:(\d)\s+L:(\d)\s+R:(\d)\s+F:(\d)")
    
    AX_MIN = 0x0001
    AX_MAX = 0x8000
    AX_CEN = 0x4000
    
    def axis(neg, pos):
        if neg and not pos: return AX_MIN
        if pos and not neg: return AX_MAX
        return AX_CEN
    
    ser = serial.Serial(PORT, BAUD, timeout=1)
    j = pyvjoy.VJoyDevice(VJOY_ID)
    
    # reset iniziale
    j.reset()
    j.set_axis(pyvjoy.HID_USAGE_X, AX_CEN)
    j.set_axis(pyvjoy.HID_USAGE_Y, AX_CEN)
    j.set_button(1, 0)
    
    print("OK - leggo seriale e mando a vJoy (CTRL+C per uscire)")
    
    last = None
    try:
        while True:
            line = ser.readline().decode("ascii", errors="ignore").strip()
            m = LINE_RE.match(line)
            if not m:
                continue
    
            up, down, left, right, fire = map(int, m.groups())
            state = (up, down, left, right, fire)
            if state == last:
                continue
            last = state
    
            j.set_axis(pyvjoy.HID_USAGE_X, axis(left, right))
            j.set_axis(pyvjoy.HID_USAGE_Y, axis(up, down))  # su = min, giu = max
            j.set_button(1, 1 if fire else 0)
    
    except KeyboardInterrupt:
        pass
    finally:
        # rilascia tutto
        j.set_axis(pyvjoy.HID_USAGE_X, AX_CEN)
        j.set_axis(pyvjoy.HID_USAGE_Y, AX_CEN)
        j.set_button(1, 0)
        ser.close()
        print("\nChiudo.")
    

    Si consiglia di testarlo su WinUAE e Sensible Soccer ๐Ÿ™‚