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

Can I measure the battery charge more accurately?

Hello

I use nrf52832 and lithium battery (3.7v, 140 mAh).
I can read the adc value of this battery through the charge IC.  I monitored the adc value while charging the battery.
Charge started when the battery was about 3v.  When I look at the adc value, it goes up quickly at first and then slowly.  This is why it is ambiguous to represent the remaining battery power as a percentage.  It goes up to 50 percent fast and then slowly increases afterwards.
How do I keep the battery charging speed constant?  Is this possible with the firmware?
//battery ADC range 
#define BAT_ADC_100 700 
#define BAT_ADC_75  655 
#define BAT_ADC_50  610 
#define BAT_ADC_10  530 //If low battery power off
#define BAT_ADC_0   520 

//If charging ADC range
#define BAT_ADC2_100 730  
#define BAT_ADC2_75  710 
#define BAT_ADC2_50  695  
#define BAT_ADC2_0   660 

int charge_state;
int charging_state = 0; //Used to prevent repeated output of CenterLED_timers_start.
int16_t bat_level; 
float bat_persent;
  
void turn_on_batter_level_led(bat_level) //battery LED. int16_t bat_level
{ 
    ret_code_t err_code;

    if(charge_state == 0) //charging
    {  
      //stop center LED, start Battery LED
      CrushLED_timers_stop(); //stop crush, start center, all led off   
      CenterLED_timers_stop();       
       
      charging_state = 1;
      bat_charge_state = 1; //In bat charging
      printf("Charging...\n");

      if(charge_state != 0) //disconnect charging
      {
        nrf_delay_ms(50);
        pwm_change_frequency(1500); 
        do_play_buzzer();
        nrf_gpio_pin_clear(POWER_SW); //LOW : power off
        //NVIC_SystemReset();
      }

      if(centerled_state == 0) //No running center led
      {

      if(bat_level >= BAT_ADC2_75) { // over 75%
        printf("over 75persent \n"); //led1,2,3 on
        BatLed1_timers_start();

        BatLed2_timers_stop();
        BatLed3_timers_stop();
      }

      else if (BAT_ADC2_75 > bat_level && bat_level >= BAT_ADC2_50) { //over 50%
        printf("over 50persent \n"); //led1,2 on
        BatLed2_timers_start();

        BatLed1_timers_stop();
        BatLed3_timers_stop();
      }
  
      else if (bat_level < BAT_ADC2_50) { //under 50%
       printf("under 50persent \n"); //led1 on
       BatLed3_timers_start();

        BatLed1_timers_stop();
        BatLed2_timers_stop();
      }  
    }

    }

    else //no charging
    {
      //charging_state = 0;
      bat_charge_state = 0;
      BatLed1_timers_stop();
      BatLed2_timers_stop();
      BatLed3_timers_stop();
      All_Led_Off();

      if(bat_level < BAT_ADC_10)
      {
        printf("Low battery.. power off \n");
        pwm_change_frequency(1500); 
        do_play_buzzer();
        nrf_gpio_pin_clear(POWER_SW); //LOW : power off
      }
    }

//=====================================================================

    //Send battery to App 
    char battery_adc[20]; 
    sprintf(battery_adc, "Battery_ADC :%u", bat_level); //Store values in array.
    uint16_t length_bat_level = strlen(battery_adc); //length measurement of string 

    err_code = ble_nus_data_send(&m_nus, &battery_adc, &length_bat_level, m_conn_handle);
    if ((err_code != NRF_ERROR_INVALID_STATE) &&
                            (err_code != NRF_ERROR_RESOURCES) &&
                            (err_code != NRF_ERROR_NOT_FOUND))
                        {
                            APP_ERROR_CHECK(err_code);
                        }   

           
    //If charging                          
    if(charge_state == 0)
    {
      char battery_charging[] = {"Charging.."};

      uint16_t length_bat_charging = sizeof(battery_charging); //length measurement of string 

      err_code = ble_nus_data_send(&m_nus, &battery_charging, &length_bat_charging, m_conn_handle);
      if ((err_code != NRF_ERROR_INVALID_STATE) &&
                            (err_code != NRF_ERROR_RESOURCES) &&
                            (err_code != NRF_ERROR_NOT_FOUND))
                        {
                            APP_ERROR_CHECK(err_code);
                        } 


    char battery_persent2[20]; 
    char persent2 = '%';
    sprintf(battery_persent2, "%.0f%c", bat_persent, persent2); //Store values in array.
    uint16_t length_bat_persent2 = strlen(battery_persent2); //length measurement of string 

    err_code = ble_nus_data_send(&m_nus, &battery_persent2, &length_bat_persent2, m_conn_handle);
    if ((err_code != NRF_ERROR_INVALID_STATE) &&
                            (err_code != NRF_ERROR_RESOURCES) &&
                            (err_code != NRF_ERROR_NOT_FOUND))
                        {
                            APP_ERROR_CHECK(err_code);
                        }  


    if(bat_level >= BAT_ADC2_75) {
        char charge_array1[] = "over 75";
        uint16_t charge_length1 = sizeof(charge_array1);

         err_code = ble_nus_data_send(&m_nus, &charge_array1, &charge_length1, m_conn_handle);
         if ((err_code != NRF_ERROR_INVALID_STATE) && 
                            (err_code != NRF_ERROR_RESOURCES) &&
                            (err_code != NRF_ERROR_NOT_FOUND))
                            {
                              APP_ERROR_CHECK(err_code);
                            }
    }


    else if(BAT_ADC2_75 > bat_level && bat_level >= BAT_ADC2_50) {
        char charge_array2[] = "over 50";
        uint16_t charge_length2 = sizeof(charge_array2);

         err_code = ble_nus_data_send(&m_nus, &charge_array2, &charge_length2, m_conn_handle);
         if ((err_code != NRF_ERROR_INVALID_STATE) && 
                            (err_code != NRF_ERROR_RESOURCES) &&
                            (err_code != NRF_ERROR_NOT_FOUND))
                            {
                              APP_ERROR_CHECK(err_code);
                            }
    } 

    else if(bat_level < BAT_ADC2_50) {    
        char charge_array3[] = "under 50";
        uint16_t charge_length3 = sizeof(charge_array3);

         err_code = ble_nus_data_send(&m_nus, &charge_array3, &charge_length3, m_conn_handle);
         if ((err_code != NRF_ERROR_INVALID_STATE) && 
                            (err_code != NRF_ERROR_RESOURCES) &&
                            (err_code != NRF_ERROR_NOT_FOUND))
                            {
                              APP_ERROR_CHECK(err_code);
                            } 
      } 

    }


    else //No charging
    {
      char battery_charging2[] = {"No charging or Full charging"};

      uint16_t length_bat_charging2 = sizeof(battery_charging2); //length measurement of string 

      err_code = ble_nus_data_send(&m_nus, &battery_charging2, &length_bat_charging2, m_conn_handle);
      if ((err_code != NRF_ERROR_INVALID_STATE) &&
                            (err_code != NRF_ERROR_RESOURCES) &&
                            (err_code != NRF_ERROR_NOT_FOUND))
                        {
                            APP_ERROR_CHECK(err_code);
                        } 

  
    char battery_persent[20]; 
    char persent = '%';
    sprintf(battery_persent, "%.0f%c", bat_persent, persent); //Store values in array.
    uint16_t length_bat_persent = strlen(battery_persent); //length measurement of string 

    err_code = ble_nus_data_send(&m_nus, &battery_persent, &length_bat_persent, m_conn_handle);
    if ((err_code != NRF_ERROR_INVALID_STATE) &&
                            (err_code != NRF_ERROR_RESOURCES) &&
                            (err_code != NRF_ERROR_NOT_FOUND))
                        {
                            APP_ERROR_CHECK(err_code);
                        }   


    if(bat_level >= BAT_ADC_75) {
        char bat_array1[] = "over 75";
        uint16_t bat_length1 = sizeof(bat_array1);

         err_code = ble_nus_data_send(&m_nus, &bat_array1, &bat_length1, m_conn_handle);
         if ((err_code != NRF_ERROR_INVALID_STATE) && 
                            (err_code != NRF_ERROR_RESOURCES) &&
                            (err_code != NRF_ERROR_NOT_FOUND))
                            {
                              APP_ERROR_CHECK(err_code);
                            }
    }


    else if(BAT_ADC_75 > bat_level && bat_level >= BAT_ADC_50) {
        char bat_array2[] = "over 50";
        uint16_t bat_length2 = sizeof(bat_array2);

         err_code = ble_nus_data_send(&m_nus, &bat_array2, &bat_length2, m_conn_handle);
         if ((err_code != NRF_ERROR_INVALID_STATE) && 
                            (err_code != NRF_ERROR_RESOURCES) &&
                            (err_code != NRF_ERROR_NOT_FOUND))
                            {
                              APP_ERROR_CHECK(err_code);
                            }
    } 

    else if(bat_level < BAT_ADC_50) {    
        char bat_array3[] = "under 50";
        uint16_t bat_length3 = sizeof(bat_array3);

         err_code = ble_nus_data_send(&m_nus, &bat_array3, &bat_length3, m_conn_handle);
         if ((err_code != NRF_ERROR_INVALID_STATE) && 
                            (err_code != NRF_ERROR_RESOURCES) &&
                            (err_code != NRF_ERROR_NOT_FOUND))
                            {
                              APP_ERROR_CHECK(err_code);
                            } 
      } 

      else {
        char bat_array4[] = "battery error?";
        uint16_t bat_length4 = sizeof(bat_array4);

         err_code = ble_nus_data_send(&m_nus, &bat_array4, &bat_length4, m_conn_handle);
         if ((err_code != NRF_ERROR_INVALID_STATE) && 
                            (err_code != NRF_ERROR_RESOURCES) &&
                            (err_code != NRF_ERROR_NOT_FOUND))
                            {
                              APP_ERROR_CHECK(err_code);
                            } 
      }
    }



    if(centerled_state == 0) //Check center led timer state
    {
      char center_state[] = {"No center led"};

      uint16_t length_center_state = sizeof(center_state); //length measurement of string 

      err_code = ble_nus_data_send(&m_nus, &center_state, &length_center_state, m_conn_handle);
      if ((err_code != NRF_ERROR_INVALID_STATE) &&
                            (err_code != NRF_ERROR_RESOURCES) &&
                            (err_code != NRF_ERROR_NOT_FOUND))
                        {
                            APP_ERROR_CHECK(err_code);
                        } 
    }

    else
    {
      char center_state2[] = {"Running center led"};

      uint16_t length_center_state2 = sizeof(center_state2); //length measurement of string 

      err_code = ble_nus_data_send(&m_nus, &center_state2, &length_center_state2, m_conn_handle);
      if ((err_code != NRF_ERROR_INVALID_STATE) &&
                            (err_code != NRF_ERROR_RESOURCES) &&
                            (err_code != NRF_ERROR_NOT_FOUND))
                        {
                            APP_ERROR_CHECK(err_code);
                        } 
    }
}

//=====================================================================

void saadc_callback(nrf_drv_saadc_evt_t const * p_event) //battery level
{ //battery A0 pin 
    ret_code_t err_code;
    int16_t bat_level = 0;
    int16_t adc_average = 0; //average adc value
    float percent_average;
    float percent_average2;

   if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
   {
        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);

        int i;
        //NRF_LOG_INFO("ADC event number: %d", (int)m_adc_evt_counter);
 

    //Average of bat_level(ADC)
    for(int a=0; a<10; a++)
    {        
        for (i = 0; i < SAMPLES_IN_BUFFER; i++)
        {
            NRF_LOG_INFO("%d", p_event->data.done.p_buffer[i]);
            bat_level += p_event->data.done.p_buffer[i];
        }

        m_adc_evt_counter++;
        bat_level /= SAMPLES_IN_BUFFER; //bat_level = bat_level / SAMPLES_IN_BUFFER

        adc_average = adc_average + bat_level;
        printf("adc_average : %u \n", adc_average);
        //nrf_delay_ms(10);
    }
   }
    adc_average /= 10;
    bat_level = adc_average;  //ADC value 


    //battery persent
    if(charge_state == 0) //In charging
    {
      bat_persent = (bat_level - BAT_ADC2_0) * 100 / 70; //BAT_100 - BAT_0

      for(int b=0; b<10; b++)
      {
        percent_average += bat_persent;
      }

      percent_average /= 10;
      //bat_persent = percent_average;
    }

    else //No charging
    {
      bat_persent = (bat_level - BAT_ADC_0) * 100 / 180; //BAT_100 - BAT_0

      for(int c=0; c<10; c++)
      {
        percent_average += bat_persent;
      }

      percent_average /= 10;
      //bat_persent = percent_average;
    }

    bat_persent = percent_average;

    if(bat_persent > 100)
    {
      bat_persent = 100;
    }
    else if(bat_persent < 0)
    {
      bat_persent = 0;
    }

    turn_on_batter_level_led(bat_level);
    //}
}


void saadc_init(void)
{
    ret_code_t err_code;
    nrf_saadc_channel_config_t channel_config =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0); //A0 pin

    err_code = nrf_drv_saadc_init(NULL, saadc_callback);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_channel_init(0, &channel_config);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);
}

static void adc_configure(void)
{
    saadc_init();
    saadc_sampling_event_init();
    saadc_sampling_event_enable();
}
                   
 
Thank you.
Parents Reply Children
No Data
Related