ADC for the OX2

I am using the Orangutan X2, and I’m having trouble getting a reading from LV-MaxSonar-EZ1 from PA0-PA7. The pins are always reading “zero”. I understand how to initialize and start the the A/D converter:

ADMUX = 0x26;
ADCSRA |= (1 << ADSC );
while ( ADCSRA & ( 1 << ADSC ));

but after that, I don’t completely understand how to gather data from the pins 0-7. Thanks for any help.


If you look at the test demo linked from the X2 page you can see an example of how to use the X2’s ADC, but that needs to be tweaked a little bit if you want to use it for your EZ1. The test demo is set up to monitor the battery voltage and the user trim pot, which are solder-jumpered on the back of your X2 to ADC6 (PA6) and ADC7 (PA7) respectively. Because of these solder jumpers, you should connect your signals to pins PA0 - PA5, or you can use a soldering iron to remove the jumpers and free up pins PA6 and PA7.

To initialize the ADC, you want to set the ADMUX register as follows:

ADMUX = 0x20 + {ADC channel} for 8-bit ADC conversion values
ADMUX = 0x00 + {ADC channel} for 10-bit ADC conversion values

The mega644 can only perform conversions on one channel at a time, so if you want to perform conversions on multiple channels you will need to cycle through them by changing ADMUX after each conversion finishes (before starting the next conversion).

You also want to configure the ADCSRA register to something like:

ADCSRA = 0x87;
setting bit 7 enables the ADC
clearing bit 6 prevents the conversion from starting yet
clearing bit 3 disables the ADC interrupt
bits 0 - 2 determine the ADC clock prescaler, which determines how long the conversions will take

You should look at the mega644 datasheet for more information about this.

So, putting it all together, if you want to measure an analog voltage on pin PA3 with 8-bit resolution, you would do something like the following:

int sum = 0;
int i;
unsigned char average;
ADCSRA = 0x87;
ADMUX = 0x23;
for (i = 0; i < 8; i++)
  ADCSRA |= 1 << ADSC;  // start conversion
  while (ADCSRA & (1 << ADSC));  // wait here for conversion to finish
  sum += ADCH;
average = sum / 8;

In general, you should average a few ADC samples together to smooth out noise and get more reliable results. Once you have your average ADC result for one channel, you can change ADMUX to a different channel and repeat the process over again.

There are several ways to perform ADC conversions, including some fancier methods that use interrupts or periodic polling to allow your MCU to continue doing things while the conversion is being performed (as opposed to waiting in a while loop as in my code above), but the example I’ve given is probably the simplest way to do it.

- Ben

Thanks for your help. It is greatly appreciated