Z MAM wiki

Přejít na: navigace, hledání

Semester work.

Exercise: Monitor power supply voltage.


While apparently being a very simple task, measuring the voltage of the power supply of your micro-controller can be very important and critical, specially for battery powered applications.

There are many ways to monitor the battery voltage level, many of them propose to add some external components. This solution don't need any external components, for all the AVR micro controllers that have an internal ADC.

MController type: ATMEGA48. (it'll also work on ATMEGA88,ATMEGA168,ATMEGA368)

Schematic: Soubor:Example.jpg

We are using 3 NiCad batteries for controller supply. Voltage with fully charged batteries is 4.2 V. It is necessary to built in LED diode (Port PB0)to show us that voltage is lower than 3.2 V.

So, to solve this problem, without adding any external component,s AVR micro controller has a very useful feature called “internal band gap reference voltage”. The band gap reference is a voltage of about 1.1V, which remains constant, even if the Vcc voltage of the micro controller changes. The B.G. (Band Gap) Voltage can be fed to the ADC like any other external voltage, except it can be done 100% programmatically, that is, with out any external connections.

First, let’s take a look at the logic. If we look at it from a mathematical point of view, we will surely understand the problem. In general, the relation between measured voltage and Digital converted value for an 8-bit ADC is as follows:

ADC_VALUE = V_measure * 255/V_REF

ADC_VALUE = V_BG * 255/V_REF - using B.G.

Vcc = 1.1 * 255/ADC_VALUE - because we know that B.G. is 1.1

There are some reasons why Band Gap based program will not work in 99% of the cases, there is one symptom and one solution: code needs some calibration in order to function correctly. The Band Gap voltage can be different from a component to another, especially if they do not come from the same batch (of 1.2V and other of 1.01V.)

So, If the Vcc that is calculated from the code above is not correct, here is what to do: Measure Vcc with a volt meter, and using this equation, knowing the value of “ADC_VALUE”, retrieve the value of V_BG:

ADC_VALUE = V_BG * 255/Vcc

Then simply replace the “1.1″ band gap voltage with the one that was calculated.


'#'include <avr\io.h>

'#'include <avr\interrupt.h>

// Global variables

float vcc;//variable to hold the value of Vcc

void setup_adc(void) {

   ADMUX = 0xE; //Set the Band Gap voltage as the ADC input
   ADCSRA = (1<<ADEN)|(1<<ADATE)|(1<<ADIE)|(1<<ADSC)|5;


ISR(ADC_vect) //ADC End of Conversion interrupt

{ unsigned char adc_data;

adc_data = ADC>>2; //read 8 bit value

vcc = 1.1 * 255 / adc_data; }

// *********************************************************** // Main program // ***********************************************************

int main(void) {

   DDRB = DDRB | (1<<PB0); //set PB0 as output (for the LED).
   sei(); //Activate interrupts
   setup_adc(); //setup the ADC
   while(1) { // Infinite loop
       if (vcc < 3.2)
           PORTB |= (1<<PB0);
           PORTB &= ~(1<<PB0);


Osobní nástroje