Shop OBEX P1 Docs P2 Docs Learn Events
ACK!!! — Parallax Forums

ACK!!!

WaldoDTDWaldoDTD Posts: 142
edited 2007-06-25 03:41 in General Discussion
Hey, lookin back over my code, how would i revise it to send a number that is double format would i just change the variable types in the assemblecommand() method? Also, how would i set it up so that it sends a start byte, a servo id number, then the double for the position then an end byte? I assume that it already does that with LF and CRs but i am not too sure. Working on something big hopefully i'll have video of it soon for you guys peace! Oh yeah the guy below me with the help of people here, i was able to create something like that check it out!-signol01

Comments

  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-10 07:39
    Yes, you must let assemblecommand comply to your choosen recordformat.
    If you send commands and arguments as readable text then CR and LF can
    serve as record end. If you want to store binary·values in your records
    you·must write an alternative to JideTerm.termIn() that allows to detect
    the record end.
    For double values·in readable decimal text that have the format ddd.fff where there is an integer part ddd
    and a fractional part fff, the class UnsignedIntMath has methods dec2frac() and frac2dec()
    that convert between 10000 based fractions and 65536 based fractions. This of course
    only supports 4 decimals (.0000 to .9999) so is not really double but rather like single precision.
    The question is if you really need doubles, you might be able to do without floating points
    and just use integers.

    I attached a command interpreter for the javelin that shows how to deal with integer arguments.

    regards peter
  • WaldoDTDWaldoDTD Posts: 142
    edited 2006-06-12 23:55
    the reason I ask is I have a program to calculate three joint angles for a crust crawler arm. The only problem is that most of the time they are humungous decimals. Is there any way to limit the number of decimal places that are returned in Java? Also is it possible to have the PSC class for the javelin interpret double variables?
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-13 00:28
    Angles have a limited range of -180 to +180 or 0 to 360.
    You can use fixed point integer math where you can use signed 16bit int
    to represent -180.00 to +180.00 degrees.
    That gives you 0.01 degree resolution.
    The psc class uses int values 0 to 1800 to represent 0.0 to 180.0 degrees
    but is easily changed to support 0.01 degree resolution.
    The simplest way to convert a double to an int
    is (int)(doublevalue*100)
    since doublevalue is in the range -180.00000.... to +180.00000....
    the conversion is in the range -18000 to +18000

    Is 0.01 degree resolution not precise enough?

    regards peter
  • WaldoDTDWaldoDTD Posts: 142
    edited 2006-06-13 21:50
    Actually that is perfect. So lemme get this straight, i would have something like,
    int x = 1;
    double y = 180.567;
    x = x*(y*100);
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-13 21:59
    Yes, but I expect you must explicitly cast to int from double.
    Another remark on precision:
    the psc board uses 2 uSec ticks, so pulsewidth's from 1msec to 2msec
    are represented by values 500 to 1000.
    So the psc board only has 500 values for 180 degrees
    which is about 0.36 degree per tick.
    My psc class angle resolution is 0.1 degree and thus is
    sufficient for the psc board.
    You can use x = (int)((y*100+50)/10)
    for having rounded values in 0.1 resolution.

    regards peter
  • WaldoDTDWaldoDTD Posts: 142
    edited 2006-06-13 22:23
    Ok,
    So if I had the program write to the COM port 0x0A first, then the servo # then the channel number then 0x0D that would work right?
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-13 23:07
    If you want to use termIn() then CR is the record end, LF is just discarded.
    So you could use
    In your pc java program:
    int x; //integer result
    String s = "setpsc "+ x.toString() + "\r\n";
    · sendString(s);

    where setpsc is a command recognized by your javelin program.
    The command setpsc would take its argument, convert it into binary form,
    then call the setpsc function.

    regards peter
    ·
  • WaldoDTDWaldoDTD Posts: 142
    edited 2006-06-14 00:12
    What if I just had the assembleCommand in the previous versions create a buffer of int variables and have it discard LF and CR then go to the first and second positions in the array to find the servo and position number?
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-14 05:33
    That is also possible but then if the binary int value has a byte of value 0x0A (low or high byte) how
    do you distinquish that databyte and a LF? You can say that each message starts with 0x0A and
    has 6 bytes: 0x0A, lowbyte data1, highbyte data1, lowbyte data2, highbyte data2, 0x0D
    but then assembleCommand looks something like

    static int index=0;
    //called frequently from main(), returns true if buf[noparse]/noparse holds command
    static boolean assembleCommand() {
    · if (rx.byteAvailable()) {
    ··· c = rx.receiveByte();
    ····switch (index) {
    ····· case 0: if (c!=0x0A) break; //message starts with 0x0A
    ················ buf[noparse][[/noparse]index++] = c;
    ··············· break;
    ····· case 5: if (c!=0x0D) {index=0; break;} //if 6th byte is not 0x0D then wait for other message
    ················ buf[noparse][[/noparse]index++] = c;
    ················ break;
    ····· default: buf[noparse][[/noparse]index++]· = c; //store received byte
    ··· }
    · }
    ··return index==6; //return true if buf[noparse]/noparse holds 6 bytes
    }

    Note that the index value 6 is now the end of record condition, not the CR character.
    Note that index must be cleared before assembleCommand() is called again, once
    it returned true.

    regards peter

    Post Edited (Peter Verkaik) : 6/14/2006 5:37:50 AM GMT
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-14 05:58
    Remark on the previous post:
    if you want to send 2 messages
    0x0A,0x0A,0x01,0x02,0x03,0x0D, 0x0A,0x02,0x03,0x04,0x05,0x0D
    and the first 0x0A is received as 0x0B due to transmission error,
    then both messages are lost because the 2nd 0x0A is treated as message start
    and the 3rd 0x0A is then supposed to be 0x0D which it then of course isn't.

    That's why with binary messages you better use a marker value that can not be
    a datavalue so the markers are easily distinguished from the datavalues.

    regards peter
  • WaldoDTDWaldoDTD Posts: 142
    edited 2006-06-15 05:29
    Ok, how would i go about making the javelin interpret the low and high bytes of the sent data?
    I am assuming that for the low and high bytes would be written
    int x = 120;
    x = x&0xff; //lowbyte
    x = x>>>8; //highbyte
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-15 05:37
    int x = 120;
    lowbyte = x&0xff; //lowbyte
    highbyte = x>>>8; //highbyte

    Recreating an int from 2 bytes is just as easy
    int y = (highbyte<<8) | (lowbyte&0xFF);

    regards peter
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-15 11:52
    A way to solve both synchronization and conversion to (int/char) array
    is by using hexdigits.
    Start a message with the character '>' (or any other convenient symbol)
    then for each byte in the message send its value as 2 hexdigits '0'-'9','A'-'F'
    End the message with CR and LF
    The above format is usable for debug output (just a string with hexdigits) and can be converted
    on-the-fly into binary values with checking (received bytes must be hexdigits) so a transmission error is
    easily recognized.

    regards peter
  • WaldoDTDWaldoDTD Posts: 142
    edited 2006-06-17 00:05
    What if instead I just use an int array and have the integers represent the servo number/angle position? Or is the char array how everything is sent? (wait that seems to be right because of the hex values i dunno)
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-17 08:08
    You can use whatever datatype you want. But data is transmitted in bytes.
    It is up to your javelin code to assemble these bytes in your preferred
    dataformats. The problem with just integers is synchronization.
    If the javelin is reset during a receive session (perhaps due to power surge)
    then synchronization is lost. That's why you need a way to recognize
    the start and end of a message.

    regards peter
  • WaldoDTDWaldoDTD Posts: 142
    edited 2006-06-18 13:31
    OK, so this way the command would look something like this then
    LF
    >130
    (the 1 is for the servo the 30 is the angle)
    CR
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-18 13:44
    Could be if you have no more than 9 servos otherwise
    you must use two chars to identify the servo (00 to 1x)
    For the angle you may need to specify 3 chars because angle is 000 to 180
    and you then still have no fractional angles

    regards peter
  • WaldoDTDWaldoDTD Posts: 142
    edited 2007-06-24 02:03
    Hey,
    Had to take a break from the project because of college but now I am nearing the completion and I need to rewrite a lot of the protocols that transmit signals to the arm. Ok, so the setup is a computer program sends a set of commands down to the Javelin Stamp. The Javelin stamp then uses the commands to tell the PSC what to do and thus the robot moves. OK, so here is the problem, is it possible to send an array of integers/float point numbers so that it is translated to the PSC? I am thinking probably converting the double to int variables before transmission then sending them down to the PSC individually. There the PSC builds it's own array of numbers. Now, the array will have specific numbers corresponding to specific commands (first number is servo assignment, second is angle, repeat for rest of the axis's of motion). Then the Javelin systematically sends commands to the PSC based off of the command array. My first question is whether or not this is possible in this fashion and two how would I convert double to int with minimal loss of precision? Thanks!-Waldo
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2007-06-24 02:23
    Your approach will work. Since the PSC only uses integer values,
    best to convert your floating point values on the pc to int values,
    then send these int values to the javelin.
    If your pc language is c, you can simply do
    int intvalue = (int)(floatvalue+0.5);
    which will round the float value into the nearest integer.
    You could send the individual fields grouped as a record, with·special
    markers identifying the start/end of a record.

    regards peter
  • WaldoDTDWaldoDTD Posts: 142
    edited 2007-06-24 23:24
    java i assume it is the same right?
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2007-06-25 03:41
    yes.
    regards peter
Sign In or Register to comment.