Sending high frequency serial data from Arduino to Matlab

I am trying to send a voltage read by an Arduino from a Waveform generator into matlab.

My trouble is sending a signal that is > 1 Hz. At 1 Hz or lower, I can send data from arduino using Serial.println() and read the data in Matlab using fgets, but this fails at higher frequencies.

I believe I need to modify my code to use Serial.write() in arduino and fread() in Matlab, but I am unsure how to do this to send a full unsigned int (2 bytes at a time).

My Arduino code is:

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(57600);
  //establishContact();  // send a byte to establish contact until receiver responds 
}

// the loop routine runs over and over again forever:
void loop() {
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  byte voltage = sensorValue; //*(5.0 / 1023.0);
  // print out the value you read:
  Serial.println(voltage);
  //Serial.write(voltage);
}

My matlab code is:

%make sure no old serial ports are open
clear
delete(instrfind({'Port'},{'/dev/tty.usbmodem411'}));

%connect to serial port and set baud rate
%s1 = serial('/dev/tty.usbmodem441','BaudRate', 9600);
s1 = serial('/dev/tty.usbmodem411','BaudRate',57600,'Terminator','CR/LF');


% open connection and send identification 
fopen(s1);
fprintf(s1, '*IDN?');

%number of points to be plotted
numberOfPoints = 10000;

%initialize with zeros, to hold yvalues
yVal(1:numberOfPoints)= 0;

% x axis points
xVal = (1:numberOfPoints);

%create an empty plot
thePlot = plot(nan);

%delay or pause so serial data doesnt stutter
%pause(1);

hold on
for index = (1:numberOfPoints)

    %reading value from Arduino
    yVal(index) = str2double(fgets(s1)); %*1.1/1023.;
    %yVal(index) = fread(s1,1,'int8');
    %every 100 points, plot the entire graph
    % this might be a bad way to do it, but at least it's "real-time"
    if mod(index,100) == 0
        set(thePlot,'YData',yVal, 'XData', xVal);
        drawnow
    end
  
end

hold off

%close the port and delete it
fclose(s1);
delete(s1)
clear('s1')
delete(instrfindall)

How can I modify my code to send data each voltage readout as bytes and read the bytes correctly in Matlab?

I was able to use the following in Arduino:

  hiByte = highByte(sensorValue); //*(5.0 / 1023.0);
  loByte = lowByte(sensorValue);
  Serial.write(hiByte);
  Serial.write(loByte);

But I am having trouble getting Matlab to read the two corresponding bytes in the right order and frequency, and to reconstruct the actual sensorValue from the two bytes.

Currently I cannot read a 10Hz signal correctly. Eventually I would like to read in a 300Hz signal. Any ideas?

Thank you.

If you don’t need to setup a timer and interrupt to get an “exact” (or at least more repeatable) sample timing, then your loop() might look something like this;

// the loop routine runs over and over again forever:
void loop() {
  // read the input on analog pin 0:
  sensorValue = analogRead(A0);
  Serial.write(highByte(sensorValue));
  Serial.write(lowByte(sensorValue));
  delayMicroseconds(XYZ); 
}

Leave the conversion to voltage for the PC/Matlab to do, it’s much faster than the Uno. I don’t know the MatLab code to read the serial port, but that’s well known and Googlable. Declare the sensorValue as a int and set the “XYZ” to whatever delay is needed to get ~300 Hz loop timing. A baud rate of 57.6k should be high enough. You may have to reverse the hi and lo byte order to make MatLab happy.

http://www.mathworks.com/help/matlab/ref/readasync.html

http://www.mathworks.com/help/matlab/ref/readasync.html

http://www.mathworks.com/matlabcentral/ … ead/170164

http://www.mathworks.com/matlabcentral/ … ead/295366

Looks like he needs a

Serial.write(0x0D);

after the second Serial.write of data as a delimiter. I don’t know matlab. Does ‘CR/LF’ mean OR or AND? Hopefully it means OR.

One thing I’m not clear on after reading the OP: What is at 300Hz? Is the sample rate or is the signal from the waveform generator intended to be 300Hz? If it’s the waveform generator then the sample rate needs to be at least 600sps just to meet Nyquist. It would need to be more like 3000sps for a nice smooth waveform reconstruction.

Each byte sent is about 175uS plus IIRC about 100uS to take the sample. Total that’s about 625uS or about 1600sps of throughput or about 800Hz Nyquist. Call it around 160Hz max signal bandwidth for a smooth waveform reconstruction. Samples of a 300 Hz signal will be pushing it, but might be doable if the signal is not too complex.

If you up the transfer rate to 115200 then the max sample rate goes up to about 2700sps which would hopefully be adequate for a 300Hz signal.

  • Chip