6
\$\begingroup\$

I am building a hobby oscilloscope on ATmega16. I am testing ADC by generating a square wave at 2kHz with small amplitude and applying it to the ADC pin through a capacitive input with a voltage divider to shift zero-level.

schematic

This is how the signal looks after being sampled by ADC: schematic

It looks fine, but after I start shifting zero-level by adjusting the potentiometer I get these strange spikes: schematic

After shifting level a bit higher it looks fine again: schematic

And then the pattern repeats: schematic schematic schematic

Overall, I get 3 ranges where the spikes appear.

Some info

  • AVR is running at 16MHz
  • ADC uses internal 2.56 reference voltage
  • ADC is in free running mode at 125kHz (prescaler=128)
  • I transfer data via CP210 to an android tablet which is used for real-time plotting. The circuit is also powered from the tablet. I get the same results when the circuit is connected to PC.
  • USART baudrate is 500000b/s (UBRR=1)
  • AVcc and AREF are not connected. I also tried connecting AVcc to Vcc and adding a .1uF cap between Gnd and AVcc but this had no effect.

Some more info

  • this noise does not come from the generator (tested with analog oscilloscope)
  • this noise does not come from the potentiometer
  • LFUSE = 0xFF, HFUSE = 0x89.

ADC initialization routine

ADMUX = (1 << REFS0); // AVCC with external capacitor at AREF pin
ADCSRA = (1 << ADEN)
        | (1 << ADIE)
        | (1 << ADATE) 
        | (1 << ADPS0)
        | (1 << ADPS1)
        | (1 << ADPS2); // Division factor = 128
MCUCR |= 1 << SM0;
MCUCR |= 1 << SE; // Sleep-mode enabled
ADCSRA |= (1 << ADSC);

ADC data transfer routine

volatile uint8_t adcLow;
volatile uint8_t adcHigh;

int main(void) {
    ....
    while (1) {
        if (ADCSRA != 0x00) {
            USARTSendByte(adcLow);
            USARTSendByte(adcHigh);
        }
    }
}

ISR(ADC_vect) {
    adcLow = ADCL;
    adcHigh = ADCH;
}
\$\endgroup\$
7
  • 1
    \$\begingroup\$ Have you tried using a different pot? \$\endgroup\$ Commented Oct 17, 2013 at 18:43
  • \$\begingroup\$ Yes, I have. The pot does not cause the problem. \$\endgroup\$
    – Ashton H.
    Commented Oct 17, 2013 at 18:46
  • \$\begingroup\$ Is it a single data point in your data or are there multiple datapoints that make up that spike. Or put differently: Is it just one single measurement causing the spike? Also: Does that also happen when you sample with a lower speed? \$\endgroup\$
    – Tom L.
    Commented Oct 17, 2013 at 18:58
  • \$\begingroup\$ When using avr-gcc you can use the following shortcut: uint16_t adcValue = ADC; \$\endgroup\$
    – jippie
    Commented Oct 17, 2013 at 19:11
  • \$\begingroup\$ I don't have a generator right now so I will have to test this tomorrow. Sampling at a lower speed is not possible because the prescaler is 128 (which is the highest possible value). However I did try using a slower usart baundrate but it didn't help. \$\endgroup\$
    – Ashton H.
    Commented Oct 17, 2013 at 19:11

1 Answer 1

6
\$\begingroup\$

The spikes are clearly clipping to very particular values (probably a power of two) or you are using signed integers that are too small to contain the whole value.

You didn't supply full source code so I'm guessing here. You probably try to fit the measured value into a too small integer. Make a dump of the vaules you get and find the peaks in them. Then look at the binary representation of these numbers and see if you can find something in common.

With quick estimation the distance between two peaks is about 1.28V, a little bit too coincidentially close to the size of a signed 8 bit integer.

I advice to use type definitions like int8_t [-128:127], uint8_t [0:255], int16_t [-32768:32767], uint16_t [0:65535], int32_t [-2147483648:2147483647] and uint32_t [0:4294967295], which clearly shows how large the variable is.

\$\endgroup\$
6
  • \$\begingroup\$ Sorry, I've updated my question with source code. adcLow and adcHigh are of uint8_t type so the size is sufficient to hold ADC values. \$\endgroup\$
    – Ashton H.
    Commented Oct 17, 2013 at 19:05
  • \$\begingroup\$ Bitten by the type-casting bug then? \$\endgroup\$
    – jippie
    Commented Oct 17, 2013 at 19:07
  • \$\begingroup\$ This might be the case. I am converting received values like this: int value = (buffer[i + 1] << 8 | (buffer[i] & 0xFF)) in Java. \$\endgroup\$
    – Ashton H.
    Commented Oct 17, 2013 at 19:15
  • \$\begingroup\$ You were correct that these spikes are software-related. I've just discovered that they occur due to transmission error. I asked another question here \$\endgroup\$
    – Ashton H.
    Commented Oct 18, 2013 at 16:15
  • \$\begingroup\$ Wait .. isn't uint8_t [0, 255], and int8_t [-128, 127] ? Wasn't the U making the type unsigned ? \$\endgroup\$
    – hingev
    Commented Nov 9, 2014 at 11:14

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.