Go Down

Topic: Bandgap voltage problems (revisited) (Read 1 time) previous topic - next topic

FigZ

I am trying to write a sketch that measures the bandgap voltage as precise as possible, and writes the value to the eeprom for future reference
I want to use a 2.5v reference ic on AREF

for those dropping in on this discussion - please read up on the matter - a good starting point is this thread:
http://arduino.cc/forum/index.php/topic,38119.0.html

My code is heavely based on the previous work of Coding Badly, and RetroLefty

My problem is - the code using the sleep mode to produce better results seems to reset the analogreference to internal - where I would like to use an external reference, using a LM336 2v5 (an affordable 2.5 volt reference ic)

my code:

Code: [Select]

// use reference 2,47v on AREF to measure the bandgap voltage

#include <avr/sleep.h>

ISR(ADC_vect)
{
}

// This performs an A/D conversion using the current ADMUX settings.  You must set ADMUX before calling this function.
int rawAnalogReadWithSleep( void )
{
  // Generate an interrupt when the conversion is finished
  ADCSRA |= _BV( ADIE );

  // Enable Noise Reduction Sleep Mode
  set_sleep_mode( SLEEP_MODE_ADC );
  sleep_enable();

  // Any interrupt will wake the processor including the millis interrupt so we have to...
  // Loop until the conversion is finished
  do
  {
    // The following line of code is only important on the second pass.  For the first pass it has no effect.
    // Ensure interrupts are enabled before sleeping
    sei();
    // Sleep (MUST be called immediately after sei)
    sleep_cpu();
    // Checking the conversion status has to be done with interrupts disabled to avoid a race condition
    // Disable interrupts so the while below is performed without interruption
    cli();
  }
  // Conversion finished?  If not, loop.
  while( ( (ADCSRA & (1<<ADSC)) != 0 ) );

  // No more sleeping
  sleep_disable();
  // Enable interrupts
  sei();

  // The Arduino core does not expect an interrupt when a conversion completes so turn interrupts off
  ADCSRA &= ~ _BV( ADIE );

  // Return the conversion result
  return( ADC );
}

int bandgapRead(byte us =250) // returns raw measurement of bandgap with aref = 2,47v
{
       
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)  // For mega boards
//  const long InternalReferenceVoltage = 1100L;  // Adjust this value to your boards specific internal BG voltage x1000
        // REFS1 REFS0          --> 0 1, AVcc internal ref. -Selects AVcc reference
        // MUX4 MUX3 MUX2 MUX1 MUX0  --> 11110 1.1V (VBG)         -Selects channel 30, bandgap voltage, to measure
  ADMUX = (0<<REFS1) | (1<<REFS0) | (0<<ADLAR)| (0<<MUX5) | (1<<MUX4) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1) | (0<<MUX0);
 
#elif defined(__AVR_ATmega8__)  // Atmega8 has a 1.3V bandgap. UNTESTED!!! // http://forums.adafruit.com/viewtopic.php?f=25&t=12547
//  const long InternalReferenceVoltage = 1300L;  // Adjust this value to your boards specific internal BG voltage x1000
        // REFS1 REFS0          --> 0 1, AVcc internal ref. -Selects AVcc external reference
        // MUX3 MUX2 MUX1 MUX0  --> 1110 1.1V (VBG)         -Selects channel 14, bandgap voltage, to measure
  ADMUX = (0<<REFS1) | (1<<REFS0) | (0<<ADLAR) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1) | (0<<MUX0);
#else  // For 168/328 boards
//  const long InternalReferenceVoltage = 1100L;  // Adjust this value to your boards specific internal BG voltage x1000
        // REFS1 REFS0          --> 0 1, AVcc internal ref. -Selects AVcc external reference
        // MUX3 MUX2 MUX1 MUX0  --> 1110 1.1V (VBG)         -Selects channel 14, bandgap voltage, to measure
  ADMUX = (0<<REFS1) | (1<<REFS0) | (0<<ADLAR) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1) | (0<<MUX0);
#endif

  delay(us);  // Let mux settle a little to get a more stable A/D conversion
        // Start a conversion 
//  ADCSRA |= _BV( ADSC );
        // Wait for it to complete
//  while( ( (ADCSRA & (1<<ADSC)) != 0 ) );
        // Scale the value
//  return ((InternalReferenceVoltage * 1023L) / ADC); // calculates for straight line value
  return (rawAnalogReadWithSleep());
}

void setup() {
    // initialize the serial port
    Serial.begin(9600);

  pinMode(10, OUTPUT);    // set the digital pin as output:
  digitalWrite (10, HIGH);

  pinMode (9, OUTPUT);  // quick and dirty - make pin9 a gnd - for easy led connection when using pin10
  digitalWrite(9, LOW);

  analogReference (EXTERNAL);
  delay (200);
  pinMode (A5, INPUT);
  int dummy = analogRead (A5); // dummyread
  delay (10000);  // measuring the AREF pin produces a nice 2.47v during this delay
                  // but as soon as we try and measure the bandgap voltage
                  // analogreference seems to revert to internal

  digitalWrite (10, LOW);
}

void loop()
{

  Serial.println (bandgapRead());
  delay(200);
}



In case someone has a atmega8, please verify if the bandgap voltage is indeed 1.3v ?
Thank you all for your contributions

johnwasser


In case someone has a atmega8, please verify if the bandgap voltage is indeed 1.3v ?


The ATmega8 datasheet says:
Min:      1.15V
Typical: 1.23V
Max:     1.40V

Your 1.3V would be in the normal range.

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy