Go Down

Topic: Serial communication Matlab-Arduino (Read 837 times) previous topic - next topic

m_dal

Hi everyone, I am having the following problem: I calculate a matrix on Matlab and I need to send this matrix to Arduino in order to move my stepper motors. The flow I implemented is the following:
I transform the matrix into a string in Matlab;
I saved the string as a .txt file;
I use Hyperterminal to send the file on the Serial port;
I read the string and I newly transform it into a matrix on the Arduino Sketch.

Everything is working well, but I need some code improvements to reduce its own complexity. Have you got any suggestions?  I know, it's possible to write on the serial port using Matlab but the problem is this one: when I try to print every single value of the Matrix just simply using a for cycle and Serial.print() command I cannot open the serial monitor to verify if the values have been correctly received, because the Serial port has just been opened to begin the communication between Matlab and Arduino. Feel free to ask me any clarifications if you don't understand my problem. Thank you all.

m_dal

Hi everyone, I am having the following problem: I calculate a matrix on Matlab and I need to send this matrix to Arduino in order to move my stepper motors. The flow I implemented is the following:
I transform the matrix into a string in Matlab;
I saved the string as a .txt file;
I use Hyperterminal to send the file on the Serial port;
I read the string and I newly transform it into a matrix on the Arduino Sketch.

Everything is working well, but I need some code improvements to reduce its own complexity. Have you got any suggestions?  I know, it's possible to write on the serial port using Matlab but the problem is this one: when I try to print every single value of the Matrix just simply using a for cycle and Serial.print() command I cannot open the serial monitor to verify if the values have been correctly received, because the Serial port has just been opened to begin the communication between Matlab and Arduino. Feel free to ask me any clarifications if you don't understand my problem. Thank you all.

Metallor

One suggestion for you, post your code. We have no idea how complex your code is if we can't see it. And remember to use code tags.

groundFungus

As you have seen, only one device at a time can be connected to a serial port.  A solution is to set up a software serial port and use a USB to TTL converter to connect the soft serial port to serial monitor for debug while using the hardware serial to talk to Matlab.

UKHeliBob

What pins on the Arduino are you using to receive the serial data ?  Not 0 and 1 perhaps ?
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

m_dal

Ok I understood; there can be a more efficient way to send data to Arduino? I want to to avoid the transformation of the matrix into a string and then re-transforming the string into a matrix. Thank you

PaulS

Quote
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.
The art of getting good answers lies in asking good questions.

m_dal

#7
Feb 18, 2019, 03:16 pm Last Edit: Feb 18, 2019, 03:20 pm by m_dal
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();
}

m_dal

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();
}
}
}
 
      }
    }

UKHeliBob

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
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

PaulS

Quote
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.

Quote
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?
The art of getting good answers lies in asking good questions.

m_dal

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.

PaulS

Quote
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.
The art of getting good answers lies in asking good questions.

Robin2

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)
Code: [Select]
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 </>


Code: [Select]
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
Two or three hours spent thinking and reading documentation solves most programming problems.

m_dal

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.

Go Up