Announcement

Collapse
No announcement yet.

Serial port problems (including overhead, speed)

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Serial port problems (including overhead, speed)

    Hi All,

    I am writing an creating an extensive set of tools, to replace and extend upon those I did using VB6 years ago, and work with a specific group of hardware with RS232 interfaces.

    The required port parameters for the hardware are: 8 data bits, 1 stop bit, no parity, no flow control. The RTS and DTR lines (or at least one of them) need to be held high to power the device. My code to open the port is:

    Code:
    FUNCTION StartComms (PortNo AS LONG) AS LONG
    LOCAL cPort AS STRING
        EndComms  'flushes the buffer and calls COMM CLOSE #nComm
     
        SLEEP 30
        cPort = "COM" & LTRIM$(STR$(PortNo))
        COMM OPEN cPort AS #nComm
        IF ERRCLEAR THEN EXIT FUNCTION       ' Exit if port cannot be opened
        COMM SET #nComm, BAUD     = 9600     ' 9600 baud
        COMM SET #nComm, BYTE     = 8        ' 8 bits
        COMM SET #nComm, PARITY   = %False   ' No parity
        COMM SET #nComm, STOP     = 0        ' 1 stop bit
        COMM SET #nComm, TXBUFFER = 1024     ' 4k transmit buffer
        COMM SET #nComm, RXBUFFER = 1024     ' 4k receive buffer
        COMM SET #nComm, XINPFLOW = 0        ' Disable Xon Xoff flow control
        COMM SET #nComm, XOUTFLOW = 0        ' Disable Xon Xoff flow control
        COMM SET #nComm, RTSFLOW  = 1        ' Raise RTS line
        COMM SET #nComm, CTSFLOW  = 0        ' Disable CTS flow control
        COMM SET #nComm, DTRFLOW  = 0        ' Disable DTR flow control
        COMM SET #nComm, DSRFLOW  = 0        ' Disable DSR flow control
        COMM SET #nComm, DTRLINE  = %True    ' Raise DTR line
        SLEEP 50 'allow the device to power up
        GetLinkType 'query the device type and version
        IF LCASE$(LEFT$(LinkType,4)) = "link" THEN FUNCTION = %TRUE
    END FUNCTION
    Most of the communication with the device consists of strings between 1 to 60 characters long. I know what length the returned string will be so here is the code I use to communicate with the device:

    Code:
     
        IF COMM(#nComm, RXQUE) THEN      'flush the buffer
            COMM RECV #nComm, COMM(#nComm, RXQUE), rStr
        END IF
     
        COMM SEND #nComm, SndString
     
         DO UNTIL i& >= numbytes OR k& = 20  'time out after 100 ms
             k& = k& + 1
             SLEEP 5
             i& = COMM(#nComm, RXQUE)
          LOOP
     
          COMM RECV #nComm, i&, RcvString
    The problem with this is that I am getting a 30 millisecond delay or overhead with every send/receive transaction. k& only ever reaches 1 or 2. Some operations require over 10 transactions so the user will be left wondering what is happening. The device itself responds within a couple of ms so I suspect the delay is happening during either the sending or querying the size of the buffer.

    My VB code, with either the now useless MSCOMM control or the excellent Marshallsoft serial library, does these transactions almost instantaneously. I would use the Marshallsoft DLL except that I am hoping to
    distribute only one DLL for this device.

    Can anyone see where I am going wrong?

    Thanks and regards,

    Rob

  • #2
    Rob,
    on an average systen, SLEEP 5 will actually sleep for 15ms because 15ms is the default timeslice. 2 of those would make the 30ms delay you mention so maybe an alternative to SLEEP might be better?
    You could look at timeBeginPeriod to see if you can set the timeslice to something smaller:
    http://msdn.microsoft.com/en-us/libr...13(VS.85).aspx

    Paul.

    Comment


    • #3
      Hi Rob,
      Welcome to the world of the serial port

      Some minor things are missing for a better explanation, but having worked with multiple devices the last 10 years with serial ports, I think I can bring some of it into perspective.

      1.) MSCOMM in its day was great (For general purposes), but lacking when needing precise timing. (I could say the same about MarshallSoft, but they got the job done better than M$ did)

      2.) What is the device you are trying to communicate with? (This could have its own "quirks"

      3.) The general format (in your configuration) would be
      Baud: 9600 Bits/Sec - Average not dead on timing
      Bits per character (ANSI): 8
      Characters: 8 bits/byte + 1 start Bit + 1 Stop Bit
      Minimum transmission per character: 8.3333333333333333333333333333333e-4 ms (And is really longer due to start/stop bits and whatever else the computer may be doing at the time.)

      All the above can account for the "General Rule of Thumb" that timeouts would be 100ms (Anything less than this is bound to NOT produce the correct results unless extreme care is taken for what is happening outside of your code.)

      I will see if I can locate some of my code to demo how even 1 character may not be retrieved within an expected 1ms (1Ms is > 0.8 ms so you would think you would have a response, but the real response could be 10ms, 30 ms or even 80ms)
      Engineer's Motto: If it aint broke take it apart and fix it

      "If at 1st you don't succeed... call it version 1.0"

      "Half of Programming is coding"....."The other 90% is DEBUGGING"

      "Document my code????" .... "WHYYY??? do you think they call it CODE? "

      Comment


      • #4
        If the timeout accuracy isn't too important you could use something like this to ensure the receive response is 'snappier'..
        Code:
        #Include "win32API.inc"
         
            IF COMM(#nComm, RXQUE) THEN      'flush the buffer
                COMM RECV #nComm, COMM(#nComm, RXQUE), rStr
            END IF
         
            COMM SEND #nComm, SndString
            t1??? = timeGetTime
            ' The timeGetTime function retrieves the system time, in milliseconds. 
            ' The system time is the time elapsed since Windows started. (NB. Count rolls every 49.71 days)
         
            DO UNTIL i& >= numbytes OR t2??? - t1??? >= 100  'time out after 100 ms (or so)
              k& = k& + 1
              t2??? = timeGetTime
              i& = COMM(#nComm, RXQUE)
            LOOP
         
            COMM RECV #nComm, i&, RcvString
        For more info on the limitations of SLEEP and some useful test code, see David Roberts' post here..
        http://www.powerbasic.com/support/pb...d.php?p=316070
        Last edited by Dave Biggs; 26 Jul 2009, 10:43 PM. Reason: sp
        Rgds, Dave

        Comment


        • #5
          Thanks heaps!

          Once again. Thanks for the really helpful replies. There is certainly something there to solve this problem and get me entirely bamboozled.

          For Cliff: I have been working with various versions of this device for years many different platforms including Palms, Wilke Tiger devices and Bluetooth links. It runs up to 57,600 baud happily but the manufacturer is making it much faster. This timing stuff is becoming more important. I am used to reading large lumps of data in one go, such as a whole logger full, but I am now doing more with smart sensors that have to be prodded just so to get the data out.

          Cheers,

          Rob

          Comment

          Working...
          X