Go Down

Topic: simple program to run on matlab to control servo motor,using serial port. (Read 5918 times) previous topic - next topic

PaulS

Code: [Select]
        fprintf(s, '%i',nr);       
        fprintf(s, '%i',position); 

This converts the values to strings.

Code: [Select]
  if( Serial.available() >=2)
  {

   
    int nr = Serial.read();          // read in servo number
    int position = Serial.read();    // read in servo position

This assumes that the data is binary.

One of them is not compatible with the other. Your choice as to which you change.

brainybrown86

Thank your for very much your reply. Unfortunately I am not completeley sure what you mean or whether your are right.
Regarding the Matlab code:

Quote

fprintf(s, '%i',nr);       
fprintf(s, '%i',position); 


I thought, that my code produces integers, because the first parameter (s) just specifies the serial port, whereas the second parameter specifies the format ('%i')? See the doc of the fprintf command.  And this is also what seems happen, if you for instance just type

Quote

fprintf('%i',10);       


Quote

fprintf('%i','any string');       



into your console, thus sending the fprintf command to your console.
What was probably wrong with my code was the third parameter, because here I handed over a string, instead of an integer (and this string was then transformed to a loooong integer). However, this fix does not solve the problem.
The servos are still not responding.

Regarding the Arduino Code, I do not understand how I can specifically say Arduino that it shall read integers from the serial port and whether they will be unsigned or not
Any Ideas, how I have to change the code in either Matlab or Arduino?

Here my slightly adapted codes that I have at the moment:
Matlab
Quote

clear all
close all
delete(instrfind('Type', 'serial')); % Assure that no serial port is open anymore

s = serial('com5');                 % Create new serial port object.
%set(s,'DataBits',8);               % ???
%set(s,'StopBits',1);               % ???
set(s,'BaudRate',9600);             % Use same baudrate specified in Arduino
%set(s,'Parity','none');            % ???
fopen(s);                           % Open Serial port

nr = 2;                           % servo to be moved           
position = 40;                    % degree

% Attach motors and bring them to default position
fprintf(s, '%i',1)        % sent servo number (in integer format)
fprintf(s, '%i',position)  % sent servo position (in integer format)

%   Try to move servo 2 every second
for i=1:100

    if rem(i,2)                     % if equal
        position = 80;
        disp(i)
        fprintf(s, '%i',nr)        % sent servo number (in integer format)
        fprintf(s, '%i',position)  % sent servo position (in integer format)
    else                           % if unequal
        disp(i)
        position = 40;
        fprintf(s, '%i',nr)       
        fprintf(s, '%i',position) 
    end
    pause(1);                       % wait one second
end   


Arduino
Quote

#include <Servo.h>


Servo servo2;
Servo servo4;
Servo servo6;
Servo servo8;
Servo servo10;



void setup()
{
  //Serial.begin(115200); // communicate fast !
  Serial.begin(9600);
  //servo2.attach(2);
  //servo4.attach(4);
  //servo6.attach(6);
  //servo8.attach(8);
  //servo10.attach(10);
}



void loop()
{
  //servo2.write(60); % move servos ones to default position
  //servo4.write(60);
  //servo6.write(60);
  //servo8.write(60);
  //servo10.write(60); // This works!!!
 
 
  if( Serial.available() >=2)
  {

   
    int nr = Serial.read();          // read in servo number
    int pos = Serial.read();    // read in servo position
    switch(nr)
    {
    case 2:
      servo2.write(pos);
      break;
    case 4:
      servo4.write(pos);
      break;
    case 6:
      servo6.write(pos);
    case 8:
      servo8.write(pos);
    case 10:
      servo10.write(pos);
      break;
    case 0:             // sent 0 plus another integer to detach servos and spare energy
      servo2.detach();
      servo4.detach();
      servo6.detach();
      servo8.detach();
      servo10.detach();
      break;
    case 1:            // send 1 plus plus default position, in order to attach the servos and bring them to default position
      servo2.attach(2);
      servo4.attach(4);
      servo6.attach(6);
      servo8.attach(8);
      servo10.attach(10);
      servo2.write(pos);
      servo4.write(pos);
      servo6.write(pos);
      servo8.write(pos);
      servo10.write(pos);
      break; 
    default:
      servo2.write(60);
      servo4.write(60);
      servo6.write(60);  // default position
      servo8.write(60);
      servo10.write(60);
      break;
    }
  }
  //sleep(100); // give the servo's some time --> Throws an "'sleep' was not declared in this scope"-error!!!
}


Again, I would be again very thankful for any help.
Cheers


brainybrown86

Hello,
unfortunately, I'm still struggling with my real-time control of five servos via Matlab.
I have now a code, that does move the servos in the expected manner and if I type in the required values into the Arduino serial monitor, it outputs the values in the right way. Thus, Matlab and Arduino at least seem to speak the same language now.

However my code only works, if I add up a lot of breaks into the Matlab code.

Here is the Matlab code:
Quote

% Commands:
% 140 --> attach all servos and bring them to position 40
% 000 --> detach all servos
% xy --> move servo x to y (y must be an integer between 0 and 180)

clear all
close all
delete(instrfind('Type', 'serial')); % Assure that no serial port is open anymore

s = serial('com5');                 % Create new serial port object.
%set(s,'DataBits',8);               % ???
%set(s,'StopBits',1);               % ???
%set(s,'Parity','none');            % ???
set(s,'BaudRate',9600);             % Use same baudrate specified in Arduino
fopen(s);                           % Open Serial port


% Attach motors and bring them to default position
pause(2);                       % give servo some time to initialize
fprintf(s, '%s\n','141')        % say arduino to attach the servos and bring them 41 degree.
pause(2);

%   Try to move servos
for i=1:100

    if rem(i,2)                   % if i is an equal number
        disp(i)       
        fprintf(s, '%s\n','240')  % sent servo number, 40 degree servo position (in string format, ended by an \n)
        pause(0.5)
        fprintf(s, '%s\n','440')       
        pause(0.5)
        fprintf(s, '%s\n','640')       
        pause(0.5)
        fprintf(s, '%s\n','840')       
        pause(0.5)
        fprintf(s, '%s\n','940')       
       
    else                           % if i is an unequal number
        disp(i)       
       
        fprintf(s, '%s\n','2100')  % sent servo number, 100 degree servo position     
        pause(0.5)
        fprintf(s, '%s\n','4100')       
        pause(0.5)
        fprintf(s, '%s\n','6100')       
        pause(0.5)
        fprintf(s, '%s\n','8100')       
        pause(0.5)
        fprintf(s, '%s\n','9100')         
        pause(0.5)
 
    end
    pause(1)
end   





Here is the Arduino code:
Quote

// Responds to the following commands:
// 140 --> attach all servos and bring them to position 40
// 000 --> detach all servos
// xy --> move servo x (can be either 2,4,6,8,9 ) to y (y must be an integer between 0 and 180)


#include <Servo.h>


Servo servo2;
Servo servo4;
Servo servo6;
Servo servo8;
Servo servo9;

String posString = "";

void setup()
{
  //Serial.begin(115200); // communicate fast !
  Serial.begin(9600);
}



void loop()
{
 
 
  if( Serial.available()>=4)  // >=4 because the \n character also has to be counted
  {


     int nr = Serial.read()- '0'; //
     Serial.println("Servo");
     Serial.println(nr);
     delay(2);   

    posString = "";
    while (Serial.available() > 0)     {
      //Serial.println("drinnen");
      char tmp = Serial.read();
      if (tmp == '\n')  {       
        Serial.println("new line");       
        break;     
      }
      else             
      {
        posString += tmp;
        Serial.println("Position");
        Serial.println(posString);     
      }
    }
   
    int pos = posString.toInt();
     
   

    switch(nr)
    {
    case 2:
      servo2.write(pos);
      break;
    case 4:
      servo4.write(pos);
      break;
    case 6:
      servo6.write(pos);
      break;
    case 8:
      servo8.write(pos);
      break;
    case 9:
      servo9.write(pos);
      break;
     
     
    // Just for attaching and detaching servos out of Matlab: 
    case 0:             // to detach servos: sent 000 plus another integer to detach servos and spare energy
      servo2.detach();
      servo4.detach();
      servo6.detach();
      servo8.detach();
      servo9.detach();
      delay(1000);
      break;
    case 1:            // to attach servos: send 1xx, in order to attach the servos and bring them to xx position
      servo2.attach(2);
      servo4.attach(4);
      servo6.attach(6);
      servo8.attach(8);
      servo9.attach(9);
      delay(1000);
      servo2.write(pos);
      servo4.write(pos);
      servo6.write(pos);
      servo8.write(pos);
      servo9.write(pos);
      delay(1000);     
      break; 
    }
  }
}


As I said, if I remove the pause statements in Matlab, either Matlab crashes or Arduino.
Does anybody have an idea how I can improve my code so that I can remove the pause statements in Matlab (or reduce them to a minimum) and get it running more stable and in real-time. Do I need some pause statements in the Arduino code?
Or do I have to use a different servo control functions?

Again I would be very very thankful, if someone could help me out.


Go Up