#define VBAT_PIN (A7) #define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096 #define VBAT_DIVIDER (0.71275837F) // 2M + 0.806M voltage divider on VBAT = (2M / (0.806M + 2M)) #define VBAT_DIVIDER_COMP (1.403F) // Compensation factor for the VBAT divider int readVBAT(void) { int raw; // Set the analog reference to 3.0V (default = 3.6V) analogReference(AR_INTERNAL_3_0); // Set the resolution to 12-bit (0..4095) analogReadResolution(12); // Can be 8, 10, 12 or 14 // Let the ADC settle delay(1); // Get the raw 12-bit, 0..3000mV ADC value raw = analogRead(VBAT_PIN); // Set the ADC back to the default settings analogReference(AR_DEFAULT); analogReadResolution(10); return raw; } uint8_t mvToPercent(float mvolts) { uint8_t battery_level; if (mvolts >= 3000) { battery_level = 100; } else if (mvolts > 2900) { battery_level = 100 - ((3000 - mvolts) * 58) / 100; } else if (mvolts > 2740) { battery_level = 42 - ((2900 - mvolts) * 24) / 160; } else if (mvolts > 2440) { battery_level = 18 - ((2740 - mvolts) * 12) / 300; } else if (mvolts > 2100) { battery_level = 6 - ((2440 - mvolts) * 6) / 340; } else { battery_level = 0; } return battery_level; } void setup() { Serial.begin(115200); while ( !Serial ) delay(10); // for nrf52840 with native usb // Get a single ADC sample and throw it away readVBAT(); } void loop() { // Get a raw ADC reading int vbat_raw = readVBAT(); // Convert from raw mv to percentage (based on LIPO chemistry) uint8_t vbat_per = mvToPercent(vbat_raw * VBAT_MV_PER_LSB); // Convert the raw value to compensated mv, taking the resistor- // divider into account (providing the actual LIPO voltage) // ADC range is 0..3000mV and resolution is 12-bit (0..4095), // VBAT voltage divider is 2M + 0.806M, which needs to be added back float vbat_mv = (float)vbat_raw * VBAT_MV_PER_LSB * VBAT_DIVIDER_COMP; // Display the results Serial.print("ADC = "); Serial.print(vbat_raw * VBAT_MV_PER_LSB); Serial.print(" mV ("); Serial.print(vbat_raw); Serial.print(") "); Serial.print("LIPO = "); Serial.print(vbat_mv); Serial.print(" mV ("); Serial.print(vbat_per); Serial.println("%)"); delay(1000); }