Sending multiple triggers using a for loop within a code component

Psychopy version 2022.2.5
What are you trying to achieve?:
I’m able to send a single trigger within a routine using the code provided in the “sending triggers via serial port” help page, but id like to modify it to send 4 triggers while a sound component is playing. For now, I am just trying to get this to work within a 15 second-ish clip of the song.

This code is sending triggers to a thermal stimulator, where “L” triggers heat and “A” stops it.

What did you try to make it work?:
I created a for loop within the “Each frame” section of the code component

Begin routine:

stimulus_pulse_started = False
stimulus_pulse_ended = False

Each frame:

for stim in [1,2,3,4]:
    if sound1.status == STARTED and not stimulus_pulse_started:
        print("starting " + str(stim))
        win.callOnFlip(port.write, str.encode('L'))
        stimulus_pulse_start_time = globalClock.getTime()
        stimulus_pulse_started  = True
        
    if stimulus_pulse_started and not stimulus_pulse_ended:
     if globalClock.getTime() - stimulus_pulse_start_time >= 4: #I want a 4 second gap between stims
        print("stopping " + str(stim))
        win.callOnFlip(port.write,  str.encode('A'))
        stimulus_pulse_started = False
        continue

What specifically went wrong when you tried that?:

The triggers do not send as expected, instead they are sent like this:
starting 1
stopping 1
starting 2
stopping 1
starting 2
stopping 1
starting 2
stopping 1
starting 2

I think this is probably due to how I have set up the for loop, but I’m not quite sure how I would fix this as im not sure where i’m going wrong. any help is much appreciated !

Update: I ended up abandoning this method! I’m assuming its because EachFrame refreshes too fast to accomplish this in the way I would like. I initially wanted to do this so I could have a music component playing throughout the routine. Instead I ended up using a builder interface loop for the triggers, and ended up playing the music using sound.Sound().

Hi elise1, I have a similar problem as well.
I need to show a stimuli for 4 s
And have to send a trigger for the first 2s and then stop it.
I tried to do this using a very similar code as yours in “Each Frame” but that seems to not work.

Instead I ended up using a builder interface loop for the triggers

Can you please explaing this approach a bit more in detail. Thanks!

Hi Prakhar, sure thing, although there were some changes to my method

I ended up with something like this for my design- a loop for the triggers within a bigger loop playing various songs for each condition. To choose whether the triggers here would get sent or not in the particular condition i had an “Nreps” variable in the conditions spreadsheet controlling the number of repetitions of the “stims” loop and set it to 1 or 0. But if you are sending the trigger every time, you dont need this inner loop. However I changed my method so that I was sending triggers and setting the length using the python library for the piece of equipment I was using where I actually did not need to keep the trigger “on” for the entire time, just call a function once. So I wasn’t really using a trigger based method in the end in the sense of setting triggers using the psychopy GUI.

I had set a file as CurrentSong and then was calling CurrentSong.play() in the “playsong” component, and it keeps going while the stim loop runs after the first 80secs of the music. I then have the “endofsong” component checking this at each frame:


if CurrentSong.status == STARTED:
    continueRoutine = True

if CurrentSong.status == FINISHED:
    continueRoutine = False


In your case its like my outer loop where you would have the stimuli started and showing for 4 secs, so youd need to set the stimulus display to not be tied to the duration of the component in builder somehow. I’m not as familiar with displaying visual stimuli as I work entirely with audio stimuli unfortunately.

You could also try two components - the first component that shows the visual stimulus for 2secs and sends a 2sec long trigger for the duration of the component. then an additional component for 2 secs that just has the visual stimulus.

good luck!