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

Battery percentage calculation

Hi Nordic,

I are working on battery operated device.

Need to measure battery percentage using ADC.

Let me know how can we select range of 0-100% for battery voltage range between 2.1 V- 3.0 V.

Fully charged battery has 3.0 V and it should give me 100%.

While 2.1 V is minimum voltage at which controller powered off.

Let me know how can we measure accurate percentage using ADC.

Parents
  • Currently I am using below function to get percentage but it is not giving correct results.

    /** @brief Function for converting the input voltage (in milli volts) into percentage of 3.0 Volts.
     *
     *  @details The calculation is based on a linearized version of the battery's discharge
     *           curve. 3.0V returns 100% battery level. The limit for power failure is 2.1V and
     *           is considered to be the lower boundary.
     *
     *           The discharge curve for CR2032 is non-linear. In this model it is split into
     *           4 linear sections:
     *           - Section 1: 3.0V - 2.9V = 100% - 42% (58% drop on 100 mV)
     *           - Section 2: 2.9V - 2.74V = 42% - 18% (24% drop on 160 mV)
     *           - Section 3: 2.74V - 2.44V = 18% - 6% (12% drop on 300 mV)
     *           - Section 4: 2.44V - 2.1V = 6% - 0% (6% drop on 340 mV)
     *
     *           These numbers are by no means accurate. Temperature and
     *           load in the actual application is not accounted for!
     *
     *  @param[in] mvolts The voltage in mV
     *
     *  @return    Battery level in percent.
    */
    static __INLINE uint8_t battery_level_in_percent(const uint16_t 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;
    }
    

Reply
  • Currently I am using below function to get percentage but it is not giving correct results.

    /** @brief Function for converting the input voltage (in milli volts) into percentage of 3.0 Volts.
     *
     *  @details The calculation is based on a linearized version of the battery's discharge
     *           curve. 3.0V returns 100% battery level. The limit for power failure is 2.1V and
     *           is considered to be the lower boundary.
     *
     *           The discharge curve for CR2032 is non-linear. In this model it is split into
     *           4 linear sections:
     *           - Section 1: 3.0V - 2.9V = 100% - 42% (58% drop on 100 mV)
     *           - Section 2: 2.9V - 2.74V = 42% - 18% (24% drop on 160 mV)
     *           - Section 3: 2.74V - 2.44V = 18% - 6% (12% drop on 300 mV)
     *           - Section 4: 2.44V - 2.1V = 6% - 0% (6% drop on 340 mV)
     *
     *           These numbers are by no means accurate. Temperature and
     *           load in the actual application is not accounted for!
     *
     *  @param[in] mvolts The voltage in mV
     *
     *  @return    Battery level in percent.
    */
    static __INLINE uint8_t battery_level_in_percent(const uint16_t 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;
    }
    

Children
  • Mihir, 

    there are some examples in the SDK that are using SAADC to sample the input voltage and convert them into battery percentage. If you search this devzone, there are a lot of discussions on how to achieve that. For example, this thread shows you that the given SDK example can be used to configure NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE that samples the given input pin that shows the voltage of the battery.

    The discharge curve realization in the software for CR2032 looks fine. For the input pin configuration to the SAADC and initialization of SAADC please look into the mentioned examples in the link.

Related