go away spammer

Author Topic: configuring ADC ports  (Read 9532 times)

0 Members and 1 Guest are viewing this topic.

Offline vidamTopic starter

  • Supreme Robot
  • *****
  • Posts: 423
  • Helpful? 1
  • Robotronics.org
    • DC/MD/VA Robotics and Automation Team
configuring ADC ports
« on: June 13, 2008, 11:21:06 AM »
Hi,

I'm having trouble configuring my ADC ports. I am using the ATmega 168.

I want to know how to set up the ADC for single mode? and for auto prescaler. BTW, what does single mode mean?

The pseudo-code is the following:

// ADC mode = single, prescaler = auto
// Start ADC.

I read the tutorial for ADC on AVRFreaks forum,  but am still not sure how to set ADC mode to single.

Thanks you in advance!

Offline benji

  • Supreme Robot
  • *****
  • Posts: 830
  • Helpful? 0
Re: configuring ADC ports
« Reply #1 on: June 13, 2008, 03:13:27 PM »
maybe you mean single converstion mode , this is when you do a convertion by hand , this means you trigger aquiring data by a function
there are other modes that does auto triggering (using a timer or somthin else)

the datasheet is your best way to fully understand how adc is intiated and work,

and its not long ,, maybe around 10 pages
good ol' BeNNy

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: configuring ADC ports
« Reply #2 on: June 22, 2008, 04:59:07 PM »
Have you looked at adc.h and adc.c in AVRlib?

Offline vidamTopic starter

  • Supreme Robot
  • *****
  • Posts: 423
  • Helpful? 1
  • Robotronics.org
    • DC/MD/VA Robotics and Automation Team
Re: configuring ADC ports
« Reply #3 on: June 22, 2008, 05:53:21 PM »
a2d.c and a2d.h are the files I have in AVRlib. I was able to figure out what the registers are set to use the simulator in BASCOM-AVR and then comparing that to the registers in AVRStudio to make sure they match. It is not the most scientific way of converting code from BASIC to C, but it works.

Offline DomoArigato

  • Full Member
  • ***
  • Posts: 54
  • Helpful? 1
Re: configuring ADC ports
« Reply #4 on: June 23, 2008, 08:43:09 AM »
I've tried both modes, what you probably want to do is single conversion mode.  When you want to get a reading from your sensor start a conversion, then in your ADC interrupt subroutine store that conversion so you can use it.  The continuous mode was far to rapid and took up too much the the AVR's resources for me. Maybe this will help, this is for the ATmega 128.  The key is just setting the flags correctly.  Here is one function to start a conversion, and the interrupt routine that will be called when the conversion is done.  When you want to get another reading, just start another conversion.  I would make sure your waiting a little bit of time (very little) to make sure the conversion is complete before you call another one.

Code: [Select]
void adcSingleConversion(AdcChannel channel)
{
// Set ADC channel.
ADMUX |= channel;
// Set ADC to single conversion mode.
ADCSRA |= ADC_SINGLE_CONVERSION_MODE;
// Start the conversion.
ADCSRA |= ADC_START_CONVERSION;
// Enable ADC interrupts.
ADCSRA |= ADC_INTERRUPT_ENABLE;
// Enable global interrupts.
SREG |= GLOBAL_INT_MASK;
}

ISR(ADC_vect)
{
// Convert ADC result to centimeters, anything over 150 cm is infinite range.
adcResult = IR_CONVERSION_CONSTANT/(ADCL|ADCH<<8);

// Store the scan into the array.
scan[scanIndex++] = adcResult;
servoAngle += servoDirection;
}
« Last Edit: June 23, 2008, 08:54:38 AM by DomoArigato »

Offline vidamTopic starter

  • Supreme Robot
  • *****
  • Posts: 423
  • Helpful? 1
  • Robotronics.org
    • DC/MD/VA Robotics and Automation Team
Re: configuring ADC ports
« Reply #5 on: June 23, 2008, 09:08:04 AM »
The math for determining the ADC prescaler value isn't hard. But how they come up with the numbers can be confusing.

The system clock frequency (fosc) is 20 MHz for the atmega168

Then on the datasheet for atmega168
on page 258 the prescaler bits are set to choose a division factor.

If I choose 64 as the prescaler factor then

20 MHz / 64 = 312Khz

My question is on whether the system clock frequency 20 MHz is the same as the xtal frequency. If not what is xtal frequency and where is it in the datasheet?

Offline vidamTopic starter

  • Supreme Robot
  • *****
  • Posts: 423
  • Helpful? 1
  • Robotronics.org
    • DC/MD/VA Robotics and Automation Team
Re: configuring ADC ports
« Reply #6 on: June 23, 2008, 09:30:25 AM »
Never mind the last post ... the datasheet says that the ADC clock frequency must be between 50kHz - 200kHz and that it derives this frequency from the system clock and a division factor that is called the prescaler.

so if

20MHz / 64 = 312kHz which is too high of a frequency for the ADC chip

so

20MHz / 128 = 156khz which is perfect in the range above.


Offline vidamTopic starter

  • Supreme Robot
  • *****
  • Posts: 423
  • Helpful? 1
  • Robotronics.org
    • DC/MD/VA Robotics and Automation Team
Re: configuring ADC ports
« Reply #7 on: June 23, 2008, 10:27:05 AM »
I've tried both modes, what you probably want to do is single conversion mode.  When you want to get a reading from your sensor start a conversion, then in your ADC interrupt subroutine store that conversion so you can use it.  The continuous mode was far to rapid and took up too much the the AVR's resources for me. Maybe this will help, this is for the ATmega 128.  The key is just setting the flags correctly.  Here is one function to start a conversion, and the interrupt routine that will be called when the conversion is done.  When you want to get another reading, just start another conversion.  I would make sure your waiting a little bit of time (very little) to make sure the conversion is complete before you call another one.

Code: [Select]
void adcSingleConversion(AdcChannel channel)
{
// Set ADC channel.
ADMUX |= channel;
// Set ADC to single conversion mode.
ADCSRA |= ADC_SINGLE_CONVERSION_MODE;
// Start the conversion.
ADCSRA |= ADC_START_CONVERSION;
// Enable ADC interrupts.
ADCSRA |= ADC_INTERRUPT_ENABLE;
// Enable global interrupts.
SREG |= GLOBAL_INT_MASK;
}

ISR(ADC_vect)
{
// Convert ADC result to centimeters, anything over 150 cm is infinite range.
adcResult = IR_CONVERSION_CONSTANT/(ADCL|ADCH<<8);

// Store the scan into the array.
scan[scanIndex++] = adcResult;
servoAngle += servoDirection;
}

DomoArigato,

Thanks for the tip on using single conversion mode! I have 16 sonar and I'm sure this will speed up the analog processing of them all.


 


Get Your Ad Here

data_list