Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] voltage detect on avr

Status
Not open for further replies.
thanks alexan that was it ...
but i made the changes and it still didn't work the led is lightning in all cases & all the time.
i think i found the error:
i rewrite the code to this:
Code:
#include <util/delay.h>
#include <avr/io.h>
#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT)) 
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT)) 
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))
int main(void)
{
float vcc,adc;
DDRD=0xFF;
PORTD=0x00;
ADMUX=0b00011110;
ADCSRA = (1<<ADEN)|(0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // prescaler = 8
 while(ADCSRA&(1<<ADSC))
    {
	SETBIT(PORTD,1);
	_delay_ms(1000);
	CLEARBIT(PORTD,1);
	_delay_ms(1000);
}	//wait for convertion to complete
adc=ADC;
vcc = 1.22 * 255 /adc;
if(vcc<3.5)
SETBIT(PORTD,5);
else CLEARBIT(PORTD,5);
}
i made the conversation goes too slowly by making the division factor = 8...
so while converting a led in port d,1 will be lightning on and off
and then if the Vcc < 3.5 another led on portd,5 will light otherwise it will turn off....
but what is happening is that nothing is lightning at all since i power the MCU it should at least light the led D,1 on and off for once....
So is the problem that the MCU isn't converting at all?!?!?!?!
 

@foxbrain
this code doesn't seem to be correct
Code:
adc=ReadADCValue();    
vcc = 1.22 * 255 / adc;
the standard way to calculate the voltage would be Vcc = Vref * ADCresult/ 1023 (for 10 bit), your equation will give a higher result as the adc value gets lower


@alexxx
the provided code can be simplified if you read the result of the adc directly using ADCW (it is already defined in winavr), in that case you can also remove the union
Code:
uint16_t ReadADCValue (void)
{
  [COLOR="#D3D3D3"]// volatile Value16Bit_t	adcVal;[/COLOR]
	
  ADCSRA |= ((1<<ADEN) | (1<<ADSC));	//enable and start ADC
  while(ADCSRA&(1<<ADSC))
    ;	//wait for convertion to complete
	
[COLOR="#D3D3D3"] // adcVal.low = ADCL;  
 // adcVal.high = ADCH;[/COLOR]
	
  ADCSRA &= ~(1<<ADEN);	//Disable ADC
		
  return ADCW;
}

Alex
 

alexan_e said:
the provided code can be simplified if you read the result of the adc directly using ADCW (it is already defined in winavr), in that case you can also remove the union
Hi Alex, I'm not aware of ADCW, I searched AVR datasheet but no results came. I use IAR EW compiler and gives me error with the use of ADCW. Maybe this is only for winavr?

@foxbrain
uint8 or uint16 is just a way to give you an idea of what kind of variable to use.
You could write
#define uint8 unsigned char
or you could just replace with known C variable types:
volatile unsigned char dummyH, dummyL;

Anyway I assumed it was obvious but I guess I was wrong.:)

Furthermore your code at post #21 misses a main loop.
The code of post #19 will not work either, because you update ADC and calculate vcc only once before main loop, so vcc value will never be updated.
Finally you now use channel 1, not VBG (is VCC connected to your PA1 pin?). So you must change the vcc calculation as Alex suggested.

Post #19 code could be modified as follows:

Code:
int main(void) 
{
   	DDRD = DDRD | (1<<PD5); //set PB0 as output (for the LED).
	uint16_t adc;
	InitADC();

   	while(1) { // Infinite loop
        adc = ReadADCValue();
        vcc = Vref * adc / 1023;  //Replace Vref with your board's Vref in mV, and you have a vcc result in mV

       	if (vcc < 3700)
        {
            PORTD |= (1<<PD5);
        }
        else
        {
            PORTD &= ~(1<<PD5);
        }

        _delay_ms(40);  //it is good to keep a time distance between measurements
    }
}

PS: Don't try to measure vcc on the PA1 pin, unless you change your reference to 2.56V (REFS0=REFS1=1 plus an external cap on AREF pin). Instead keep vcc steady and try to change the analog value on this pin with a potentiometer.


Hope that helped.
 

Hi Alex, I'm not aware of ADCW, I searched AVR datasheet but no results came. I use IAR EW compiler and gives me error with the use of ADCW. Maybe this is only for winavr?

I haven't used IAR but I know it is already defined in codevision and winavr.
You can't find it in the datasheet because it is not a register name, it is just a way to access two (contiguous) 8bit registers as one of 16bit

in winavr it is defined
Code:
#define ADCW	_SFR_IO16(0x04)
#define ADCL    _SFR_IO8(0x04)
#define ADCH    _SFR_IO8(0x05)

and in codevision
Code:
sfrb ADCL=4;
sfrb ADCH=5;
sfrw ADCW=4;      // 16 bit access

if you check the header in IAR you can probably define it yourself (maybe it is already defined with another name)

Alex
 

Referring to ADCW means that you are referring to ADCH:ADCL as a 2-byte (16-bit) register. This is equivalent to writing
Code:
ADCW = (ADCH << 8) | ADCL;

Hope this helps.
Tahmid.
 

PS: Don't try to measure vcc on the PA1 pin, unless you change your reference to 2.56V (REFS0=REFS1=1 plus an external cap on AREF pin). Instead keep vcc steady and try to change the analog value on this pin with a potentiometer.
so i should replace in the equation 2.56 instead of Vref , and (1<<REFS0) , (1<<REFS1) and connect PA1 to Vcc but what do u mean by: external cap on AREF pin? in datasheet they wrote : internal 2.56 voltage with external capacitor at AREF pin...so to where should i connect the capacitor + and what is the value of it?
thanks
 

To be able to obtain good accuracy with the ADC the analog supply voltage must be decoupled separately, in the same manner as the digital supply voltage. AREF must also be decoupled, a typical value for the capacitor is 100nF.

http://www.atmel.com/dyn/resources/prod_documents/doc2521.pdf

Disconnect the AREF pin from VCC and connect the capacitor from pin to ground.
VCC goes to the PA1 pin through a voltage divider. Use two 4K7 resistors. The equation would then be

vcc = 2*(2.56*adc/1023), the result will be in Volts.
 
it finally worked.:razz:
thank you guys...........................
 

I realize I am posting on a VERY old thread. I am having the exact same problem you were, and using almost the exact same code. Any way you can post your full solution if you get a chance! I would be eternally grateful!!
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top