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;

}

Related