Shop OBEX P1 Docs P2 Docs Learn Events
trying to understand what I need to do with using values from received data — Parallax Forums

trying to understand what I need to do with using values from received data

charleyshfcharleyshf Posts: 165
edited 2011-02-23 17:52 in Propeller 1
Hoping to get some direction on what I am doing wrong..

I have been working with a Robo Claw motor controller hooked up to my prop since last week and I am either missing the ball here, or just not going about this the right way.

The end result I am looking for is to have the prop control my custom robot along with keeping track of my wheel encoders which the Robo Claw does, I just have to read the values in from the Robo Claw and use them "correctly". I probably could of used the quadencoders.spin file from the OBEX, but I wanted to have the Robo Claw do all the hard work so my prop has one less thing to deal with.
The code I am working on now will display all 6 bytes in the PST like this:

0,0,0,16,10000100,36
0,0,3,122,10000000,13
0,0,7,44,10000000,67
0,0,13,51,10000000,80
0,0,18,137,10000000,43

The first problem I have is the first 4 bytes will count up to 255 then the number to the left will go up by one, so if byte 4 goes over 255, byte 3 goes up by one, and byte 4 starts over at 0,so clearly I am not doing this correctly.

Next, if the encoder goes in reverse, and all 4 bytes are at 0, all 4 bytes go to 255 which is not what I expected to see, I would like to see "-" and then the count

I am VERY lost on byte 5, it contains 8 bits and it looks like it's displaying in PST backwards, how would I reverse that so PST show's it correctly, maybe more important though I am only interested in certain bits, maybe just the direction bit (Bit1) how would I just display that bit?

From the manual on the Robo Claw:

Byte 1,2,3 and 4 make up a long variable which is received MSB first and represents the current count which can be any value from 0 - 4,294,967,295. Each pulse from the quadrature encoder will increment or decrement the counter depending on the direction of rotation.

Byte 5 is the status byte for M1 decoder. It tracks counter under
flow, direction, overflow and if the encoder is operational. The byte value represents:
Bit0 - Counter Underflow (1= Underflow Occurred, Clear After Reading)
Bit1 - Direction (0 = Forward, 1 = Backwards)
Bit2 - Counter Overflow (1= Underfl ow Occurred, Clear After Reading)
Bit3 - Reserved
Bit4 - Reserved
Bit5 - Reserved
Bit6 - Reserved

Bit7 - Encoder OK (1 = OK, 0 = FAIL)

Byte 6 is the CRC checksum. It is calculated the same way as sending a command. It can be used to validate the resulting data. The following example will read M1 counter register, status byte and CRC value with Robo Claw address set to 128.

''Baudrate to RoboClaw is at 2400
''PINOUTS:
''P12 - Tx to RoboClaw Rx with 2.2k resistor
''P13 - Rx to RoboClaw Tx with 2.2k resistor
 
CON
  _clkmode = xtal1 + pll16x
  _xinfreq = 5_000_000
  MS_001 = 80_000_000 / 1_000                           ' To calculate when using the pause method in MS If you want to wait 0.1 seconds, 
                                                        ' you use pause(100). Want to wait 2.5 seconds, use pause(2_500).
  RX_Pin = 13
  TX_Pin = 12                                                      
VAR
long Lenc[6]
   
OBJ
    SERIAL : "Extended_FDSerial_128ByteBuffers"
    PST : "Parallax Serial Terminal"
 

PUB Main
    
      repeat
       showcountl
PUB showcountl | j
    PST.START (2400)                       ' Starts PST
    PAUSE(1_000)          
    SERIAL.START(RX_Pin, TX_Pin, 0, 2400)     ' Starts FullDuplexSerial in another cog
    Pause (1_000)
    serial.RXflush                    
    serial.tx(128)                   ' this resets the encoder count to zero for both encoders
    Pause(2)
    serial.tx(18)                    ' same 
    Pause(2)
    serial.tx(148 & %01111111)       ' same
    pause (1_000)
  repeat
        repeat j from 0 to 5            'gets first 4 bytes which is encoder data
         serial.tx(128)
         serial.tx(16)
         Lenc[j] := Serial.rx
         Lenc[6] := 0
     PST.Dec(Lenc[0])
     PST.Str(string(","))
     PST.Dec(Lenc[1])
     PST.Str(String(","))
     PST.Dec(Lenc[2])
     PST.Str(String(","))
     PST.Dec(Lenc[3])
     PST.Str(String(","))
     PST.Bin(Lenc[4],8)
     PST.Str(String(","))
     PST.Dec(Lenc[5])
     PST.Newline
     Pause (500)
     serial.RxFlush
 

PUB pause(ms) | t
  t := cnt
  repeat ms
    waitcnt(t += MS_001)



I would really appreciate any ideas on this, thank you.

Comments

  • John AbshierJohn Abshier Posts: 1,116
    edited 2011-02-22 10:29
    I think what you want is to combine the 4 bytes into a long. Off the top of my head and not tested

    encoderValue := Lenc[0] << 24 | Lenc[1] << 16 | Lenc[2] << 8 | Lenc[3]
    PST.Dec(encoderValue)

    John Abshier
  • MagIO2MagIO2 Posts: 2,243
    edited 2011-02-22 11:19
    Everything is fine, you only have to understand how to read the things.

    255,255,255,255 is one long which belongs together. If you convert it to hexadecimal things might get clearer because there you can simply concatenate the strings to convert it to a long.
    $FF,$FF,$FF,$FF
    Now make one long out of it: $FF_FF_FF_FF.

    A long as such can have different meanings. For example you can store a 4 character string in one long. Or it can be an unsigned number with a range from 0 to 2^32 -1 which is something around 4 billion. Or it can be a signed number. Looking at the hexadecimal representation of signed number is also interesting:
    $00_00_00_00 = 0
    the max. positive number is:
    $7F_FF_FF_FF which is something around 2 billion (= 2^31 - 1)
    The negative numbers start from
    $FF_FF_FF_FF = -1
    The smallest negative number is:
    $80_00_00_00 which is something around -2 billion ( = -2^31 )

    So, if you get 4 times 255 it means that you received a -1.

    Bitfields have the same rules as usual numbers. The most significant digit is on the left. And that's what your terminal shows you!
    Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0

    If you are only interested in one bit you can extract it with boolean operations.
    If you want to keep the value of that bit:
    theBit := Lenc[ 4 ] & |< 1
    1 is simply the number of the bit. But I think you want something like:
    theBit := ( Lenc[ 4 ]>>1 ) & 1
    Here 1 is as well the bit number you're interested in. You make the bit of interest the least significant bit by shifting all bits of the received byte to the right one time. The & 1 then will set all other bits to zero and only keep the value of bit 0 (which now contains the value of former bit 1).

    Then you can replace the PST.BIN( Lenc[ 4 ], 8 ) by a
    PST.BIN( theBit, 1 ) to display only that one bit

    or

    PST.BIN( Lenc[ 4 ]>>1, 1 )
    if you only want to display the bit and you don't need the result in the code following.
  • charleyshfcharleyshf Posts: 165
    edited 2011-02-22 12:58
    Thank you for the QUICK responces!!

    @John, your code worked great!
    @MagIO2, thank you for explaining what I was missing, I have to admit it's been a while since I was programming in spin and feel like I just went back to the beginning of it all, it's taken me a few reads to get a grip around it, thank you again.
  • charleyshfcharleyshf Posts: 165
    edited 2011-02-23 09:32
    Well I hate to admit it, but I am stuck, again.... This time I am trying to send data from my prop to the robo claw controller, I have something that works, but I can't imagine typing all these lines everytime I want to send data to the robo claw. What I want to do is take:
    Serial.Tx (2)
    Serial.Tx (0)
    Serial.Tx (0)
    Serial.tx (0)
    Serial.tx (2)
    Serial.tx (0)
    Serial.tx (0)
    Serial.tx (0)
    Serial.tx (169 & %01111111)
    

    and turn it into something like this:
    long QspeedM1, QspeedM2
     
    PUB MixedMove | y
      QspeedM1 := 2000    'motor 1 speed
      QspeedM2 := 2000    'motor 2 speed
      Serial.RXflush
      Serial.tx(128)
      Serial.tx(37)
            repeat y from 0 to 3
              Serial.tx (QspeedM1[y])
    '' QspeedM1[4] := 0
        repeat y from 0 to 3
           Serial.tx (QspeedM2[y])
    ''QspeedM2[4] := 0
    Serial.tx(169 & %01111111)
    

    This does not work and I am doing something wrong here, I also sent this to the PST, and I do not see anything that would resemble 2000. Any ideas where I went wrong? Thanks in advance
  • MagIO2MagIO2 Posts: 2,243
    edited 2011-02-23 10:20
    Qspeed is a long, so if you access it via index the spin interpreter will also treat it as an array of longs.

    You have to use the array named byte which is buildin in SPIN:
    byte[ @QspeedM1 ][0]
    byte[ @QspeedM1 ][1] ....
    So, in your code you'd call tx with byte[ @QspeedM1 ][y]

    PS:
    Currently I'm not sure of the order of the bytes of a long. Maybe you have to count y down from 3 to 0 to send it in the right order.
  • charleyshfcharleyshf Posts: 165
    edited 2011-02-23 10:57
    MagIO2 wrote: »
    Qspeed is a long, so if you access it via index the spin interpreter will also treat it as an array of longs.

    You have to use the array named byte which is buildin in SPIN:
    byte[ @QspeedM1 ][0]
    byte[ @QspeedM1 ][1] ....
    So, in your code you'd call tx with byte[ @QspeedM1 ][y]

    PS:
    Currently I'm not sure of the order of the bytes of a long. Maybe you have to count y down from 3 to 0 to send it in the right order.

    Thank you for getting back to me so quick!!

    I tried the following code:
    PUB MixedMove | y  
        QspeedM1 := 2000
        QspeedM2 := 2000
        Serial.RXflush
        Serial.tx(128)
        Pause(2)
        Serial.tx(37)
        Pause(2)
          repeat y from 3 to 0
             Serial.tx (byte [ @QspeedM1 ][y] )
             PST.Dec (byte [ @QspeedM1 ][y])
             PST.NewLine    
     
       Serial.tx(2)
       Serial.tx(0)
       Serial.tx(0)
       Serial.tx(0)
    ''        pause(2)
    ''        QspeedM2[4] := 0
       Serial.tx(169 & %01111111)
    return
    

    I also tried 0 to 3 on the repeat line, in PST I get back 007208 when I use 3 to 0 and I get 208700
    when I use 0 to 3. Maybe I have the serial.tx line wrong??

    Thanks again for your help
  • JasonDorieJasonDorie Posts: 1,930
    edited 2011-02-23 11:19
    Try using PST.Hex() instead of PST.Dec() - Printing numbers in decimal makes it VERY hard to see where one ends and the next one starts, unless you delimit them with spaces or something. Using Hex lets you specify the number of digits (use 2 for a byte) and then the numbers will be easier to get into the right order.

    2000 in decimal is $7D0 in hex, or $00_00_07_D0 if you were to write it as four delimited byte values. What you're seeing in your output is 0, 0, 7, 208 (007208) or 208, 7, 0, 0 (208700). 208 is the decimal value of hex $D0.

    So, given that when you read the numbers from the controller you're getting them high-byte to low-byte, you want to use the 0 to 3 loop, not the 3 to 0 loop.

    If you're not comfortable reading hex numbers, you could just put a delimiter in loop, like this:
    repeat y from 0 to 3
             Serial.tx (byte [ @QspeedM1 ][y] )
             PST.Dec (byte [ @QspeedM1 ][y])
             PST.tx( 32 )  'print a space, or use 44 for a comma
             PST.NewLine
    

    And one last note - Spin doesn't do any optimization, so if you want to squeeze the most speed out of your code, and save a little memory, use the CONSTANT keyword where possible, like this:

    Serial.tx(  constant(169 & %01111111)  )
    

    That tells Spin that the expression is constant, so it computes the value 41 at compile time, instead of doing it at runtime in your code.
  • charleyshfcharleyshf Posts: 165
    edited 2011-02-23 11:20
    Something else, I just changed QspeedM1 from 2000 to 2, and the result in PST is 2000
  • MagIO2MagIO2 Posts: 2,243
    edited 2011-02-23 11:47
    You say 007208? Sounds good for me! As already stated you don't use a separator and the numbers are hard to distinguish.

    0 * 2^24 + 0 * 2^16 + 7 * 2^8 + 208 = 2000

    You have to understand what you output and hex helps here:

    2000 = $00_00_07_D0

    You have to transmit this as 4 separate bytes to the robo-thing. Sending it as single numbers to PST will first send $00 , then $00, then $07 and then $D0 which is 0 0 7 208 and without separator it reads like 007208 ;o)

    2 = $00_00_00_02

    Send it in the wrong order and you get 2 0 0 0 or 2000 without separator.
  • charleyshfcharleyshf Posts: 165
    edited 2011-02-23 13:45
    Thank you for the responces, honestly I am brain fried at this point, i've been digging in to the prop manual under the bytes section trying to understand what I am missing. The code I have now is:
    PUB MixedMove | y  
        QspeedM1 := 2000
        QspeedM2 := 2000
        Serial.RXflush
        Serial.tx(128)
        Pause(2)
        Serial.tx(37)
        Pause(2)
          repeat y from 3 to 0
             Serial.tx ( byte [ @QspeedM1 ][y] )
             PST.Hex ( byte [ @QspeedM1 ] [y] ,2)         
             PST.char(95)    
     
     
    ''  Serial.Tx(2)
    ''  Serial.Tx(0)
    ''  Serial.Tx(0)
    ''  Serial.tx(0)
    ''  pause(2)
     
     
    ''      repeat i from 0 to 3
       Serial.tx(2)
       Serial.tx(0)
       Serial.tx(0)
       Serial.tx(0)
    ''        pause(2)
    ''        QspeedM2[4] := 0
       Serial.tx(169 & %01111111)
    return
    

    What the robo claw manual says is this:
    [LEFT][SIZE=2][FONT=Verdana][B][SIZE=2][FONT=Verdana]37 - Mix Mode Drive M1 / M2 With Signed Speed[/FONT][/SIZE][/B][/FONT][/SIZE]
    [FONT=Verdana][SIZE=2][FONT=Verdana][SIZE=2]Drive M1 and M2 in the same command using a signed speed value. The sign indicates which direction[/SIZE][/FONT][/SIZE][/FONT]
    [SIZE=2][FONT=Verdana][SIZE=2][FONT=Verdana]the motor will turn. This command is used to drive both motors by quad pulses per second. Different[/FONT][/SIZE][/FONT][/SIZE]
    [SIZE=2][FONT=Verdana][SIZE=2][FONT=Verdana]quadrature encoders will have different rates at which they generate the incoming pulses. The values[/FONT][/SIZE][/FONT][/SIZE][/LEFT]
     
    [SIZE=2][FONT=Verdana][SIZE=2][FONT=Verdana]used will differ from one encoder to another. Once a value is sent the motor will begin to accelerate [/FONT][/SIZE]
    [SIZE=2][FONT=Verdana]as [/FONT][/SIZE][SIZE=2][FONT=Verdana]fast as possible until the rate de[/FONT][/SIZE][/FONT][/SIZE][FONT=Verdana][SIZE=2][FONT=Verdana][SIZE=2]fi[/SIZE][/FONT][/SIZE][/FONT][FONT=Verdana][SIZE=2][FONT=Verdana][SIZE=2]ned is reached. The command syntax:[/SIZE][/FONT][/SIZE][/FONT]
     
    
    [LEFT][FONT=Courier New][SIZE=2][FONT=Courier New][SIZE=2]Sent: [Address, CMD, QspeedM1(4 Bytes), QspeedM2(4 Bytes), CRC][/SIZE][/FONT][/SIZE][/FONT][/LEFT]
    
     
    
    [LEFT][FONT=Verdana][SIZE=2][FONT=Verdana][SIZE=2]4 Bytes (long) are used to express the pulses per second. Quadrature encoders send 4 pulses per tick.[/SIZE][/FONT][/SIZE][/FONT][/LEFT]
    
     
     
     
    
    [LEFT][SIZE=2][FONT=Verdana][SIZE=2][FONT=Verdana]So 1000 ticks would be counted as 4000 pulses.[/FONT][/SIZE][/FONT][/SIZE][/LEFT]
    
    

    I'm wondering about the 4 bytes (long) thing they are talking about.
  • MagIO2MagIO2 Posts: 2,243
    edited 2011-02-23 14:23
    A byte has 8 bits, each bit has a value starting from bit 0 with value 1, to bit 1 with value 2 ... up to bit 7 with value 128. So, with a byte you can have 256 diferent values in the range from 0 = no bit set up to 255 = all bits set.
    These values are not enough for a valid representation of the speed. So you have to take more than one byte. The people who build the robo claw decided to use a long = 4 bytes. In a long you have 32 bits and a value range from 0 to 2^32 - 1. For signed numbers this range is simply divided in 2 parts, one representing the positive numbers (0 to 2^31-1 ) and the other half representing the negative numbers ( -1 to -2^31 ).

    Problem is, that the serial interface is transferring data bytewise. So these longs representing the speeds of M1 and M2 have to be transferred bytewise. There is no way around that.

    The developers also decided to transfer the longs as binary data and not as strings because this is the fastest way to transfer a long. This means that you simply transfer one byte after the other like they are stored in the memory. That's why they mentioned 4 bytes in the description. So, for your number 2000 which is equal to $00_00_07_D0 in hexadecimal writing (in hex two digits are exactly one byte) you have to send $00, then $00, the $07 and then $D0.
    For the PST you did NOT send binary data, because we can not read that. You send the bytes converted to a decimal string or now in your latest version as a hexadecimal string, so that you can read it on the terminal.

    The only question open so far is, what is the expected order of the 4 bytes. Do you have to send most significant byte (MSB) first or least significant byte (LSB) first? Depending on this answer you either have to count y upwards from 0 to 3 or downwards from 3 to 0.

    Serial.tx(2)
    Serial.tx(0)
    Serial.tx(0)
    Serial.tx(0)
    is wrong. It is not 2000! It's either $02_00_00_00 or $00_00_00_02 for the robo claw depending of the way it assembels the bytes back to a long either MSB or LSB.
  • charleyshfcharleyshf Posts: 165
    edited 2011-02-23 15:24
    I don't know if this will help any but they have a code example for a Basic Atom Pro which is:
    [LEFT][SIZE=1][FONT=Courier New][FONT=Arial][SIZE=2]CMD var byte[/SIZE][/FONT][/FONT][/SIZE][SIZE=1][FONT=Courier New]
    [FONT=Arial][SIZE=2]Speed var long[/SIZE][/FONT]
    [FONT=Arial][SIZE=2]Speed2 var long[/SIZE][/FONT]
    [FONT=Arial][SIZE=2]CRC var byte[/SIZE][/FONT]
    [FONT=Arial][SIZE=2]Address con 128[/SIZE][/FONT]
    [FONT=Arial][SIZE=2]ENABLEHSERIAL ;used on AtomPro24 and AtomPro28. AtomPro40 and ARC-32 use EnableHSerial2[/SIZE][/FONT]
    [FONT=Arial][SIZE=2]SetHSerial H38400,H8DATABITS,HNOPARITY,H1STOPBITS[/SIZE][/FONT]
    [FONT=Arial][SIZE=2]Mixed_Forward[/SIZE][/FONT]
    [FONT=Arial][SIZE=2]            CMD=37[/SIZE][/FONT]
    [FONT=Arial][SIZE=2]            Speed=12000[/SIZE][/FONT]
    [FONT=Arial][SIZE=2]            Speed2=12000[/SIZE][/FONT]
    [FONT=Arial][SIZE=2]            CRC = (address + cmd + speed.byte3 + speed.byte2 + speed.byte1 + speed.byte0 + |[/SIZE][/FONT]
    [FONT=Arial][SIZE=2]                                           speed2.byte3 + speed2.byte2 + speed2.byte1 + speed2.byte0)&0x7F[/SIZE][/FONT]
    [FONT=Arial][SIZE=2]             hserout [address,cmd,speed.byte3,speed.byte2,speed.byte1,speed.byte0, |[/SIZE][/FONT]
    [FONT=Arial][SIZE=2]                                          speed2.byte3,speed2.byte2,speed2.byte1,speed2.byte0,crc][/SIZE][/FONT][/LEFT]
    [FONT=Arial][SIZE=2]pause 4000[/SIZE][/FONT]
    [/FONT][/SIZE]
    
  • charleyshfcharleyshf Posts: 165
    edited 2011-02-23 16:28
    Just to make sure, this is the current code I am working on, I tried sending the data MSB and LSB, no luck, unless I have calculated the CRC wrong that's sent in the end. CRC is calculated as address[128] + command[37] + data [169]

    ''Baudrate to RoboClaw is at 9600
    ''PINOUTS:
    ''P4 - Tx to RoboClaw Rx
    ''P5 - Rx to RoboClaw Tx
     
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
     
      MS_001 = 80_000_000 / 1_000                           ' To calculate when using the pause method in MS If you want to wait 0.1 seconds, 
                                                            ' you use pause(100). Want to wait 2.5 seconds, use pause(2_500).
      RX_Pin = 13
      TX_Pin = 12                                                      
    VAR
    byte indatarec[serial#MaxStrLength]
    byte x[3] 
    long QspeedM1, QspeedM2  
     
    OBJ
        SERIAL : "Extended_FDSerial_128ByteBuffers"
        PST : "Parallax Serial Terminal"
     
    PUB MixedMove | y
        PST.START (9600)                       ' Starts PST
        PAUSE(1_000)          
        SERIAL.START(RX_Pin, TX_Pin, 0, 9600)     ' Starts FullDuplexSerial in another cog
        Pause (1_000)  
        QspeedM1 := 2000
        QspeedM2 := 2000
        Serial.RXflush
        Serial.tx(128)
        Pause(2)
        Serial.tx(37)
        Pause(2)
          repeat y from 3 to 0
             Serial.tx ( byte [ @QspeedM1 ][y] )
             PST.Hex ( byte [ @QspeedM1 ] [y] ,2)         
             PST.char(95)    
     
     
    ''  Serial.Tx(2)
    ''  Serial.Tx(0)
    ''  Serial.Tx(0)
    ''  Serial.tx(0)
    ''  pause(2)
     
     
         repeat y from 3 to 0
             Serial.tx ( byte [ @QspeedM2 ][y] )
             PST.Hex ( byte [ @QspeedM2 ] [y] ,2)         
             PST.char(95)    
    ''     Serial.tx(2)
    ''     Serial.tx(0)
    ''     Serial.tx(0)
    ''     Serial.tx(0)
       Serial.tx(169 & %01111111) ' send CRC checksum
    repeat
     
    PUB pause(ms) | t
      t := cnt
      repeat ms
        waitcnt(t += MS_001)
    
  • kuronekokuroneko Posts: 3,623
    edited 2011-02-23 16:44
    From comparison with the BASIC code fragment, your CRC is wrong (83). Try this:
    serial.tx(128)
      Pause(2)
      serial.tx(37)
      Pause(2)
    
      crc := 128 + 37                             ' preset
    
      repeat y from 3 to 0
        serial.tx(QspeedM1.byte[y])
        Pause(2)
        crc += QspeedM1.byte[y]
    
      repeat y from 3 to 0
        serial.tx(QspeedM2.byte[y])
        Pause(2)
        crc += QspeedM2.byte[y]
    
      serial.tx(crc & $7F)
    
  • JasonDorieJasonDorie Posts: 1,930
    edited 2011-02-23 17:31
    The CRC is likely what's wrong. Their code does this:

    CRC = (address + cmd + speed.byte3 + speed.byte2 + speed.byte1 + speed.byte0 +
    speed2.byte3 + speed2.byte2 + speed2.byte1 + speed2.byte0) & 0x7F

    Adding up the individual byte values of a number is a lot different than adding the values as longs. For example, the number 4096 is $1000 in hex, or (16, 0) as two bytes. If you added it to itself, you'd get a value of 8192, $2000 hex, or (32, 0) as two bytes. Taking 8192 and masking off the bottom 7 bits would give you zero, whereas taking the individual bytes of the two values and adding them all up:

    16 + 00 + 16 + 00 = 32

    Short version: You need to add the bytes up. It'd probably be easiest to do it in your send loop. Every time you transmit a byte value, add it to a running sum. When you're done sending everything (except the crc), you take that running sum, mask the bottom 7 bits, and send those too.

    You could create a function like this:
      pub TxWithCrc( value )
        Serial.tx( value )
        RunningSum += value
    
    Then just use that in your code, like this:
        Serial.RXflush
        RunningSum := 0
        TxWithCrc(128)
        Pause(2)
        TxWithCrc(37)
        Pause(2)
          repeat y from 3 to 0
             TxWithCrc( byte [ @QspeedM1 ][y] )
             PST.Hex ( byte [ @QspeedM1 ] [y] ,2)         
             PST.char(95)    
    
      ' ...and so on
    
      Crc := RunningSum & $7F;
      Serial.Tx( Crc )
    
    
  • charleyshfcharleyshf Posts: 165
    edited 2011-02-23 17:41
    @ kuroneko, That's it!!!! It works perfectly!!, Now to try to make sense of it... I see where I went wrong with calculating crc, but you have value.byte, what's the difference with byte.value?
  • kuronekokuroneko Posts: 3,623
    edited 2011-02-23 17:44
    charleyshf wrote: »
    ... but you have value.byte, what's the difference with byte.value?
    Nothing, but you have to admit that value.byte[y] looks infinitely better than byte[@value][y] :)
  • charleyshfcharleyshf Posts: 165
    edited 2011-02-23 17:47
    LOL, NICE!! I've got some serious reading to do..
    kuroneko wrote: »
    Nothing, but you have to admit that value.byte[y] looks infinitely better than byte[@value][y] :)
  • charleyshfcharleyshf Posts: 165
    edited 2011-02-23 17:52
    Thank you!!

    I think that's where I was going wrong before(among other things), treating it like a long.. I have to take some time and get some reading in on this stuff, my only brain cell just lit up, fell out, and hit the floor.....
    now where the hec did I leave the advil....

    Thanks again


    JasonDorie wrote: »
    The CRC is likely what's wrong. Their code does this:

    CRC = (address + cmd + speed.byte3 + speed.byte2 + speed.byte1 + speed.byte0 +
    speed2.byte3 + speed2.byte2 + speed2.byte1 + speed2.byte0) & 0x7F

    Adding up the individual byte values of a number is a lot different than adding the values as longs. For example, the number 4096 is $1000 in hex, or (16, 0) as two bytes. If you added it to itself, you'd get a value of 8192, $2000 hex, or (32, 0) as two bytes. Taking 8192 and masking off the bottom 7 bits would give you zero, whereas taking the individual bytes of the two values and adding them all up:

    16 + 00 + 16 + 00 = 32

    Short version: You need to add the bytes up. It'd probably be easiest to do it in your send loop. Every time you transmit a byte value, add it to a running sum. When you're done sending everything (except the crc), you take that running sum, mask the bottom 7 bits, and send those too.

    You could create a function like this:
      pub TxWithCrc( value )
        Serial.tx( value )
        RunningSum += value
    
    Then just use that in your code, like this:
        Serial.RXflush
        RunningSum := 0
        TxWithCrc(128)
        Pause(2)
        TxWithCrc(37)
        Pause(2)
          repeat y from 3 to 0
             TxWithCrc( byte [ @QspeedM1 ][y] )
             PST.Hex ( byte [ @QspeedM1 ] [y] ,2)         
             PST.char(95)    
     
      ' ...and so on
     
      Crc := RunningSum & $7F;
      Serial.Tx( Crc )
     
    
Sign In or Register to comment.