Serial Port Returning Garbage. Why?

Bengt Richter bokr at oz.net
Thu Jul 18 14:31:53 EDT 2002


On Tue, 16 Jul 2002 22:15:48 -0600, bowman <bowman at montana.com> wrote:

>max wrote:
>>
>> No, I'm not. It's just Transmit, Receive, and Ground. Our device
>> doesn't use any of the other signals, and the implementation doesn't
>> use QON/QOFF. Would it make a significant difference if I do?
>
>It might, if the slave end is a relatively slow device. For instance, the 
>older SBC UARTs or microcontroller internal UARTs might not be able to keep 
>up with the transmission, particularly if they have to do something with 
>each byte as it is received. Usually the receiver will use a DTR signal to 
Perhaps Max could test the speed theory by slowing down the program output,
e.g. by putting time.sleep(0.25) between each character output to simulate
something closer to typing speed.

If it's not convenient to do that where the characters originate, perhaps
it's possible to intercept the output stream and slow things down there. E.g.,
this uses a simple class to slow down stdout to 4 char/sec:

 >>> class SlowStream:
 ...     from time import sleep
 ...     def __init__(self, out): self.out = out
 ...     def write(self, s):
 ...         for c in s:
 ...             self.sleep(.25) # simulate typing
 ...             self.out.write(c)
 ...
 >>> import sys
 >>> ss = SlowStream(sys.stdout)
 >>> sys.stdout = ss
 >>> print '54321 !'
 54321 !

That was slow enough that you can see it, if you try this.
Don't forget to restore the old stdout (or whatever stream)
 >>> sys.stdout = ss.out

Oops, I see from a previous post that you are using os.write for output.
In that case maybe try just replacing that with, e.g.,

 >>> class SlowOsWrite:
 ...     from time import sleep
 ...     def __init__(self, osw): self.osw = osw
 ...     def __call__(self, fd, s):
 ...         for c in s:
 ...             self.sleep(.25) # ought to be plenty for test
 ...             self.osw(fd, c)
 ...

We'll test with a file instead of the serial port, and hope it works for you ;-)
 >>> import os
 >>> fd = os.open('test.txt',os.O_CREAT|os.O_WRONLY)

Create the slow writer, which incidentally saves the old os.write function internally
 >>> sw = SlowOsWrite(os.write)

Replace os.write so your other software doesn't see any difference (hopefully)
 >>> os.write = sw

Try it
 >>> os.write(fd,'write this slowly')

That did take a while, at 4 char/sec. Now close it.
 >>> os.close(fd)

We'll have a look using ordinary python file i/o 
 >>> f=file('test.txt','rb')
 >>> f.read()
 'write this slowly'

Looks ok.
 >>> f.close()

Look at slow writer and os.write FTHOI
 >>> sw.osw
 <built-in function write>
 >>> os.write
 <__main__.SlowOsWrite instance at 0x007D2040>

Restore os.write
 >>> os.write=sw.osw

Note that delays are terrible substitutes for handshakes.
I hope you don't have to use anything like the above as a
final solution, because most likely it will not be final.

But it should help verify that lack of handshake is the problem.

>indicate it is busy, and the sender won't start the next byte until the 
>receiver is ready. I'm assuming by 3 wires, you mean RX, TX and GND, so 
>even if the hardware handshake is being attempted, it won't be seen across 
>the cable.
>
>It is hard to say without knowing your setup. It is possible when you test 
>with HyperTerminal, you are typing the command in, so it really is sent 
>very slowly, but in the working system the master sends the command string 
>much faster and they are getting out of sync.
>
Hopefully the above will help diagnose this.

>Or, it could just be that HyperTerm is setting the start/stop bits, parity, 
>or something a little differently. I don't think it is the baud rate, since 
>that usually results in all garbage characters.
> 
Maybe the OP can query the settings while hyperterminal is connected?

Regards,
Bengt Richter



More information about the Python-list mailing list