Measuring the ADC Noise (Deflection) and Introduction to the ADC Noise Reduction Mode

Measuring the ADC Noise (Deflection) and Introduction to the ADC Noise Reduction Mode

Let's measure the amount returned to us by Mrs. ADC. Is she being a good clerk, or is she baffled with all of the noise around her. We can find out exactly! Just determine the difference from each of her responses and add it all up in the end. We are doing this to see how well Mr. Cap and the brothers in that family launder the currency the best and keep the currency in Mrs. ADC's hands fast enough for us to use her returned number currency. We need this number currency pretty fast because we may have some critical systems that we need to keep stable. For instance, we may need to feed this information to a balancing robot that is charged to keep the enemy aliens at bay without falling down and failing at his duties.

Let's get scientific with the ADC. If we keep the voltage currency as level as possible from Mr. Gravity (the accelerometer) then we can determine how well Mrs. ADC is responding with her number currency. Because of all the n oises around her, we don't really know what she will give us. So, when she gives us a response, remember that response and then when she gives another response, we can subtract the one we remembered and the one that we just received. Now we have a delta (the difference between the remembered response from Mrs. ADC and the new response). Now we can forget that remembered response, because we now have the delta in our back pocket, but we need to remember the new response for the next response we will get. We will keep all of these deltas that we collected and add them all up.

The remembered response is:

static volatile uint16_t previousResult = 0;

and later used in the interrupt routine like this:

previousResult = theTenBitResults;

The assignment of theTenBitResult is done only after the sample of the difference of the previous and current result is determined.

The static volatile is used so that the variable will not be "optimized out" by the compiler (the mechanism that turns our code into a .hex file that the microcontroller can understand). I have found that this static volatile is needed when the variable will be used in interrupt routines.

The uint16_t is the datatype used because the previous result can be as high as the result, which is a 10-bit number.

The deflection (difference from the previous response and the current response) is declared in the interrupt routine becuase it is local to the interrupt routine. In other words, the number will be used in a total summation in the variable "totalDeflectionOverTime" so don't need to remember the deflection variable outside of the interrupt routine.

int deflection = theTenBitResults - previousResult;
if (deflection < 0 ) deflection = previousResult - theTenBitResults;
Send_An_IntegerToMrLCD(13,2,deflection, 4);
...
totalDeflectionOverTime += deflection;

The deflection is declared as an int because we need to know if the subtraction it does is negative or positive. We can't use uint8_t or uint16_t because those are always positive numbers. Since we always want positive numbers in the end, we need to know if the subtraction will create a negative number so we can reverse the subtraction problem.

The variable totalDeflectionOverTime is the total of all of the differences, but only for a set number of samples, so we can compare apples to apples with other components such as Mr. Cap and his brother Caps (various Capacitor values) and how well they can clean our voltage curency.

We needed to hire an intern to stand next to Mrs. ADC with a clicker (a counter) to count how many samples we are getting so the intern can inform us when to display our total and zero the totalDeflectionOverTime variable so we can start all over.

If all of this were to be put together in a concise program, it might look like this:

#include
#include
#include "MrLCD.h"
static volatile uint16_t previousResult = 0;
static volatile int totalDeflectionOverTime = 0;
static volatile uint16_t sampleCount = 0; int main(void)
{
InitializeMrLCD();
Send_A_StringToMrLCDWithLocation(1,1,"ADC Result:");
Send_A_StringToMrLCDWithLocation(1,2,"Deflection:");
Send_A_StringToMrLCDWithLocation(1,3,"Total:");

ADCSRA |= 1< ADMUX |= (1< ADCSRA |= 1< ADCSRA |= 1<
sei();

MCUCR |= 1< MCUCR |= 1<
ADCSRA |= 1<
while (1)
{
}
}
ISR(ADC_vect)
{
uint8_t theLowADC = ADCL;
uint16_t theTenBitResults = ADCH<<8 | theLowADC;
Send_An_IntegerToMrLCD(13,1,theTenBitResults, 4);

int deflection = theTenBitResults - previousResult;
if (deflection < 0 ) deflection = previousResult - theTenBitResults;
Send_An_IntegerToMrLCD(13,2,deflection, 4);
previousResult = theTenBitResults;
totalDeflectionOverTime += deflection;

sampleCount++;

if (sampleCount >= 300)
{
Send_An_IntegerToMrLCD(8,3,totalDeflectionOverTime, 6);
totalDeflectionOverTime = 0;
sampleCount = 0;
}

ADCSRA |= 1<
}
Back to blog

Leave a comment

Please note, comments need to be approved before they are published.