I like the idea of this feature, but cant employ it properly. I have a 5v voltage source that i need to read. Th goal is to have a green led illuminate when the voltage is above 4.8 v and a red led illuminate if below 4.4.
uint16_t readVcc() { // set reference to internal 1.1V reference
ADMUX = _BV(MUX5) | _BV(MUX0); // MUX3 & MUX2 select the 1.1V reference for measurement
delay(2); // wait for Vref to settle
ADCSRA |= _BV(ADSC); // Start the conversion
while (bit_is_set(ADCSRA, ADSC)); // WAIT FOR CONVERSION TO COMPLETE
uint16_t low = ADCL;
uint8_t high = ADCH;
long vcc = (high<<8) | low;
vcc = (1125300L / vcc) /1000; //Calculate Vcc in volts
return vcc; // Vcc in volts}
void loop() {
// battery reading
readVcc();
if (vcc <= 4.40) { digitalWrite(rd_led, HIGH), digitalWrite(grn_led, LOW); } // Low Battery
if (vcc >= 4.8) { digitalWrite(rd_led, LOW), digitalWrite(grn_led, HIGH); } // Good battery
}
Your function returns a 16 bit unsigned integer, so it can never give you the voltage as decimal values.
That said there's no point converting the A2D value to volts, just find out what value from the A2D represents low and normal supply voltage and compare with those values directly.
However, I suspect you might have another problem when the voltage is very close to the threshold, the LED might flicker on and off as the measured value hovers around the threshold. To fix this you need 2 threshold values close together, one to turn the LED on, the other to turn it off.
I think you be better off sticking with integers too.
Manipulating stuff by converting to float then dividing by big numbers can introduce errors or mislead you into thinking you have more resolution .
If you can , just use the raw integer values or use map to translate into say 1/10 volts and use that .
Some form of calibration routine will be needed anyway .
add a print statement to print the raw values and just use the numbers at 4.8 volts or whatever .
Hmmm … not sure about that !
Questions and answers seem in an odd style :
“ Operator function means operation defined for that operator so if user defines a function for an operator then that is called operator overloading i.e. overloading already present operator function.”
const float InternalReferenceVoltage = 1.096; // as measured
void setup ()
{
Serial.begin (115200);
ADCSRA = bit (ADEN); // turn ADC on
ADCSRA |= bit (ADPS0) | bit (ADPS1) | bit (ADPS2); // Prescaler of 128
ADMUX = bit (REFS0) | bit (MUX3) | bit (MUX2) | bit (MUX1);
delay (10); // let it stabilize
bitSet (ADCSRA, ADSC); // start a conversion
while (bit_is_set(ADCSRA, ADSC))
{ }
float results = InternalReferenceVoltage / float (ADC + 0.5) * 1024.0;
Serial.print ("Voltage = ");
Serial.println (results);
} // end of setup
void loop () { }
...gives a hint at where your 1125.3 magic number comes from. It is 1.1*1023=1125.3 from the bandgap voltage and the TOP value of the ADC. Nick would use a different magic number: 1024 *1.1=1126.4 or measure your bandgap voltage and do the math.
You could use a DMM to measure your chip's actual 1.1V reference by exposing it on the AREF pin per: