Arduino communication with MATLAB is too slow
28 views (last 30 days)
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
0 Comments
Answers (3)
Klont
on 16 Mar 2015
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?
0 Comments
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
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.
0 Comments
See Also
Categories
Find more on MATLAB Support Package for 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!