arduino joystick library, don't stop joystick

842 views Asked by At

I'm making a gamepad on a joystick using an arduino pro micro.

Input commands such as up and down from the console, raspberry pi's gpio will output them and the arduino will receive them and input them to the game machine.

I use the ArduinoJoystickLibrary. https://github.com/MHeironimus/ArduinoJoystickLibrary

I want to play a GBA game, but the Dpad stays typed. How can I press the up key only once?

Also, in the gif below, the up and down keys are pressed once at a time, but pressing the right key or other keys in the middle does not respond.

As an addendum, I use a game console called retro freak. retro freak enter image description here

The code uses the following

arduino_pro_micro_gamepad.ino

#include <Joystick.h>

#define OFFSET_BUTTON 2
#define OFFSET_DPAD 18

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD,
  4, 0,                  // Button Count, Hat Switch Count
  true, true, false,     // X and Y, but no Z Axis
  false, false, false,   // No Rx, Ry, or Rz
  false, false,          // No rudder or throttle
  false, false, false);  // No accelerator, brake, or steering

void setup() {
  // Initialize Button Pins
  pinMode(2, INPUT_PULLUP);  // Button 1
  pinMode(3, INPUT_PULLUP);  // Button 2
  pinMode(4, INPUT_PULLUP);  // Button 3
  pinMode(5, INPUT_PULLUP);  // Button 3
  
  pinMode(18, INPUT_PULLUP); // D-pad Up
  pinMode(19, INPUT_PULLUP); // D-pad Right
  pinMode(20, INPUT_PULLUP); // D-pad Down
  pinMode(21, INPUT_PULLUP); // D-pad Left

  Joystick.begin();
  Joystick.setXAxisRange(-1, 1);
  Joystick.setYAxisRange(-1, 1);
  Joystick.setYAxis(0);
  Joystick.setYAxis(0);
}

// Last state of the buttons
int lastDpadState[4] = {0,0,0,0};  // Up, Right, Down, Left
int lastButtonState[4] = {0,0,0,0};  // Button 1 - 4

void updateDpad() {
  for (int i = 0; i <= 3; i++) {
    int currentDpadState = digitalRead(i + OFFSET_DPAD);
    if (currentDpadState != lastDpadState[i]) {
      switch (i) {
        case 0: // UP
          if (currentDpadState == 1) {
            Joystick.setYAxis(-1);
          }
          break;
        case 1: // RIGHT
          if (currentDpadState == 1) {
            Joystick.setXAxis(1);
          }
          break;
        case 2: // DOWN
          if (currentDpadState == 1) {
            Joystick.setYAxis(1);
          }
          break;
        case 3: // LEFT
          if (currentDpadState == 1) {
            Joystick.setXAxis(-1);
          }
          break;
        }
      lastDpadState[i] = currentDpadState;
    }
  }
}

void updateButton() {
  for (int i = 0; i <= 3; i++) {
    int currentButtonState = !digitalRead(i + OFFSET_BUTTON);
    if (currentButtonState != lastButtonState[i]) {
      Joystick.setButton(i, currentButtonState);
      lastButtonState[i] = currentButtonState;
    }
  }
}

void loop() {
  updateDpad();
  updateButton();
  delay(5);
}

raspi_game_input.py

import RPi.GPIO as GPIO
from time import sleep

GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup(27, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup(23, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup(24, GPIO.OUT, initial=GPIO.HIGH)

GPIO.setup(16, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup(20, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup(21, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup(26, GPIO.OUT, initial=GPIO.HIGH)


def on(gpio_number):
  GPIO.output(gpio_number, GPIO.LOW)
  sleep(0.05)
  GPIO.output(gpio_number, GPIO.HIGH)

def key_select(input_key):
  if input_key == 'a':
    on(17)
  elif input_key == 'b':
    on(27)
  elif input_key == 'home':
    on(23)
  elif input_key == 'game':
    on(24)
  elif input_key == 'u':
    on(16)
  elif input_key == 'd':
    on(20)
  elif input_key == 'r':
    on(21)
  elif input_key == 'l':
    on(26)
  else:
    pass


if __name__ == '__main__':
  try:
    while True:
      print('push button')
      key = input()
      print(f'input is ${key}')
      key_select(key)

  except KeyboardInterrupt:
    GPIO.cleanup()
2

There are 2 answers

0
TĂșlio Rossi On

Just a little fix in the code, in setup();

  Joystick.setYAxis(0);
  Joystick.setYAxis(0);

change to:

  Joystick.setXAxis(0);
  Joystick.setYAxis(0);

Try to reset to initial values before... or after the action.

if (currentDpadState != lastDpadState[i]) {
   reset();
   switch (i) {
    ...
   }
}


void reset(){
Joystick.setXAxis(0);
Joystick.setYAxis(0);
}
0
Kouji Kawasaki On

My problem was using a joystick instead of a hatSwitch.

The implementation I wanted was to enter the arrow keys only once, so I used hatswitch.

#include <Joystick.h>

#define OFFSET_BUTTON 2
#define OFFSET_DPAD 18

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, 
  JOYSTICK_TYPE_GAMEPAD,
  9,1,
  false, false, false, false, false, false,
  false, false, false, false, false);

void setup() {
  pinMode(2, INPUT_PULLUP);  // Button 1
  pinMode(3, INPUT_PULLUP);  // Button 2
  pinMode(4, INPUT_PULLUP);  // Button 3
  pinMode(5, INPUT_PULLUP);  // Button 4
  pinMode(6, INPUT_PULLUP);  // Button 5
  pinMode(7, INPUT_PULLUP);  // Button 6
  pinMode(8, INPUT_PULLUP);  // Button 7
  pinMode(9, INPUT_PULLUP);  // Button 8
  pinMode(10, INPUT_PULLUP);  // Button 9

  pinMode(18, INPUT_PULLUP); // D-pad Up
  pinMode(19, INPUT_PULLUP); // D-pad Right
  pinMode(20, INPUT_PULLUP); // D-pad Down
  pinMode(21, INPUT_PULLUP); // D-pad Left
  
  Joystick.begin();
}

// Last state of the pins
int lastDpadState[2][4] = {{0,0,0,0}, {0,0,0,0}};
int lastButtonState[10] = {0,0,0,0,0,0,0,0,0,0};  // Button 1 - 10


void updateDpad(){
  bool valueChanged[2] = {false, false};
  int currentPin = 18;

  // Read pin values
  for (int hatSwitch = 0; hatSwitch < 2; hatSwitch++){
    for (int index = 0; index < 4; index++){
      int currentDpadState = !digitalRead(currentPin++);
      if (currentDpadState != lastDpadState[hatSwitch][index]){
        valueChanged[hatSwitch] = true;
        lastDpadState[hatSwitch][index] = currentDpadState;
      }
    }
  }

  for (int hatSwitch = 0; hatSwitch < 2; hatSwitch++)
  {
    if (valueChanged[hatSwitch]) {
      if ((lastDpadState[hatSwitch][0] == 0)
        && (lastDpadState[hatSwitch][1] == 0)
        && (lastDpadState[hatSwitch][2] == 0)
        && (lastDpadState[hatSwitch][3] == 0)) {
          Joystick.setHatSwitch(hatSwitch, -1);
      }
      if (lastDpadState[hatSwitch][0] == 1) {
        Joystick.setHatSwitch(hatSwitch, 0); // up
      }
      if (lastDpadState[hatSwitch][1] == 1) {
        Joystick.setHatSwitch(hatSwitch, 90); // right
      }
      if (lastDpadState[hatSwitch][2] == 1) {
        Joystick.setHatSwitch(hatSwitch, 180); // down
      }
      if (lastDpadState[hatSwitch][3] == 1) {
        Joystick.setHatSwitch(hatSwitch, 270);
      }
    } // if the value changed
  } // for each hat switch
}

void updateButton() {
  for (int i = 0; i <= 9; i++) {
    int currentButtonState = !digitalRead(i + OFFSET_BUTTON);
    if (currentButtonState != lastButtonState[i]) {
      Joystick.setButton(i, currentButtonState);
      lastButtonState[i] = currentButtonState;
    }
  }
}

void loop() {
  updateDpad();
  updateButton();
  delay(50);
}