Sending triggers to brainvision EEG system from Psychopy coderview

Hi @yh-luo and @ypohcysp!

I FIGURED IT OUT!
Here are the steps I followed to get psychopy to send triggers via a parallel port to a BrainVision EEG system.

  1. Download the inpout32.dll driver from the following website:http://www.highrez.co.uk/downloads/inpout32/ by clicking on " Binaries only - x86 & x64 DLLs and libs" under Downloads.
    This file is needed to give Windows access to the parallel port installed in the display computer.

  2. Unzip the folder, and run “InstallDriver” which is found in the Win32 folder by clicking on the driver. When properly installed, you should get a confirmation message saying it’s done!
    For me, unlike described in other posts, it did not seem to matter if I had the 32 or 64 bit Python and Psychopy applications downloaded. The inpout32.dll suggested in step 1 seems to be compatible with both (at least for Windows 10).

  3. Copy the inpout.dll file found in the Win32 folder to the following locations:
    ** Note: it’s possible that it is not required to place the file in all these locations. However, I did just to be safe!

  • C:/Program Files/Psychopy3
  • C:/Program Files/Psychopy3/DLLs
  • C:/Program Files(x86)/Psychopy3
  • C:/Program Files/Psychopy3/DLLs
  • The folder where your psychopy script is saved.

I previously had not noticed that there was a DLLs folder within each psychopy3 folder. Once I added the driver to these folders, it solved my problem.

  1. To get the parallel port address, I followed the steps suggested above by @ypohcysp. Here they are:
  • download the parallel port tester from: http://www.downtowndougbrown.com/2013/06/parallel-port-tester/
  • Open parallel port tester, and choose the parallel port you have installed on the display computer (bottom right corner). This should display the correct address to be used in your Psychopy code. (e.g. mine is a PCIe with address: 0x3FF8)
    This is the same address that shows up in device manager, if you are more familiar with that method of finding the address.
  • If you launch BrainVision Recorder on the acquisition computer, go to Amplifier > Digital Port Settings, you will have the parallel port installed on the display computer show up. By turning some pins from low to high (pins 2-9) you should see the pins change in the BrainVision recorder too. This confirms that the parallel port is indeed installed correctly and working ‘manually’.
  1. Add code to your task!
    If you are like me, you did not know much about how parallel ports work. They work by sending out bits out from their individual pins (yes, the little pins you see when you look into it). it can only send data out of pins 2 to 9. By looking at the Digital port settings and/or the parallel port tester, you will see what bits each pin is going to set out when set to high (or ‘active’). Importantly, once a pin has sent out a trigger and thus, is set to high, it needs to be set back to low before it can send anything else out of that pin again.
    Now the following code should make sense…
# goes at the start of your script.
from psychopy import parallel, core
port = parallel.ParallelPort(address=0x3FF8) # imports function for parallel port communication and finds the port at the address specified.

# example trigger 
        port.setData( int("00000001", 2) ) # send S 1; the 0's and 1's here reffer to if each pin is set to high(1) or low(0), which will consequently send out the trigger associated with the number that results from the pins set to high. Here my first pin (pin2) is set to send out 1 so sends out S1.     
        core.wait(0.2) # need to wait before setting pin back to low in order to ensure the trigger is sent
        port.setData(0) # set all pins back to low(0) 

If you want to make sure your triggers are being sent at the exact time the stimulus appears (which is often the case!) you here is another example I recently used in an oddball task:

if trialList[t] == 'regular': 
                trig = "00000100"    # S 4
            elif trialList[t] == 'oddball':
                trig ="00000011"    # S 3
            else: 
                print('trigger for new trial not sent!')
                
            newTrial.draw()  
            win.callOnFlip(port.setData, int(trig, 2) )
            win.flip()
            core.wait(stimTime) # this serves both as my stimulus display time and my core.wait before resetting my pins to low.
            port.setData(0)

That’s pretty much it!
If you have any questions, let me know!

Alexa

2 Likes