├── ESP32_ADC_Read_Voltage_Accuracy_V2.ino ├── ESP32_ADC_VREF.ino └── README.md /ESP32_ADC_Read_Voltage_Accuracy_V2.ino: -------------------------------------------------------------------------------- 1 | #include "esp_adc_cal.h" 2 | 3 | #define ADC_PIN 35 // Set for the Lolin D32 board with on-board voltage divider 4 | #define voltage_divider_offset 2.174 // Should be a value of 2.000, but ADC input impedance loads the voltage divider, requiring a correction 5 | 6 | void setup() { 7 | Serial.begin(115200); 8 | } 9 | 10 | void loop() { 11 | float unadjusted_voltage = (analogRead(ADC_PIN) / 4095.0 * 3.3 * voltage_divider_offset); 12 | float adjusted_voltage = ReadVoltage(ADC_PIN); 13 | Serial.println("Un-adjusted voltage = " + String(unadjusted_voltage,3) + "v"); 14 | Serial.println(" Adjusted voltage = " + String(adjusted_voltage,3) + "v"); 15 | Serial.println(); 16 | delay(5000); 17 | } 18 | 19 | float ReadVoltage(byte ADC_Pin) { 20 | float calibration = 1.000; // Adjust for ultimate accuracy when input is measured using an accurate DVM, if reading too high then use e.g. 0.99, too low use 1.01 21 | float vref = 1100; 22 | esp_adc_cal_characteristics_t adc_chars; 23 | esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, 1100, &adc_chars); 24 | vref = adc_chars.vref; // Obtain the device ADC reference voltage 25 | return (analogRead(ADC_Pin) / 4095.0) * 3.3 * voltage_divider_offset * (1100 / vref) * calibration; // ESP by design reference voltage in mV 26 | } 27 | 28 | // The esp_adc_cal/include/esp_adc_cal.h API provides functions to correct for differences 29 | // in measured voltages caused by variation of ADC reference voltages (Vref) between chips. 30 | // Per design the ADC reference voltage is 1100 mV, however the true reference voltage can 31 | // range from 1000 mV to 1200 mV amongst different ESP32's 32 | -------------------------------------------------------------------------------- /ESP32_ADC_VREF.ino: -------------------------------------------------------------------------------- 1 | #include "esp_adc_cal.h" 2 | 3 | #define ADC_PIN 36 4 | 5 | void setup() { 6 | Serial.begin(115200); 7 | } 8 | 9 | void loop() { 10 | float unadjusted_voltage = (analogRead(ADC_PIN) / 4095.0 * 3.3); 11 | float adjusted_voltage = ReadVoltage(ADC_PIN); 12 | 13 | Serial.println(" Input Voltage = 3.000 v"); 14 | Serial.println("------------------------------"); 15 | Serial.println(" Adjusted Voltage = " + String(adjusted_voltage, 3) + "v " + String(adjusted_voltage / 3.00 * 100 - 100) + "% error"); 16 | Serial.println("Un-adjusted Voltage = " + String(unadjusted_voltage, 3) + "v " + String(unadjusted_voltage / 3.00 * 100 - 100) + "% error"); 17 | Serial.println(); 18 | delay(5000); 19 | } 20 | 21 | float ReadVoltage(byte ADC_Pin) { 22 | float calibration = 1.000; // Adjust for ultimate accuracy when input is measured using an accurate DVM, if reading too high then use e.g. 0.99, too low use 1.01 23 | float vref = 1100; 24 | esp_adc_cal_characteristics_t adc_chars; 25 | esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, 1100, &adc_chars); 26 | vref = adc_chars.vref; // Obtain the device ADC reference voltage 27 | return (analogRead(ADC_Pin) / 4095.0) * 3.3 * (1100 / vref) * calibration; // ESP by design reference voltage in mV 28 | } 29 | 30 | // The esp_adc_cal/include/esp_adc_cal.h API provides functions to correct for differences 31 | // in measured voltages caused by variation of ADC reference voltages (Vref) between chips. 32 | // Per design the ADC reference voltage is 1100 mV, however the true reference voltage can 33 | // range from 1000 mV to 1200 mV amongst different ESP32's 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP32-ADC-Accuracy-Improvement 2 | Extracting the ESP32 ADC reference voltage to improve ADC reading accuracy 3 | 4 | The 'esp_adc_cal/include/esp_adc_cal.h' API provides a function to correct for differences 5 | in measured voltages caused by variation of ADC reference voltages (Vref) between chips. 6 | 7 | By-design the ADC reference voltage is 1100 mV, however the true reference voltage can 8 | vary from device-to-deice and range from 1000 mV to 1200 mV amongst different ESP32's. 9 | 10 | Reading the reference voltage enables a correction to be made which then improves ADC reading accuracy. 11 | 12 | NOTE: 13 | 14 | For most boards with an on-board voltage divder of 2 series 220K resistors, the divide by 2 factor needs to be adjusted to 2.174 to allow for ADC input impedance loading the voltage divider. 15 | 16 | The V2 code makes that correction. 17 | --------------------------------------------------------------------------------