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

Unaccurate battery level measurment on Beacon device

Hi,

I know that a lot of question exists on that subject, but I can't manage to have an accurate battery measure on [Nordic Beacon device] (battery CR1632 3V) (www.nordicsemi.com/.../nRF51822-Bluetooth-Smart-Beacon-Kit). The measure is always -100mV-300mv to low and I can't understand why.

First of all, I read the Nordic GitHub project to inpired me and then modify the configuration to fit my need, but I certainly did a mistake.

The battery measurment is done before any bluetooth stack is involved (before starting the advertisment) : in summary no advertising and device not connected.

Here is my code :

#define ADC_REF_VOLTAGE_IN_MILLIVOLTS        1200                                       /**< Reference voltage (in milli volts) used by ADC while doing conversion. */
#define ADC_PRE_SCALING_COMPENSATION         3                                          /**< The ADC is configured to use VDD with 1/3 prescaling as input. And hence the result of conversion is to be multiplied by 3 to get the actual value of the battery voltage.*/
#define DIODE_FWD_VOLT_DROP_MILLIVOLTS       270                                        /**< Typical forward voltage drop of the diode (Part no: SD103ATW-7-F) that is connected in series with the voltage supply. 
                                                                                             This is the voltage drop when the forward current is 1mA. Source: Data sheet of 'SURFACE MOUNT SCHOTTKY BARRIER DIODE ARRAY' available at www.diodes.com. */
#define ADC_RESULT_IN_MILLI_VOLTS(ADC_VALUE)\
        ((((ADC_VALUE) * ADC_REF_VOLTAGE_IN_MILLIVOLTS) / 255) * ADC_PRE_SCALING_COMPENSATION)  
              
//ADC initialization
static void adc_init(void)
{	
	/* Enable interrupt on ADC sample ready event*/		
	NRF_ADC->INTENSET = ADC_INTENSET_END_Msk;   
	sd_nvic_SetPriority(ADC_IRQn, NRF_APP_PRIORITY_LOW);  
	sd_nvic_EnableIRQ(ADC_IRQn);

  // Configure ADC
  NRF_ADC->CONFIG     = (ADC_CONFIG_RES_8bit                        << ADC_CONFIG_RES_Pos)     |  /*!< 8bit ADC resolution. */ 
                        (ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos)  |
                        (ADC_CONFIG_REFSEL_VBG                      << ADC_CONFIG_REFSEL_Pos)  |  /*!< Use internal 1.2V bandgap voltage as reference for conversion. */
                        (ADC_CONFIG_PSEL_Disabled                   << ADC_CONFIG_PSEL_Pos)    |
                        (ADC_CONFIG_EXTREFSEL_None                  << ADC_CONFIG_EXTREFSEL_Pos); /* Bits 17..16 : ADC external reference pin selection. */
	
	/* Enable ADC*/
	NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled;
}

void ADC_IRQHandler(void)
{
	if (NRF_ADC->EVENTS_END != 0)
	{
		uint8_t   adc_result;
        uint16_t  batt_lvl_in_milli_volts;
		
		NRF_ADC->EVENTS_END = 0;
		adc_result  = NRF_ADC->RESULT;
		NRF_ADC->TASKS_STOP = 1;

		//Release the external crystal
		sd_clock_hfclk_release();

		batt_lvl_in_milli_volts = ADC_RESULT_IN_MILLI_VOLTS(adc_result);
		
		m_bat_level  = (batt_lvl_in_milli_volts / 10) - 100;
		kernel_setSignal(SIGNAL_BATTERY_CHECK);
	}


void kernel_battery_check(void)
{
    uint32_t p_is_running = 0;

	sd_clock_hfclk_request();
	while(! p_is_running) {  							//wait for the hfclk to be available
		sd_clock_hfclk_is_running((&p_is_running));
	}            
    NRF_ADC->EVENTS_END  = 0;    // Stop any running conversions.	
	NRF_ADC->TASKS_START = 1;
}
Parents Reply Children
No Data
Related