diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h index 91eeb16bc..f4eb2ff2f 100644 --- a/cores/arduino/Arduino.h +++ b/cores/arduino/Arduino.h @@ -137,6 +137,8 @@ int digitalRead(uint8_t pin); int analogRead(uint8_t pin); void analogReference(uint8_t mode); void analogWrite(uint8_t pin, int val); +float batteryVoltageRead(void); + unsigned long millis(void); unsigned long micros(void); diff --git a/cores/arduino/wiring_analog.c b/cores/arduino/wiring_analog.c index 0de64f785..0611d2c8c 100644 --- a/cores/arduino/wiring_analog.c +++ b/cores/arduino/wiring_analog.c @@ -27,6 +27,51 @@ uint8_t analog_reference = DEFAULT; + +float batteryVoltageRead(void) +{ +#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#define ADMUX_VCCWRT1V1 (_BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1)) +#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) +#define ADMUX_VCCWRT1V1 (_BV(MUX5) | _BV(MUX0)) +#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) +#define ADMUX_VCCWRT1V1 (_BV(MUX3) | _BV(MUX2)) +#else +#define ADMUX_VCCWRT1V1 (_BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1)) +#endif + +// Read 1.1V reference against AVcc + // set the reference to Vcc and the measurement to the internal 1.1V reference + #if defined(ADMUX) + if (ADMUX != ADMUX_VCCWRT1V1) + { + ADMUX = ADMUX_VCCWRT1V1; + + // Bandgap reference start-up time: max 70us + // Wait for Vref to settle. + delayMicroseconds(350); + } + #endif + + #if defined(ADCSRA) && defined(ADCL) + // Start conversion and wait for it to finish. + ADCSRA |= _BV(ADSC); + while (bit_is_set(ADCSRA,ADSC)) {}; + + // Result is now stored in ADC. + + // Calculate Vcc (in V) + float vcc = 1.1*1024.0 / ADC; + + return vcc; + +#else + return 0; +#endif +} + + + void analogReference(uint8_t mode) { // can't actually set the register here because the default setting