Help with Serial requested

  1. ‹ Older
  2. 2 weeks ago

    Derk J

    Jul 9 Pre-Release Testers, Xojo Pro
    Edited 2 weeks ago

    @Chris M sorry if it isn't clear from the example but the data in the string is actually a string of decimal numbers which is what the analyser is expecting. That part is being transferred correctly. The problem lies with the initial non-printing character which seems to get garbled.
    If I was using C/C++ I would do this -

    byte tx[] = {0x8F, 0x78, 0x30, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30......... }etc

    and then pass the byte array into the serial object write method.

    Did you even tried it ?

    String is a "bucket of bytes"

    But you are sending HUMAN READABLE ASCII "0xx050000000000050019999"

    Since XOJO strings are UTF8 by default you can just use Chr(143) + the exact string to be send (as it will be send over the line).

    You are saying it sends BYTES in C/C++ then send them as bytes in Xojo as well.

    Serial1.Write(Chr(143) + DecodeHex("050000000000050019999"))

    To send "8f ef bb bf c2 8f 78 30 35 30 30 30 30 30 30 30"
    The code example above does the same and just says "Send my hex values as binary" or DIY ChrB(143) + ChrB(&h8f) + ChrB(&hef) + etc......

    ChrB should be used yes as well

    OR create a New MemoryBlock and assign the values to it.

    To get a hexadecimal value ChrB(&hFF) the "&h" is the xojo equivalent of "0x" in C/C++

  3. last week

    Hi Derk
    sorry but there is still some misunderstanding here. It is not the actual data in the string that is the problem but what is happening to the Hex 8F at the front when it gets to the Serial.write.

    If I examine the string tx before it is sent it shows 8f 78 30 35 30 30 30 30 30 30 30 30 30 35 30 30 31 39 39 39 39 which is absolutely correct. This is what I am intending to send. However when I put a trace on the code that is actually coming out of the serial port I see 8F EF BB BF C2 8F 78 30 35 30 30 30 30 30 30 30 30 30 30 30 35 30 30 31 39 39 39 39 . Somehow the initial 8F has been transformed into 8F EF BB BF C2 8F. Actually, it is transformed into what appears to be a random set of bytes with 8F at the front and back. I have seen 8F E7 8F as well as 8F C5 E2 66 54 8F

    It appears that somehow the data is getting corrupted as it is being passed in, or there is something odd with the buffer initialisation perhaps? As you can see the code around the serial write is pretty simple so I am at a loss to understand what is causing the data to be changed and I'm hoping someone can tell me.
    Thanks

  4. Derk J

    Jul 10 Pre-Release Testers, Xojo Pro
    Edited last week

    you are flushing before writing, one thing IF you should even flush then do it AFTER .Write()

    in your video you say i have to send in... "0x... "
    Can you post some protocol information (datasheet or so) or orginal code c/c++ ?

  5. Kevin G

    Jul 10 Pre-Release Testers, Xojo Pro Gatesheed, England

    If you have pasted the string into Xojo it might contain some gremlins that you cannot see but are being transmitted. Try selecting the code in the IDE, context clicking the selection and choosing the clean invisible ascii characters option.
    If there are some there you might also be able to see them by trying to cursor through the string as the cursor sometimes appears to stick on a character when there are invisibles.

  6. @Chris Mower — This is likely a problem of internal encoding conversion. For example, the code point 8F is represented as "C2 8F" in UTF8 which corresponds to a part of the unwanted characters you reported.

    I think you should set the string encoding to nil before using it:

    tx = DefineEncoding( tx, nil )

    It should prevent conversion errors, since nil-encoded strings are left intact with ConvertEncoding.

  7. Chris C

    Jul 10 Pre-Release Testers, Xojo Pro Thatcham, Berkshire, UK, Europ...
    Edited last week

    I agree that this is all about the encoding, though I find CharB, rather than Char is necessary for setting the `143` byte.

    I've done a few tests, using an arduino to show me the hex string received by the `target`

    The following seems to work...

        self.objComTTY.Write(DefineEncoding(ChrB( 143 ), Encodings.ASCII))
        self.objComTTY.Write(DefineEncoding("x050000000000050019999", Encodings.ASCII))

    as does

        dim tx as string
        tx = DefineEncoding(ChrB( 143 ), Encodings.ASCII)
        tx = tx + DefineEncoding("x050000000000050019999", Encodings.ASCII)
       self.objComTTY.Write(tx)

    Note: Combining the 2 by:-

        self.objComTTY.Write( DefineEncoding(ChrB( 143 ) + "x050000000000050019999", Encodings.ASCII))

    does NOT work

  8. Chris C

    Jul 10 Pre-Release Testers, Xojo Pro Thatcham, Berkshire, UK, Europ...

    @Stéphane ;Mons ...
    I think you should set the string encoding to nil before using it
    ...

    Note: I also tried the above with `nil` encoding - and that worked too.

  9. Well I have sort-of tracked the problem down and it would appear that the problem is caused by me calling the Flush method after the Write. Not sure why but when I disable the flush the serial data is correct, but when the flush is enabled it has the garbage at the front. Very odd.

  10. Chris Mower — That really sounds like a bug. Flush should not change anything.

  11. I had been having problems with the port holding on to short length packets as the documentation implied The device I'm trying to talk to is a swine for requiring a strict protocol and unless the packets arrive all together it ignores the data. I had been experiencing data sent to the serial being aggregated hence my using the Flush method to force the data out.
    I think I'm going to have to write my own serial port driver. It shouldn't be too difficult as it is fixed at 57600,n,8,1 with no handshaking so I might be able to write directly to the /dev/ttyUSB driver.

  12. @Chris M — Maybe I am wrong but it seems to me that bytes are padded to either 4 or 8 bytes ; that would explain why you obtain different results sometimes.

    You may want to add enough NUL characters to achieve that padding manually.

  13. I did try padding but the protocol requirements of the spectrum analyser are awful and any spurious bytes in the command string cause havoc. To be honest I really don't like the fact that they use a string rather than an a byte array to send data to a serial port. It is much easier to format non-ascii data into a byte array. Also the data that comes back is effectively made up of two byte 16 bit words representing signal strength so i need to figure out how to extract them from a string and put them into an array of Int16.

  14. Chris C

    Jul 10 Pre-Release Testers, Xojo Pro Thatcham, Berkshire, UK, Europ...

    BTW: My tests were on Windows 7... but I still think encoding is the main issue. Flush after Write seems logical to me.

  15. @Chris M — Well if you prefer a byte array, you can use it in Xojo as well with:

    dim myArray() as UInt8

    Populate it and then you can build a MemoryBlock object of the right size, use Byte to set every byte

    dim mb as new MemoryBlock( ubound( myArray ) + 1 )
    for i as integer=0 to ubound( myArray )
        dim myByte as UInt8 = myArray( i )
        mb.Byte( i ) = myByte
    next

    then send the data:

    sendData  DefineEncoding( mb.StringValue( 0, ubound( myArray ) + 1 ), nil )( 
  16. Stéphane

    you may be able to help me with my struggle to extract the return data. What comes back is a number of 16 bit words representing signal strength, a typical example is -
    70EF BFBD 70EF 70DD 71BE 69AA 71AE

    I need to convert that to, in this case, 7 words -
    28911, 49085, 28911, 28893, 29118, ......etc

    but i can't seem to find anything in the language which will extract the data from the string and put it into an array of UInt16.
    If you can provide a clue as to how this can be done I would be most grateful

  17. @Chris Mower — The result depends on the byte-ordering but it seems easy in your case because &h70EF = 28911

    The easiest way to convert really depends on the format of your data at first. Here, I will consider that you got a string ("70EF BFBD 70EF 70DD 71BE 69AA 71AE") and want to get the values out of it.

    dim values() as string = Split( "70EF BFBD 70EF 70DD 71BE 69AA 71AE", " " ) //Split all the 16-bit values
    
    for each s as string in values //Parse the 16-bit values
        dim numValue as integer = Val( "&h" + s )  // Evaluate each string value prepended with "&h"
        //>>>> Do something with the numerical value
    next
  18. sorry but there is still a misundersatnding. The data that comes back is not ASCII as such but raw binary. It comprises the byte values 70EFBFBD70EF70DD71BE69AA71AE and not the ascii characters "70EFBFBD70EF70DD71BE69AA71AE"
    Therefore I need to extract the first four bytes, 70EF and convert that to the UInt16 value 28911, then the next four values BFBD and convert that to 49085 and so on to the end of the input data. I haven't been able to find a way to do that in Xojo but as I am new to it I may be missing something.

  19. @Chris Mower — Then you can also use a MemoryBlock to handle the resulting "String" (aka suite of bytes) as a MemoryBlock and a String are interchangeable !

    dim mb as MemoryBlock = myResultAsString
  20. Aha, that looks like what I am needing. Let me give it a try.
    Thanks

  21. Stéphane

    thanks for that it works exactly as I need. This gives me the conversion to a double array

    Dim LoopCount As Int16
    Dim mb As New MemoryBlock( 4096 )
    Dim db As Double
    
    mb = InputData
    If x = (  2 * DataCount  ) Then
      For LoopCount = 0 To x - 1 Step 2
        db = mb.UInt16Value( LoopCount )
        data.Append( db )
      Next LoopCount
    End If
    

    Many thanks for the help
    Chris

or Sign Up to reply!