Shop OBEX P1 Docs P2 Docs Learn Events
Prop to Prop communications with Simple serial library object — Parallax Forums

Prop to Prop communications with Simple serial library object

sjanickisjanicki Posts: 3
edited 2012-06-24 10:37 in Propeller 1
I am fairly new to propeller programing so excuse me if these questions seem simple.

I wrote a program that utilizes the simple serial library object for communicating between two propellers. I can transmit a single byte but am having a difficult time getting multiple different bytes sent. I am sort of at a loss as where to start with sending more then one value serially.

My project is a tethered underwater ROV and I am trying to communicate a large number of different values down to the machine from the surface for motor control, lights, etc. If someone has an object that they think would work well for this then that would work great as well!:smile:

Any help would be greatly appreciated.

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2012-06-08 12:21
    Sending multiple bytes with Simple_Serial is just like sending multiple bytes with anything else ... you essentially send them one byte at a time. If you're sending word or long values, you send them a byte at a time in some consistent order (low order byte first or high order byte first). You may need to have some way to synchronize things so the receiving end "knows" when a group of values is starting. Usually this is done by sending some kind of unique prefix. Almost anything will do that won't accidentally occur in the actual data bytes.

    If you want more specific advice, you're going to have to be more specific in your questions. What do you want to send? What have you been able to do so far? What is or isn't working for you and what happens with the failures? What equipment do you have on the surface. I assume you have a Prop in the ROV, but how is it connected and what else is it doing? Details are important.
  • sjanickisjanicki Posts: 3
    edited 2012-06-08 12:44
    Thanks very much for the prompt response. I apologize for the lack of details in the first message.

    What I want to do: The prop onboard the ROV will be mounted on a PCB that has 8 h-bridge controllers for brushed motor control, a stepper motor amplifier, 4 DAC channels using PWM and a low pass filter. I have prototyped the motor controllers on a bread board and work fairly well. Same with the stepper motor and DAC. No value that I need to transmit is larger than a byte. The prop on the surface is also on a PCB with multiple switches and pushbuttons. It also has input from the MCP-3208 ADC for speed control of the motors from an analog joystick. Both PCBs have not yet been built and therefore can be changed as much as needed to get this to work.

    What I have gotten to work so far: I have transmitted single bytes fairly easily but run into issues when I try to send more then that.

    What I have tried: I have tried sending a known value to let the second prop know when to start storing the values, I then sent the values one at a time. I then tried to display said values on the Parallax serial terminal with results being either blank screen or garbled numbers.

    Thanks so much for your help.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-06-08 13:09
    Here is an example of how I send data to my prop, it is not turn key but should get you started.

    Basically bytes are put into an array when pst.RxCheck sees that there is data waiting

    if the byte ends up being a "13" which is the decimal value of a carriage return, it considers that the "terminating byte" and it then sends the string through my parsing objects.

    Delimiter finder will look for a specific delimiter (for me it was the = sign) so if I said speed=10, it would find the = sign and then parse the prefix and suffix. Variableupdator would then set the global variable of speed to a value of 10.

    If you follow the logic, the code should make general sense. I'm not sure how to apply it to your application and your code.

    1.) check for serial bytes, add them to a character array
    2.) check for carriage return
    3.) after carriage return is found, entire string is now available
    4.) parse through string looking for delimiter, and therefore prefix and suffix
    5.) set the prefix to the value of suffix (has to be global variables)

    Continue
    CON
    
      _byteLimit = 100 
    
    OBJ
      pst    : "Parallax Serial Terminal"                                                                                         
      n      : "Numbers" 
    
    var
    
    ' Arrays
      byte b_delimiter, b_prefix[_byteLimit], b_suffix[_byteLimit]
      byte b_waitingToBeParsed[_byteLimit]
      byte b_byteMoveIndex
    
    ' Variables for main object
      long l_updateRateDenominator, l_sendAllValuesOnce, l_sendAllValues, l_myReceivedByte
      byte b_RxString[_byteLimit]
    
    
    PUB Com
    
           l_myReceivedByte := pst.RxCheck
           b_delimiter := "="
           
          if l_myReceivedByte <> -1
            b_waitingToBeParsed[b_byteMoveIndex++] := l_myReceivedByte
           
    
           
            if l_myReceivedByte == 13
              DelimiterFinder(@b_waitingToBeParsed)
              ByteFill(@b_waitingToBeParsed, 0, strsize(@b_waitingToBeParsed))
              b_byteMoveIndex := 0  
    
    PUB DelimiterFinder(RxStringAddr) : idx | localCount, localIndex, pstDelimiterFinder                                            
    
      ' Initialize variables here
      localIndex := 0
      pstDelimiterFinder := 0
     
      repeat
        ifnot localCount := byte[RxStringAddr][idx++]                ' ifnot c, itterate to the next byte in byte[RxStringAddr] ?
        
          printAt( 1,40, String("No delimiter, aborted"))
          return -1
    
        charAt(1+idx,39,localCount)
        ' pst.dec(localCount)
        ' pst.str(string(pst#NL))  
      until localCount == b_delimiter'localCount == "="
     
      bytemove(@b_prefix, RxStringAddr, --idx)              ' idx points to the character after the delimiter, copy prefix
      b_prefix[idx] := 0                                    ' add terminator  
      RxStringAddr += idx + 1                               ' advance pointer, skip delimiter (+1)                                                 
      bytemove(@b_suffix, RxStringAddr, strsize(RxStringAddr) +1)                   ' copy tail including the existing terminator (+1)
      variableUpdator(@b_prefix, @b_suffix)
    
    
    
    
    PUB variableUpdator(preAddr, sufAddr) | localIndex, pstVariableUpdator, updateValue   ' variableUpdator(@prefix, @suffix)
    
      ' Initialize variables here
      localIndex := 0
      pstVariableUpdator := 0
      
      if strcomp(preAddr, string("updateRateDenominator")) 'strcomp(@prefix, var1)
        
        l_updateRateDenominator := n.FromStr(sufAddr, %000_000_000_0_0_000000_01010) ' n.FromStr(@suffix, %000_000_000_0_0_000000_01010)    ' converts from a string to a dec
        pst.str(l_updateRateDenominator)
        'pst.str(string(pst#NL))
    
      if strcomp(preAddr, string("sendAllValuesOnce")) 'strcomp(@prefix, var1)
        
        l_sendAllValuesOnce := n.FromStr(sufAddr, %000_000_000_0_0_000000_01010) ' n.FromStr(@suffix, %000_000_000_0_0_000000_01010)    ' converts from a string to a dec
        pst.str(l_sendAllValuesOnce)
        'pst.str(string(pst#NL))
    
      if strcomp(preAddr, string("sendAllValues")) 'strcomp(@prefix, var1)
        
        l_sendAllValues := n.FromStr(sufAddr, %000_000_000_0_0_000000_01010) ' n.FromStr(@suffix, %000_000_000_0_0_000000_01010)    ' converts from a string to a dec
        pst.str(l_sendAllValues)
        'pst.str(string(pst#NL))
    
      {if strcomp(preAddr, string("degreeoffset")) 'strcomp(@prefix, var1)
        
        updateValue := n.FromStr(sufAddr, %000_000_000_0_0_000000_01010) ' n.FromStr(@suffix, %000_000_000_0_0_000000_01010)    ' converts from a string to a dec
        genCa.setVariableDegreeDelay(updateValue)
        charAt( 12, 40, " " )
        pst.dec(updateValue)}
    
      if strcomp(preAddr, string("camcorr")) 'strcomp(@prefix, var1)
        
        l_camCorrection := n.FromStr(sufAddr, %000_000_000_0_0_000000_01010) ' n.FromStr(@suffix, %000_000_000_0_0_000000_01010)    ' converts from a string to a dec
        simCam.setCorrection(l_camCorrection)
        'genCa.setVariableDegreeDelay(updateValue)
        'charAt( 12, 40, " " )
        'pst.dec(updateValue)     
    
      if strcomp(preAddr, string("update")) 'strcomp(@prefix, var1)
            
        l_updateTest := n.FromStr(sufAddr, %000_000_000_0_0_000000_01010) ' n.FromStr(@suffix, %000_000_000_0_0_000000_01010)    ' converts from a string to a dec
        'genCa.setVariableDegreeDelay(updateValue)
        'charAt( 12, 40, " " )
        'pst.dec(updateValue)
    
      if strcomp(preAddr, string("update")) 'strcomp(@prefix, var1)
            
        l_updateTest := n.FromStr(sufAddr, %000_000_000_0_0_000000_01010) ' n.FromStr(@suffix, %000_000_000_0_0_000000_01010)    ' converts from a string to a dec
        
    
    
    
    
  • turbosupraturbosupra Posts: 1,088
    edited 2012-06-08 13:33
    Actually it's very turn key, I just added it to another object to test it and it worked perfectly. I believe the only part you'll need to tweak is the bolded parts, using your own global variable name and terminology. You'll need to have one of those groups of lines for each variable you want to be "updatable"

    If you have problems, report back and I'll try and get it working for you. I remember this took me a long time to figure out and develop when I was in your shoes and had it not been for the patience of a couple of forum members (Duane Degn was one of them IIRC) I would have never gotten this to work.


    if strcomp(preAddr, string("[b]whatyoutypeintothepsttopbar[/b]")) 'strcomp(@prefix, var1)
        
       [b] l_nameofglobalvariabletoupdatevalueto[/b]:= n.FromStr(sufAddr, %000_000_000_0_0_000000_01010) ' n.FromStr(@suffix, %000_000_000_0_0_000000_01010)    ' converts from a string to a dec
    
    
  • sjanickisjanicki Posts: 3
    edited 2012-06-08 20:24
    @ turbosupra: Thanks so much! I'll try this out and see if I can get it to work for my application. One question though, I may just be reading the code wrong but it seems like it is for sending information from the serial terminal on the PC to the prop, not for one prop talking to another.

    Thanks again!
  • turbosupraturbosupra Posts: 1,088
    edited 2012-06-08 21:03
    Correct, it is for using the terminal. The reason this is applicable IMO is because once you are able to get it so that you can send commands via typing them in the terminal, you can then automate that and have a transmitting prop and a receiving prop, with the transmitting prop doing the automated typing/sending of strings. This may not be the way you want to do it, but this is the way I would attack the problem which was why I offered this solution.

    sjanicki wrote: »
    @ turbosupra: Thanks so much! I'll try this out and see if I can get it to work for my application. One question though, I may just be reading the code wrong but it seems like it is for sending information from the serial terminal on the PC to the prop, not for one prop talking to another.

    Thanks again!
  • kbchiewkbchiew Posts: 2
    edited 2012-06-23 08:42
    Guys, not too sure if I am robbing the thread BUT I also have question about Simple_Serial object. Sorry if I did.

    Can someone advise me why ???

    repeat x from 0 to strsize(@outp1)
    tx(byte[@outp1][x])

    The above works where outp1 is BYTE in DAT.

    BUT below is NOT ???

    strAddr := @outp1
    repeat x from 0 to strsize(strAddr)
    tx(byte[strAddr][x])
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-06-23 10:54
    What kind of variable is "strAddr"?

    It needs to be a word or long sized variable.
  • kbchiewkbchiew Posts: 2
    edited 2012-06-24 07:26
    Duane, thank you for your reply. Actually I was trying to use the PUB in Simple_Serial Obj.

    PUB str(strAddr)
    if txOkay
    repeat strsize(strAddr)
    tx(byte[strAddr++])

    BUT when I send in str(@outp1), it is not working. I am not sure what strAddr is declared as ?
    Since passing @outp1 not working I have to try other ways....

    BTW, at DAT, outp1 Byte "Get Data 1",0[10]

    I know there must be something wrong somewhere but just can't figure out
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-06-24 10:37
    I think we'll need to see all your code to see what's wrong.

    If you're program is short you can post it with code blocks. Here's a link to a tutorial on how to use code blocks.

    attachment.php?attachmentid=78421&d=1297987572

    You can attach you code as an archive by compiling your program, then choosing File\Archive\Project...

    You also need to keep in mind that simple serial can only use baud settings of 9600 or less.

    I had a problem using simple serial in one of my projects. I never did figure out what the problem was. I decided it was easier to just use one of the other serial drivers since I had a cog I could spare.

    Have you tried using the other serial objects?
Sign In or Register to comment.