vadc_usage.c File Reference


Detailed Description

Routines for voltage reference calibration and VADC measurements.

This contain functions for reading out signature row data, bandgap initialisation and bandgap calibration. Functions for start of VADC measurements, interrupt routine for measurements and calculation of cell voltages, vadc inputs and bandgap temperature are also included.

Application note:
AVR353: Voltage Reference Calibration and Voltage ADC Usage.
Documentation
For comprehensive code documentation, supported compilers, compiler settings and supported devices see readme.html
Author:
Atmel Corporation: http://www.atmel.com
Support email: avr@atmel.com
Revision
4814
Date
2008-11-04 12:29:56 +0100 (ti, 04 nov 2008)

Copyright (c) 2008, Atmel Corporation All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. The name of ATMEL may not be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Definition in file vadc_usage.c.

#include <ioavr.h>
#include <inavr.h>
#include "vadc_usage.h"
#include "calibration.h"
#include "ATmega8HVA_16HVA_signature.h"

Include dependency graph for vadc_usage.c:

Go to the source code of this file.

Defines

#define module_vadc_usage   1
 < Define for vadc_usage.h to avoid including the external variables.

Functions

void CalculateADCResults (void)
 Calculate results from the VADC raw values.
int8_t CalibrateVREF (void)
 Voltage reference calibration.
int8_t InitBandgap (void)
 Bandgap initialisation.
void InitCoeff (void)
 Function to load coefficients needed from the signature row.
int16_t MeasureVADCerror (void)
 Measure VADC error.
void StartVADCScan (void)
 Start a scan of all VADC channels.
__interrupt void VADC_ISR (void)
 Interrupt Service Function to measure VADC values.

Variables

uint16_t bg_temp
 Global variable for the result of band-gap temperature measurement/calculation.
uint16_t cell_gain [NO_CELLS]
 Gain coefficients for Cells.
int8_t cell_offset [NO_CELLS]
 Offset for cells.
uint16_t cell_v [NO_CELLS]
 Global variable for results of Cell Voltage measurements/calculations.
uint16_t vadc_gain [NO_VADC]
 VADC channel gain.
uint16_t vadc_measurement [NO_VADC_CHANNELS]
 Global variable for VADC samples. Sized to number of VADC channels.
int8_t vadc_offset [NO_VADC]
 VADC channel offset.
uint8_t vadc_scan_complete
 Flag for signalling VADC sampling complete.
uint16_t vadc_v [NO_VADC]
 Global variable for results of Voltage ADC measurements/calculations.
uint16_t vptat_coeff
 Internal temperature sensor coefficient.


Define Documentation

#define module_vadc_usage   1

< Define for vadc_usage.h to avoid including the external variables.

Definition at line 54 of file vadc_usage.c.


Function Documentation

void CalculateADCResults ( void   ) 

Calculate results from the VADC raw values.

Function uses values from vadc_measurement variable and stores results in global variables cell_v and bg_temp. The formulas are found in the data sheet and details in the application note.

Definition at line 300 of file vadc_usage.c.

References bg_temp, CELL1, cell_gain, cell_offset, cell_v, NO_CELLS, NO_VADC, VADC0, vadc_gain, vadc_measurement, vadc_offset, VADC_SCALE_BITS, vadc_v, VPTAT, and vptat_coeff.

Referenced by main().

00301 {
00302     uint32_t calc;
00303     uint8_t index;
00304 
00305     // Calculate new cell voltages.
00306     for(index = 0 ; index < NO_CELLS ; index++) {
00307         calc = vadc_measurement[index + CELL1];
00308         calc -= cell_offset[index];
00309         calc *= cell_gain[index];
00310         cell_v[index] = (uint16_t)(calc >> VADC_SCALE_BITS);
00311     }
00312 
00313     /* Code checking for under or over-voltage, and/or calculating cell
00314      * impedances could be inserted here.
00315      */
00316 
00317     // Calculate new VADC voltages.
00318     for(index = 0 ; index < NO_VADC ; index++) {
00319         calc = vadc_measurement[index + VADC0];
00320         calc -= vadc_offset[index];
00321         calc *= vadc_gain[index];
00322         vadc_v[index] = (uint16_t)((calc >> VADC_SCALE_BITS)/10);
00323     }
00324 
00325     // Calculate temperature from measurement of internal temp sensor (VPTAT).
00326     calc = vadc_measurement[VPTAT];
00327     calc *= vptat_coeff;
00328     calc >>= VADC_SCALE_BITS;
00329     bg_temp = (uint16_t)(calc);
00330 
00331     /* Code for calculating temperature from external thermistors connected to
00332      * VADC0 and/or VADC1 could be inserted here. Gain and offset coefficients for
00333      * vadc inputs are stored in signature row.
00334      */
00335 }

int8_t CalibrateVREF ( void   ) 

Voltage reference calibration.

Calibrates the bandgap reference. Assumes 4096mV in on PV1 (Cell1). Values in calibration.h have to be adjusted if any other value is used. The reference needs to be calibrated to factory default before performing this calibration, and if it fails the reference is not correct and factory defaults should be used.

Calibration of bandgap at room temperature only needs to be done if device isn't calibrated so in Atmel factory. Otherwise calibration can be done by reading out signature data.

Returns:
Status, SUCCESS or FAILED as defined in vadc_usage.h

Definition at line 353 of file vadc_usage.c.

References CAL_CHANNEL, FAILED, MeasureVADCerror(), SUCCESS, temp_cal, and vcalibration_level.

Referenced by main().

00354 {
00355     volatile uint32_t temp;
00356     int16_t v_error;        // Variable to keep error after conversion.
00357     int16_t last_v_error;   // Value used to keep old error value during linear scan.
00358     int8_t counter;         // Value used to count BGCCR value and index.
00359 
00360     // Select terminal input defined in calibration.h
00361     VADMUX = CAL_CHANNEL;
00362 
00363     // Enable the VADC.
00364     VADCSR = (1 << VADEN);
00365 
00366     // Start a VADC conversion and clear any pending interrupts
00367     VADCSR |= (1 << VADSC) | (1 << VADCCIF);
00368 
00369     // Wait while conversion in progress
00370     do {} while(!(VADCSR & (1 << VADCCIF)));
00371 
00372     // Dummy read to ensure correct data for next conversion.
00373     temp = VADC;
00374 
00375 
00376     /* If using cell balancing (e.g ATmega406, and not on ATmega8/16HVA),
00377      * code should be inserted here to wait for error to cancel out.
00378      */
00379 
00380     // First we do the BGCRR / temperature stability calibration.
00381     v_error = MeasureVADCerror();
00382     counter = 8;
00383 
00384     // Check for all different test limits.
00385     while ( (v_error < vcalibration_level[counter]) && (counter >= 0) ) {
00386         counter--;
00387     }
00388 
00389     // Set BGCRR to correct setting.
00390     BGCRR = temp_cal[counter];
00391 
00392     // Then we do the BGCCR / absolute value calibration.
00393     v_error = MeasureVADCerror();
00394 
00395     if (v_error < 0){
00396         do {
00397             // Ratio_counter bit 6 set means calibration failed.
00398             if(--BGCCR == 0x40){
00399                 // Return with fail flag.
00400                 return FAILED;
00401             }
00402             last_v_error = v_error;
00403             v_error = MeasureVADCerror();
00404 
00405         } while (v_error < 0);
00406 
00407         // Neighbor check, as previous step can select the next best value.
00408         if (v_error > -last_v_error){
00409             BGCCR++;
00410         }
00411 
00412     }else{
00413         do{
00414             // Ratio_counter bit 6 set means calibration failed.
00415             if(++BGCCR == 0x40){
00416                 // Return with fail flag.
00417                 return FAILED;
00418             }
00419             last_v_error = v_error;
00420             v_error = MeasureVADCerror();
00421 
00422         } while (v_error < 0);
00423 
00424         // Neighbor check, as previous step can select the next best value.
00425         if(-v_error > last_v_error){
00426             BGCCR--;
00427         }
00428     }
00429 
00430     /* The found values should be stored in eeprom or possibly flash for
00431      * correct initialisation if device is reset.
00432      */
00433     return SUCCESS;
00434 }

Here is the call graph for this function:

int8_t InitBandgap ( void   ) 

Bandgap initialisation.

Initialises the bandgap voltage reference to factory calibration. If second calibration has been done at room temperature those values are loaded. BGCCR need to be changed slowly to avoid BOD. See appnote for details.

Return values:
FAILED Loading of signature data failed.
CALIB_ROOM Signature data for second insertion test found.
CALIB_HOT Signature data only for fist insertion test found.

< Factory calibration of BGCCR and BGCRR.

Definition at line 156 of file vadc_usage.c.

References BANDGAP_ADJ_DELAY, CALIB_HOT, CALIB_ROOM, FAILED, READ_SIGNATUREBYTE, SIG_BGCCR_CALIB_25C, SIG_BGCCR_CALIB_HOT, and SIG_BGCRR_CALIB_25C.

Referenced by main().

00157 {
00159     uint8_t bgccr_cal, bgcrr_cal;
00160     int8_t  mode;
00161 
00162     bgcrr_cal = READ_SIGNATUREBYTE(SIG_BGCRR_CALIB_25C);
00163 
00164 #ifdef IGNORE_2ND_CAL
00165     // To do second point calibration on parts that already have.
00166     bgcrr_cal = 0xFF;
00167 #endif
00168 
00169     /* Please note that breaking within 2 cycles of completing a signature byte
00170      * reading will corrupt further AVR Studio flash readout until a reset is issued.
00171      */
00172     if ( bgcrr_cal != 0xFF ){
00173         // Check to see if part was calibrated at room temperature.
00174         bgccr_cal = 0x3F & READ_SIGNATUREBYTE(SIG_BGCCR_CALIB_25C);
00175         mode = CALIB_ROOM;
00176     } else {
00177         bgcrr_cal = 0x0F;
00178         bgccr_cal = 0x3F & READ_SIGNATUREBYTE(SIG_BGCCR_CALIB_HOT);
00179 
00180         if (bgccr_cal == 0x3F) {
00181             return FAILED;
00182         }
00183 
00184         mode = CALIB_HOT;
00185     }
00186 
00187     BGCRR = bgcrr_cal;
00188 
00189     // If done this way device may enter BOD so use method below.
00190     // BGCCR = bgccr_cal;
00191 
00192     while (BGCCR < bgccr_cal){
00193         // Adjust BGCCR up if needed. Slowly to avoid BOD.
00194         BGCCR++;
00195         __delay_cycles(BANDGAP_ADJ_DELAY);
00196     }
00197 
00198     // Adjust down if necessary. (Safe - but results in wrong ADC measurements until VREF is stabilized)
00199     BGCCR = bgccr_cal;
00200 
00201     return mode;
00202 }

void InitCoeff ( void   ) 

Function to load coefficients needed from the signature row.

Loads all signature data into an array and then stores the relevant ones in (file) global variables.

Definition at line 91 of file vadc_usage.c.

References cell_gain, cell_offset, READ_SIGNATUREBYTE, SIG_END_ADDRESS, SIG_VADC_ADC0_GAIN_H, SIG_VADC_ADC0_GAIN_L, SIG_VADC_ADC0_OFFSET, SIG_VADC_ADC1_GAIN_H, SIG_VADC_ADC1_GAIN_L, SIG_VADC_ADC1_OFFSET, SIG_VADC_CELL1_GAIN_H, SIG_VADC_CELL1_GAIN_L, SIG_VADC_CELL1_OFFSET, SIG_VADC_CELL2_GAIN_H, SIG_VADC_CELL2_GAIN_L, SIG_VADC_CELL2_OFFSET, SIG_VADC_RAW_ADC0_H, SIG_VADC_RAW_ADC0_L, SIG_VADC_RAW_CELL1_H, SIG_VADC_RAW_CELL1_L, SIG_VPTAT_H, SIG_VPTAT_L, vadc_gain, vadc_offset, and vptat_coeff.

Referenced by main().

00092 {
00093     uint8_t signature_array[SIG_END_ADDRESS+1];
00094 
00095     for(uint8_t i=0 ; i <= SIG_END_ADDRESS ; i++){
00096         signature_array[i] = READ_SIGNATUREBYTE(i);
00097     }
00098 
00099     /* Please note that breaking within 2 cycles of completing a signature byte
00100      * reading will corrupt further AVR Studio flash readout until a reset is issued.
00101      */
00102 
00103     // Coefficient for temperature calculation from internal sensor.
00104     vptat_coeff = signature_array[SIG_VPTAT_L];
00105     vptat_coeff |= signature_array[SIG_VPTAT_H] << 8;
00106 
00107     // Coefficients for cell gain and offset.
00108     cell_gain[0] = signature_array[SIG_VADC_CELL1_GAIN_L];
00109     cell_gain[0] |= signature_array[SIG_VADC_CELL1_GAIN_H] << 8;
00110     cell_offset[0] = signature_array[SIG_VADC_CELL1_OFFSET];
00111 
00112     cell_gain[1] = signature_array[SIG_VADC_CELL2_GAIN_L];
00113     cell_gain[1] |= signature_array[SIG_VADC_CELL2_GAIN_H] << 8;
00114     cell_offset[1] = signature_array[SIG_VADC_CELL2_OFFSET];
00115 
00116     // Coefficients for VADC gain and offset.
00117     vadc_gain[0] = signature_array[SIG_VADC_ADC0_GAIN_L];
00118     vadc_gain[0] |= signature_array[SIG_VADC_ADC0_GAIN_H] << 8;
00119     vadc_offset[0] = signature_array[SIG_VADC_ADC0_OFFSET];
00120 
00121     vadc_gain[1] = signature_array[SIG_VADC_ADC1_GAIN_L];
00122     vadc_gain[1] |= signature_array[SIG_VADC_ADC1_GAIN_H] << 8;
00123     vadc_offset[1] = signature_array[SIG_VADC_ADC1_OFFSET];
00124 
00125 // Only load raw calibration values if needed.
00126 #ifndef USE_CAL_GAIN
00127 
00128 // Using Cell1 for calibration.
00129 #ifdef USE_CELL1_CAL
00130     // RAW Cell1 measurements for 4096mV in.
00131     raw_cal = signature_array[SIG_VADC_RAW_CELL1_L];
00132     raw_cal |= signature_array[SIG_VADC_RAW_CELL1_H] << 8;
00133 
00134 // Using VADC0 for calibration.
00135 #else
00136     // RAW VADC0 measurements with (4096/5)mV in.
00137     raw_cal = signature_array[SIG_VADC_RAW_ADC0_L];
00138     raw_cal |= signature_array[SIG_VADC_RAW_ADC0_H] << 8;
00139 #endif
00140 
00141 #endif
00142 
00143 }

int16_t MeasureVADCerror ( void   ) 

Measure VADC error.

Subroutine for measurement of VADC input and calculation of error. Uses defines from calibration.h.

Returns:
VADC_error

Definition at line 444 of file vadc_usage.c.

References CAL_GAIN, CAL_OFFSET, VADC_SCALE_BITS, and VCALIB_VALUE.

Referenced by CalibrateVREF().

00445 {
00446     // Variable to keep error after conversion.
00447     int32_t vadc_error;
00448 
00449     // Start a VADC conversion and clear any pending interrupts
00450     VADCSR |= (1 << VADSC) | (1 << VADCCIF);
00451 
00452     // Wait while conversion in progress
00453     do {} while(!(VADCSR & (1 << VADCCIF)));
00454 
00455     // Calculate error of VADC measurement.
00456     vadc_error = VADC;
00457 
00458 #ifdef USE_CAL_GAIN
00459     vadc_error -= CAL_OFFSET;
00460     vadc_error *= CAL_GAIN;
00461 
00462     // Divide by 16384.
00463     vadc_error >>= VADC_SCALE_BITS;
00464 #endif
00465 
00466     vadc_error -= VCALIB_VALUE;
00467     return (int16_t) vadc_error;
00468 }

void StartVADCScan ( void   ) 

Start a scan of all VADC channels.

VADC is set up and interrupts enabled. Global interrupts are also enabled, so make sure all other interrupts are correctly configured before running this. The interrupt routine VADC_ISR does the actual vadc measurements.

Note:
If not using ADC0-1 exclusively as analog inputs, you must modify the disabling of the ADC0-1 digital input buffer.

Definition at line 215 of file vadc_usage.c.

References FIRST_VADC_MEAS, and vadc_scan_complete.

Referenced by main().

00216 {
00217     //disable ADC0-1 digital input buffer.
00218     DIDR0 = 0x03;
00219     vadc_scan_complete = 0;
00220 
00221     // Start set up for first channel.
00222     VADMUX = FIRST_VADC_MEAS;
00223 
00224     // Clear any pending interrupt
00225     VADCSR = (1<<VADEN) | (1<<VADCCIF);
00226 
00227     //Start the first conversion & enable interrupts
00228     VADCSR = (1<<VADEN) | (1<<VADSC) | (1<<VADCCIE);
00229 
00230     // Make sure interrupt are enabled.
00231     __enable_interrupt();
00232 }

__interrupt void VADC_ISR ( void   ) 

Interrupt Service Function to measure VADC values.

Measurements are stored in global array vadc_measurement[]. The ISR scans all inputs and then disables itself. It starts with temperature sensor and normal VADc channels. Cells are measured last to give possiblity to disable cell balancing in relevant devices (HVB/m406). This routine can be simplified for HVA.

Definition at line 245 of file vadc_usage.c.

References BOTTOM_CELL, LAST_VADC_MEAS, TOP_CELL, vadc_measurement, and vadc_scan_complete.

00246 {
00247     uint8_t temp;
00248 
00249     // Used for indexing the vadc_measurement variable
00250     static uint8_t vadc_index = 0;
00251 
00252     temp = VADMUX;
00253 
00254     // Save the result
00255     vadc_measurement[vadc_index] = VADC;
00256 
00257     /* Code could be added here to store current with the associated cell
00258      * voltage if doing cell impedance measurements.
00259      */
00260 
00261     temp++;
00262     vadc_index++;
00263 
00264     /* Check for disabling of cell balancing could be inserted here or in "if"
00265      * below. Timing must be adjusted according to discharge time constant.
00266      */
00267 
00268     if(temp > LAST_VADC_MEAS){
00269         // Finished with no cell inputs. Do cell measurements.
00270         temp = BOTTOM_CELL;
00271     } else {
00272         // Finished with all cells also?
00273         if(temp == (TOP_CELL+1)){
00274             // Flag that we have new samples!
00275             vadc_scan_complete = 1;
00276 
00277             /*  Possibly re-enable cell balancing here. */
00278 
00279             // Disable this ADC and its Interrupt.
00280             VADCSR = 0;
00281             vadc_index = 0;
00282             return;
00283         }
00284     }
00285 
00286     VADMUX = temp;
00287 
00288     //Start next conversion now.
00289     VADCSR |= (1<<VADSC);
00290 }


Variable Documentation

uint16_t bg_temp

Global variable for the result of band-gap temperature measurement/calculation.

Definition at line 79 of file vadc_usage.c.

Referenced by CalculateADCResults().

uint16_t cell_gain[NO_CELLS]

Gain coefficients for Cells.

Definition at line 67 of file vadc_usage.c.

Referenced by CalculateADCResults(), and InitCoeff().

int8_t cell_offset[NO_CELLS]

Offset for cells.

Definition at line 68 of file vadc_usage.c.

Referenced by CalculateADCResults(), and InitCoeff().

uint16_t cell_v[NO_CELLS]

Global variable for results of Cell Voltage measurements/calculations.

Definition at line 77 of file vadc_usage.c.

Referenced by CalculateADCResults().

uint16_t vadc_gain[NO_VADC]

VADC channel gain.

Definition at line 69 of file vadc_usage.c.

Referenced by CalculateADCResults(), and InitCoeff().

uint16_t vadc_measurement[NO_VADC_CHANNELS]

Global variable for VADC samples. Sized to number of VADC channels.

Definition at line 76 of file vadc_usage.c.

Referenced by CalculateADCResults(), and VADC_ISR().

int8_t vadc_offset[NO_VADC]

VADC channel offset.

Definition at line 70 of file vadc_usage.c.

Referenced by CalculateADCResults(), and InitCoeff().

Flag for signalling VADC sampling complete.

Definition at line 80 of file vadc_usage.c.

Referenced by main(), StartVADCScan(), and VADC_ISR().

uint16_t vadc_v[NO_VADC]

Global variable for results of Voltage ADC measurements/calculations.

Definition at line 78 of file vadc_usage.c.

Referenced by CalculateADCResults().

uint16_t vptat_coeff

Internal temperature sensor coefficient.

Definition at line 66 of file vadc_usage.c.

Referenced by CalculateADCResults(), and InitCoeff().


Generated on Wed Nov 5 08:17:26 2008 for AVR353: Voltage Reference Calibration and Voltage ADC Usage by  doxygen 1.5.5