Serial communication Matlab-Arduino

I want to to avoid the transformation of the matrix into a string and then re-transforming the string into a matrix.

I can't see how to apply a matrix to a stepper motor. So, I have to wonder why you want to send a matrix to the Arduino. The PC can do a better job of determining how many steps a motor should take, and just that/those value(s) to the Arduino.

I use AccelStepper and MultiStepper libraries because i have six different stepper motors to be controlled and to be moved simultaneously: the motors move a robotic arm. The matrix has a number of rows equal to the number of position to be assumed by the arm and each column represent a single motor (six motors so six columns). I use a for cycle to send each row of the matrix to the function moveTo() provided by the library to move each motor: the function takes an array as an input which is represented by a single row of the matrix and when all the motors have reached their target, the for loop allow to go to the following line of the matrix and move the motors to the new target. here is a part of the code:

if (conta5==1788){ //once B has been completed store each row in a 1-D array and move the robot (1788 represents the numbers of the matrix 298 rows 6 columns)
long positions [6];
for (int i=0;i<298;i++){
for (int j=0;j<6;j++){
positions [j]=B [j];
}
steppers.moveTo(positions);
steppers.runSpeedToPosition();
}

here is the entire code: note that in Matlab I transformed the matrix into a string and saved it into a .txt file: the string is like this one:
2 3 4;5 6 8; 12923 3475 -2] for example
(I used ; char to understand when to fill the following row of the matrix and ] as a string terminator)

I have six motors representing the joints of my robotic arm and I use accelstepper and multi stepper libraries to have a simultaneous movement of all the motors.

String stringa= ""; //create a string to store what comes from serial
char c; //create a variable char to store each character from serial
int B [298][6]; //matrix that must be filled with data read from serial
int count=0; //counter that increased if a ';' is found
int conta4=0; //counter to store the length of the string
int conta5=0; //counter that increases if a value is added to B
int conta2=0; //counter that increases if a numeric value is found on the string
int conta3=0; //counter that increases if a value is added to B
//(it is set to 0 if a row of B has been entirely filled)
int num; //variable that stores the value of x(char array) into integer
bool s=false; //to repeat the loop only once
char q=';';
char w=' ';
char y=']';
char x[9];//variable char to store values until ';' ' ' or ']' will be found
#include <AccelStepper.h>
#include <MultiStepper.h>

// Define some steppers and the pins the will use (first pin for the number of wires,
// second one for the number of steps,
// and third one for direction)
AccelStepper stepper1(1,9,8);
AccelStepper stepper2(1,2,3);
AccelStepper stepper3(1,10,11);
AccelStepper stepper4(1,22,23);
AccelStepper stepper5(1,24,25);
AccelStepper stepper6(1,26,27);

MultiStepper steppers;

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

stepper1.setMaxSpeed(500.0);
Serial.print("stepper1 in posizione:");
Serial.println(stepper1.currentPosition());

stepper2.setMaxSpeed(500.0);
Serial.print("stepper2 in posizione:");
Serial.println(stepper2.currentPosition());

stepper3.setMaxSpeed(500.0);
Serial.print("stepper3 in posizione:");
Serial.println(stepper3.currentPosition());

stepper4.setMaxSpeed(500.0);
Serial.print("stepper4 in posizione:");
Serial.println(stepper3.currentPosition());

stepper5.setMaxSpeed(500.0);
Serial.print("stepper5 in posizione:");
Serial.println(stepper3.currentPosition());

stepper6.setMaxSpeed(500.0);
Serial.print("stepper6 in posizione:");
Serial.println(stepper3.currentPosition());

steppers.addStepper(stepper1);
steppers.addStepper(stepper2);
steppers.addStepper(stepper3);
steppers.addStepper(stepper4);
steppers.addStepper(stepper5);
steppers.addStepper(stepper6);

delay(3000);

}
void loop() {
if (Serial.available() > 0) { //read from serial

c = Serial.read(); // read Char
stringa = stringa + c; // add Char to string
conta4=conta4+1; //increase counter to store the length of the string
}
if(s==false){
if(stringa.charAt(conta4-1)==y){//enter in if only is the string has been acquired
for ( int i=0;i<conta4-1;i++)//go through the i-char of the string
{
if(stringa.charAt(i)==q) //if ';' is found
{
count=count+1; //increase count (go to the following row of the matrix)

}

if (stringa.charAt(i)!= q && stringa.charAt(i)!= w) //(a number has been found)
{
x[conta2]=stringa.charAt(i); //add number to x
conta2=conta2+1; //increase the counter if a number or a sign has been found
}
if(stringa.charAt(i)==w || stringa.charAt(i+1)==q|| stringa.charAt(i+1)==y){ //the number
//to be stored in the matix
//has been read
num= atoi(x); //convert the char array x into a number
if (conta3==6){ //the row of B has been completed
conta3=0;
}
for (int i=0; i<conta2;i++){
x*=' ';//set all the values of char array x to ' ' once x has been converted to integer*

  • }*

  • B[count][conta3 % 6]=num; //add num to B*

  • s=true; //exit from loop once the for cycle is over*

  • conta2=0; //set to 0 the index of x*

  • conta3=conta3+1; //increase counter because a number has been added to the matrix B*

  • conta5=conta5+1;//increase counter because a number has been added to the matrix B*

  • }*

  • }*

  • if (conta5==1788){ //once B has been completed store each row in a 1-D array and move the robot*
    long positions [6];
    for (int i=0;i<298;i++){

  • for (int j=0;j<6;j++){*
    positions [j]=B*[j];*
    }
    steppers.moveTo(positions);
    steppers.runSpeedToPosition();
    }
    }
    }

* }*
* }*

Do you see those italic characters in your code ?

You did not use code tags when you posted it so some of your code has been interpreted as HTML commands. Please read read this before posting a programming question and follow the instructions about posting code

The matrix has a number of rows equal to the number of position to be assumed by the arm

Doesn't matter. You should be sending data for ONE position at a time, and only when the arm is at the last position sent.

each column represent a single motor

So, you need to send 6 values, not a matrix. Much simpler.

When WILL you learn to use code tags?

Sorry I am new, later I will post my code in the correct way. I have a trajectory made of several points (around 300) to be reached by the arm; so each row of the matrix represents a single point of the trajectory. I just tried to send via serial one row of the matrix at a time (so an array of six values) but the problem is to syncronize the movement of all the motors with the time of sending values to serial: for example while the motors are completing their movements it’s possible that different rows are sent via serial and I miss one because motors are still moving: that’s why I prefer to send the entire matrix and then using a for loop to go through each row of the matrix.

for example while the motors are completing their movements it's possible that different rows are sent via serial and I miss one because motors are still moving:

You need to STOP matlab from spamming the Arduino. Only send a new row when the Arduino is ready for you to send a new row. That doesn't necessarily mean when it has completed a move. It could be working on a move while receiving data for the next move.

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.

The technique in the 3rd example will be the most reliable. It is what I use for Arduino to Arduino communication.

You can send data in a compatible format with code like this (or the equivalent in any other programming language)

Serial.print('<'); // start marker
Serial.print(value1);
Serial.print(','); // comma separator
Serial.print(value2);
Serial.println('>'); // end marker

And to make it easy for people to help you please modify your post and use the code button </>
codeButton.png

so your code looks like this and is easy to copy to a text editor. See How to use the Forum

Your code is too long for me to study quickly without copying to my text editor. The text editor shows line numbers, identifies matching brackets and allows me to search for things like all instances of a particular variable or function.

Also please use the AutoFormat tool to indent your code for easier reading.

...R

PaulS:
You need to STOP matlab from spamming the Arduino. Only send a new row when the Arduino is ready for you to send a new row. That doesn't necessarily mean when it has completed a move. It could be working on a move while receiving data for the next move.

Yes it's clear but the risk is the one I explained: a new row is sent on the serial and the robot is still completing the previous movement, there could be the possibility that another row is sent on the serial so I lose one position. The problem is to synchronize the time in which a row is sent on serial and the movement of the robot itself: there would be perfect that a new row arrive immediately after a movement is completed but I don't know how to make this synchronization. So it could be easier to receive the entire matrix and then move row by row once the matrix has been entirely received.

this is my code:

String stringa= ""; //create a string to store what comes from serial
char c; //create a variable char to store each character from serial
int B [298][6]; //matrix that must be filled with data read from serial
int count=0; //counter that increased if a ';' is found
int conta4=0; //counter to store the length of the string
int conta5=0; //counter that increases if a value is added to B
int conta2=0; //counter that increases if a numeric value is found on the string
int conta3=0; //counter that increases if a value is added to B 
            //(it is set to 0 if a row of B has been entirely filled)
int num; //variable that stores the value of x(char array) into integer
bool s=false; //to repeat the loop only once
char q=';';
char w=' ';
char y=']';
char x[9];//variable char to store values until ';' ' ' or ']' will be found
#include <AccelStepper.h>
#include <MultiStepper.h>

// Define some steppers and the pins the will use (first pin for the number of wires, 
                                                 // second one for the number of steps,
                                                 // and third one for direction)
AccelStepper stepper1(1,9,8);  
AccelStepper stepper2(1,2,3);
AccelStepper stepper3(1,10,11);
AccelStepper stepper4(1,22,23);
AccelStepper stepper5(1,24,25);
AccelStepper stepper6(1,26,27);

MultiStepper steppers;

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

stepper1.setMaxSpeed(500.0);
Serial.print("stepper1 in posizione:");
Serial.println(stepper1.currentPosition());
   
   
stepper2.setMaxSpeed(500.0);
Serial.print("stepper2 in posizione:");
Serial.println(stepper2.currentPosition());


stepper3.setMaxSpeed(500.0);
Serial.print("stepper3 in posizione:");
Serial.println(stepper3.currentPosition());


stepper4.setMaxSpeed(500.0);
Serial.print("stepper4 in posizione:");
Serial.println(stepper3.currentPosition());


stepper5.setMaxSpeed(500.0);
Serial.print("stepper5 in posizione:");
Serial.println(stepper3.currentPosition());



stepper6.setMaxSpeed(500.0);
Serial.print("stepper6 in posizione:");
Serial.println(stepper3.currentPosition());



steppers.addStepper(stepper1);
steppers.addStepper(stepper2);
steppers.addStepper(stepper3);
steppers.addStepper(stepper4);
steppers.addStepper(stepper5);
steppers.addStepper(stepper6);

delay(3000);

 
}
void loop() {
  if (Serial.available() > 0) { //read from serial

   c = Serial.read(); // read Char
   stringa = stringa + c; // add Char to string
   conta4=conta4+1; //increase counter to store the length of the string
   }
   if(s==false){
if(stringa.charAt(conta4-1)==y){//enter in if only is the string has been acquired
for ( int i=0;i<conta4-1;i++)//go through the i-char of the string
{
   if(stringa.charAt(i)==q) //if ';' is found
   {
       count=count+1; //increase count (go to the following row of the matrix)

   }
   
   if (stringa.charAt(i)!= q && stringa.charAt(i)!= w) //(a number has been found)
   {
     x[conta2]=stringa.charAt(i); //add number to x
     conta2=conta2+1; //increase the counter if a number or a sign has been found
   }
if(stringa.charAt(i)==w || stringa.charAt(i+1)==q|| stringa.charAt(i+1)==y){ //the number 
                                                                           //to be stored in the matix
                                                                           //has been read
num= atoi(x); //convert the char array x into a number
if (conta3==6){ //the row of B has been completed
       conta3=0;
}
   for (int i=0; i<conta2;i++){
   x[i]=' ';//set all the values of char array x to ' ' once x has been converted to integer
   }
   B[count][conta3 % 6]=num; //add num to B
   s=true; //exit from loop once the for cycle is over
   conta2=0; //set to 0 the index of x
  conta3=conta3+1; //increase counter because a number has been added to the matrix B
  conta5=conta5+1;//increase counter because a number has been added to the matrix B
     
   
     }
   }
   if (conta5==1788){ //once B has been completed store each row in a 1-D array and move the robot
long positions [6];
for (int i=0;i<298;i++){
 for (int j=0;j<6;j++){
positions [j]=B[i][j];
}
steppers.moveTo(positions);
steppers.runSpeedToPosition();
}
}
}

     }
   }

The code is working properly: I have used Hyperterminal to send my txt file containing the matrix converted into string and then I have verified if the matrix has been received printing with Serial.println() all the values of the matrix containing the number of steps for each position. My other question is: I can write on serial with Matlab using a simple function but how can I verify if I received all my values if I can't print on the serial because it's occupied? I know Arduino DUE has three serials but how can i use them?

The problem is to synchronize the time in which a row is sent on serial and the movement of the robot itself

Time has little or nothing to do with it. Have the Arduino signal Matlab that it is ready to receive a new row of data when it can deal with it.

This could be matlab code:

s = serial('COM1');
fopen(s);
for i=1:length(matrix)
x=matrix(i,:); %single row of the matrix
fprintf(s,'%s',x) %write single row of the matrix as a string of char
end
fclose(s)

I could also add '<' and '>' as string starting and terminator, as you suggested.

In this way I write a single row of the matrix on the serial through Matlab, then in the Arduino Code the string must be converted into a vector to move the stepper motors with the functions I reported on my Sketch. THERE IS A PROBLEM: how can I know that while matlab is writing on serial a movement has been completed? for example matlab could send one row, the robot starts to move and matlab send another row while the roboti is still completing the movement, perhaps matlab sends another row and in this way I jump a position.

As I have already suggested, have the Arduino signal Matlab that it is ready to receive a new row of data when it can deal with it.

I don't understand well, can you explain how can i do this?

Matlab sends one row of data
Arduino receives one row of data
The robot executes the commands in the data
The Arduino sends a serial message to Matlab to ask for more data
Repeat until all rows have been received and acted upon

Here is a simple code I wrote to send through matlab a 3 x 3 matrix row by row:

Matlab code

A=[123 13 20; 343 49588 11; 4387 -11 989];
s = serial('COM3');
fopen(s);
c='y';
count=1;

if c=='y' %if yes received send a new row
x=A(count,:); %single row of the matrix
fprintf(s,x); %write single row of the matrix as a string of char
count=count+1;
datas=fread(s,'int32') %arduino sends to matlab the received data
c ='n'; %c variable is set to 'n' until 3 seconds are passed 
c=fread(s,'char'); %c is set newly to y(sent by Arduino) to re-enter into if
end

Arduino code

int matlabData[3]={0,0,0}; //row of three elements

void setup(){

  Serial.begin(9600);
}

void loop()
{
  if(Serial.available()>0) // store the MATLAB data into the array
  {
    for (int i=0; i<3; i++)
    {
      matlabData[i]=Serial.read();// read data
    }
  }
    delay(1000);
      for (int i=0; i<3;i++)
      {
      Serial.print(matlabData[i]); //send data back to matlab, and store into the matlab variable
      }
      delay(3000); //wait three seconds (simulation of robot movement)
      Serial.print('y'); //yes means the movement has been completed and send the value to matlab
      
    }
  if(Serial.available()>0) // store the MATLAB data into the array
  {
    for (int i=0; i<3; i++)
    {
      matlabData[i]=Serial.read();// read data
    }
  }

Summary : make sure that at least one byte of data is available. Read three bytes even if only one is available

Query : what happened to the other 3 rows ?

Comment : Serial.read() reads a byte up to 255 in value but some of the values in Matlab are greater than 255 or negative. Will that work ?

So have I to convert the numeric value into a char and then reconvert it into integer using atoi() function?

So have I to convert the numeric value into a char

No. You have to convert the value to a string (a NULL terminated ARRAY of chars).