Skip to content

Instantly share code, notes, and snippets.

@Miraculix200
Last active July 17, 2022 14:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Miraculix200/0cae0e6b91275d1f9045b3df7d822335 to your computer and use it in GitHub Desktop.
Save Miraculix200/0cae0e6b91275d1f9045b3df7d822335 to your computer and use it in GitHub Desktop.
/*
Using the VDDIO2 pin of AVR Dx MCUs (e.g. AVR128DB32 or other DB, DD MCUs)
to measure battery voltage without a voltage divider
(when using Arduino IDE with DxCore)
Instructions: Connect the battery positive pin to VDDIO2 (and negative pin to ground obviously)
Note that a voltage higher than 6.5V on the VDDIO2 pin may destroy your MCU. Stable operation up to maximum of 5.5V
Sauce: http://ww1.microchip.com/downloads/en/Appnotes/GettingStarted-MVIO-AVRDB-DS90003287A.pdf
*/
#ifndef MVIO
#error Needs MVIO
#endif
// the setup routine runs once when you press reset:
void setup()
{
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
delay(100);
Serial.println("ohai");
analogReadResolution(12); // 12 bit ADC
float vddio2_voltage = getVDDIO2voltage(4095); // ignore the first reading
}
float getVDDIO2voltage(uint16_t adc_resolution)
{
uint8_t original_vref = VREF.ADC0REF; // remember current VREF
uint8_t original_ctrlb = ADC0.CTRLB; // remember current CTRLB
VREF.ADC0REF = VREF_REFSEL_1V024_gc; /*Select the 1.024V referance for ADC0*/
ADC0.MUXPOS = ADC_MUXPOS_VDDIO2DIV10_gc; /*Select VDDIO2DIV10 as input for ADC0*/
ADC0.CTRLB = ADC_SAMPNUM_ACC16_gc; /* Enable 16 oversamples*/
ADC0.CTRLA = ADC_ENABLE_bm; /*Enable ADC0*/
ADC0.COMMAND = ADC_STCONV_bm; /*Start an ADC conversion*/
while (!(ADC0.INTFLAGS & ADC_RESRDY_bm))
; /*Wait for the ADC conversion to be done*/
/*Read the RES register and shift the result 4 bits to compensate for the 16 oversamples*/
uint16_t result = (ADC0.RES >> 4);
VREF.ADC0REF = original_vref; // revert back to original VREF
ADC0.CTRLB = original_ctrlb; // revert back to original CTRLB
// VDDIO2 = (ADC RESULT * VREF * 10) / ADC_RESOLUTION
float vddio2_voltage = (result * 1.024 * 10) / adc_resolution;
return vddio2_voltage;
}
unsigned long lastBlinkMs;
// the loop routine runs over and over again forever:
void loop()
{
if (millis() - lastBlinkMs > 5000) {
float vddio2_voltage = getVDDIO2voltage(4095);
Serial.print("VDDIO2: ");
Serial.print(vddio2_voltage);
Serial.println("V");
lastBlinkMs = millis();
}
delay(1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment