Shop OBEX P1 Docs P2 Docs Learn Events
Servo Controller HELP! — Parallax Forums

Servo Controller HELP!

CyrusCyrus Posts: 7
edited 2007-07-17 10:50 in General Discussion
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

I will be using a single standard fuaba servo.

Cheers,

Cyrus

Comments

  • PARPAR Posts: 285
    edited 2007-03-31 04:33
    Cyrus said...
    ...
    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.
    ...
    I will be using a single standard fuaba servo.
    ...
    You need to create the equivalent matlab outputs to the ones found in

    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
  • CyrusCyrus Posts: 7
    edited 2007-04-03 06:26
    I got my PSC in, but I cant communicate with it using matlab. Please help!

    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!?
  • CyrusCyrus Posts: 7
    edited 2007-04-04 21:55
    OK, I got it working in HYPERTERMINAL,

    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?
  • Mike GreenMike Green Posts: 23,101
    edited 2007-04-04 22:11
    You can't use ".LOWBYTE" or ".HIGHBYTE" in the actual text of the command. For that matter, the only thing you can have literally is the "!SC". In the case of the bytes that follow the "!SC" or any of the other commands, you need to have the actual 8-bit byte value sent. What you need to send is a sequence of 8 bytes. The first is the numeric value of "!", the second is the numeric value of "S", the third is the numeric value of "C", then two bytes with a numeric value of zero. If you want a servo position of 1500, the next byte is the numeric value of the lower 8 bits of 1500. The byte after that is the numeric value of the upper 8 bits of 1500. Lastly is the number 13 (or $0D or the return character).

    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.
  • CyrusCyrus Posts: 7
    edited 2007-04-05 03:07
    Mike Green said...
    You can't use ".LOWBYTE" or ".HIGHBYTE" in the actual text of the command. For that matter, the only thing you can have literally is the "!SC". In the case of the bytes that follow the "!SC" or any of the other commands, you need to have the actual 8-bit byte value sent. What you need to send is a sequence of 8 bytes. The first is the numeric value of "!", the second is the numeric value of "S", the third is the numeric value of "C", then two bytes with a numeric value of zero. If you want a servo position of 1500, the next byte is the numeric value of the lower 8 bits of 1500. The byte after that is the numeric value of the upper 8 bits of 1500. Lastly is the number 13 (or $0D or the return character).

    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.
    Ok, so I need to send a series of 8-bits at a time.

    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
  • Mike GreenMike Green Posts: 23,101
    edited 2007-04-05 03:13
    Assuming that MATLAB uses C conventions
    fprintf(ser,"!SC%c%c%c%c%c",0,0,mod(x,256),fix(x/16),13)
    


    This might work, I'm not sure, but it'd be close.
  • CyrusCyrus Posts: 7
    edited 2007-04-05 03:17
    Ill give your advice a shot Mike,

    BTW I edited my post above after you posted. And a BIG THANKS for taking time out to help me! Your a life saver!
  • CyrusCyrus Posts: 7
    edited 2007-04-05 03:37
    I tried it but it did not work.

    What does the 'mod' and 'fix' subroutines do?
  • CyrusCyrus Posts: 7
    edited 2007-04-07 07:04
    im using your commands but nothings happening, any thoughts mike?

    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
  • Mike GreenMike Green Posts: 23,101
    edited 2007-04-07 14:39
    1) sprintf is not the same as fprintf. A zero byte will terminate a string and you need to transmit zero bytes. fprintf should do this properly.

    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.
  • GuzzmanGuzzman Posts: 1
    edited 2007-07-17 10:50
    Hi Cyrus,

    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 !
Sign In or Register to comment.