ADC and timing

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Freaks,

I get a bad server request error 400 everytime I try to post in the AVR forum. So I am posting my question in here. Moderators, please move this to the AVR forum.

< Done; Plons >

Hi Freaks,

I am measuring a voltage on an ADC pin on my M328P AVR at 8MHz.

I have attached my code, I think the browser kept rejecting my post because of something in the code.

This is the relevant part of the code. I am measuring a diode drop for certain pins of an IC. Each timer pulse is 500 ms. When I increment PORTC, I am selecting the particular MUX line that will complete the path to GND for the ADC input (basically switch GND). I have a pull up on the ADC input pin to 5V to set the current.

I set a flag in my timer interrupt and display the value through an RS232 connection to my PC.

I am also waiting 100 ms before every ADC conversion.

My problem is some pins read voltages that are very close to GND. (about 50 - 100 mV above GND) and the ADC is reading them as 0V.

I would like the ADC to measure this low voltage and report it back to my PC.

How can I achieve this? Is this because I may be sampling the ADC input at the wrong time? I do the MUX GND switching before the ADC read but maybe this timing is critical?

Thanks.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The well known Forum posing bug:
You cannot post a percent-sign followed by a letter.

Most C printf() format strings contain this type of sequence. There are several alternatives.

1. replace the % by a #
2. replace the % by 'percent'

Note that many number formats use width modifier digits, so you can get away with:

printf("number is formatted with a width of %02d\n", width);

It is a pain but it is easier to do a swift edit than to attach files.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
ADCSRA |= (1 << ADSC);
ADC_dummy = ADC;

You start conversion but you don't wait for it to complete. You should either use an ADC interrupt, or wait until (ADCSRA & _BV(ADIF)) != 0.

The Dark Boxes are coming.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Pat, if you edit the % sign out, I will move the thread

Nard

A GIF is worth a thousend words   They are called Rosa, Sylvia, Tricia, and Ulyana. You can find them https://www.linuxmint.com/

Dragon broken ? http://aplomb.nl/TechStuff/Dragon/Dragon.html for how-to-fix tips

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks, guys.

Plans, here is my code with the percent sign removed:

void timer_init()
{

    TCCR1B |= (1 << WGM12);
    TIMSK1  |= (1 << OCIE1A);

    sei();

    OCR1A = 5000; 

     TCCR1B |= (1 << CS12) | (0 << CS11) | (0 << CS10);

}

ISR(TIMER1_COMPA_vect)
{
PORTC += 1;
flag = 1;
}


int main (void)
    {

       
	   DDRC = 0x0F;//SELECT OUTPUT FOR PORTC use port C to select MUX lines
	   PORTC = 0x00;

           USART0_init();
	   ADC_init(); 
	   timer_init();

          for(;;)
            {
			  	  
	             _delay_ms(100);
			  
         	     ADCSRA |= (1 << ADSC);
						    ADC_dummy = ADC;
						                          ADC_buffer_dummy = ADC_dummy * 5;
		     a = ADC_buffer_dummy/1000;
                     b = ADC_buffer_dummy%1000;
                     if(flag==1)
	               {
						                              printf("Pin d value = d.dV \n",pin_count,a,b);
                          flag = 0;
                       }
              }
    }

@svofski,

I understand, but I am getting all correct values for the other pins. I verified using a curve tracer. I have a group of pins that have diode drops very close to zero volts which I have also confirmed using a curve tracer and would like to read them with my AVR. I will also try waiting for conversion complete.

edit: Also I am using the ADC in free running mode with a 100 ms delay before I pick up the ADC value. Would I still need to poll it?

Last Edited: Sat. Dec 12, 2009 - 04:32 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your subjectively correct reading may be a product of multiple errors =)

The Dark Boxes are coming.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
       ADC_init();

And what does this function look like?

Quote:
Also I am using the ADC in free running mode

Then there is no need to continually set the ADCS bit.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok I added the (ADCSRA & _BV(ADIF)) != 0 and I still get about 0V for the one pin that should read about 0.1V.

Here is what my ADC_init looks like:

void ADC_init()

{
   ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADATE); 
   ADMUX = (1 << REFS0) | (1 << MUX2) | (1 << MUX0); // Set ADC reference to AVCC,select channel 5
   //using all 10 bit of ADC; so do not left justify the ADC value
   DIDR0 = (1 << ADC5D); //turn off the digital driver
   // No MUX values needed to be changed to use ADC0
   ADCSRA |= (1 << ADEN);  // Enable ADC
}

I have 8MHz as my clock frequency. With a divide by 128, I am getting 62.5ksps in one second (decided by my timer interrupt and updated in the USART).

Should I average out the ADC readings?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
DIDR0 = (1 << ADC5D); //turn off the digital driver 

What is this register? Some alias for DDR(A/B/C)? I can't find anything like this in the datasheet.

The Dark Boxes are coming.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

npat_avr wrote:

I have 8MHz as my clock frequency. With a divide by 128, I am getting 62.5ksps in one second (decided by my timer interrupt and updated in the USART).

Should I average out the ADC readings?

I have used the ADC of an AT90PWM3B in the past, it was clocked with the 8MHz internal RC oscillator and the ADC clock divider was set to 4, to generate an ADC clock of 2MHz. The conversion time was about 8us, so I got a sample rate of about 125ksps. The sample noise was about 1LSB with an external reference voltage of 3.9 Volt. So averaging doesn't seem to be necessary to me.

"Digital is a special case of analog" - George Philbrick

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

svofski wrote:

DIDR0 = (1 << ADC5D); //turn off the digital driver 

What is this register? Some alias for DDR(A/B/C)? I can't find anything like this in the datasheet.


DIDR0 – Digital Input Disable Register 0, datasheet section 23.9.5:
When this bit is written logic one, the digital input buffer on the corresponding ADC pin is disabled.
The corresponding PIN Register bit will always read as zero when this bit is set.

/Martin.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Weird, it seems to be 48,88.. specific. What is the point of this register and how other AVR's manage without one?

The Dark Boxes are coming.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

svofski wrote:
Weird, it seems to be 48,88.. specific. What is the point of this register and how other AVR's manage without one?

It reduces the power-consumption by turning off the digital buffer.
Several AVR's have this register (at least ATmega48(P), ATmega1284P, ATmega164P, ATmega165P, ATmega325(P), ATmega329, ATmega406, ATmega640, ATmega8HVA, AT90CAN128, AT90PWM, AT90USB, ATtiny13, ATtiny2313, ATtiny24, ATtiny25, ATtiny48).
I don't know, how the other AVR's manage it.

/Martin.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I had no idea. Live and learn!

The Dark Boxes are coming.