How to send specific bytes in Python

Hi all,

We are sending serial port signals for an EEG experiment. Our serial port device is Neurospec’s MMBT-S. We are sending signals in ‘character’ type. As far as I can tell these character type signals are then transformed to byte type values. Then these are sent through the device.

Our problem is that we cannot send byte values larger than 10 within Psychopy’s code components. Here is an example (ser is the defined serial port variable):

trigger = ‘50’ # character type port signal value
ser.write(trigger.encode()) # sending this signal to EEG recorder software

In MATLAB this signal would appear as “S50” in the recorder software. However, in Psychopy. this signal appears as a number smaller than 10 (e.g. “S5”), always.

We tried sending just integer type values, Psychopy crashed. It does not allow that to happen. We are thinking maybe we should directly use byte type values. However, we are not sure what is the correct format for that. If anyone has dealt with this issue and has a solution, we would appreciate your help!

Thanks.

If you want to send the character ‘S’ to an external device using a serial com port, try the following:
import serial
ser = serial.Serial(…)
ser.write(bytes(‘S’,‘utf-8’))
Set the timeout to a small value if timing is critical.
To send the characters ‘S’,‘5’,‘0’ try ser.write('bytes(‘S50’,‘utf-8’))

Hi @FrankS

Thanks for the reply!

I accidentally write a confusing explanation there, sorry. We are only sending numbers (1 to 15) through the port, but EEG recorder software just adds “S” as a suffix. You can ignore every S in my previous post, that is not something we send.

What we are having trouble with is that we cannot send NUMBERS that are larger or equal to 10 using Psychopy. Larger numbers just appear as single digit numbers in the recorder software. However, we don’t have a problem with that while using MATLAB.

I am having some difficulty understanding your problem. Perhaps if you provide the MATLAB code that is working properly I will be able to understand the issue better (Since MATLAB is my “native” progamming language).

I’ll first detail the route of signals.

Experiment PC sends the signal (via Psychopy or MATLAB) > Recorder PC receives the signal (via Brainvision Recorder). Received signals appear as markers on the recorder software. These markers are named as S1, S2… S255 depending on the byte you send via MATLAB or Psychopy.

If you send “1” with the port write function, you will see “S1” marker on the recorder software. If you send “5”, you will see “S5” on the recorder software. We do not type “S” anywhere in the code, that is just automatically created within the recorder software

Below you can see the code for sending signals from MATLAB and Psychopy:

MATLAB
port_handle = ‘COM4’
trigger_val = 3,
fwrite(port_handle, trigger_val)

% This signal is registered as “S3” in recorder software.

Psychopy Python
stimulusSignal = “3”
win.callOnFlip(ser.write, stimulusSignal.encode())

% This signal is registered as “S3” in recorder software.

WHAT IS THE PROBLEM? Problem occurs when we write bytes larger than 9 (two digit bytes)

MATLAB (works fine)
port_handle = ‘COM4’
trigger_val = 15,
fwrite(port_handle, trigger_val)
% This signal is registered as “S15” in recorder software.

Psychopy (does not work)
stimulusSignal = “15”
win.callOnFlip(ser.write, stimulusSignal.encode())
% This signal is registered as “S1” in recorder software instead of “S15”.

Looks like ‘trigger’ in MATLAB is a numerical value = 15. fwrite() in MATLAB sends it as a single 8-bit value (i.e., char or unsigned byte data type). stimulusSignal = “15” in Python is a STRING consisting of the [‘1’] and [‘5’] characters. Python ser.write() sends a ‘1’ character’ and then a ‘5’ character sequentially to the serial port output channel. I believe what you need to do is send a single 8-bit value equal to 15 = 0x0F = 0b00001111. Research how to do this and let me know if you need more assistance. Remember: This is all my best guess as I am not familiar with your specific hardware setup.

@FrankS

Thank you, I will do that and get back to you!

Hi @FrankS

I’ve changed it the way you suggested and it works now! For people who struggle with this, here is the code that works:

trigger = '0b1110' # number 14 in bits
ser.write(trigger.encode()) # 'ser' is the serial port object

Basically, find the bit version of the number you want to send. Create a char variable from it. Send it using .encode() function. Using raw bits won’t work.

Thanks again.