1
\$\begingroup\$

I am sending ADC results from an ATmega16 controller to a PC through CP2102. Baudrate: 0.5Mb/s, 8 data-bits, 1 stop bit, no parity. I've written a software to visualize received data. Here is an example of ADC results from sampling a sine wave signal:

chart

At some point my PC was under heavy load and this is the result that I had:

chart_spikes

In my previous question I assumed that these spikes were caused by the ADC itself. However it is clearly seen now that these spikes are caused by transmission errors.

As far as I understand this problem occurs due to the overflow of CP210 TX buffer. Is my assumption correct? And if so, what can be done to prevent this?

Besides these spikes I've also found another problem. I am sending two bytes consecutively (ADCL and ADCH). What I've noticed is that sometimes the received bytes are swapped (i.e. ADCH is received before ADCL).

I've dumped some data where the spikes occur (first byte is ADCH, second is ADCL and the number is the resulting integer value)

Example 1:

821 : 00000011, 00110101
803 : 00000011, 00100011
783 : 00000011, 00001111
1018 : 00000011, 11111010
740 : 00000010, 11100100
718 : 00000010, 11001110
694 : 00000010, 10110110

Example 2:

229 : 00000000, 11100101
237 : 00000000, 11101101
246 : 00000000, 11110110
255 : 00000000, 11111111
10 : 00000000, 00001010
276 : 00000001, 00010100
289 : 00000001, 00100001

Update: added usart initialization routine

#define F_CPU 16000000UL
#define USART_BAUDRATE 500000
#define BAUD_PRESCALE ((F_CPU / (USART_BAUDRATE * 16UL)) - 1)

void USARTInit() {
    UBRRH &= ~(1 << URSEL);
    UBRRH = (unsigned char) (BAUD_PRESCALE >> 8);
    UBRRL = (unsigned char) BAUD_PRESCALE;
    UCSRB = (1 << TXEN) | (1 << RXEN) | (1 << RXCIE);
    UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0); // 1 stop bit, 8-bit data length
}

Update: added a simple test for usart

I've disabled ADC and replaced my main routine with a simple loop:

for (uint16_t i = 0; i < 1023; i++) {
    USARTSendByte(uint8_t(i));
    USARTSendByte(uint8_t(i >> 8));
}  

When I start the terminal on my computer and put the system under heavy load (lots of background processes) I sometimes receive results like this:

...
252 : 00000000, 11111100
253 : 00000000, 11111101
254 : 00000000, 11111110
255 : 00000000, 11111111
0 : 00000000, 00000000
257 : 00000001, 00000001
513 : 00000001, 00000010
769 : 00000001, 00000011
260 : 00000001, 00000100
261 : 00000001, 00000101
...
\$\endgroup\$
10
  • \$\begingroup\$ Are you using the internal RC oscillator on an external crystal time base? \$\endgroup\$
    – jippie
    Oct 18, 2013 at 17:01
  • \$\begingroup\$ I'm using a 16MHz crystal \$\endgroup\$
    – Ashton H.
    Oct 18, 2013 at 17:06
  • \$\begingroup\$ It looks like you are reading stop bits 11111010, left most bit is transmitted last. Are you sure the baud rate is accurate? \$\endgroup\$
    – jippie
    Oct 18, 2013 at 17:08
  • \$\begingroup\$ I've added another dump. Yes, baund is 500000. At 16Mhz it is supposed to give 0.0% error according to the datasheet. \$\endgroup\$
    – Ashton H.
    Oct 18, 2013 at 17:13
  • 1
    \$\begingroup\$ Any way you can think of you can verify the oscillator frequency? Does the problem go away if you decrease the baud rate? \$\endgroup\$
    – jippie
    Oct 18, 2013 at 18:24

1 Answer 1

1
\$\begingroup\$

As far as I understand this problem occurs due to the overflow of CP210 TX buffer. Is my assumption correct?

We don't have enough details to answer this - but it sounds highly likely.

And if so, what can be done to prevent this?

The CP210x provides the RS232 handshake signals, e.g. RTS/CTS - but that would require a buffer for the UART data on the ATmega.

Try using a big buffer on the PC side: USB transfers work without much CPU interventions in most cases. Note that you cannot elimitnate the data loss when the PC load is too high, you can only try to migitate it with some sort of protocol.

\$\endgroup\$
1
  • \$\begingroup\$ Great tip, I will try using a bigger buffer on the host side. I still have one question though: how does cp210 perform buffering? Does it have to wait for the host to accept the data before sending another frame? \$\endgroup\$
    – Ashton H.
    Oct 19, 2013 at 16:55

Your Answer

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

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