Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Strange serial port output problem

  1. Aug 29, 2007 #1

    I've been writing a program to communicate with an embedded system via rs485

    The protocol in use utilizes stick parity, where stick parity is defined as the first byte (which corresponds to the address of the device) having its parity bit set to 1, and the rest of a packet have its parity bit set to 0.

    So, when developing my program, I was having some issues with reliability. I attached an oscilloscope to determine the problem. From this I determined that the address byte was preceding the rest of the packet by about 6-8ms. I assume this is due to the parity shift taking place (going from mark parity on the address byte, to space parity for the rest of the packet). So after some trial and error I found that introducing a 2ms delay in between each byte worked extremely well.

    However, I now have an intermittent problem popping up that I cant explain.
    Every once and a while , the communications will totally fail, the CPU wont even respond (nack, ack, cancel, busy), so I once again, attach a scope. This time, I see that the time between all bytes sent is around 12-15ms. This problem occurs intermittently, I'll be changing some aspect of my code totally unrelated to communications and when I start it back up, this problem occurs. Sometimes it occurs when I leave my program idle or when I restart my program. There also is nothing I can do to get it back into a working state, I just have to wait until the packets become normally timed, as if by some whim of my computer.

    I attached a crude MS paint drawing to illustrate what I am seeing on the scope.

    Each spike represents one byte. I'm using a packet with 11 bytes as my guinea pig.
    I'm transmitting at 19200 baud. 1 stop bit, stick parity.

    The top image shows what the packet looks like when communication is working.
    The bottom shows what it looks like when the problem is occuring.

    I have tried this on two different computers, and I have the same issue on both. I have ruled out all other hardware except for the computers themselves. (I have scope attached directly to serial port). This problem will occur without any change to code, and then also suddenly start working without any change to code.

    Any help would be much appreciated


    Attached Files:

    Last edited: Aug 29, 2007
  2. jcsd
  3. Aug 29, 2007 #2
    Here's the packet I'm sending

    Code (Text):
     Dim TX(12) As Byte

            TX(0) = CURRENT_CPU                         ' ADDRESS OF THE CPU
            TX(1) = 9                       ' NUMBER OF BYTES TO FOLLOW
            TX(2) = PURGE_BARS
            TX(3) = PURGE_CONTROL_BYTE                  ' DETERMINES WHICH BARS TO PURGE
            TX(4) = PURGE_TIME_BAR1
            TX(5) = PURGE_TIME_BAR2
            TX(6) = PURGE_TIME_BAR3
            TX(7) = PURGE_TIME_BAR4
            TX(8) = PURGE_TIME_BAR5
            TX(9) = PURGE_TIME_BAR6
            TX(10) = CByte(get_checksum(TX, 10))               'TWO'S COMPLEMENT OF THE SUM OF THE PACKET

            For i As Integer = 0 To 10


                If i = 0 Then

                    sp.Parity = IO.Ports.Parity.Mark


                    System.Threading.Thread.Sleep(2) ' 2mS pause
                    If Not sp.Parity = IO.Ports.Parity.Space Then
                        sp.Parity = IO.Ports.Parity.Space
                    End If

                End If

                sp.Write(TX, i, 1)

                While (sp.BytesToWrite <> 0)
                End While

            Next i
  4. Aug 29, 2007 #3


    User Avatar

    Staff: Mentor

    Just to clarify, you are sending this somehow from a Windows PC, and the receiving node is an embedded uC?

    If so, what operating system are you running on the PC? Most PC OS's are not real-time. What port are you coming out of the PC on? Are you coming out of the RS-232 port and converting that to RS-485 somehow? If so, how? Is your RS-485 network doubly-terminated like it's supposed to be?
  5. Aug 29, 2007 #4
    yeah, mainly im using my latptop with has windows vista, im using a usb -> rs232 converter (com4) to convert to to rs232, then to rs485 when I get to the device,

    ive also used a desktop with windows XP sp2, using an actual rs232 port (com1)

    but the issue occurs even when im disconnected from the rs485 network

    its perhaps a problem with the operating system?
  6. Aug 29, 2007 #5


    User Avatar

    Staff: Mentor

    That's a fairly convoluted path for getting out to a real-time network (no offense meant, I'm just saying that it is). In general, for a real-time network (especially if it has an error-detection and retry protocol layered on it), you will need real-time devices at all connection points. The RS-232 serial port out of your PC has its own driver mechanism and UART chip to ensure that the baud rate stays within tolerances. But when you write a program on a PC to send things out ports byte-at-a-time or whatever, then the OS jitter will affect what actually goes out.

    The best way for you to do a PC-based interface to the real-time network, would be to make a network interface device that has a microcontroller (uC) in it. You would send the uC the data via the RS-232 serial port or USB port, and the uC would serve as the gateway to get the data out onto the network, and report the replies back up to the PC. Dedicated hardware is the common way to interface PCs (and their non-real-time operating systems) to real-time data communication networks.
  7. Aug 30, 2007 #6


    User Avatar
    Homework Helper

    Windows XP uses a 64hz ticker, this corresponds to an interval of 15.625ms. A sleep(2) is only guaranteed to provide a 2ms minimum delay, to the next 15.625ms boundary. The multimedia functions, timeBeginPeriod() and timeEndPeriod() are supposed to allow a program to change the "minimum timer resolution" as low as 1ms, but I'm not sure if this is the same timer as the one used for sleep().

    An alternative is to bump up thread priority and loop on QueryPerformanceFrequency() (instead of using sleep), which I assume is based on the high frequency timer in a Pentium cpu. Grab an initial value from QueryPerformanceFrequency(), then base all future events by looping on QueryPerformanceFrequency() until it reaches an appropriate difference from the initial captured value. To prevent wrap-around issues, subtract of the original time from the current time, and then compare to a desired delay.
Share this great discussion with others via Reddit, Google+, Twitter, or Facebook