Analog Joystick
-
Hey everyone. I'm trying to put the finishing touches on my PSPi, but I need some help.
I'm using an MCP3002 analog/digital converter. I've got the OS correctly reading the values (not easy because spidev could not be installed until I did a full reinstall of python 2.7.9), and I need to know how to get it working in games. I've searched everywhere for this answer and cannot find it. I hacked some code together, and right now the python script below grabs the values from the ADC and uses uinput to send the values to ABS_X and ABS_Y. I know the ABS method was a long shot, but it was worth a try.
I know that the most recent version of Retropie asks for analog up/down/left/right during configuration, so something is obviously built in. Can anyone tell me how to connect the dots? I have no hair left to pull out.
#!/usr/bin/python import spidev import time import os import uinput DEBUG = 0 spi = spidev.SpiDev() spi.open(0,0) spi.max_speed_hz = 100000 def get_adc(channel): if ((channel > 1) or (channel < 0)): return -1 r = spi.xfer2([1,(2+channel)<<6,0]) ret = ((r[1]&31) << 6) + (r[2] >> 2) return ret device =uinput.Device([uinput.ABS_X+(0,1023,0,0), uinput.ABS_Y+(0,1023,0,0), ]) joy_x=1 joy_y=2 #!/usr/bin/python import spidev import time import os import uinput DEBUG = 0 spi = spidev.SpiDev() spi.open(0,0) spi.max_speed_hz = 100000 def get_adc(channel): if ((channel > 1) or (channel < 0)): return -1 r = spi.xfer2([1,(2+channel)<<6,0]) ret = ((r[1]&31) << 6) + (r[2] >> 2) return ret device =uinput.Device([uinput.ABS_X+(0,1023,0,0), uinput.ABS_Y+(0,1023,0,0), ]) joy_x=1 joy_y=2 while True: joy_x_value=ReadChannel(joy_x) device.emit(uinput.ABS_X,joy_x_value,syn=False) joy_y_value=ReadChannel(joy_y) device.emit(uinput.ABS_Y,joy_y_value) time.sleep(0.020)
-
@adamspc said in Analog Joystick:
I know that the most recent version of Retropie asks for analog up/down/left/right during configuration, so something is obviously built in.
so is it getting picked up here?
I need to know how to get it working in games.
in retroarch cores there's an analog to digital configuration option that will work if your answer to my previous question is 'yes'. check out https://github.com/retropie/retropie-setup/wiki/Configuration-Editor
-
@dankcushions
It's not.I'm using retrogame, so when I press a button to configure input it says its using keyboard as an input. I then configure the regular buttons and it gets to analog, and moving the stick around does nothing.
For clarification, so far I've only managed to print the current ACD values and then use uinput to send those values to ABS_X/Y. That's as far as I've made it and I'm not even sure ABS_X/Y is the right thing to do.
-
@adamspc so when you say the OS can 'see' it, what do you mean by that? it appears as a js device in jstest?
-
@dankcushions the OS is communicating with the ADC and receiving the values using the Python file. The only info I could find was one person saying use uinput and ABS, so that's as far as I got. I havent used jtest but im researching it now. Im just trying to connect the dots on getting this configured as a joystick. I know it's not that something is wrong with it. I just can't find the information.
-
http://thiemonge.org/getting-started-with-uinput
uinput is a linux kernel module that allows to handle the input subsystem from user land. It can be used to create and to handle input devices from an application. It creates a character device in /dev/input directory. The device is a virtual interface, it doesn't belong to a physical device.
looks to me like this wouldn't be visible to ES or retroarch which are looking for keyboard or joystick devices. i think you'd need to create your own driver to translate like http://blog.petrockblock.com/2014/06/01/xarcade2jstick/
-
@dankcushions I appreciate the responses. My hope was that someone in the forum had already done what I'm attempting and I could get a shortcut to the solution. I'm continuing to research and I'll post the solution once I find it (or create it). I'm digging into some slightly different code now that I found here.
""" rpi-gpio-jstk.py by Chris Swan 9 Aug 2012 GPIO Joystick driver for Raspberry Pi for use with 80s 5 switch joysticks based on python-uinput/examples/joystick.py by tuomasjjrasanen https://github.com/tuomasjjrasanen/python-uinput/blob/master/examples/joystick.py requires uinput kernel module (sudo modprobe uinput) requires python-uinput (git clone https://github.com/tuomasjjrasanen/python-uinput) requires python RPi.GPIO (from http://pypi.python.org/pypi/RPi.GPIO/0.3.1a) for detailed usage see http://blog.thestateofme.com/2012/08/10/raspberry-pi-gpio-joystick/ Changes 19 Aug 2012 - inputs set to use internal pull ups rather than external 10k resistors """ import uinput import time import RPi.GPIO as GPIO GPIO.setmode(GPIO.BOARD) # Up, Down, left, right, fire GPIO.setup(11, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(13, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(15, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(16, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(7, GPIO.IN, pull_up_down=GPIO.PUD_UP) events = (uinput.BTN_JOYSTICK, uinput.ABS_X + (0, 255, 0, 0), uinput.ABS_Y + (0, 255, 0, 0)) device = uinput.Device(events) # Bools to keep track of movement fire = False up = False down = False left = False right = False # Center joystick # syn=False to emit an "atomic" (128, 128) event. device.emit(uinput.ABS_X, 128, syn=False) device.emit(uinput.ABS_Y, 128) while True: if (not fire) and (not GPIO.input(7)): # Fire button pressed fire = True device.emit(uinput.BTN_JOYSTICK, 1) if fire and GPIO.input(7): # Fire button released fire = False device.emit(uinput.BTN_JOYSTICK, 0) if (not up) and (not GPIO.input(11)): # Up button pressed up = True device.emit(uinput.ABS_Y, 0) # Zero Y if up and GPIO.input(11): # Up button released up = False device.emit(uinput.ABS_Y, 128) # Center Y if (not down) and (not GPIO.input(13)): # Down button pressed down = True device.emit(uinput.ABS_Y, 255) # Max Y if down and GPIO.input(13): # Down button released down = False device.emit(uinput.ABS_Y, 128) # Center Y if (not left) and (not GPIO.input(15)): # Left button pressed left = True device.emit(uinput.ABS_X, 0) # Zero X if left and GPIO.input(15): # Left button released left = False device.emit(uinput.ABS_X, 128) # Center X if (not right) and (not GPIO.input(16)):# Right button pressed right = True device.emit(uinput.ABS_X, 255) # Max X if right and GPIO.input(16): # Right button released right = False device.emit(uinput.ABS_X, 128) # Center X time.sleep(.02) # Poll every 20ms (otherwise CPU load gets too high)
-
Sorry for necroposting a little, but I was wondering if @adamspc had ever actually managed to get an analog joystick to work, since it has been several months and I haven't seen anything else posted about this.
-
@Shojiro No progress yet, but that's only because all my time is taken working on the boards I'm designing. I ended up doing a simple joystick using an LM339, but that's only a temporary solution.
I will succeed in getting the analog working using the MCP3002, but it won't be soon. Hopefully one of the software guys reading this has time to help out.
-
@adamspc I know this thread is old, but I'm currently having the same issue. Did you manage to made any progress with the analog joystick?
Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.
Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.