Arduino communication with MATLAB is too slow
Show older comments
I recently tried to connect my arduino Uno with MATLAB R2014a. In mathworks.com they suggest the use of the following new package http://www.mathworks.com/hardware-support/arduino-matlab.html
Now it seems that many commands that existed in previous versions are no longer supported (e.g. analogRead is now readVoltage) My problem is that the communication between MATLAB and Arduino is VERY slow. I timed a readVoltage() command and it takes about 25-35 ms to read the voltage of an analog pin. Is that as fast as it can get? I hope not! But what am I missing here?
You can see what I mean in the attempted real time plot that I'm trying to do below...
a=arduino();
interv=50;
elapsed_time=0;
figure
initial_time=tic;
while(elapsed_time<interv)
elapsed_time=toc(initial_time);
b=readVoltage(a,0);
plot(elapsed_time,b)
hold on
end
clear a
Answers (3)
Klont
on 16 Mar 2015
0 votes
i get the same ~30 ms latencies on my setup (windows 7, asus n550jv laptop, aduino uno r3, matlab 2014b). very disappointing. does anyone know how fast the equivalent calls are in when using compiled C-code?
Maarten
on 21 May 2015
I have the same problem if I read multiple analog ports. However your code could be faster if you do not update your plot within the loop. Without plotting I have a sample time of around 70 Hz.
a = arduino(serialPort);
input = nan(1,round(time/dt));
sampleRate = nan(1,round(time/dt));
i = 1;
h = waitbar(0,'Reading sensor output');
tic
while toc < time
tstart = tic;
waitbar(toc/time,h);
input(1,i) = readVoltage(a,0);
sampleRate(1,i) = toc(tstart);
i = i+1;
end
close(h)
plot(sampleRate)
5 Comments
Kiki
on 22 Mar 2016
Hi!
How did you define dt?
I tried the following codes, but it gives me an error of "nan" that indicates "Maximum variable size allowed by the program is exceeded".
interv=1;
tic
readVoltage(a,0);
toc
time=nan(1, round(interv/(toc-tic)));
sampleRate= nan(1, round(interv/(toc-tic)));
elapsed_time=0;
figure
i=1;
tic
while(elapsed_time<interv)
initial_time=tic;
%elapsed_time=toc(initial_time);
input(1,i)=readVoltage(a,0);
sampleRate(1,i) = toc(initial_time);
%plot(elapsed_time,b)
hold on
end
plot(sampleRate)
Walter Roberson
on 22 Mar 2016
I recommend you use timeit() to time the call to readVoltage. Also I recommend calculating the number of entries to read and putting a maximum limit on it before calling nan with that size.
I also recommend that you use zeros() or -infinity*ones() instead of nan, as operations on nan are slower than operations on any number.
Kiki
on 23 Mar 2016
Hi Walter
Thank you for your advice. Here is my code. It works, but the sampling rate is only around 8Hz. Would it be possible to get a higher one?
a = arduino();
input=zeros(1, 500);
sampleRate=zeros(1,500);
interv=5;
i=1;
tic
while(toc<interv)
tstart = tic;
input(1,i) = readVoltage(a,0); %0.114-0.125s
i = i+1;
end
figure(7)
plot(input(1:42))
i
mean(input, 'omitnan')
clear a
Walter Roberson
on 23 Mar 2016
I recommend that you do not name a variable "input" as that interferes with using the input() function.
What speed (baud) do you have the arduino configured to communicate at?
Kiki
on 29 Mar 2016
Hi
The baud I use is 115200. Do I just set the baud rate for the arduino, or do I need to write other functions in my arduino code in order to use the readVoltage() function?
Brian Rasnow
on 19 Oct 2022
Edited: Brian Rasnow
on 19 Oct 2022
The Arduino package has enormous overhead, both in Matlab, and on the Arduino. I program the Arduino in C using its IDE to respond to simple commands, e.g.,
const int analogOutPin = 5;
#define NUMSAMP 400
int data[NUMSAMP + 1][2], i;
unsigned long t0, t1;
void measureWaveformsBinary()
{ //read A0 and A1 NUMSAMP times and return with the elapsed time
t0 = micros(); // time it to compute sample rate
for (i = 0; i < NUMSAMP; i++)
{
data[i][0] = analogRead(A0);
data[i][1] = analogRead(A1);
}
t1 = micros();
data[i][0] = t1 - t0; // put dt at end of data
data[i][1] = (t1 - t0) >> 16; // most significant 2 bytes
Serial.write((uint8_t*)data, (NUMSAMP + 1) * 2 * sizeof(int));
} // measureWaveformsBinary
void setup()
{
Serial.begin(115200);
pinMode(analogOutPin, OUTPUT);
} // setup
void loop()
{
if (Serial.available())
{
switch (Serial.read())
{
case 'p': // set pwm value
{
int pwmVal = Serial.parseInt();
analogWrite(analogOutPin, constrain(pwmVal, 0, 255));
break;
}
case 'b':
{
measureWaveformsBinary();
break;
}
} // switch
}
delay(1);
} // loop
Upload that code to the Arduino in the IDE, then quit the IDE or disconnect it from the Arduino (set menu Tools -> Port -> to anything else), since serial devices can't be shared between apps. In Matlab, open a serial port to the Arduino. I haven't found a great way to identify the Arduino in the port list, but on my Macintosh, it's always the last in the list so, in Matlab:
ports = serialportlist;
ard = serialport(ports{end},115200)
ard.Timeout = 1;
clear ports;
pause(1); % time to boot
To read and plot the data, send the 'b' character to the Arduino and then read the buffer. readLine and writeLine work for ascii data, but the buffer size isn't predictable, and binary is faster:
write(ard,'b','char');
bin = read(ard,802,'int16');
dt = bitshift(bin(802),16)+bin(801); % microseconds
data = reshape(bin(1:800),2,400)';
t = linspace(0,dt/2/1000,400)'; % calibrate the time axis
plot(t, data, '.-')
xlabel('msec'); ylabel('ADU')
legend('A0','A1');
Data is read at ~8.9kHz, each channel half of that and there is channel skew (which spline or fft can fix). This loops around 3 times per second, with plot being the bottleneck. h = plot(...) the first time, and changing the line data in the graphics objects speeds that up significantly. Want faster? I could get >20 frames per second with a Raspberry pi Pico or Teensy microcontroller (and 12 bits ...).
Added a uicontrol radiobutton to a figure to toggle an oscilloscope display, and you can nicely see audio waveforms and the like, using just Matlab and a $5 microcontroller.
Categories
Find more on Arduino Hardware in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!