I’m coding a Nback task and want to use a joystick/gamepad for the button press. It’s a Logitech F310 gamepad controller. After some tinkering it works but the output/controller is still not working properly. If I press a button once in a trial (each trial allowing multiple button presses) then it records it as a button press multiple times.
joy = joystick.Joystick(0)
bttnPress = joy
bttnPress.clock = core.Clock()
# *bttnPress* updates
if t >= 0.0 and bttnPress.status == NOT_STARTED:
# keep track of start time/frame for later
bttnPress.tStart = t
bttnPress.frameNStart = frameN # exact frame index
bttnPress.status = STARTED
win.callOnFlip(bttnPress.clock.reset) # t=0 on next screen flip
if bttnPress.status == STARTED:
theseKeys = []
theseRTs = []
if moviePres.status == FINISHED:
bttnPress.status == FINISHED
if bttnPress.getButton(1): # at least one key was pressed
bttnPress.rt.append(bttnPress.clock.getTime())
bttnPress.keys.append('A_Button')
theseKeys.append('A_button')
theseRTs.append(t)
continueRoutine = True
...
...
...
if len(bttnPress.keys)==0: # No response was made
bttnPress.keys=None
if bttnPress.keys != None:# bttnPress.keys != None:# moviePres.status == FINISHED # we had a response #joy.getButton(1):
VideoPlays.addData('bttnPress.rt', bttnPress.rt)
VideoPlays.addData('bttnPress.keys', bttnPress.keys) #theseKeys
# the Routine "moviePlayer" was not non-slip safe, so reset the non-slip timer
routineTimer.reset()
thisExp.nextEntry()
This only works in a pygame window, pyglet creates an error.
I realize some of my code is excessive but I’m a newbie. Currently I’m trying this on version 3.0.09 and using it on Mac OSX Sierra 10.13.6.
If it helps, attached is a csv sample output of this code.
I’ve never worked with joystick code, but I suspect it is treating the buttons like a mouse does. This is different to the way that the standard PsychoPy keyboard object works. i.e. with a keyboard, we detect keys as a single event (e.g. the a key was pressed). We don’t get information about whether the key is still being held down, or when or if it was released. But when checking for mouse buttons, we get the instantaneous state of the button (i.e. is it held down at this precise moment in time).
A button press has a finite duration that is often longer than the sampling period we are using to detect it. So a single mouse press can be detected as being pressed on multiple consecutive checks. If that is the issue, then you need to alter your logic to detect the first time that the button is detected as down. You’d then set a flag like button_down = True. You don’t record anything again until button_down = False (which you set when the button is not detected as pressed.
Suggested code for handling this issue with a mouse is here:
Hi, after playing around I got it. I took it from the code produced by the mouse click in the builder gui. It’s as follows:
from psychopy.hardware import joystick
joy = joystick.Joystick(0)
bttnPress = joy
bttnPress.status = None
if t >= 0.0 and bttnPress.status == NOT_STARTED:
# keep track of start time/frame for later
bttnPress.tStart = t
bttnPress.frameNStart = frameN # exact frame index
bttnPress.status = STARTED
prevButtonState = bttnPress.getButton(1) # if button is down already this ISN'T a new click
if bttnPress.status == STARTED and bool(postMovieFix.status == FINISHED):
bttnPress.status = STOPPED
if bttnPress.status == STARTED: # only update if started and not stopped!
buttons = bttnPress.getButton(1)
if buttons != prevButtonState: # button state changed?
prevButtonState = buttons
if buttons:#sum(buttons) > 0: # state changed to a new click
x = 'Pushed'
bttnPress.x.append(x)
bttnPress.time.append(moviePlayerClock.getTime())
This may be a bit excessive but it works and just required repurposing preexisting code. Thanks for the help!