Can I reduce the serialport 's write function call time

5 views (last 30 days)
Hello,
Question: Are there settings for the serial port that will make the write command run faster?
I developed a code to write uint16 words to a Teensy board connected to the USB serial port. Teensy reports back the values received.
teensy expects a code in the form
signal = [25600,word1,word1,word3,word4,word5];
and sends back to the USB the 12 LSB bits of the words received in uint16 format.
running the comand below in a for loop for 1000 cycles takes 278msec, resulting in a write operation taking 278us or 3.5KHz
write(USB,signal,"uint16");
However, if I create a signal containing 2000 sequences as above, using
for i = 1:1999 signal = [signal [25600,1234,2341,3412,4095,3210]]; end % signal has now 2000 samples of 6 uint16
a single write command of 2000x6 words takes less than 7.7ms correspondind to a frequency of 250KHz for a 6 words cycle
I assume the write command has a handshake mechanism to send the data into the COM port buffer, and that slows down the speed.
Can that be adjusted to increase the speed?
code below needs a Teensy, but could be tested using a loopback device on the USB serial port.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear;
%%%%%%USER SETUP
USBPORT = 'COM18'; %UPDATE w/ Teensy COM port
% Setup Teensy COM port
delete(instrfindall); %Delete any hung COM ports
USB = serialport(USBPORT,6000000);
%fopen(USB);
write(USB,'h',"char");
pause(0.1);
read(USB,USB.NumBytesAvailable,"string")
signal = [25600,1234,2341,3412,4095,3210];
write(USB,signal,"uint16"); % this line writes Hex code for d followed by 5 16bit values
pause(0.003);
%read(USB,USB.NumBytesAvailable,"string")
read(USB,USB.NumBytesAvailable/2,"uint16")
signal = [25600,1234,2341,3412,4095,3210];
% contains Hex code for 'd' followed by 5 16bit values
% Teensy drops d and sends back the 5 values in 16 bit to be signal.read
tic
for k = 1:1000
write(USB,signal,"uint16"); % this line serial.writes Hex code for d followed by 5 16bit values
end
writespeed = 1000/toc % measures the write speed and reports write cycle frequency
% pause(0.002);
tic
x =read(USB,USB.NumBytesAvailable/2,"uint16");
% pause(0.01)
readspeed = 1000/toc % reports read cycle frequency
for i = 1:1999 signal = [signal [25600,1234,2341,3412,4095,3210]]; end % signal has now 2000 samples of 6 uint16
tic
write(USB,signal,"uint16"); % this line writes Hex code for d followed by 5 16bit values
if (USB.NumBytesAvailable>0)
x =read(USB,USB.NumBytesAvailable/2,"uint16");
end
writereadspeed = 2000/toc

Answers (1)

Walter Roberson
Walter Roberson on 15 Jun 2023
Are there settings for the serial port that will make the write command run faster?
I developed a code to write uint16 words to a Teensy board connected to the USB serial port.
Yes. The best way to make a serial port write execute faster is not to use USB.
USB over serial is defined to buffer data until either a USB packet is full or else a timer has expired with no new input. The USB standard defines a "push" operation that means "stop waiting, send the packet as soon as can be scheduled", but MATLAB does not make that operation available to the users.
Therefore if you have time-sensitive serial packets. do not use USB.
  2 Comments
Dorin Calbaza
Dorin Calbaza on 20 Jun 2023
Thank you Walter,
Unfortunately, Laptop computers have only USB ports that can be used for communications.
I am able to run up to about 500kB/sec by sending arrays of 4096 bits at a time.
however, there seems impossible to send a continuous stream of data at such speed.
there are 2 questions answered by you about the possibility of sending continuous data through USB, and the answers point to links that do not exist.
I would ask that again, maybe you or another technical support can provide the links.
Walter Roberson
Walter Roberson on 21 Jun 2023

If you must use a serial port then switch hardware to a computer that has a serial port or has an expansion port that a serial port can be added to.

In some cases the best approach is to switch to Ethernet, possibly wifi.

There is no possibility of using serial() or serialport() for sustained high speed serial communication over USB. The design of USB 1 and USB 2 and USB 3.0 and USB 3.1 do not allow for the possibility. (USB 3.2 had changes that I have not studied yet but I know serial() and serialport() were not designed for that.)

To do sustained high speed data transfer over usb then the device needs to identify itself as providing audio or video or similar, in which case the USB controller will schedule time every controller cycle (1000 times per second) and will support sending multiple packets; the overhead per-frame buffer size would have to be set in advance. This would not be individual samples, this would be (for example) 2048 samples per cycle... samples that would not be time-tagged (unless the device tagged them and sent that information along with the samples). serial() and serialport() do not support this process.

You could also consider using a daq and the daq toolbox. The daq toolbox does support internal management of bulk usb transfer, and these days can time-tag each buffer-full.

Sign in to comment.

Products


Release

R2021a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!