Serial port interface code -- a performance comparison

MATLAB has a fairly new (R2019B+) serial port interface, Serialport. Some of my arduino control code had previously used the serial command that MATLAB has now deprecated. So I was curious to compare the old and new interfaces. In addition I also compared IOPort, the PTB serial controller.

For the test I basically toggled the state of a digital pin on a Seeduino Xiao as fast as possible. I used the legacy MATLAB arduino interface sketch, which receives and sends the data via USB serial commands. Baudrate was set to 115200. MATLAB R2020B on Ubutnu 20.10.

t = tic;
for i = 1:10000
	
	digitalWrite(PIN,mod(i,2));
	
end
fprintf('It took %.4f seconds for 10,000 iterations\n',toc(t));

I used an oscilloscope to ensure the output signal was well formed, and used its measurement function to measure average rise-time widths. I also used a simplistic method[1] to generate a 1ms TTL using digitalWrite(1);WaitSecs(0.001);digitalWrite(0) to see how close to 1ms we got:

Serial

10,000 iterations = 6.1 seconds
Risetime range = 540 - 790 µs
1ms pulse width = 3.27 ms

Serialport

10,000 iterations = 3.4 seconds
Risetime range = 320 - 350 µs
1ms pulse width = 2.52 ms

IOPort

10,000 iterations = 0.7 seconds
Risetime range = 50 - 74 µs
1ms pulse width = 1.28 ms

Conclusions

The new serialport is clearly faster than the old one, and the variance is considerably lower. However, IOPort is still much faster than either MATLAB option, I was quite surprised as normally you cannot achieve such fast command-response times with USB devices (the Seeduino Xiao is faster than an Arduino Uno and uses USB 3). If you need to send triggers in a PTB drawing loop and you don’t have much overhead (i.e. fast monitor or complex stimuli), then this should help…


[1] for timed TTLs, it is better to send the timing command to the Arduino, that way MATLAB returns immediately and doesn’t wait for the digitalWrite to finish. See Arduino · Psychtoolbox-3/Psychtoolbox-3 Wiki · GitHub for details.

3 Likes

Hi Ian -

Thanks for this. Is the code for IOPort for use with the Seeduino Xiao included? Would you mind posting it if it is not in a Psychtoolbox demo already? I just ordered some from Amazon for a new stimulus setup.

Best
Steve

Hi Steve, I use a slightly modified version of the MATLAB legacy arduino interface. This utilises an arduino sketch that acts as a server receiving commands and then performing the task. The interface is really simple, you send bytes encoding the action required and the parameters, so for example, sending the serial command 0c1: 0=set pin mode as input or output | c=use pin 2 | 1=set to output. The sketch is a simple state machine that uses the first byte to change state then process the parameters. You can use any serial terminal to send these commands:

I then use the MATLAB interface class (I modified MATLAB’s original that uses serial, my update uses IOPort):

To use it, burn adio.ino to your Xiao or Arduino using the Arduino software. Work out what serial port is used (on linux it is normally /dev/ttyACM0 or /dev/ttyUSB0). Then call the MATLAB class like so (Xiao can use pin 0–10, arduino requires pin 2–13):

s = arduinoIOPort('/dev/ttyACM0',10,0); %parameters: port, end pin, start pin
s.pinMode(2,'output');
s.pinMode(6,'output');
s.timedTTL(2,5); %send a 5ms TTL on pin 2
s.digitalWrite(6,1); %write pin 6 HIGH
s.digitalWrite(6,0); %write pin 6 LOW
clear s; % close the serial port

Currently I only use the arduino/seeduino for single TTL commands, I do want to update to enable strobed 8-10bit words (for which I normally use Display++ or a LabJack, but the Xiao/Arduino is just as capable).

Thanks Ian! This is wonderful and now I see your opticka library for the first time. Great stuff there.

Best
Steve