2

I want to send an array of three floating point numbers to Arduino from MATLAB. I'm trying to check if these values have been received by Arduino by sending these values back from the Arduino to MATLAB. It seems that Arduino only reads the first element in the array correctly.

My array, 'parameters' is:

measurement_interval = 5.0;
ec_ref_thickness = 2.0;
e_ref_thickness = 3.0;
parameters = [measurement_interval ec_ref_thickness e_ref_thickness];

I established communication with Arduino as:

arduino = serial('COM4');
set(arduino,'DataBits',8);
set(arduino,'StopBits',1);
set(arduino,'BaudRate',9600);
set(arduino,'Parity','none');
fopen(arduino);

I send it to Arduino using:

fprintf(arduino, '%f', parameters);
fprintf(arduino, '\n');

And in Arduino I have:

float parameters[3]
void setup()
 {
    Serial.begin(9600);
    while (Serial.available() == 0)
    {
    }
    if (Serial.available() > 0)
    {
      for (int i=0; i < 3 ; i++)
      {
          parameters[i] = Serial.parseFloat();
      }
      Serial.flush();
    }

I send back from the Arduino over the serial port as:

void loop()
{
  Serial.print(parameters[0])
  Serial.print("  ");
  Serial.print(parameters[1]);
  Serial.print("  ");
  Serial.print(parameters[2]);
}

And read in MATLAB as:

output = fscanf(arduino);

'output' should be [5.0 2.0 1.0]. However, what I get is [5.00 0.00 0.00]

So only the first element '5.0' is returned correctly. How can I adapt this to read all the numbers in the array?

Afzal
  • 189
  • 3
  • 14
  • [`Serial.read()`](https://www.arduino.cc/en/Serial/read) reads a single byte. I am not familiar with Matlab but I assume `fprintf(arduino, '%d', parameters);` prints a string representing a single integer value. And `char parameters[3] = { '0','0','0'};` is obviously not an array of floats. – gre_gor Feb 09 '17 at 18:01
  • I've read up on `Serial.parseFloat()`, but I do not understand how to implement it for my case. – Afzal Feb 09 '17 at 18:05
  • `char parameters[3]` is an array of 3 `char` elements. Are you trying to read three `float`s into 3 `char`s? – Rotem Feb 09 '17 at 18:39

4 Answers4

3

First off, if you're trying to pass the parameters as floats, you should probably use a '%f' as the format specifier in your MATLAB code.

Next, you are going to want to wait for Serial data to become available before trying to parse the floats.

float parameters[3];

void setup(){
  Serial.begin(9600);
  while(!Serial || Serial.available() <= 0);
  for (int i=0; i<3; i++){
    parameters[i] = Serial.parseFloat();
  }
}
void loop(){
  for(size_t i=0; i<3; ++i){
    Serial.print(parameters[i]);
    Serial.print(i<2 ? '\t' : '\n');
  }
}

If for some reason that still doesn't work, you could try checking if your serial data is getting to the arduino properly:

void setup(){
  Serial.begin(9600);
  while(!Serial || Serial.available() <= 0);
  while(Serial.available() > 0){
    Serial.print(Serial.read());
  }
}
void loop(){}

If for some bizarre reason that still doesn't work, you could always try to parse the data into floats another way. Here is one quick example:

float parameters[3];

void setup(){
  Serial.begin(9600);
  while(!Serial);

  while(Serial.available() <= 0);
  for(int i=0; i<3; ++i){
    String param_string = "";
    int c;
    while( (c = Serial.read()) >= 0 ){
      if((char)c == '\n') break;
      param_string += (char)c;
    }
    parameters[i] = param_string.toFloat();
  }
}

void loop(){
  for(size_t i=0; i<3; ++i){
    Serial.print(parameters[i]);
    Serial.print(i<2 ? '\t' : '\n');
  }
}
Jeffrey Cash
  • 1,023
  • 6
  • 12
  • I've tried the second method, but it only successfully returns the first floating point number in the array. – Afzal Feb 09 '17 at 22:19
1

The answer by @JeffreyCash is very good and I think that it takes 100% care of the code on the Arduino side. However, since you still have problems, I'd like to post this to cover the Matlab side..


I read in your question that you send values from Matlab with

fprintf(arduino, '%d', parameters);

However:

  • you should use %f to print float
  • as far as I know, with this instruction you only send one value, and that's why when you run JeffreyCash's code you successfully print only one float.

Perhaps you should write

fprintf(arduino, '%f\n', parameters(1));
fprintf(arduino, '%f\n', parameters(2));
fprintf(arduino, '%f\n', parameters(3));

or

fprintf(arduino, '%f\n%f\n%f\n', parameters(1),
        parameters(2), parameters(3));
Patrick Trentin
  • 7,126
  • 3
  • 23
  • 40
  • `fprintf(arduino, '%f\n', parameters(1)); fprintf(arduino, '%f\n', parameters(2)); fprintf(arduino, '%f\n', parameters(3));` works – Afzal Feb 10 '17 at 00:07
  • Thanks, fixed it. – Patrick Trentin Feb 10 '17 at 02:36
  • I, too, know nothing of MATLAB, with the exception of some repressed memories of courses that required it, so I did a lazy internet search and found [this pdf, which states all of the values in the vector should have been printed](http://ocw.uci.edu/upload/files/mae10_w2011_lecture08.pdf). I guess this might not be the case – Jeffrey Cash Feb 10 '17 at 13:28
  • @JeffreyCash there are [this](http://stackoverflow.com/questions/14924181/how-to-display-print-vector-in-matlab) and [this](http://stackoverflow.com/questions/6024775/print-a-vector-with-variable-number-of-elements-using-sprintf) questions on StackOverflow which try to use this approach, only that **sprintf()** is used.. perhaps the lecture material you found is wrong. But I admit that since your code was perfect on the *Arduino* side, I jumped to the only viable conclusion without even checking the sources. That was reckless, but apparently it worked for the OP. (: – Patrick Trentin Feb 10 '17 at 13:35
1

First of try to put some delay after fopenf(arduino) in matlab for about 3 sec i.e.

fopen(arduino);
pause(3);

secondly, send the array of parameters one at a time i.e.

for i = 1:4
   fprintf(arduino, '%5.3f\n', parameters (i)); 
   pause(0.5);       
end

This should work fine and finally in the arduino side, your setup looks fine but the loop where you trying to send array back to matlab try doing

 void loop()
{ for (int i = 0; i < 3; i++){
  Serial.println(parameters[0]);  //sends data back in every new line 
  delay (20);

}

and yeah try to create an array of zeros in matlab side to store the received value from arduino i.e.

receiveData = zeros (1, 4);
  for i = 1:4
  output = fscanf(arduino, '%f');
  receiveData =output;
 end

this should work fine for you Cheers

0

I tested your code after adding small modifications, and it works well.

MATLAB code:

measurement_interval = 5.0;
ec_ref_thickness = 2.0;
e_ref_thickness = 3.0;
parameters = [measurement_interval ec_ref_thickness e_ref_thickness];

arduino = serial('COM3');
set(arduino,'DataBits',8);
set(arduino,'StopBits',1);
set(arduino,'BaudRate',9600);
set(arduino,'Parity','none');
fopen(arduino);
pause(2)

fprintf(arduino, '%f %f %f', parameters);


line = fgets(arduino);
values = strsplit(line, ",");
Final_values = str2double(values)

Arduino code:

float parameters[3];

void setup(){
Serial.begin(9600);

}
void loop(){
while(!Serial || Serial.available() <= 0);
for (int i = 0; i < 3; i++) {
parameters[i] = Serial.parseFloat();
}
Serial.print(parameters[0]);
Serial.print(",");
Serial.print(parameters[1]);
Serial.print(",");
Serial.print(parameters[2]);
}