Chaotic triggers sending from Psychopy using USB2TTL8 adapter

Hi fellow Psychopyers,

I came across some trigger sending problems with USB2TTLB adapter.

OS (e.g. Win10): macOS Big Sur 11.6.1
PsychoPy version (e.g. 1.84.x): v2022.1.1
What are you trying to achieve?:

I would like to send triggers with different values to mark the presence of different visual stimuli via a USB2TTL8 adapter.

What did you try to make it work?:

I had a “code” component inserted. In the “each frame” I set different values for different stimuli:

if present.status == STARTED:
    sconn.write(b"WRITE %d\n" % 5)
    pulse_start_time = globalClock.getTime()
    pulse_started = True
    
if target.status == STARTED:
    sconn.write(b"WRITE %d\n" % 20)
    pulse_start_time = globalClock.getTime()
    pulse_started = True

if pulse_started and not pulse_ended:
    if globalClock.getTime() - pulse_start_time >= 0.01:
        sconn.write(b"WRITE %d\n" % 0)
        pulse_ended = True

I also had a routine for feedback. Here, I had another “code” component to send triggers for different feedback. The following codes were put in the “Begin Routine” tab to check participants’ responses from the last routine and send triggers based on the responses:

pulse_started = False
pulse_ended = False

if not key_resp.keys:
    thisFeedback = 'Missed!'
    respColor = 'orange'
    sconn.write(b"WRITE %d\n" % 40)
    pulse_start_time = globalClock.getTime()
    pulse_started = True
elif key_resp.corr:
    thisFeedback = 'Correct'
    respColor = 'greenyellow'
    sconn.write(b"WRITE %d\n" % 25)
    pulse_start_time = globalClock.getTime()
    pulse_started = True
else:
    thisFeedback = 'Incorrect'
    respColor = 'tomato' 
    sconn.write(b"WRITE %d\n" % 35)
    pulse_start_time = globalClock.getTime()
    pulse_started = True

trials.addData('Ans', thisFeedback)

if pulse_started and not pulse_ended:
    if globalClock.getTime() - pulse_start_time >= 0.01:
        sconn.write(b"WRITE %d\n" % 0)
        pulse_ended = True

What specifically went wrong when you tried that?:

i) Trigger pins were activated improperly with some of the hex values. For example, when I tried to send a value of 100 with the codes above, the trigger pins were turned on but could not be turned off leading to continuous trigger peaks, even though the trigger duration was set as 0.01s.

ii) Trigger pins could not be turned on with some of the hex values. For example, no triggers were sent to the port with some specific values, so no trigger peaks presented; or only the very first trigger with some specific values was properly sent to the port but the following triggers with that values could not be sent to the port.

iii) The values that I set for the triggers were not the values that I read in DataEditor. For example, I set a value of 20 for the triggers but the value that I read for these triggers in DataEditor was 100000. Another trigger with a value setting of 5 was read as 40000 or 50000 varied across trials.

I tried a range of values and found 5, 20, 25, 35, 40 could work properly for my experiment. But when I used some of these values for another experiment, some of them did work.

Sorry for the long massage. Please let me know if anything is unclear or if any further information is needed. Thanks in advance!
3.MEG_feedback.psyexp (66.2 KB)

3.MEG_feedback.psyexp (66.2 KB)
Please find my Builder design here.

Maybe my question was not clear.

I was wondering if Psychopy would compute/translate the values when sending them to the serial port via USB2TTL8 adapter or if there is a list of values that can be used with USB2TTL8 adapter?

It’s not really clear what your question is, which might be why it hasn’t attracted any answers so far. e.g. it isn’t clear what the actual problem is: the value sent seems to be a red herring, with the structure of the code making it unlikely to produce short trigger pulses at all. e.g this code seems designed to produce pulses that will never end, because it keeps resetting the pulse_start_time value on each frame, so the check for the pulse duration would never work:

I’d suggest that you need to add a second check for when to start the pulse, e.g.

if present.status == STARTED and not pulse_started:

and

if target.status == STARTED and not pulse_started:

That way, the pulse is only started once, and its onset time is also only recorded once (and hence the subsequent check to end it after 10 ms should then work). But I don’t really understand what you want to achieve: it might be that you need to keep track of different variables for each of the different pulses, rather than a single pulse_started for example (such as to keep track of whether the “present” vs “target” pulses have been sent).

Then in the feedback routine, your code starts a pulse, but you don’t provide any code that would end that pulse.

It can be worth debugging this stuff conceptually on paper: sketch a line for each pulse which shows each trigger signal signal, starting at 0 and then stepping upwards when sent, and back to 0 when it is cleared. Then in your mind, step though each line of code in the “begin routine” and “each frame” tabs, keeping track of a time value and the current status of each trigger. What happens if you follow through the code line by line? Do your trigger pulses start and finish as intended?