Servo Controller HELP!
Hi guys,
I am doing a project for school and I need to get a servo to interface in matlab, namely simulink. I want to be able to command the servo within my PID loop.
I just bought this http://www.parallax.com/detail.asp?product_id=28823·which hooks up to the USB. I know I have to open the com port for this device in matlab, but im not exactly sure what else has to be done to get it to work.
Can someone help me out, PLEASE?![freaked.gif](http://forums.parallax.com/images/smilies/freaked.gif)
I will be using a single standard fuaba servo.
Cheers,
Cyrus
I am doing a project for school and I need to get a servo to interface in matlab, namely simulink. I want to be able to command the servo within my PID loop.
I just bought this http://www.parallax.com/detail.asp?product_id=28823·which hooks up to the USB. I know I have to open the com port for this device in matlab, but im not exactly sure what else has to be done to get it to work.
Can someone help me out, PLEASE?
![freaked.gif](http://forums.parallax.com/images/smilies/freaked.gif)
I will be using a single standard fuaba servo.
Cheers,
Cyrus
Comments
http://www.parallax.com/dl/docs/prod/motors/ServoControllerManualRevBv2_4.pdf
(assuming that you are connecting the servo directly to the matlab system's hardware/software).
This is the documentation for the·serial port version of the Parallax Servo Controller, but it is the one with a description of the commands you need to know about (the outputs you need to have the matlab send to the PSC). The "Position" command is the only one that may be a bit tricky to formulate.
PAR
I can get it to work using the user interface PCI software though.
Here is what I assumed.
Baud 2400
no parity
two stop bits
eight data bits
terminator 'CR'
COM4
But when I try to open it, I dont think its connecting.
clear
clc
% opens the COM1 serial port and sends a series of commands to a servo
ser = serial('COM4');
set(ser, 'BaudRate', 2400,'StopBits',2);
set(ser,'Terminator','CR','Parity','none');
set(ser, 'DataBits', 8); % set data bits to 8
set(ser, 'StopBits', 2);
fopen(ser); % open the serial port connection
fprintf(ser,'!SCVER?$0D');
PLEASE HELP!?
CAN someone help me figure out how to send it servo commands?
I gave it the command
!SC 0 0 500.LOWBYTE 2500.HIGHBYTE, $OD
but nothing happened. Where do you command the servo position pulsewidth?
The PBasic compiler in compiling a SEROUT statement for a Stamp processor, will do this process for you if you put "!SC",0,0,x.lowbyte,y.highbyte,$0D in the square brackets of a SEROUT statement after you set the variable x to 1500.
To do the equivalent in MATLAB, you'll have to study the manual on serial transmission and formatting. I'm afraid I don't know MATLAB.
Here is a quick example I will try in matlab to see if it works or not. I can, for instance, give it the input command !SCVER?$0D
That means that I should give it, in binary:
100001-1010011-1000011-1010110-1000101-1010010-0111111-0100101-0110000-1000100
Where the - is for clarity and is equivalent to !SCVER?$0D
Is this what you mean?
Post Edited (Cyrus) : 4/5/2007 5:52:30 PM GMT
This might work, I'm not sure, but it'd be close.
BTW I edited my post above after you posted. And a BIG THANKS for taking time out to help me! Your a life saver!
What does the 'mod' and 'fix' subroutines do?
I am able to ask it the version in matlab....but I cant send it commands.
fprintf(ser,'!SCVER?'); does work
output=fscanf(ser,'%s',ser.BytesAvailable) <-reads the output from the board
But this yields no results...
string=sprintf('!SC%c%c%c%c',0,0,mod(x,256),fix(x/16))
·I assume that your x inside of the mod and fix commands is where I should put in my Pulse value x->1250, for example.
According to matlab:
" MOD··· Modulus after division.
··· MOD(x,y) is x - n.*y where n = floor(x./y) if y ~= 0.· If y is not an
··· integer and the quotient x./y is within roundoff error of an integer,
··· then n is that integer.· By convention, MOD(x,0) is x.· The input
··· x and y must be real arrays of the same size, or real scalars.
··· The statement "x and y are congruent mod m" means mod(x,m) == mod(y,m).
··· MOD(x,y) has the same sign as y while REM(x,y) has the same sign as x.
··· MOD(x,y) and REM(x,y) are equal if x and y have the same sign, but
··· differ by y if x and y have different signs."
"FIX··· Round towards zero.
··· FIX(X) rounds the elements of X to the nearest integers
··· towards zero."
Is Matlabs mod and fix doing the same things as your mod and fix? If not, this might be the problem!
Post Edited (Cyrus) : 4/7/2007 7:10:30 AM GMT
2) FIX throws away the fractional portion of a number and that's what I want to do after dividing by 256. I just want the quotient. The 16 should also be 256 ... I thought I had corrected that.
3) MOD should give the remainder after division (in this case by 256). Essentially, I'm trying to get the lower 8 bits and upper 8 bits of the value for the servo pulse width.
Again, I don't know MATLAB and this isn't a MATLAB support forum. You should get help from your instructor or some kind of MATLAB forum since this is a MATLAB programming problem, not something with the servo controller.
I'm using the serial version PSC on my COM1 through Matlab. The problems with matlab are device and string handling.
If the COM port isn't set up properly it won't work. I also found out that the fprintf() has problems with the '!', so I use
the sprintf() to generate the string and fwrite() to transmit it.Here is some code I use with our students for setting up the
COM port :
% Delete all instances that are connected to the COM ports
a = instrfind;
delete(a);
clear;
%Connect to the PSC on COM1
ComPort = serial('COM1');
fclose(ComPort);
% setup parameters
set(ComPort,'BaudRate',2400,'Databits',8,'Parity','none', 'StopBits',2)
fopen(ComPort);
% create string for the PSC, terminate with $0D
str = sprintf('!SCVER?\r');
% write to PSC
fwrite(ComPort,str);
% read reply string from PCS
str = fscanf(ComPort,'%c',3);
disp(str);
This displays 1.4 in my Matlab window.
To position your servo you should determine the hi and lo byte of the position, in my case servoPos:
servoPos = 300;
chan = 0;
sramp = 0;
% calculate lo and hi byte values
hiByte = floor(servoPos/256);
loByte = servoPos - hiByte * 256;
% display servoPos value
str = sprintf('servoPos = %6d Lo = %3d Hi = %3d', servoPos, loByte, hiByte);
disp(str);
% create string for the PSC, terminate with $0D
str = sprintf('!SC%c%c%c%c\r',chan,sramp,loByte,hiByte);
% write to PSC
fwrite(ComPort,str);
Good luck !