Shop OBEX P1 Docs P2 Docs Learn Events
Questions/problems with coding a serial connection — Parallax Forums

Questions/problems with coding a serial connection

JomsJoms Posts: 279
edited 2009-03-21 03:54 in Propeller 1
Two questions on the attached .spin file...

1.· I am trying to make the variables dst & src output four hex characters which is working fine.· Example, if the variable = 111 then it outputs '30,30,36,45'.· The problem is I am trying to calculate the checksum and it requires that I add all of the transmitted digits including the '30,30,36,45'.· I arrived at the 301 by adding all of the fixed tx bytes together manually.· If I manually add the 4 hex bytes together and replace the variables with them the checksum calculates properly.

2.· I was having a problem with it not sending the entire string of data.· I discovered that because I am using the .tx pub that it would stop the cog before the buffer was actually empty.· To make this work temporarily I just added a one second delay.· My question, is there anyway to tell when the buffer is empty so that I don't waste extra time just waiting?

Thanks in advance for all the help...

After about a month of working with it, I am really starting to like the propeller...

Comments

  • StefanL38StefanL38 Posts: 2,292
    edited 2009-03-18 16:54
    Hello Joms,

    I don't understand your question 1

    so I'm asking back:
    which variable has value 111
    how is the value 111 translated into the hexbytes 30,30,36,45 ?

    If 30,30,36,45 should be ASCII-Code this means "0","0","6","E". What does this have to with value 111 ????

    Is Your EncoreRouterControl.spin-file the TOP-object-file ?

    If this is the case it will only run ONCE the method SendSource and that's all

    You shouldn't start and stop the FullDuplexSerialPlus-object (FDS+)all the time inside method Sendsource and GetSource

    The FDS+-object is menat to use it in the following way
    right at the beginning you call ONLY ONE Time SendData.Start(31, 30, 0, 9600)

    and as long as you do not run out of cogs you NEVER stop it

    The FDS+-object works as some kind of a driver in the backround
    you start it and then it runs in the backround
    waiting for bytes to be send AND waiting for bytes to be received (send and receive at the SAME time as this is what the FULLDUPLEX means)

    You can imagine this
    starting the FDS+object is like employing a butler
    once you have engaged him
    you can shout commands at him
    "send the following bytes" "ABCDEFG01234567890"
    the butler will write all bytes onto a sheet of paper and send them
    while you can do already other things
    and you even can shout another command at him while he is still sending bytes
    "receive a string" or whatever
    and he is abe to do both things at the same time
    after finishing your commands he stands there in idle-mode waiting for new commands

    you don't have to fire him (call senddata.stop)
    and hire him again (call senddata.start(..) all the time
    you would like to do him a little send or receive-job

    If you need something to male sure that send and receive does NOT run crossed over
    you could add a method to the FDS+-object that is just
    LOOKING for rx_head == rx_tail

    WITHOUT taking bytes out of the receivebuffer
    (like rxcheck does it)

    same thing for the sendbuffer
    LOOKING for tx_head == tx_tail
    WITHOUT sending a byte

    about your checksum-problem
    please post in DETAIL what you are adding manually and what you are doing else
    and how you get a hexcode sequence 30,30,36,45 out of a value 111

    best regards

    Stefan
  • JomsJoms Posts: 279
    edited 2009-03-18 20:00
    GREAT EXPLINATION STEFAN!!!

    On the first question of how I arrived at the 6E part.· I actually messed up and should have put the number 110, the first thing I do in this object is subtract 1.· Anyways, here is how I got there…

    DEC 110 = HEX 006E,· Character 6 = HEX 36,· Character E = HEX 45,· Character 0 = HEX 30

    The device I am trying to send the data to wants to see 4 hex characters for each variable…

    This EncoreRouterControl.Spin is not the top object file.· My top file actually calls on the senddata PUB or the getsource PUB.· Part of the reason I was trying to not leave the FullDuplexSerialPlus running all the time is because I will actually be using it to output data to about 4 different devices, meaning I will want to change the tx and rx pins that are declared when I start it.· I would like to only use 1 cog to send the data to each device as I will never be sending data to multiple devices at the same time.· If there is a better way to send multiple devices information using the same FDS cog that I am not aware of, please let me know…

    I actually do not need to send and receive data at the same time but when I tried the Simple_Serial out of the Propeller Library there was no way to do SendData.hex(dst,4) that I found anyway…

    ·As for the Checksum Calculation Algorithm, the checksum is calculated on the items following the SOH (Hex 01) and before the inserted checksum value.· The calculation is a negative sum mod 256 of those values.· The way I arrived at the 301 is by manually adding up all of the hex bytes that I am sending out using the SendData.tx command.

    Thanks for the long explaination and all the help so far… I am fairly new to the serial communications and been trying all sorts of different things for the checksum calculation and can’t seem to make anything I try work.
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-03-18 20:36
    I did not have a closer look to the sources of other objects by myself yet, but if there would be a need, I'd try to enhance the features of FullDuplexSerial. Why not having a command to switch the pins?

    Starting point is the start function where you set the pins and speed initially. See what happens there with the parameters and try to figure out where the cog stores those pin information. As I understood Stefan, there is a command interface to the COG. You have to expand this by a new command which switches the pins while the COG is running.

    Maybe I have some time later to check that out as well.
  • JomsJoms Posts: 279
    edited 2009-03-18 20:47
    You know, to be honest I never thought about trying it that way... I am going to see how hard it would be to modify the FullDuplexSerial...

    If worst comes to worst I will just end up putting a delay in there of a few milliseconds or something that allows enough time for it to complete...

    Any ideas on the checksum format problem I am having?, that is where I am really stumped...


    ---EDIT---

    Another thought I just had as a work around would be to stop the FullDuplexSerial right before I start it whenever I need to switch pins.· Might not be the best way, but it would work for testing without the delay anyways...

    Post Edited (Joms) : 3/18/2009 8:52:28 PM GMT
  • StefanL38StefanL38 Posts: 2,292
    edited 2009-03-19 02:11
    Hello Joms,

    it's always the same:
    as soon as there is more information available new suggestions can be made to solve a problem

    In the obex there is an object Multiple serial port driver
    that supports up to 4 serial ports per cog. With this driver there is no need to change pins.

    I'm not familiar with checksum calculation. But I'm quite good in mathemathics in general. To make life easier for me
    can you post the general formula and an example with some bytes

    a.) what the result of the checksum-calculation should be
    b.) what the result is that you get from the calculation in your SPIN-program

    For debugging I would add debugoutput showing step by step what is calculated
    and run through the variable src from zero to max and analyse what sould be calculated and what you really get
    from the SPIN-code

    If I summarize your fixed bytes
    01
    78
    48
    84
    73
    09
    09

    I get 302. You add 301 do you have to substract 1 for this part too ?
    As you are sending these values as single bytes could it be that EACH byte has to be substracted by one ?

    I'm really unsure about how the calculation SHOULD be made and therefore I need an example
    shown mathematically and not as SPIN-code

    best regards

    Stefan
  • JomsJoms Posts: 279
    edited 2009-03-19 02:39
    Sorry if there was some confusion...· Perhaps the attached document will help...


    I am going to look for that 4 port serial driver as that would be a HUGE help!· I was just putting together the code for the serial port and running into problems and I think a 4 port will be a big help...

    Thanks a million for all the help on this one...
  • StefanL38StefanL38 Posts: 2,292
    edited 2009-03-19 09:30
    Hello Joms,

    OK catched the bug

    your codeline

      cksm := (-1*((301 + dst + src)//256))+256
    
    
    



    is wrong

    Let's say variable src contents value 111 (111-1=110 decimal = hexadecimal $6E
    and variable dst contains value 103 decimal (103-1=102 decimal = hexadecimal $66
    as your PDF-example shows

    you have to translate the value of src - 1 and dst -1 into FOUR SINGLE ASCII-coded hexadecimal digits
    decimal 110 has to be translated into "0", "0", "6", "E"

    ASCII-Code of "0" is decimal 48 and hexadecimal 30 (3*16 + 0 = 48)
    ASCII-Code of "0" is decimal 48 and hexadecimal 30 (3*16 + 0 = 48)
    ASCII-Code of "6" is decimal 54 and hexadecimal 36 (3*16 + 6 = 54)
    ASCII-Code of "E" is decimal 69 and hexadecimal 45 (4*16 + 5 = 69)

    so for calculating the checksum of src-value 110 you have to add decimal 48 + 48 + 54 + 69 = 219
    but your codeline simply adds 110 and the add of 2x 09 is missing and I think this is the bug

    same thing for variable dst - 1

    for this converting you can use the codelines of the method hex in FDS+ as a BASE
    define four bytes scr_byte1...scr_byte4 for the four digits and store the ASCII-code
    of the digits inside these bytes

    then your checksum has to be calculated like this

    to make the code more readable I would divide the whole calculation in several parts

      cksm := _protocol_ID + _SeqNo  + _T + _I 
    
      cksm := cksm + _TAB
      cksm := cksm + dst_byte1 + dst_byte2  + dst_byte3  + dst_byte4 
    
      cksm := cksk + _TAB
      cksm := cksm + src_byte1 + src_byte2 + src_byte3 + src_byte4
    
      cksm := cksm // 256
      cksm := 256 - cksm 'now the right checksum should be calculated
    
    




    use EXACTLY the values of the PDF-example to TEST your code

    here it is useful if you define constants and variables

    CON 
      _SOH = 1
      _protocol_ID = 78
      _SeqNo = 48
      _T = 84
      _I = 73
      _zero = 48
      _TAB = 9
      _EOT = 4
    
    VAR
      dst_byte1
      dst_byte2
      dst_byte3
      dst_byte4
    
      src_byte1
      src_byte2
      src_byte3
      src_byte4
    
    
    



    then your method PUB SendSource(dst, src) | cksm

    looks like this

      SendData.tx(_SOH)
      SendData.tx(_protocol_ID)
      SendData.tx(_SeqNo)
    
      SendData.tx(_T)
      SendData.tx(_I)
    
      SendData.tx(_TAB)
      SendData.hex(dst,4)
    
      SendData.tx(_TAB)
      SendData.hex(src,4)
    
      SendData.hex(cksm,2)
    
      SendData.tx(_EOT)
    
    
    



    I did not test this code and the codelines show NOT everything

    best regards

    Stefan

    P.S.: without the PDF-description I would have NEVER found the bug !

    Post Edited (StefanL38) : 3/19/2009 9:40:01 AM GMT
  • JomsJoms Posts: 279
    edited 2009-03-19 21:23
    Thanks for the explination... I now understand what is going on, but I am having problems with the formatting part...

    After I declare the dst_byte1, dst_byte2, dst_byte3, dst_byte4, and the respective sources, How do I do the calculation to put the 110 into them?· Basically what I mean, is how do I determine their values before it gets to the calculation point?

    Sorry if you already explained this and I just don't understand it as I am currently learning spin.· You have been a huge help so far, and Thank You for that...

    (EDIT)·- I·re-read what I wrote and it might·be a little hard to understand, so what I mean is how·do I translate the single·byte (dst) into the four·bytes·(byte1, byte2, byte3, byte4) ?

    As a side note that might relate with this problem, durring part of this same project I need to access the bits within another byte that I am storing.· Basically what I am doing is I have a spin file that is scanning a parrallel to serial IC and inputing a byte depending on which input is active.· How do I actually turn that byte into 8 seperate bits, as it is my understanding that bits are not supported in spin.

    This is of course a different question that I am having with this same program I am makeing, but I have a feeling that when I figure out how to fix the original question I was asking, that it will be self-explanitory on how to fix this issue...

    Thanks again for all the help!

    Post Edited (Joms) : 3/19/2009 9:56:54 PM GMT
  • StefanL38StefanL38 Posts: 2,292
    edited 2009-03-20 06:25
    hello Joms,

    as a quick answer

    your parameters "src" and "dst" are longs. which means the are four bytes = 4x8bits = 32bits big

    take a close look into the method hex of the FDS+-object

    this is the original version

    PUB hex(value, digits)
    
      '' Print a hexadecimal number
    
      value <<= (8 - digits) << 2
      repeat digits
        tx(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))
    
    
    



    it is very compact coded
    you gave in a value to this method and the method sends out as many digits as you said by the value if variable digits

    this line converts the value into ONE hexadecimal digit

      lookupz((value <-= 4) & $F : "0".."9", "A".."F"))
    
    



    of course you need the lines around to do it for all digits

    as a hint

    the lines

      repeat digits
        tx(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))
    
    
    



    send out the hexadecimal digits
    and for your program you have to modify it that the digits get stored into your variables
    dst_byte1, dst_byte2 ...

    I'm not a friend of serving completed code because you won't learn much from this way

    write some own code to analyse what is happending here

    if you have CONCRETE questions about whatever feel free to post them here


    to get single bits you simply do a AND-command with the interesting bit set to one

    example your value is

    bitno   87654321
    value  %10101000
    
    bitno   87654321
    Mask   %00001000
    
    value and Mask
    
    value  %10101000
    Mask   %00001000
    result %00001000
    
    
    value  %10101000
    Mask   %00000001
    result %00000000
       
    
    



    result contains zero if the interesting bit is zero
    or a value <> zero if the interesting bit was 1

    best regards

    Stefan
  • JomsJoms Posts: 279
    edited 2009-03-21 03:54
    Great... After pulling my hair out all after noon I did get the orginal problem to work. It ended up being a type-o on my part, and I felt like an idiot after I figured it out...

    I do have a question on the mask thing, but I think I am going to start a new post on that. Thanks for your help with that problem. I understand not giving the code as I would not have learned anything...
Sign In or Register to comment.