This youtube video sums up how to read bandgap voltage and use it to derive your battery voltage.
Or you could just use the code that's been posted a million places around the web:
/******************************************************************************
*
* readVcc()
*
******************************************************************************/
unsigned int readVcc(bool restoreMux) {
unsigned long result;
byte saveADMUX;
saveADMUX = ADMUX;
// Read 1.1V reference against AVcc
// set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284P__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
ADMUX = _BV(MUX3) | _BV(MUX2);
#else
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif
#if defined(__AVR_ATmega2560__)
/****
it took me a while to figure-out the problem, but on MEGA 2560, immediately after analogRead(A8), ADCL started returning zero.
So every attempt to read from A8-A16 on Arduino MEGA will damage the functionality of readVcc().
I've resolved the problem by adding:
ADCSRB = 0;
just before
delay(2);
**********************************/
//ADCSRB &= ~_BV(MUX5); // Without this the function always returns -1 on the ATmega2560
ADCSRB = 0;
#endif
delay(20); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Start conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both
result = (high<<8) | low;
// Serial.print("BatteryResult="); Serial.print(result);
result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 (because...= 3300*1023/3 since 1.1 is exactly 1/3 of 3.3V)
// Serial.print(", after calculation:"); Serial.println(result);
if (restoreMux) ADMUX = saveADMUX;
return result; // Vcc in millivolts
}
Tom
UPDATED: removed PRINT macros and added restoreMux.
In addition to being sometimes erroneous, I notice the first reading of the ADC also seems to take quite a bit longer than subsequent readings. On an atmega328p running at 8Mhz, what I get is:
0. raw relative bandgap voltage=486 Elapsed time=0uS
1. raw relative bandgap voltage=397 Elapsed time=216uS deltaT=216uS
2. raw relative bandgap voltage=360 Elapsed time=336uS deltaT=120uS
3. raw relative bandgap voltage=348 Elapsed time=456uS deltaT=120uS
4. raw relative bandgap voltage=344 Elapsed time=576uS deltaT=120uS
5. raw relative bandgap voltage=343 Elapsed time=696uS deltaT=120uS
6. raw relative bandgap voltage=343 Elapsed time=816uS deltaT=120uS
7. raw relative bandgap voltage=343 Elapsed time=936uS deltaT=120uS
8. raw relative bandgap voltage=343 Elapsed time=1056uS deltaT=120uS
9. raw relative bandgap voltage=343 Elapsed time=1176uS deltaT=120uS
from this sketch:
// number of microseconds for ADC to setttle before taking a measurement
#define ADC_SETTLE_MICROSECONDS 1000
#define NUM_ADC_SAMPLES 10
uint16_t getRelativeBandgapVoltage() {
uint16_t rawBandgapMeasurement;
// Read bandgap voltage reference (~1.1V) against AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); //need to do this for every sample or just the first?
//delayMicroseconds(ADC_SETTLE_MICROSECONDS); // Settle before taking ADC measurement
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
rawBandgapMeasurement = ADCL; //get the low order bits of ADC
rawBandgapMeasurement |= ADCH<<8; //combine with high order bits of ADC
return rawBandgapMeasurement;
}
void setup() {
long timeInMicroseconds[NUM_ADC_SAMPLES];
uint16_t rbgv[NUM_ADC_SAMPLES]; // relative bandgap voltage
Serial.begin(115200);
for (int i=0;i<NUM_ADC_SAMPLES;i++) {
timeInMicroseconds[i] = micros();
rbgv[i] = getRelativeBandgapVoltage();
}
for (int i=0;i<NUM_ADC_SAMPLES;i++) {
Serial.print(i);
Serial.print(F(". raw relative bandgap voltage="));
Serial.print( rbgv[i]);
Serial.print(F(" Elapsed time="));
Serial.print(timeInMicroseconds[i] - timeInMicroseconds[0]);
Serial.print(F("uS"));
if (i>0) {
Serial.print(F(" deltaT="));
Serial.print(timeInMicroseconds[i]-timeInMicroseconds[i-1]);
Serial.print(F("uS"));
}
Serial.println();
Serial.flush();
}
}
void loop() {
}
With just minimal testing so far, I've already noticed a variation of anywhere from one to seven samples needed before arriving at the final number, so Tom's idea of only waiting for the same number to repeat two times in a row sounds nicely frugal while remaining easy to implement. Not sure if there are conditions under which more than two in a row would be preferable.
The number of cycles can also be reduced just by adding some delay (ADC_SETTLE_MICROSECONDS, which is presently commented out in the above sketch). So, maybe adding some sleep time (or simply attending to other matters) in place of a pure delay would be even more energy efficient. Some of the common sketches for readVcc do sleep during the samples (to minimize noise and/or save energy), but I don't know of any that purposely sleep extra long so as to reduce the number of samples needed.
As illustrated by the above example in this post, the amount of elapsed time before converging on a particular number can definitely add-up to become non-trivial. With that in mind, I'm curious to know whether freezing temperatures and/or high ambient heat and/or low VCC and/or a weak battery might affect the convergence time, and so I'll eventually run some tests to try to characterize that. For instance, a weak battery might easily affect the settle time and/or samples required because AVcc might be falling from one sample to the next due to load. For that reason, perhaps the number of samples and/or settle time should be reported and monitored as yet another possible indicator that a battery may need to be changed. In the worse case, a weak battery might become even weaker just from chasing after an accurate measure of how weak it is! With BOD turned off, it might even run itself into the ground. So, for really weak batteries that are just barely holding on, maybe it might even make sense to halt reading the Vcc until it can be replaced...
Can anyone think of any other concerns that might play a role? If so, I can maybe run some tests for those as well and post the results afterward.
@Whitehare, if you're running this test as soon as your system turns on, the culprit might be the cap on ARef settling into its final charge. What happens if you don't run the test (leaving the ADC ref at its power on default) for a few milliseconds?
I had a similar thought, so to test that I inserted a "delay(1000)" (surely plenty of overkill, right?) at the very start of the setup() procedure on a stock Moteino R4 RFM69HW board (the earlier results I posted were from just an 8Mhz Pro Mini running at 3.3v). On the Moteino, it turns out that with or without the added setup() delay, the first ADC sample takes the same 212uS either way:
0. raw relative bandgap voltage=386 Elapsed time=0uS
1. raw relative bandgap voltage=363 Elapsed time=212uS deltaT=212uS
2. raw relative bandgap voltage=353 Elapsed time=324uS deltaT=112uS
3. raw relative bandgap voltage=349 Elapsed time=436uS deltaT=112uS
4. raw relative bandgap voltage=348 Elapsed time=548uS deltaT=112uS
5. raw relative bandgap voltage=347 Elapsed time=660uS deltaT=112uS
6. raw relative bandgap voltage=347 Elapsed time=772uS deltaT=112uS
7. raw relative bandgap voltage=347 Elapsed time=884uS deltaT=112uS
8. raw relative bandgap voltage=347 Elapsed time=996uS deltaT=112uS
9. raw relative bandgap voltage=347 Elapsed time=1108uS deltaT=112uS
So, the first surprise was that it made no difference. The second surprise was that running the same code on a 16Mhz Moteino was barely any faster than on an 8Mhz Pro Mini. I haven't yet checked the datasheet to confirm, but it would seem the ADC moves at its own pace (?).
[Edit1: That said, it is just a one time thing after power-up or reboot, at least while awake. I confirmed that by putting the whole thing in a loop with a 30 second delay separating each batch of ADC reads. However, I expect there will nonetheless be a similar price to pay each time the atmega328p wakes up from a full powerdown sleep.]
[Edit2: Anyhow, the main upshot from doing these time measurements was to motivate me to do an ADC noise reduction sleep whlie taking the ADC readings. Noise doesn't presently seem to be an issue, but if doing that, then I'm hopeful (though haven't confirmed) that the somewhat lengthy ADC sampling will not tally up over time into a significant drain on battery life.]
[Edit3: By the way, the approach I'm taking to measuring bandgap voltage for calibration purposes is simply to power VCC during calibration with a known voltage source (whose value I input just once during the calibration using the serial console) and then automatically impute the true bandgap voltage by measuring the bandgap against it. The above is part of the code which is leading to that. Like others have done, I'm planning to store this validated bandgap voltage constant somewhere TBD in the eeprom memory and use that instead of just a "typical" value for bandgap voltage. I expect that doing this will probably improve the accuracy of reported voltage measurements.]
I think I found a workable solution. :) According to the datasheet, "When the ADC is turned off and on again, the next conversion will be an extended conversion." So, I simply start a conversion as the very first step in the setup() function by adding two lines of code at its very beginning:
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
ADCSRA |= _BV(ADSC); // Convert
I don't have the atmega328p waste time waiting for the conversion to complete, but rather just have it move on from there as per usual. At least on the 8Mhz Pro Mini, doing that gets the first "extended conversion" speed bump entirely out of the way before the regular sampling starts:
0. raw relative bandgap voltage=312 Elapsed time=0uS
1. raw relative bandgap voltage=325 Elapsed time=120uS deltaT=120uS
2. raw relative bandgap voltage=328 Elapsed time=240uS deltaT=120uS
3. raw relative bandgap voltage=329 Elapsed time=360uS deltaT=120uS
4. raw relative bandgap voltage=330 Elapsed time=480uS deltaT=120uS
5. raw relative bandgap voltage=330 Elapsed time=600uS deltaT=120uS
6. raw relative bandgap voltage=330 Elapsed time=720uS deltaT=120uS
7. raw relative bandgap voltage=330 Elapsed time=840uS deltaT=120uS
8. raw relative bandgap voltage=330 Elapsed time=960uS deltaT=120uS
9. raw relative bandgap voltage=330 Elapsed time=1080uS deltaT=120uS
On the 16Mhz Moteino, the results at first don't appear to be as good:
0. raw relative bandgap voltage=388 Elapsed time=0uS
1. raw relative bandgap voltage=363 Elapsed time=156uS deltaT=156uS
2. raw relative bandgap voltage=352 Elapsed time=268uS deltaT=112uS
3. raw relative bandgap voltage=348 Elapsed time=380uS deltaT=112uS
4. raw relative bandgap voltage=347 Elapsed time=492uS deltaT=112uS
5. raw relative bandgap voltage=346 Elapsed time=604uS deltaT=112uS
6. raw relative bandgap voltage=346 Elapsed time=716uS deltaT=112uS
7. raw relative bandgap voltage=346 Elapsed time=828uS deltaT=112uS
8. raw relative bandgap voltage=346 Elapsed time=940uS deltaT=112uS
9. raw relative bandgap voltage=346 Elapsed time=1052uS deltaT=112uS
but I think that's probably because at 16Mhz it finishes with the rest of setup() before the conversion initiated at the start of setup completes. So, rather than resetting the "extended conversion" that's already in progress, I'm hypothesizing that the ADC makes the mcu wait (156-112=44uS) until the "extended conversion" completes before initiating a new sample. In real life, using the method of running on its 8Mhz internal resonator to gain the benefits of a 3.8uS wake-up, I expect the Moteino results will be the same as the 8Mhz Pro Mini above.
Good catch. It does seem strange, especially when you consider that the same pro mini in the earlier sketch (reply #28) had a falling voltage.
As a cross-check, I plugged a different pro mini into the same usb-to-ttl adapter as used by the Moteino, and it also demonstrates a rising voltage when running the most recent sketch. So, I don't know why these Pro Mini's are behaving differently in that respect, when running the latest version of the sketch.
Changing the subject, here's some food for thought: if on the Moteino I add a 330uSec delay before starting the regular sampling loop (but still having launched the extended conversion as before at the start of the setup() function), then over several trial runs the ADC appears to nail the final bandgap voltage on its first try every time:
0. raw relative bandgap voltage=346 Elapsed time=0uS
1. raw relative bandgap voltage=346 Elapsed time=116uS deltaT=116uS
2. raw relative bandgap voltage=346 Elapsed time=228uS deltaT=112uS
3. raw relative bandgap voltage=346 Elapsed time=340uS deltaT=112uS
4. raw relative bandgap voltage=346 Elapsed time=452uS deltaT=112uS
5. raw relative bandgap voltage=346 Elapsed time=564uS deltaT=112uS
6. raw relative bandgap voltage=346 Elapsed time=676uS deltaT=112uS
7. raw relative bandgap voltage=346 Elapsed time=788uS deltaT=112uS
8. raw relative bandgap voltage=346 Elapsed time=900uS deltaT=112uS
9. raw relative bandgap voltage=346 Elapsed time=1012uS deltaT=112uS
That leads me to wonder whether running the multiple samples without any pause at the beginning, as before, is of any benefit, or worse yet, may actually slow down the sampling capacitor from reaching its final settled voltage level.
[Edit: I don't know that 330uSec is the magic number that would work on all Moteino's in all conditions, but perhaps it is, or perhaps there is a more conservative number like, say, 400uSec, that is such a magic number, and where you come out ahead (at least on average) by using it. I really don't know, as I just now stumbled across this.]
Here's the sketch:
// number of microseconds for ADC to setttle before taking a measurement
#define ADC_SETTLE_MICROSECONDS 330
#define NUM_ADC_SAMPLES 10
uint16_t getRelativeBandgapVoltage() {
uint16_t rawBandgapMeasurement;
// Read bandgap voltage reference (~1.1V) against AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); //need to do this for every sample or just the first?
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
rawBandgapMeasurement = ADCL; //get the low order bits of ADC
rawBandgapMeasurement |= ADCH<<8; //combine with high order bits of ADC
return rawBandgapMeasurement;
}
void setup() {
long timeInMicroseconds[NUM_ADC_SAMPLES];
uint16_t rbgv[NUM_ADC_SAMPLES]; // relative bandgap voltage
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
ADCSRA |= _BV(ADSC); // Convert
Serial.begin(115200);
delayMicroseconds(ADC_SETTLE_MICROSECONDS);
for (int i=0;i<NUM_ADC_SAMPLES;i++) {
timeInMicroseconds[i] = micros();
rbgv[i] = getRelativeBandgapVoltage();
}
for (int i=0;i<NUM_ADC_SAMPLES;i++) {
Serial.print(i);
Serial.print(F(". raw relative bandgap voltage="));
Serial.print( rbgv[i]);
Serial.print(F(" Elapsed time="));
Serial.print(timeInMicroseconds[i] - timeInMicroseconds[0]);
Serial.print(F("uS"));
if (i>0) {
Serial.print(F(" deltaT="));
Serial.print(timeInMicroseconds[i]-timeInMicroseconds[i-1]);
Serial.print(F("uS"));
}
Serial.println();
Serial.flush();
}
}
void loop() {
}
Forgive me for necro'ing this thread but picking up on WhiteHare's work, I've been able to get pretty good readings much faster by cranking up the ADC from 125kHz to 1Mhz. The datasheet says not to run it faster than 200kHz for 10-bit precision and then basically says if you run it at 1Mhz you don't lose much precision. Much more information here: http://www.microsmart.co.za/technical/2014/03/01/advanced-arduino-adc/
Actually, on my TH Nodes, I've been able to take battery voltage readings in 0 extra time! I wake up and start a conversion and rather than twiddling my thumbs waiting for the ADC to finish, I start issuing commands to my HTU21D. Right before going to sleep to wait for my first no hold temperature measurement I grab the results from the ADC. Issuing a command on the fastest possible I2C bus takes around 92us which is longer than the ADC needs for an extended measurement when the prescaler is cranked up to 32 instead of the default 128. Net result, I get my battery voltage for free except the extra current to keep the ADC on for 100us.
startT = micros(); // ==================== START THE CLOCK ====================
sbi(ADCSRA, ADSC); // start a conversion
issueCommand(WRITE_USER_REGISTER, ELEVEN_BIT_TEMP); // this conversation takes 88uS - plenty long enough for the ADC
issueCommand(TRIGGER_TEMP_MEASURE_NOHOLD,0);
Vcc = ADCL;
Vcc |= ADCH<<8;
//Vcc = 112296/Vcc; // 16-bit math takes way too long adding around 40us to this timed loop
LowPower.powerDown(SLEEP_15MS, ADC_OFF, BOD_OFF);
readRaw(&data[0]);
issueCommand(WRITE_USER_REGISTER, EIGHT_BIT_RH);
issueCommand(TRIGGER_HUMD_MEASURE_NOHOLD,0);
LowPower.powerDown(SLEEP_15MS, ADC_OFF, BOD_OFF);
readRaw(&data[2]);
stopTWI();
elapsed = micros()-startT; // ==================== STOP THE CLOCK ====================
Maybe it's thanks to the atmega328p's now very fast 4usec wake-up from sleep, but I was finding the ADC a bit slow at getting up to speed.
Prior to sleeping the atmega, I am turning off the ADC with this:
ADCSRA = 0; // disable ADC
which is also how Nick Gammon does it. (https://www.gammon.com.au/forum/?id=11497)
Presently I'm using TomWS's method of reading the ADC until I get two of the same values in a row. It seems like a good approach. However, I'm finding that if the atmega328p doesn't do one or the other of the the below code snippets to reanimate the ADC immediately after the 4usec wake-up, then TomWS's method often seems to yield erroneous values.
I noticed that ADCSRA has the value 144 just prior to turning it off, so now I wake the ADC up with:
ADCSRA=144; //restore ADC settings from just prior to sleeping
as soon as the atmega328p awakens. That does seem to help.
Instead of that, I've seen code where some people do:
ADCSRA |= (1<<ADEN); //Power up the ADC
ADCSRA |= (1<<ADSC); //Start converting
At the moment, I'm not sure which is better.
What are you all doing in this respect?
144 is setting bits 7 (ADEN) and 4 (ADIF) which according to the datasheet is cleared by writing a logical 1 to this bit:
• Bit 4 – ADIF: ADC Interrupt Flag
This bit is set when an ADC conversion completes and the Data Registers are updated. The ADC Conversion
Complete Interrupt is executed if the ADIE bit and the I-bit in SREG are set. ADIF is cleared by hardware when
executing the corresponding interrupt handling vector. Alternatively, ADIF is cleared by writing a logical one to
the flag. Beware that if doing a Read-Modify-Write on ADCSRA, a pending interrupt can be disabled. This also
applies if the SBI and CBI instructions are used.
You are also setting the ADC clock div to 2 by zeroing out bits 2:0 so you are running your ADC at 8MHz assuming you are running the 328p at 16MHz anyway.
To make your code more readable I'd change your wakeup to:
ADCSRA |= (1<<ADEN) | (1<<ADIF); // Power up the ADC and reset the interrupt flag
EDIT: Thinking about it a little further, you are reading 144 just prior to sleeping because a conversion was finished. Setting the ADIF bit doesn't actually set it so just setting the ADEN bit should be completely equivalent to setting ADCSRA = 144.
Sorry, I failed to answer how I do it.
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define ENABLE_ADC cbi(PRR, PRADC); sbi(ADCSRA, ADEN); // Enable the ADC
#define DISABLE_ADC cbi(ADCSRA, ADEN); sbi(PRR, PRADC); // Disable the ADC to save power
Just gave this a try and my readings all seem to take double the amount I see from WhiteHare,
Any ideas why this could be?
(I'm using WhiteHare's code on a Moteino modded to 8mhz, mixed with some other radio code that doesn't touch the ADC or anything)
0. raw relative bandgap voltage=333 Elapsed time=0uS
1. raw relative bandgap voltage=333 Elapsed time=416uS deltaT=416uS
2. raw relative bandgap voltage=333 Elapsed time=640uS deltaT=224uS
3. raw relative bandgap voltage=333 Elapsed time=864uS deltaT=224uS
4. raw relative bandgap voltage=333 Elapsed time=1088uS deltaT=224uS
5. raw relative bandgap voltage=333 Elapsed time=1312uS deltaT=224uS
6. raw relative bandgap voltage=332 Elapsed time=1536uS deltaT=224uS
7. raw relative bandgap voltage=333 Elapsed time=1760uS deltaT=224uS
8. raw relative bandgap voltage=333 Elapsed time=1984uS deltaT=224uS
9. raw relative bandgap voltage=333 Elapsed time=2208uS deltaT=224uS
No, just with defaults, which I'm not sure what those are.
If you have handy code that would be great, otherwise I will dig the DS or web when I get some time...
Thanks
The default ADC speed set by init() which is called in Setup() is 125kHz. Ask and ye shall receive...
#include "Arduino.h"
// Define various ADC prescaler
#define ADC_PS_16 (1 << ADPS2)
#define ADC_PS_32 (1 << ADPS2) | (1 << ADPS0)
#define ADC_PS_64 (1 << ADPS2) | (1 << ADPS1)
#define ADC_PS_128 (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0)
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define START_ADC_CONVERSION sbi(ADCSRA, ADSC); // start a conversion
#define ENABLE_ADC cbi(PRR, PRADC); sbi(ADCSRA, ADEN); //ADCSRA |= bit(ADEN); // Enable the ADC
#define DISABLE_ADC cbi(ADCSRA, ADEN); sbi(PRR, PRADC); // Disable the ADC to save power
static inline void Fast_ADC_Init(void) {
sei();
// Timer 0 initialization from wiring.c for a ATmega 328P (Arduino Uno rev 3) + 12 bytes to sketch size
TCCR0A = _BV(WGM01) | _BV(WGM00); // set timer 0 prescale factor to 64
TCCR0B = _BV(CS01) | _BV(CS00); // set timer 0 prescale factor to 64
TIMSK0 = _BV(TOIE0); // enable timer 0 overflow interrupt
// Timer 2 initialization from wiring.c for an ATmega 328P (Arduino Uno rev 3) + 20 bytes to sketch size
TCCR2A |= _BV(COM2A1) | _BV(WGM20); // Enable timer 2 to _delay_ms() works properly
TCCR2B |= CS22; // set clkT2S/64 (From prescaler)
// ADC Housekeeping
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // Set the multiplexer to read the internal bandgap voltage
//ADCSRA &= ~ADC_PS_128; // Unset the bits set by init()
ADCSRA |= ADC_PS_32; // set our own prescaler to 32
}
Just call Fast_Init_ADC() in your setup code and you'll be running at 1MHz and comparing to the internal 1.1V bandgap. I never invoke init() in my release code so I have to do those things in my Fast_Init_ADC. If you are calling init() either directly or by using Arduino's Setup() routine, then you can change Fast_Init_ADC() to just:
static inline void Fast_ADC_Init(void) {
// ADC Housekeeping
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // Set the multiplexer to read the internal bandgap voltage
ADCSRA &= ~ADC_PS_128; // Unset the bits set by init()
ADCSRA |= ADC_PS_32; // set our own prescaler to 32
}
Thanks ChemE,
I'm running 8mhz so to get 1mhz I think the setting has to be:
The power-on ADC prescaler is 128 (62.5khz at FCPU=8mhz).
I seem to get flat readings at 500khz though so I think i'll stick with that. I have to first clear the prescaler bits before setting a new value.
Results:
ADCSRA = 10000100
0. raw relative bandgap voltage=296 Elapsed time=0uS
1. raw relative bandgap voltage=297 Elapsed time=200uS deltaT=200uS
2. raw relative bandgap voltage=296 Elapsed time=392uS deltaT=192uS
3. raw relative bandgap voltage=296 Elapsed time=592uS deltaT=200uS
4. raw relative bandgap voltage=296 Elapsed time=784uS deltaT=192uS