1
\$\begingroup\$

When I send a data stream from my PC to a CP2102 USB-to-Serial Bridge, the data coming out of the RS232 side is sometimes corrupted. The receiving micro (an ATmega2560) reports frame errors when this happens.

I send a command of 30 characters every 180ms. for every 10000 commands there are around 15 to 30 failures.

I use 9600.8N1, so a start bit plus 8 data bits should take 0.9375ms. Flow control is set to None.

It is always the first byte and sometimes (1 in 20) the second byte that is corrupted. I've captured the data on an oscilloscope and measured the byte times (beginning of start bit to beginning of first stop bit).

If I have corrupted data, the time is around 1.000ms. Good data takes between 940us and 960us.

It is always the last few data bits (i.e. the highest bits) and the stop bit that is the problem.

See image below for an example of the second byte being corrupted: enter image description here

The character between the vertical cursor lines should be a 'P', but it takes 1.000ms and is received as 0xd0 instead of 0x50. The byte before it is a '*' (0x2a) and is fine, it takes 0.940us.

What could cause these frame errors?

\$\endgroup\$
7
  • \$\begingroup\$ it seems to be running slow when the output is low, is the power supply to the chip stable?] \$\endgroup\$ Commented Feb 4, 2020 at 3:59
  • \$\begingroup\$ What is the clock source and frequency of the AVR? UBRR value? What program on PC is sending the data? \$\endgroup\$
    – Justme
    Commented Feb 4, 2020 at 5:50
  • \$\begingroup\$ @Justme The AVR clock is an Xtal and its frequency is 11059200Hz. It's specifically for creating baud rates. The UBRRL is 71 and UBRRH is zero. I've also fed the signal coming out of the CP2102N into a CP2102 and it reports the same frame errors as the AVR. The problem is therefore not the AVR; you can clearly see on the scope traces that the signal coming out of the CP2102N has incorrect timing. \$\endgroup\$
    – NZD
    Commented Feb 4, 2020 at 18:08
  • \$\begingroup\$ @Jasen The supply to the chip comes from the USB bus. The chip has the recommended 100n and 10uF caps for decoupling on both the VREGIN and VDD pins, just next to the chip. There is a 50mV ripple on the 5V from the USB. The supply remains stable, even if there is a frame error. \$\endgroup\$
    – NZD
    Commented Feb 4, 2020 at 18:23
  • 1
    \$\begingroup\$ @NZD I just skimmed through the PySerial win32 code the other week. Do you write one byte or buch of bytes at a time? Do you flush the output? It may make a difference. Buffer size may make a difference. Serial timeouts are not controllable unless PySerial win32 code is modified. Anyway it uses asynchronous reading and writing under the hood, so random delays here and there may help. \$\endgroup\$
    – Justme
    Commented Feb 4, 2020 at 20:00

1 Answer 1

2
\$\begingroup\$

I eventually found the problem: It is caused by setting the serial parameters while using the port at the same time.

I read the serial port in a separate thread that calls the following method in a loop:

def read(self):
    serstring = ""
    try:
        if self.is_reading_lines:
            self.serial.timeout = READING_LINES_TIMEOUT
            serstring = self.sio.readline().rstrip()
        else:
            self.serial.timeout = READING_CHARS_TIMEOUT
            serstring = self.serial.read(100)
    except:
        pass
    else:
        if len(serstring):
            self.process_read(serstring)
    return serstring  # if called directly

I use different timeouts for reading lines (responses to commands) and for reading binary data.

I update the timeout attribute before every read, not realising that this results in a call to method _reconfigure_port in file serialwin32.py in the pyserial module.

One of the calls in method _reconfigure_port is to win32.SetCommState. This is the ultimate cause: This affects the hardware of the CP2102 chip and causes it to interfere with outputting serial data on the RS232 port, which causes stretched data bits.

It makes perfect sense that updating the hardware settings interferes with the operation of the chip, even though the settings remain the same.

I replaced updating the timeout attribute in the read method with a separate method to set it only once and this fixed my problem.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.