0

I am using a button box connected via a serial port for running an experiment in Psychopy.

from binascii import hexlify
import serial
import serial.tools.list_ports as port_list
ports = list(port_list.comports()) # search for the devices
#for p in ports: print (p)

ser = serial.Serial('/dev/ttyUSB0', 19200, bytesize=8, parity='N', stopbits=1, timeout=0)


if(ser.isOpen() == False): #open the serial port only if NOT open yet
    ser.open()

ser.flush()

In the experiment, I have 4 routines. Suppose that each routine contains a written text, accordingly text_1, text_2, text_3 and text_4. If the participant is, for example, in text_1 and he/she clicks the button, the experiment moves to text_2.

However, I am facing the following problem. If the participant is in text_1 and presses quickly twice the button the experiment moves to text_3 and not to text_2 as if something is storing the information. I would like instead that if you are in text_1 and you press twice, only the first press is considered.

Each text code is like that

ser.flush()

for line in ser.read(1):
    hex = hexlify(line)
    num_1=int(hex, 16)
    continueRoutine = False #this makes the experiment go to the next text

What could I add to make it like there is no storing of information (if this is what is really happening)?

  • Could you include a `time.sleep` call to wait a certain amount of time before the participant can continue? – jkr Feb 26 '20 at 17:48
  • I tried, but the problem is not solved (if I did it correctly), because the button box will still keep recording all the presses, only the effect of the presses will be delayed. – Giorgio Papitto Feb 27 '20 at 10:03
  • The only drastic solution I have found so far is to use `ser.close()` and `ser.open()` at the beginning and end of every `text` component. – Giorgio Papitto Feb 27 '20 at 10:11
  • Instead of closing and opening the port, try clearing the buffer with [`ser.reset_output_buffer()`](https://pyserial.readthedocs.io/en/latest/pyserial_api.html#serial.Serial.reset_output_buffer) at the beginning of every `text` component. I'm not sure if you should clear the input or output buffer, but both methods are available. – jkr Feb 27 '20 at 12:43
  • I did not know about this. It seems to work perfectly, and yes it is the input one, `ser.reset_input_buffer()`. – Giorgio Papitto Feb 27 '20 at 13:48
  • Great. I'll submit that as an answer – jkr Feb 27 '20 at 14:39

1 Answers1

0

Serial port communications are buffered, which means that there is temporary storage of the messages. If a participant presses the button box multiple times in a trial, those presses will be stored in the buffer. When you read from the serial port, you will read the buffered messages.

To solve your problem, you can clear the serial port buffer at the beginning of each trial. Use the serial.Serial.reset_input_buffer() method to accomplish this. Here is the documentation on this method:

reset_input_buffer()

Flush input buffer, discarding all its contents.


And for an excellent analogy on buffered communications, refer to https://stackoverflow.com/a/648324/5666087:

Imagine that you're eating candy out of a bowl. You take one piece regularly. To prevent the bowl from running out, someone might refill the bowl before it gets empty, so that when you want to take another piece, there's candy in the bowl.

The bowl acts as a buffer between you and the candy bag.

jkr
  • 17,119
  • 2
  • 42
  • 68