Millisecond Forums

Reading Parallel Port as Response Device

https://forums.millisecond.com/Topic13990.aspx

By DrLand - 8/14/2014

Hi,
I'm a new user of Inquisit 4, and I have been searching for an answer to a question, but haven't been able to find a clear answer.
I am trying to use Pin 2 of an LPT port as the valid response to a trial. I have looked at the Port Monitor, and I can see the check on Pin 2 change as the signal goes from high to low or low to high. My question is, what code/element allows me to read in a particular pin on an lpt port (Pin 2 in my case), and look for a change in voltage (either going high, or going low). 
Thanks!
By Dave - 8/14/2014

First you need to define the respective LPT port as /inputdevice for your <trial>(s), e.g.

<trial mytrial>
/ inputdevice = lpt1
/ validresponse = ("00000010")
...
</trial>

for LPT1. Then you can use the /validresponse and/or /inputmask attributes to define the signal you are looking for.
By DrLand - 8/15/2014

Thank you for your quick feedback. I have setup my trial as follows:

<trial numbers>
/stimulusframes = [1=trials]
/ inputdevice = lpt3
/ validresponse = ("00000010")
/ correctresponse = ("00000010")
</trial>

However, when I try and run the experiment, I get the following Error.
ERROR /validresponse: '00000010' is not a valid setting.

ERROR /correctresponse: '00000010' is not a valid setting.

ERROR /validresponse: 'No response' can not be specified unless the trial has a timeout.


By Dave - 8/15/2014

Two things to try, please:

#1: When you specify

<trial numbers>
/stimulusframes = [1=trials]
/ inputdevice = lpt3
/ validresponse = (anyresponse)
</trial>

what's recorded in the data file's 'response' column? Same for

<trial numbers>
/stimulusframes = [1=trials]
/ inputdevice = lpt3
/ inputmask = "00000010"
/ validresponse = (anyresponse)
</trial>

?

#2: How does the trial behave when specifying

<trial numbers>
/stimulusframes = [1=trials]
/ inputdevice = lpt3
/ validresponse = (00000010)
/ correctresponse = (00000010)
</trial>

?

Thanks.
By DrLand - 8/15/2014


Dave (8/15/2014)
Two things to try, please:

#1: When you specify

<trial numbers>
/stimulusframes = [1=trials]
/ inputdevice = lpt3
/ validresponse = (anyresponse)
</trial>

what's recorded in the data file's 'response' column? Same for

<trial numbers>
/stimulusframes = [1=trials]
/ inputdevice = lpt3
/ inputmask = "00000010"
/ validresponse = (anyresponse)
</trial>

?

Ok, both the above two codes produce a response indicating value 127

#2: How does the trial behave when specifying

<trial numbers>
/stimulusframes = [1=trials]
/ inputdevice = lpt3
/ validresponse = (00000010)
/ correctresponse = (00000010)
</trial>

?

There is no response with the above code, although it doesn't produce an error message

Thanks.

So I can make the /correctresponse = (127), however, the problem that I am seeing is that it instantly runs through all the trials.
Let me explain exactly what I'm doing. I'm trying to write a simple code that displays the trial number (e.g., 1, 2....). Every time an event happens, pin 2 goes high and stays high until the end of the trial when the pin is set back to low...
So I would like my code to see the change from low to high on pin 2, and then change the trial number.
When I'm running the code now, it immediately cycles through all of my trial numbers without me even sending the event trigger. I'm wondering if when pin 2 is high and staying high...the code is acting like it's a continuous valid response and thus cycles to the next trial.



By Dave - 8/15/2014

Whether the pin remains high would be something that your device has to do -- if it never lowers the pin or doesn't do it quickly enough, trials will cycle rapidly. Several things you can do:

#1: Work with /pre- and /posttrialpauses and/or

#2: Require a /pre- and/or /postrrialsignal from the lpt3 port (to ensure the pin is low again).
By DrLand - 8/15/2014

I still can't seem to get it to work without immediately cycling through all of the trials.
First, on the parallel port monitor, does the check mean that the pin is high or low? (regardless of whether pin 2 is checked or not (based on my device), the program still immediately cycles through all of the trials. So i'm not sure the input I'm getting is associated with pin 2).
Although I am only interested on the activity on pin two, a number of the other pins have checkmarks in their box.
My understanding is that I can use the inputmask = "00000010" to make the system only look at pin 2, however, no matter what value I put in for the inputmask (e.g., 11111111) this doesn't change how the program behaviors. I am now thinking that the (127) value that I identified in the previous post may belong to a pin other than pin 2 (one of the other pins that have a checkmark in the box according to parallel port monitor, and one that never changes, thus cycles my program).
So I need a way to figure out exactly what value is associated with pin 2 (and pin 3 eventually).
Since pin 2 goes high and stays high for a matter of seconds before going back low, I will try and incorporate the posttrialsignal to wait for a change from pin 3 (at which time pin 2 will go back low again). However, I have to identify exactly how to make the system watch for pin 2 and pin 3



By Dave - 8/15/2014

Just to clarify: The check mark sets a pin to high when you want to *send* a signal *to* your device via the parallel monitor -- check the pin(s) and hit 'send'.

You don't need to check any when you want to *receive* signals *from* the device -- hit receive, (push button on the device or the like if necessary) and the parallel port monitor should tell you what it received. A check mark means the respective pin is high. For some more details, see the "How to Use the Parallel Port Monitor Tool" topic in the documentation.

About the '127', this would indicate as many as 7 bits set to high (127 -> 01111111 in binary).

Another thing to consider is that there's a difference between

/inputdevice = lpt<n>

which will read from the port's *status* register and

/inputdevice = lptdata<n>

which will read from the *data* register. Based on your last description, I assume you want the latter.

Given that your device apparently keeps the pin(s) high for several seconds, you should definitely work with either /pre- or /posttrialpause and/or /pre- or /posttrialsignal to allow for the pin(s) to go low between trials. Otherwise the rapid cycling through all trials is exactly what should be expected with pins remaining high for so long.
By DrLand - 8/15/2014

Ok, now we are starting to get somewhere. You are right, I needed to use /inputdevice = lptdata3
From using the parallel port monitor, I also figured out that the port value goes from 240 to 241 when pin two is activated. So my code is

<trial checkportsignal>
/ stimulusframes = [1=button]
/ inputdevice = lptdata3
/ validresponse = (241)
</trial>
This now doesn't immediately cycle through the trials, but waits until the first event (pin 2 goes high). However, after that, it then cycles through the trials. This is were I need to setup a posttrialsignal
So I made my device send a signal to pin 3, and turn pin 2 to low at the end of the trial. According to the parallel port monitor, my port value is registered at 242 when pin 2 is low and pin 3 is high. I would therefore use this as the signal to stop the trial. My code is as follows:

<trial checkportsignal>
/ stimulusframes = [1=button]
/ inputdevice = lptdata3
/ validresponse = (241)
/posttrialsignal = (lptdata3, 242)
</trial>

The trial now starts on the correct event, but it is not stopping, so the posttrialsignal isn't working to end the trial. Any ideas.

Thanks for all the help.


By DrLand - 8/15/2014

Just a little more information about the posttrialsignal issue, the error message says "unknown" "Unable to obtain the address for parallel port -1"
Just as a test, I made the posttrialsignal a button press from the keyboard, and that worked. So I just need to get it working off the parallel port.
By Dave - 8/15/2014

Hmm, if the trial doesn't move on, that would indicate it's still waiting to receive the specified /posttrialsignal. The problem here likely is that /posttrialsignal only recognizes lpt, not lptdata (as per the documentation -- I don't have a suitable device for testing around at this very moment).

What's the device's status register state when the respective pins are low?
By DrLand - 8/15/2014

I think the issue is that the /posttrialsignal doesn't work with reading from lptdata. Even though I can't control the pins that are "watched" by the lpt status register, it holds a value of (127). If I use /posttrialsignal = (lpt3, 127), then this works to stop the trial. However, this doesn't fix my orignal problem with cycling through my trials. So it appears that this is a limitation with the software. I'm not sure how to fix the problem at the moment.
By Dave - 8/15/2014

For how long does your device keep the pins high? Can you configure that duration?
By DrLand - 8/15/2014

This isn't something that I can control. I am tracking the trajectory of a ball toss. When the ball crosses a start line, my motion analysis system will turn pin 2 to high. When the ball rolls past the finish line, the system turns pin 2 back to low. 
By Dave - 8/15/2014

Here's an idea. Simply have another <trial> check for the 'low' state instead of using /posttrialsignal. I.e., do

<trial checkportsignal>
/ stimulusframes = [1=button]
/ inputdevice = lptdata3
/ validresponse = (241)
/ branch = [trial.checkportstatuschange]
</trial>

<trial checkportstatuschange>
/ inputdevice = lptdata3
/ validresponse = (242)
</trial>

That should do the trick (provided I'm not missing anything).
By DrLand - 8/15/2014

Bingo! That's it! The level of support on this site is unmatched. Thanks for all the help.
By Dave - 8/15/2014

Great! And thank you for the kind words, too!
By DrLand - 8/22/2014

Ok, to follow up on the previous script, I have run into another problem when reading inputs from the parallel port. I am wanting a sound stimulus to be played when a correctresponse occurs from the parallel port. Here is the code:

<trial lowtones>
/ stimulusframes = [1=lowtrials]
/ inputdevice = lptdata3
/ validresponse = (241, 244)
/correctresponse = (241)
/correctmessage = true(lowtone, 1000)
/ branch = [trial.trialendcheck]
</trial>

<trial trialendcheck>
/ inputdevice = lptdata3
/ validresponse = (244)
</trial>

The trial starts and stops fine, but no tone is played. However, if for instance I don't use the parallel port for the input, but base it on a keyboard command...the tone plays when the correct response is given. It's only when I'm using the parallel port input that I'm not getting the sound feedback.

By Dave - 8/22/2014

What happens when you use /responsemessage instead of /correctmessage?

/ responsemessage = (241, lowtone, 1000)

Also, what do the 'response' and 'correct' columns in the data file actually indicate for the given trial? Are the values recorded there '241' and '1', respectively?
By DrLand - 8/22/2014

Hi Dave,
Thanks for your quick response. Your reply cued me in to the problem. I have it working now. It works with both the /responsemessage and /correctresponse.
Basically what was happening was...at the start of the trial, one pin I had set to go high, and another set to go low. At the end of the trial, the pins would switch in preparation for the next trial. Even though I was switching both pins at the "same" time, one pin was switching first and thus throwing a different value for a split second. So my data output file wasn't showing the correct value. I was able to fix this on the device side of things.

One final quick question: My trials are based on input from the parallel port, but it would be nice if I could /stop a block early with input from a keyboard. I believe I read in the documentation that you couldn't mix parallel port inputs with a keyboard input. I wasn't sure if there was any work around for this.
By Dave - 8/22/2014

A given <trial> element can only have one type of /inputdevice, so that's not really possible. If your aim is merely to terminate a given <block> for testing purposes, you can use the built-in CTRL+B key combo. Otherwise, you'd have to set up a separate <trial> element with /inputdevice=keyboard after one (or several) of your regular <trial>'s and then use that <trial>'s response to /stop the <block>.
By DrLand - 8/22/2014

Great! CRTL+B does exactly what I was trying to do. Thanks again!