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.

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

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

After shifting level a bit higher it looks fine again:

And then the pattern repeats:

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.

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

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


volatile uint8_t adcLow;

int main(void) {
....
while (1) {
}
}
}

}

• Have you tried using a different pot? – Ignacio Vazquez-Abrams Oct 17 '13 at 18:43
• Yes, I have. The pot does not cause the problem. – Ashton H. Oct 17 '13 at 18:46
• 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? – Tom L. Oct 17 '13 at 18:58
• When using avr-gcc you can use the following shortcut: uint16_t adcValue = ADC; – jippie Oct 17 '13 at 19:11
• 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. – Ashton H. Oct 17 '13 at 19:11

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.

• 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. – Ashton H. Oct 17 '13 at 19:05
• Bitten by the type-casting bug then? – jippie Oct 17 '13 at 19:07
• This might be the case. I am converting received values like this: int value = (buffer[i + 1] << 8 | (buffer[i] & 0xFF)) in Java. – Ashton H. Oct 17 '13 at 19:15
• 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 – Ashton H. Oct 18 '13 at 16:15
• Wait .. isn't uint8_t [0, 255], and int8_t [-128, 127] ? Wasn't the U making the type unsigned ? – hingev Nov 9 '14 at 11:14