This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

What's wrong with measuring lithium battery voltage?

Hi all, I met a problem with measuring lithium battery voltage. I used 1Mohm and 250Kohm divided voltage, and used the internal VBG voltage as reference, and used ADC0 as input. I measured the P0.0 voltage is 0.930V and the lithium battery voltage is 3.770V, but I get the value from ADC0 is always 0x1EF(581mV). What's wrong with it? Here is my code:

#define ADC_REF_VOLTAGE_IN_MILLIVOLTS 1200
#define ADC_PRE_SCALING_COMPENSATION 4
#define DIODE_FWD_VOLT_DROP_MILLIVOLTS 50

#define ADC_RESULT_IN_MILLI_VOLTS(ADC_VALUE)
((((ADC_VALUE) * ADC_REF_VOLTAGE_IN_MILLIVOLTS) / 1024) * ADC_PRE_SCALING_COMPENSATION)

void ADC_IRQHandler(void) { if (NRF_ADC->EVENTS_END != 0) { uint16_t adc_result; uint16_t batt_lvl_in_milli_volts; uint8_t percentage_batt_lvl; uint32_t err_code;

    NRF_ADC->EVENTS_END     = 0;
    adc_result              = NRF_ADC->RESULT;
    NRF_ADC->TASKS_STOP     = 1;

    batt_lvl_in_milli_volts = ADC_RESULT_IN_MILLI_VOLTS(adc_result) +
                              DIODE_FWD_VOLT_DROP_MILLIVOLTS;
    percentage_batt_lvl     = battery_level_percent(batt_lvl_in_milli_volts);
    err_code = ble_bas_battery_level_update(&bas, percentage_batt_lvl);

    if (
        (err_code != NRF_SUCCESS)
        &&
        (err_code != NRF_ERROR_INVALID_STATE)
        &&
        (err_code != BLE_ERROR_NO_TX_BUFFERS)
        &&
        (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
    )
    {
        APP_ERROR_HANDLER(err_code);
    }
}

}

void battery_start(void) { uint32_t err_code;

// Configure ADC
NRF_ADC->INTENSET   = ADC_INTENSET_END_Msk;

NRF_ADC->CONFIG     = (ADC_CONFIG_RES_10bit                       << ADC_CONFIG_RES_Pos)     |
                      (ADC_CONFIG_INPSEL_AnalogInputNoPrescaling  << ADC_CONFIG_INPSEL_Pos)  |
                      (ADC_CONFIG_REFSEL_VBG                      << ADC_CONFIG_REFSEL_Pos)  |
                      (ADC_CONFIG_PSEL_AnalogInput0               << ADC_CONFIG_PSEL_Pos)    |
                      (ADC_CONFIG_EXTREFSEL_None                  << ADC_CONFIG_EXTREFSEL_Pos);

NRF_ADC->EVENTS_END = 0;
NRF_ADC->ENABLE     = ADC_ENABLE_ENABLE_Enabled;

// Enable ADC interrupt
err_code = sd_nvic_ClearPendingIRQ(ADC_IRQn);
APP_ERROR_CHECK(err_code);

err_code = sd_nvic_SetPriority(ADC_IRQn, NRF_APP_PRIORITY_LOW);
APP_ERROR_CHECK(err_code);

err_code = sd_nvic_EnableIRQ(ADC_IRQn);
APP_ERROR_CHECK(err_code);

NRF_ADC->EVENTS_END  = 0;    // Stop any running conversions.
NRF_ADC->TASKS_START = 1;

}

Parents
  • Hi Paul

    As Håkon said, your measurement is close to the calculated value, but it should be closer. So there are a few things to consider.

    If you are using the ADC setup for Lithium battery measurement given on this thread then your resistance values for your voltage divider should be R1=10Mohm and R2=2.2Mohm. Have you measured the actual resistance values? They might be a little different, depending on the tolerance of your chosen resistors.

    Another thing to consider is when measuring voltage on the nRF51 analog input pin (AIN). Voltage meters or oscilloscopes typically have 1Mohm-10Mohm internal resistor to measure the voltage. When you measure your AIN voltage, the internal resistor of your voltage meter is in paralell with the R2 resistor in the voltage divider, making the measurement very inaccurate.

    The method I would suggest for evaluating the ADC accuracy is as follows: [list=1] Measure the exact output voltage of the battery, or even better, use a power supply to provide a stable known voltage to the voltage divider. The battery will gradually lower its output voltage as the battery is drained. Measure the actual resistance values of R1 and R2 in the voltage divider Calculate the AIN voltage based on the actual values on R1, R2 and supply voltage. From the AIN voltage, calculate the expected ADC output value based on the chosen reference voltage and ADC output resolution. [/list]

    The input resistance that Håkon mentioned earlier for different prescale settings is what you can expect and is what you might approximately measure. However, there is also an internal voltage source involved. The actual model of the ADC is shown in this thread as well as statistics for the AIN input resistance for different prescale settings.

Reply
  • Hi Paul

    As Håkon said, your measurement is close to the calculated value, but it should be closer. So there are a few things to consider.

    If you are using the ADC setup for Lithium battery measurement given on this thread then your resistance values for your voltage divider should be R1=10Mohm and R2=2.2Mohm. Have you measured the actual resistance values? They might be a little different, depending on the tolerance of your chosen resistors.

    Another thing to consider is when measuring voltage on the nRF51 analog input pin (AIN). Voltage meters or oscilloscopes typically have 1Mohm-10Mohm internal resistor to measure the voltage. When you measure your AIN voltage, the internal resistor of your voltage meter is in paralell with the R2 resistor in the voltage divider, making the measurement very inaccurate.

    The method I would suggest for evaluating the ADC accuracy is as follows: [list=1] Measure the exact output voltage of the battery, or even better, use a power supply to provide a stable known voltage to the voltage divider. The battery will gradually lower its output voltage as the battery is drained. Measure the actual resistance values of R1 and R2 in the voltage divider Calculate the AIN voltage based on the actual values on R1, R2 and supply voltage. From the AIN voltage, calculate the expected ADC output value based on the chosen reference voltage and ADC output resolution. [/list]

    The input resistance that Håkon mentioned earlier for different prescale settings is what you can expect and is what you might approximately measure. However, there is also an internal voltage source involved. The actual model of the ADC is shown in this thread as well as statistics for the AIN input resistance for different prescale settings.

Children
No Data
Related