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, ¢er_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, ¢er_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.