ADC voltage referance not behaving as expected

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

Hello all. I have a very simple setup that was working great untill I changed the voltage referance settings on my ATMEGA48.

The goal of the system is to read a small voltage on the ADC and send the raw reading to the UART. It is a very simple circuit.

When I had the referance voltage set to AVcc the systme worked great, but when I changed the referance voltage to use the AREF pin, the ADC always converts to 1023. When I measure the voltage at ADC PIN0, I get 91 mV. When I measure the voltage at AREF I get 183 mV. I am using a high impedance multimeter (Fluke 16). Vcc is 3.28 Volts.

The AREF voltage is supplied by a voltage divider that uses 20 OHM and 340 OHM resistors.

Any help is greatly appreciated.
-Daniel

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

Quote:
The AREF voltage is supplied by a voltage divider that uses 20 OHM and 340 OHM resistors.
That sucks up a bit of current, they can be 10 times higher.

May want to post your code just in case it is NOT doing what you think it should be doing.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Voltage divider of 340 ohms and 20 ohms is WAAY to small value. Assuming this is connected to 5V, your current is 3.28V/(340+20) = 3.28/360 = 9.1ma.

Second, the ADC has a lower limit on the allowed reference voltage. You don't say which processor you are using. Looking at a Mega88p (in the ADC Characteristics section of Electrical Characteristics), for example, the minimum is 1.0V. I suspect that you are well below the Vref operating limit for your ADC.

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

Quote:
You don't say which processor you are using
You want to try reading again? :)

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Uhhhh OK.. Mega48.. Duhh.

ADC reference still has a minimum acceptable value.

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

ka7ehk wrote:
Voltage divider of 340 ohms and 20 ohms is WAAY to small value. Assuming this is connected to 5V, your current is 3.28V/(340+20) = 3.28/360 = 9.1ma.

Second, the ADC has a lower limit on the allowed reference voltage. You don't say which processor you are using. Looking at a Mega88p (in the ADC Characteristics section of Electrical Characteristics), for example, the minimum is 1.0V. I suspect that you are well below the Vref operating limit for your ADC.

Jim

Thanks for the tip. I looked up the min acceptable VREF voltage and it is indeed 1.0 Volts. I will reconfigure to use the 1.1V internal regulator. I still don't understand why I am getting 1023 and not something closer to 0.

As far as the resistance values, I was fully aware of the unnecessary current draw, this is a quick and dirty project and I was just using the parts that I have on hand. I am not planning on trying to get an energy star rating on this one ;)

Here is my code. I recommend veiwing it in full screen mode for maximum veiwing pleasure.

#include 
#include 
#include 
#include 
#include "Initialize.h"

#define F_CPU 8000000  // Note: if this is changed, A/D settings must change
#define BAUD 57600
#define DOUBLESPEED 1
#define UBRR ((uint16_t)(F_CPU/((2 - DOUBLESPEED)*8.0*BAUD) - 1 + 0.5))//0.5 is for proper rounding
#define FREQ 500
#define CH0 0
#define CH1 1
#define RANGE 32

volatile uint8_t latch_flag = 0;
volatile uint16_t adata0_f;
uint16_t adata0;
uint16_t adata1;
uint16_t history[RANGE];
uint8_t h_pointer;
uint32_t filter_pool;



ISR(USART_RX_vect)
{
	UDR0 = UDR0;
}

ISR(ADC_vect)
{
		adata0 = ADCW;
		filter_pool = filter_pool - adata0_f + adata0;
		adata0_f = filter_pool>>7;
		transmit_code(0, (adata0));// - 512));
		latch_flag = 1;
		TIFR1 |= (1<<TOV1);//Clear the timer overflow interrupt flag
}

int main(void)
{	
	//Initialize UART*******************************************************************
	UBRR0H = (uint8_t)(UBRR>>8);
    UBRR0L = (uint8_t)(UBRR);
	UCSR0A |= ((1<<U2X0)*DOUBLESPEED); // DOUBLE SPEED MODE (BAUD = XTAL/(8*(UBRR+1)))
	UCSR0B = (1<<TXEN0)|(1<<RXEN0)|(1<<RXCIE0);  //ENABLE UART
	UCSR0C = (3<<UCSZ00);  //8-BIT RS232, 1 STOP BIT, NO PARITY
	
	//Initialize Timer
	TCCR1A = (1<<WGM11)|(1<<WGM10); 		 				 //NON-INVERTED, OCR1A FREQ CONTROL
	TCCR1B = (1<<ICES1)|(1<<WGM13)|(1<<WGM12)|(2<<CS10);   //FAST PWM MODE, PCK=XTAL/8 (PWM FREQ=XTAL/(8*(1+ICR1))), ICP noise canceling, positive edge trigger
	OCR1A = ((F_CPU/(8*FREQ))) - 1;//

	//Initialize ADC
	ADMUX = CH0;  //SET REFERANCE VOLTAGE TO AREF, CHOOSE PIN 0
	ADCSRA = (1<<ADEN)|(1<<ADSC)|(1<<ADATE)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1);  //ENABLES ADC, STARTS 1ST CONVERSION, AUTOTRIGGER, ADCLOCK = XTAL/8
	ADCSRB |= (1<<ADTS2)|(1<<ADTS1);//Select TOV1 as interrupt source.
	
	sei();
	
	while(1)
	{	
		_delay_loop_1(5);
		cli();
		if((TCNT1 > (F_CPU/(16*FREQ))) && latch_flag)
		{
			sei();
			transmit_code(1, (adata0_f));// - 512));
			latch_flag = 0;
		}
		sei();
	}

	return(1);
}