SerialPort control using RTS/CTS seems to loose bytes

  • Thread starter Thread starter davewilliamson55555
  • Start date Start date
D

davewilliamson55555

Using Compact Framework 2 SP1 on Windows Mobile 5 VB.NET 2005
SerialPort control on both the PC and WM sides using hardware
handshaking ...

If I send a byte array across the serial port a byte at a time then the
other side seems to receive all the bytes ... but if I send a chunk of
the byte array at a time (1024 bytes ... even tried as low as 100
bytes) the other side doesn't always receive all the bytes.

'this works but takes a year and a day to transmit the data
dim b() as byte = {1024 * 100, 32}
for n as system.int32 = 0 to b.length -1
SerialPort1.Write(b,n,1)
next

'this does not work
SerialPort1.Write(b,n,1024)

And reading the documentation is even more confusing because it reads
like b is the serial buffer .... probably a copy and paste from the
Read method documentation that just didn't get edited.

To really exagerate the condition do this and hardly any of the bytes
makes it to the receiver:
dim b() as byte = {1024 * 100, 32}
SerialPort1.Write(b,0,b.length)

Can anyone help me understand what bad assumptions I must be making?
 
The help documentation for the SerialPort.Write Method (Byte[], Int32,
Int32) method says ...

Writes a specified number of bytes to an output buffer at the specified
offset.

..
..
..
Parameters
buffer
The byte array to write the output to.

offset
The offset in the buffer array to begin writing.

count
The number of bytes to write.


For "buffer" that doesn't look right. Seems like the buffer would be
the byte array I want to send out the port and not the port's buffer
(basestream i assume).

Can someone confirm this?
 
See also:

WriteBufferSize

If your array exceeds WriteBufferSize, data will be lost (TxOverflow error).

Dick

--
Richard Grier, MVP
Hard & Software
Author of Visual Basic Programmer's Guide to Serial Communications, Fourth
Edition,
ISBN 1-890422-28-2 (391 pages, includes CD-ROM). July 2004, Revised March
2006.
See www.hardandsoftware.net for details and contact information.
 
Wasn't sure of that but tis good to know.

I have been watching both the BytesToWrite for the sender and the
BytesToRead for the receiver and neither one approaches the read or
write buffer size.

The reading side just does a simple:

dim b2r as system.int32 = serialport1.bytestoread
if b2r > 0 then
redim b(b2r -1)
serialport1.read(b,0,b.length)
end if

the byte array "b" is passed in by ref and the caller writes those
bytes to a file then reads again after setting b=nothing. pretty
simple stuff but the number of bytes that end of being received do not
match the number of bytes sent (varies but usually 3 or 4 thousand are
missing).

Yet if I send each byte 1 at a time it works every time. I'm
absolutely perplexed.
 
Note that this only seems to happen for large byte transfers ... if the
file is 10K not problem ... but one that is 2236970 never seems to make
it.
 
Hi, Dave,

Are you calling SerialPort.Close() right after the last write? If so, try
calling Close some time afterwards.

Cheers,

Alejandro Mezcua
MVP Device Application Development
http://www.byteabyte.net/
 
Alejandro,

I am not calling .Close right after the last write in this case ... the
bytes that are missing are not always the last bytes ... as a matter of
fact it is random bytes throughout the byte transfer that are missing
.... sometimes it even is in the 1st few K of bytes transferred.

I have read some posts by Dick Grier stating that some USB->RS232
converters don't work well with the new SerialPort in .NET so today I
will try switching over to a PC that has a RS232 and see if that is the
problem.
 
This time I slowed the sending side way down ... it does a Sleep(1000)
after each serialport1.write of 2048 bytes. The receiver remained
polling as fast as possible (in a do loop) yet bytes were still not
received on the other side.

So I left the sender at full speed and then slowed the receiver down
with a Sleep(100) after each serialport1.read and even more bytes were
lost ... this tells me the problem is in the receive buffer on the
receiving side ... my initial thoughts are a buffer overflow but
watching the BytesToRead never shows more than about 1500 bytes (the
readbuffersize is set to 4096 * 4 ... keep in mind this is windows
mobile 5 and therefore that setting is just a suggestion). So now my
brain is wondering if bytes are trying to be written to the buffer at
the same time i am reading bytes out of the buffer and there is some
sort of SyncLocking issue going on. There is no fancy threading in my
app (simply a GUI form with a serialport control dropped on it). The
serialport control uses a seperate thread and I am not reading the port
within the DataReceived event but am instead polling with my own
subroutine that calls serialport1.read(mybytearray,0,mybytearray.length
.... where mybytearray is dimensioned to the serialport1.bytestoread).
 
Hi,

If data are being lost, I suspect that either some intervening hardware or
system (is there one) is loosing them, or there is a receive buffer
overflow. Are you checking for that error?

You MUST use hardware flow control for reliable data transfer. Software
flow control work ONLY for ASCII data, not binary. AND, you must use flow
control. Are you doing so?

Dick

--
Richard Grier, MVP
Hard & Software
Author of Visual Basic Programmer's Guide to Serial Communications, Fourth
Edition,
ISBN 1-890422-28-2 (391 pages, includes CD-ROM). July 2004, Revised March
2006.
See www.hardandsoftware.net for details and contact information.
 
Dick,

I'm using hardware handshaking for flow control. The cable being used
has CTS and RTS crossed and RXD and TXD crossed (as well as DSR/DTR but
I'm not using that).

The SerialPort on both sides is setup like this:

With SerialPort1
Try
.PortName = "COM1" 'windows mobile 5
.ReadBufferSize = 4096 * 4
.WriteBufferSize = 4096
.Open()
.BaudRate = 115200
.Parity = IO.Ports.Parity.None
.DataBits = 8
.StopBits = IO.Ports.StopBits.One
.Handshake = IO.Ports.Handshake.RequestToSend
.ReadTimeout = 500
.WriteTimeout = 500

.Encoding = System.Text.Encoding.UTF8
.ReceivedBytesThreshold = 1
.DiscardInBuffer()
.DiscardOutBuffer()
Catch ex As Exception
MsgBox(ex.Message)
Exit Sub
End Try
End With

Receive Buffer Overflow .... yes ... the receiver is reporting an
Overrun ... (stupid me I should have been trapping those errors all
along anyway).

Now I need to figure out why with RTS/CTS it is getting an overrun.
 
Both sides have to agree that hardware flow control is being used. If the
sender doesn't agree, it won't respond to the stop-sending signal and you'll
get an overflow; if the receiver doesn't agree, it won't send the
stop-sending signal and the sender will keep sending causing the overflow.
Problems of this sort almost always come down, in my experience, to one
program or the other doing something wrong.

Paul T.
 
I stuck a message box in and


Private Sub SerialPort1_ErrorReceived(ByVal sender As Object, ByVal e
As System.IO.Ports.SerialErrorReceivedEventArgs) Handles
SerialPort1.ErrorReceived
MsgBox("SerialPort error " & e.EventType.ToString & " Bytes to
Read=" & SerialPort1.BytesToRead.ToString & " Read Buffer Size=" &
SerialPort1.ReadBufferSize.ToString)
End Sub


When the Overrun does occur the BytesToRead are low numbers like 51 or
211 and the ReadBufferSize is 16384.

Now why is the buffer overrun if the BytesToRead is so low?
 
The BytesToRead is low because the buffer has changed by the time the
msgbox is being formed.

I conducted an experiment. On both sides I changed the handshaking to
None. On the PC side I put a button that toggles the
SerialPort1.RTSEnabled between True and False. On the Device (Symbol
MC70) I watch the CTSHolding.

When the PC toggles the RTSEnable on and off the device changes the
CTSholding accordingly ... this to me says the 2 sides are wired
correctly to respond RTS/CTS.

Does anyone know if the RTS line goes low (RTSEnable=false) when the
buffer is getting close to being full ... or does it wait until it is
completely full?
 
I figured that was the norm but I was holding out hope. I guess then
the only real way to keep from overflowing the buffer is to send each
byte 1 at a time.

Which means back in the MSComm32.ocx days it must have been sending 1
byte at a time because back then we just said mscomm1.output = {a crap
load of data} and it never got an overflow.
 
Or instead of just blasting the bytes to the receiver a ack/nak
protocol can be implemented that limits the blasts to a managable size
that fits in the buffer.
 
Hi,

Is this an internal serial port or external? Some manufacturers disable HW
handshaking on internal hardware (to be used with ActiveSync).

--
Richard Grier, MVP
Hard & Software
Author of Visual Basic Programmer's Guide to Serial Communications, Fourth
Edition,
ISBN 1-890422-28-2 (391 pages, includes CD-ROM). July 2004, Revised March
2006.
See www.hardandsoftware.net for details and contact information.
 
Also, you need to make sure that you are using a full cable connection.
Note, what I said about the internal port limitation on some hardware.
However, if you are using a null modem adapter, some adapters loop RTS back
to CTS on the same side, instead of crossing it over between sender and
receiver. Check your cable or adapter for this issue.

--
Richard Grier, MVP
Hard & Software
Author of Visual Basic Programmer's Guide to Serial Communications, Fourth
Edition,
ISBN 1-890422-28-2 (391 pages, includes CD-ROM). July 2004, Revised March
2006.
See www.hardandsoftware.net for details and contact information.
 
Hi,

Well, that's one of the things that a protocol like XMODEM does. It doesn't
rely on hardware handshaking, because the transmit data packet size is 128
bytes (plus overhead).

Dick

--
Richard Grier, MVP
Hard & Software
Author of Visual Basic Programmer's Guide to Serial Communications, Fourth
Edition,
ISBN 1-890422-28-2 (391 pages, includes CD-ROM). July 2004, Revised March
2006.
See www.hardandsoftware.net for details and contact information.
 
Back
Top