Last active
July 17, 2022 14:25
-
-
Save Miraculix200/0cae0e6b91275d1f9045b3df7d822335 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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