# Serial port interface code -- a performance comparison

**URL:** https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781
**Category:** Hardware
**Tags:** io, linux
**Created:** [March 25, 2021, 2:21am UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781 "2021-03-25T02:21:35Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![Ian-Max-Andolina](https://yyz2.discourse-cdn.com/free1/user_avatar/psychtoolbox.discourse.group/ian-max-andolina/32/4_2.png) [@Ian-Max-Andolina](https://psychtoolbox.discourse.group/u/Ian-Max-Andolina)
#### Post date: [March 25, 2021, 2:21am UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/1 "2021-03-25T02:21:35Z")

</div>

MATLAB has a fairly new (R2019B+) serial port interface, [`Serialport`](https://www.mathworks.com/help/matlab/serial-port-devices.html). Some of my arduino control code had previously used the [`serial`](https://www.mathworks.com/help/matlab/ref/serial.html) 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](https://wiki.seeedstudio.com/Seeeduino-XIAO/) as fast as possible. I used the legacy MATLAB [arduino interface sketch](https://github.com/iandol/opticka/blob/master/communication/arduino/adio/adio.ino), which receives and sends the data via USB serial commands. Baudrate was set to 115200. MATLAB R2020B on Ubutnu 20.10.

```matlab
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](https://github.com/Psychtoolbox-3/Psychtoolbox-3/wiki/Arduino) for details.

---

<div class="post-metadata">

### Author: ![stevevanhooser](https://avatars.discourse-cdn.com/v4/letter/s/73ab20/32.png) [@stevevanhooser](https://psychtoolbox.discourse.group/u/stevevanhooser)
#### Post date: [April 2, 2021, 2:25pm UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/2 "2021-04-02T14:25:14Z")

</div>

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

---

<div class="post-metadata">

### Author: ![Ian-Max-Andolina](https://yyz2.discourse-cdn.com/free1/user_avatar/psychtoolbox.discourse.group/ian-max-andolina/32/4_2.png) [@Ian-Max-Andolina](https://psychtoolbox.discourse.group/u/Ian-Max-Andolina)
#### Post date: [April 3, 2021, 3:24am UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/3 "2021-04-03T03:24:21Z")

</div>

Hi Steve, I use a slightly modified version of the [MATLAB legacy arduino interface](https://www.mathworks.com/matlabcentral/fileexchange/32374-legacy-matlab-and-simulink-support-for-arduino). 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:

> <https://github.com/iandol/opticka/blob/master/communication/arduino/adio/adio.ino>

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

> <https://github.com/iandol/opticka/blob/master/communication/arduinoIOPort.m>

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):

```matlab
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).

---

<div class="post-metadata">

### Author: ![stevevanhooser](https://avatars.discourse-cdn.com/v4/letter/s/73ab20/32.png) [@stevevanhooser](https://psychtoolbox.discourse.group/u/stevevanhooser)
#### Post date: [April 5, 2021, 12:13pm UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/4 "2021-04-05T12:13:41Z")

</div>

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

Best  
Steve

---

<div class="post-metadata">

### Author: ![oroymd](https://avatars.discourse-cdn.com/v4/letter/o/d2c977/32.png) [@oroymd](https://psychtoolbox.discourse.group/u/oroymd)
#### Post date: [October 7, 2022, 1:26pm UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/5 "2022-10-07T13:26:56Z")

</div>

Hi,  
Thanks for this code. Everything works well except I’m having a problem with digitalRead. I can digitalWrite on Outputs but when I try to digitalRead on Inputs I get “NaN”. The pinMode of the pin is correctly set to ‘input’.  
Any idea?

---

<div class="post-metadata">

### Author: ![Ian-Max-Andolina](https://yyz2.discourse-cdn.com/free1/user_avatar/psychtoolbox.discourse.group/ian-max-andolina/32/4_2.png) [@Ian-Max-Andolina](https://psychtoolbox.discourse.group/u/Ian-Max-Andolina)
#### Post date: [October 10, 2022, 9:32am UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/6 "2022-10-10T09:32:11Z")

</div>

I’m stuck out of the lab and it is hard for me to test for a week or so. What code and what board exactly are you using? One thing to try is to use the original Legacy arduino package:

> **[Legacy MATLAB and Simulink Support for Arduino](https://www.mathworks.com/matlabcentral/fileexchange/32374-legacy-matlab-and-simulink-support-for-arduino)**
>
> MATLAB class and Simulink blocks for communicating with an Arduino microcontroller board

It is really easy to install and test (uses the older `serial` command, I modified it to use IOPort…), see if you can use digitalRead there?

---

<div class="post-metadata">

### Author: ![oroymd](https://avatars.discourse-cdn.com/v4/letter/o/d2c977/32.png) [@oroymd](https://psychtoolbox.discourse.group/u/oroymd)
#### Post date: [October 10, 2022, 11:23am UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/7 "2022-10-10T11:23:04Z")

</div>

Yes, sorry I couldn’t find a way to edit my previous post. I already tested it with both the Legacy and current Matlab versions of Arduino support and both work. It’s just the adaptation with the IOPort that doesn’t.

I am using an Arduino Uno with a simple switch on digital pin 2. On the the current/legacy Matlab versions, when I press the switch it reads “1”, otherwise “0”, which is expected.

```auto
s = arduinoIOPort('/dev/cu.usbmodem101',13,2)
s.pinMode(2, 'input');
s.digitalRead(2); % I also tried digitalRead(s, 2);

```

Thanks!

---

<div class="post-metadata">

### Author: ![Ian-Max-Andolina](https://yyz2.discourse-cdn.com/free1/user_avatar/psychtoolbox.discourse.group/ian-max-andolina/32/4_2.png) [@Ian-Max-Andolina](https://psychtoolbox.discourse.group/u/Ian-Max-Andolina)
#### Post date: [October 10, 2022, 2:05pm UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/8 "2022-10-10T14:05:40Z")

</div>

Hm, looking at the `arduinoIOPort.digitalRead()` code and I can see one potential problem, I’ll rummage around to find an uno to test…

---

<div class="post-metadata">

### Author: ![oroymd](https://avatars.discourse-cdn.com/v4/letter/o/d2c977/32.png) [@oroymd](https://psychtoolbox.discourse.group/u/oroymd)
#### Post date: [October 10, 2022, 2:16pm UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/9 "2022-10-10T14:16:48Z")

</div>

> [@Ian-Max-Andolina](#):
>
> m, looking at the `arduinoIOPort.digitalRead()` code and I can see one potential problem, I’ll rummage around to find an uno to test…

Thank you, much appreciated!

---

<div class="post-metadata">

### Author: ![Ian-Max-Andolina](https://yyz2.discourse-cdn.com/free1/user_avatar/psychtoolbox.discourse.group/ian-max-andolina/32/4_2.png) [@Ian-Max-Andolina](https://psychtoolbox.discourse.group/u/Ian-Max-Andolina)
#### Post date: [October 10, 2022, 4:37pm UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/10 "2022-10-10T16:37:54Z")

</div>

I think the problem is a non-blocking mode typo, try this as the code for `function val=digitalRead(a, pin)`, I also added a bit more error checking:

```matlab
	if a.isDemo; return; end
	[n, ~, err] = IOPort('Write',a.conn,uint8([49 97+pin]),2);
	if n ~= 2; warning(['digitalRead send command went wrong?']); end
	[val, ~, err] = IOPort('Read',a.conn, 1, 3);
	if isempty(val)
		if ~isempty(err);
			warning(['arduinoIOPort.digitalRead() failed:' err]); 
		else
			warning('arduinoIOPort.digitalRead() empty');
		end
		val = NaN;
	else
		val = str2double(char(val(1)));
	end

```

The important bit is `IOPort('Read',a.conn, 1, 3)` which blocks [1] until 3 characters are available, IIRC the read data should be the value itself then a 13[CR] and 10[LF] so 3 bytes in total, but untested and this is from memory, see if it works…

---

<div class="post-metadata">

### Author: ![oroymd](https://avatars.discourse-cdn.com/v4/letter/o/d2c977/32.png) [@oroymd](https://psychtoolbox.discourse.group/u/oroymd)
#### Post date: [October 11, 2022, 7:55am UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/11 "2022-10-11T07:55:15Z")

</div>

It still returns NaN. The `IOPort('Read',a.conn, 1, 3)` part returns an empty matrix.

---

<div class="post-metadata">

### Author: ![Ian-Max-Andolina](https://yyz2.discourse-cdn.com/free1/user_avatar/psychtoolbox.discourse.group/ian-max-andolina/32/4_2.png) [@Ian-Max-Andolina](https://psychtoolbox.discourse.group/u/Ian-Max-Andolina)
#### Post date: [October 15, 2022, 11:43pm UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/12 "2022-10-15T23:43:45Z")

</div>

Hm, I just tested with an Uno clone and a Seeeduino Xiao and I do get data back, and it is 3 bytes for digitalRead (`[data CR NL]`). I noticed the first read of the Uno sometimes is delayed, so perhaps you are hitting the IOPort timeout? I’ve tweaked the code a bit for both `adio.ino` and `arduinoIOPort.m`. You can use configure to change the timeouts, e.g. `IOPort('ConfigureSerialPort', conn, 'ReadTimeout=1.5')`, I added a function to wrap this with `arduinoIOPort.m` too: `a.configure('ReadTimeout=1.5')`.

> <https://github.com/iandol/opticka/blob/master/communication/arduinoIOPort.m>

> <https://github.com/iandol/opticka/blob/master/communication/arduino/adio/adio.ino>

What happens if you try to use the Serial Monitor in the Arduino IDE directly? You can send commands and read the reply (make sure baud = 115200). So the ascii command to set e.g. pin 4 to input is **`0e0`** , then a digital read is: **`1e`** — in this command-response language the first byte is the command (a number), the second byte is the pin (a letter), the third byte is optional data. To test, you can send **`99`** which should return `0`, or **`X3`** to return the same number, e.g. `3` in this case. This is the “raw” connection so we can exclude any MATLAB issue…

---

<div class="post-metadata">

### Author: ![oroymd](https://avatars.discourse-cdn.com/v4/letter/o/d2c977/32.png) [@oroymd](https://psychtoolbox.discourse.group/u/oroymd)
#### Post date: [October 16, 2022, 10:07am UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/13 "2022-10-16T10:07:45Z")

</div>

Wow, thanks! It does work now. Maybe it’s the USB A-\>C converter I use that added a delay so that the timeout became an issue? What kind of hub are you using?  
Thanks again BTW, great work!

---

<div class="post-metadata">

### Author: ![Ian-Max-Andolina](https://yyz2.discourse-cdn.com/free1/user_avatar/psychtoolbox.discourse.group/ian-max-andolina/32/4_2.png) [@Ian-Max-Andolina](https://psychtoolbox.discourse.group/u/Ian-Max-Andolina)
#### Post date: [October 17, 2022, 4:17am UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/14 "2022-10-17T04:17:13Z")

</div>

Something is still a bit strange with your setup. The default IOPort timeout is 1 second, and normally you should never hit that timeout; for me the time to open the device is ~13ms and the first digitalRead around 3ms (my arduinoManager is just a wrapper around arduinoIOPort):

```auto
>> a=arduinoManager('board','Xiao');
--->arduinoManager: Ports available: /dev/ttyS0
--->arduinoManager: Ports available: /dev/ttyACM0
>> a.open
===> All possible serial ports: /dev/ttyACM0 /dev/ttyS0 
===> Your specified port /dev/ttyACM0 is present
===> Your specified port /dev/ttyACM0 is available
===> It took 0.013 secs to establish response: 0...
===> Basic Analog and Digital I/O (adio.ino) sketch detected !
===> Arduino successfully connected to port: /dev/ttyACM0!
>> tic;val=a.digitalRead(4);disp(['Value was: ' num2str(val)]);toc
Value was: 1
Elapsed time is 0.003512 seconds.

```

In this case I am using a USB3 hub built-in to my Dell monitor. According to LabJack engineers, command-response times are better for USB-2 devices when using a hub, but we are talking about a few ms either way, not a second…

---

<div class="post-metadata">

### Author: ![oroymd](https://avatars.discourse-cdn.com/v4/letter/o/d2c977/32.png) [@oroymd](https://psychtoolbox.discourse.group/u/oroymd)
#### Post date: [October 17, 2022, 10:52am UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/15 "2022-10-17T10:52:38Z")

</div>

Here is what I get with a Teensy4.1. There is quite a variability in the digitalRead. Even more so at the begining of the reading sequence.

```auto
===> All possible serial ports: /dev/cu.Bluetooth-Incoming-Port /dev/cu.usbmodem124098601 /dev/tty.Bluetooth-Incoming-Port /dev/tty.usbmodem124098601 
===> Your specified port /dev/cu.usbmodem124098601 is present
===> Your specified port /dev/cu.usbmodem124098601 is available
===> It took 0.016 secs to establish response: 0...
===> Basic Analog and Digital I/O (adio.ino) sketch detected !
===> Arduino successfully connected to port: /dev/cu.usbmodem124098601!
>> tic;val=s.digitalRead(2);disp(['Value was: ' num2str(val)]);toc
Value was: 0
Elapsed time is 0.011491 seconds.
>> tic;val=s.digitalRead(2);disp(['Value was: ' num2str(val)]);toc
Value was: 0
Elapsed time is 0.002888 seconds.
>> tic;val=s.digitalRead(2);disp(['Value was: ' num2str(val)]);toc
Value was: 0
Elapsed time is 0.010729 seconds.
>> tic;val=s.digitalRead(2);disp(['Value was: ' num2str(val)]);toc
Value was: 0
Elapsed time is 0.005121 seconds.

```

For 10000 iterations of digitalRead:

```auto
b = [];
pause(1)
for i = 1:10000	
    tic;
	s.digitalRead(2);
    b(i) = toc;
end
>> mean(b)

ans =

   0.001013402959300

```

 ![untitled1](https://global.discourse-cdn.com/free1/uploads/psychtoolbox/original/1X/2cb588e6d725c928241665e6eaaac3e22b09c22e.png)

However, digitalWrite is way faster:

```auto
a = [];
pause(1)
for i = 1:10000
    tic;
	s.digitalWrite(14,mod(i,2));
    a(i) = toc;
end
>> sum(a)

ans =

   0.432772365000000

>> mean(a)

ans =

     4.327723649999997e-05

```

Even then, though, the first writes of the sequence are orders of magnitude slower (ie, the first write is 6.074 ms).

> **[untitled2](https://ibb.co/xqkPgmz)**
>
> Image untitled2 hosted in ImgBB

With an Arduino Uno:

```auto
===> All possible serial ports: /dev/cu.Bluetooth-Incoming-Port /dev/cu.usbmodem101 /dev/tty.Bluetooth-Incoming-Port /dev/tty.usbmodem101 
===> Your specified port /dev/cu.usbmodem101 is present
===> Your specified port /dev/cu.usbmodem101 is available
===> It took 0.531 secs to establish response: 0...
===> Basic Analog and Digital I/O (adio.ino) sketch detected !
===> Arduino successfully connected to port: /dev/cu.usbmodem101!

```

For 10000 iterations of digitalRead, we can see there is indeed, a problem.

```auto
b = [];
pause(1)
for i = 1:10000	
    tic;
	s.digitalRead(2);
    b(i) = toc;
end
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
Warning: arduinoIOPort.digitalRead() was empty 
> In arduinoIOPort/digitalRead (line 237) 
>> sum(b)

ans =

     8.888205034199996e+02

```

(cannot post the plot, limited by the forum)

However, digitalWrite is still way faster:

```auto
>> a = [];
pause(1)
for i = 1:10000
    tic;
	s.digitalWrite(3,mod(i,2));
    a(i) = toc;
end
>> mean(a)

ans =

     2.542173692000001e-04

```

Although, it is not pretty either.

> **[untitled4](https://ibb.co/4KjQ6hM)**
>
> Image untitled4 hosted in ImgBB

This is with the original USB-B to USB-A long cable provided with Arduino Uno with the USB-A to C adapter so, this might be a cause.

Of note, these tests are conducted on my own personnal machine (MacBook Pro M1 Max 2021) and not the one I plan to use for the experiment. So, it runs Matlab through Rosetta. The timings are thus, of course, not too good nor reliable. Nevertheless, the question of why the digitalReads are so inconsistent remains. Maybe there is something wrong with my Uno since the Teensy reading are so much better. However, the reason why the first readings of the sequence are slow eludes me. It is as if the digitalRead should be initialized or something.

---

<div class="post-metadata">

### Author: ![Ian-Max-Andolina](https://yyz2.discourse-cdn.com/free1/user_avatar/psychtoolbox.discourse.group/ian-max-andolina/32/4_2.png) [@Ian-Max-Andolina](https://psychtoolbox.discourse.group/u/Ian-Max-Andolina)
#### Post date: [October 18, 2022, 12:44am UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/16 "2022-10-18T00:44:21Z")

</div>

Hm, testing using Ubuntu 22.04 on my Uno (actually it is a chinese clone of a genuine arduino) I get a digitalRead mean of 4.1ms ( ±0.001 SE) and my Seeeduino Xiao as 0.62ms ( ±0.0006 SE):

 ![plot](https://global.discourse-cdn.com/free1/uploads/psychtoolbox/original/1X/4ef5ea09aa9fa684d9703b555de739f036f85c58.png)

 ![hist](https://global.discourse-cdn.com/free1/uploads/psychtoolbox/original/1X/0446a571ed958ccd320567c87b340a39174b20be.png)

The Xiao at least has pretty low variance. The Uno is slightly bimodal, and ~4ms would not be so acceptable in a tight display loop. Neither show any increased variance over time. I think your M1 laptop is most of this problem, and on something native it would work more reliably.

As a workaround you can “warm up” the board by doing some digital reads in a loop before any experiment. I tend to do this with all my PTB functions, making sure MATLAB has everything in memory etc.

---

<div class="post-metadata">

### Author: ![oroymd](https://avatars.discourse-cdn.com/v4/letter/o/d2c977/32.png) [@oroymd](https://psychtoolbox.discourse.group/u/oroymd)
#### Post date: [October 19, 2022, 6:56pm UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/17 "2022-10-19T18:56:04Z")

</div>

> [@Ian-Max-Andolina](#):
>
> I think your M1 laptop is most of this problem, and on something native it would work more reliably.

Yeah, most probably. I’m waiting for our new PC to arrive so I can test it on Ubuntu. Thanks for the help!

---

<div class="post-metadata">

### Author: ![NaHan](https://yyz2.discourse-cdn.com/free1/user_avatar/psychtoolbox.discourse.group/nahan/32/449_2.png) [@NaHan](https://psychtoolbox.discourse.group/u/NaHan)
#### Post date: [December 14, 2022, 12:46pm UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/18 "2022-12-14T12:46:29Z")

</div>

hi lan-  
Thanks for this code.Everything works well except，but when I use a PTB drawing loop，the Risetime change from 70 µs to 0.7 s（when iii \>1757). Do you have any idea about this problem ?

Best!  
-NAHAN

> [win, winRect] = Screen(‘OpenWindow’, 2,[],[],32);  
> ifi = Screen(‘GetFlipInterval’, win);  
> arduino\_u = arduinoIOPort(‘COM9’); %parameters: port, end pin, start pin  
> vblTS = Screen(‘Flip’,win);  
> timelist = [];
> 
> for iii=1:1800  
> Screen(‘FillRect’,win, [255 128 0],winRect);  
> tic  
> arduino\_u.digitalWrite(13,1);  
> tt2=toc;  
> vblTS = Screen(‘Flip’,win,vblTS+ifi \* 0.5);  
> Screen(‘FillRect’,win, [0 0 255],winRect);  
> tic  
> arduino\_u.digitalWrite(13,0);  
> tt4=toc;  
> vblTS = Screen(‘Flip’,win,vblTS+ifi \* 0.5);  
> timelist=[timelist;tt2 tt4];  
> end

---

<div class="post-metadata">

### Author: ![NaHan](https://yyz2.discourse-cdn.com/free1/user_avatar/psychtoolbox.discourse.group/nahan/32/449_2.png) [@NaHan](https://psychtoolbox.discourse.group/u/NaHan)
#### Post date: [December 14, 2022, 12:48pm UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/19 "2022-12-14T12:48:09Z")

</div>

![image](https://global.discourse-cdn.com/free1/uploads/psychtoolbox/original/1X/e283a0dd253beae05919f980adcce941beac95b5.png)

---

<div class="post-metadata">

### Author: ![Ian-Max-Andolina](https://yyz2.discourse-cdn.com/free1/user_avatar/psychtoolbox.discourse.group/ian-max-andolina/32/4_2.png) [@Ian-Max-Andolina](https://psychtoolbox.discourse.group/u/Ian-Max-Andolina)
#### Post date: [December 17, 2022, 7:49am UTC](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781/20 "2022-12-17T07:49:47Z")

</div>

I can’t reproduce your problem, I tested to 3000 frames using your code at a 60Hz framerate, using Ubuntu 22.04 and PTB 3.0.18 with a Seeeduino Xiao:

 ![Test](https://global.discourse-cdn.com/free1/uploads/psychtoolbox/original/1X/f876fe361cc09c38d83e889d3629620e321e45d7.png)

My oscilloscope shows a really nice square wave @ 33ms period time confirming the digitial write.

[Next page](https://psychtoolbox.discourse.group/t/serial-port-interface-code-a-performance-comparison/3781.md?page=2)
