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

SAADC to measure battery voltage not getting proper result

Hi,

I am new to the SAADC concept in nrf52. I have to measure the battery voltage using SAADC over ANI0 pin. I using battery with voltage 4.1 volt.

This voltage is divided using voltage divider with two resistances of 10 kohm and 3.5 kohm . I am applying 1 volt to the ANI0 pin through this network.

SAADC configuration is the default one with single ended. reference = 0.6volt gain = 1/6

So as per the formula given in datasheet,under this condition I should get ADC output as

((1*(1/6))*256)/0.6=71.11

but i am getting 4 or 5 or 6 as output on UART. following is the code,

    /* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
 *
 * The information contained herein is property of Nordic Semiconductor ASA.
 * Terms and conditions of usage are described in detail in NORDIC
 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
 *
 * Licensees are granted free, non-transferable use of the information. NO
 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
 * the file.
 *
 */

/** @file
 * @defgroup nrf_adc_example main.c
 * @{
 * @ingroup nrf_adc_example
 * @brief ADC Example Application main file.
 *
 * This file contains the source code for a sample application using ADC.
 *
 * @image html example_board_setup_a.jpg "Use board setup A for this example."
 */

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "nrf.h"
#include "nrf_drv_saadc.h"
#include "boards.h"
#include "app_uart.h"
#include "app_error.h"
#include "app_util_platform.h"
#include "nrf_drv_clock.h"
#include "nrf_drv_rtc.h"
#include "nrf_delay.h"

#define UART_TX_BUF_SIZE 256 /**< UART TX buffer size. */
#define UART_RX_BUF_SIZE 1   /**< UART RX buffer size. */

#define SAMPLES_IN_BUFFER 1               //Number of SAADC samples in RAM before returning a SAADC event. Do not change this constant for low power SAADC
#define UART_PRINTING_ENABLED							//Enable to see SAADC output on UART. Comment out for low power operation.

void saadc_init(void);

volatile uint8_t state = 1;

const nrf_drv_rtc_t            rtc = NRF_DRV_RTC_INSTANCE(0); /**< Declaring an instance of nrf_drv_rtc for RTC0. */
static nrf_saadc_value_t       m_buffer_pool[2][SAMPLES_IN_BUFFER];
//static uint32_t                m_adc_evt_counter;
/**
 * @brief UART events handler.
 */
void uart_events_handler(app_uart_evt_t * p_event)
{
}

/**
 * @brief UART initialization.
 */
void uart_config(void)
{
    uint32_t                     err_code;
    const app_uart_comm_params_t comm_params =
    {
        RX_PIN_NUMBER,
        TX_PIN_NUMBER,
        RTS_PIN_NUMBER,
        CTS_PIN_NUMBER,
        APP_UART_FLOW_CONTROL_DISABLED,
        false,
        UART_BAUDRATE_BAUDRATE_Baud115200
    };

    APP_UART_FIFO_INIT(&comm_params,
                       UART_RX_BUF_SIZE,
                       UART_TX_BUF_SIZE,
                       uart_events_handler,
                       APP_IRQ_PRIORITY_LOW,
                       err_code);

    APP_ERROR_CHECK(err_code);
}

static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
{
                uint32_t err_code;
    if (int_type == NRF_DRV_RTC_INT_COMPARE0)
    {
                                saadc_init();
                                nrf_drv_saadc_sample();
                        
                                LEDS_INVERT(BSP_LED_0_MASK);        //Toggle LED1 to indicate SAADC sampling start
                        
                                err_code = nrf_drv_rtc_cc_set(&rtc,0,2000,true);
                                APP_ERROR_CHECK(err_code);
                                nrf_drv_rtc_counter_clear(&rtc);
    }
}

static void lfclk_config(void)
{
    ret_code_t err_code = nrf_drv_clock_init();
    APP_ERROR_CHECK(err_code);

    nrf_drv_clock_lfclk_request(NULL);
}

static void rtc_config(void)
{
    uint32_t err_code;

    //Initialize RTC instance
    err_code = nrf_drv_rtc_init(&rtc, NULL, rtc_handler);
    APP_ERROR_CHECK(err_code);

    //Set compare channel to trigger interrupt after COMPARE_COUNTERTIME seconds
    err_code = nrf_drv_rtc_cc_set(&rtc,0,2000,true);
    APP_ERROR_CHECK(err_code);

    //Power on RTC instance
    nrf_drv_rtc_enable(&rtc);
}


void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
    if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
    {
        ret_code_t err_code;
                        
        LEDS_INVERT(BSP_LED_1_MASK);        //Toggle LED2 to indicate SAADC sampling start			
     
        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
#ifdef UART_PRINTING_ENABLED
        //printf("ADC event number: %d\r\n",(int)m_adc_evt_counter);
        for (int i = 0; i < SAMPLES_IN_BUFFER; i++)
        {
            printf("%x\r\n", p_event->data.done.p_buffer[i]);
        }
        //m_adc_evt_counter++;
#endif //UART_PRINTING_ENABLED				
                                
        nrf_drv_saadc_uninit();
        NRF_SAADC->INTENCLR = (SAADC_INTENCLR_END_Clear << SAADC_INTENCLR_END_Pos);
        NVIC_ClearPendingIRQ(SAADC_IRQn);
    }
}

void saadc_init(void)
{
    ret_code_t err_code;
     //	nrf_drv_saadc_config_t saadc_config;
    nrf_saadc_channel_config_t channel_config =
            NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
                //Configure SAADC
    channel_config.reference = NRF_SAADC_REFERENCE_VDD4;
    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);
}

/**
 * @brief Function for main application entry.
 */
int main(void)
{	
  LEDS_CONFIGURE(LEDS_MASK);     //Configure all leds
  LEDS_OFF(LEDS_MASK);           //Turn off all leds
  //NRF_POWER->DCDCEN = 1;         //Enabling the DCDC converter
        
#ifdef UART_PRINTING_ENABLED
    uart_config();                 //Configure UART. UART is used to show the SAADC sampled result.
    printf("\n\rSAADC HAL simple example.\r\n");	
#endif //UART_PRINTING_ENABLED	

                lfclk_config();                //Configure low frequency 32kHz clock
                rtc_config();									 //Configure RTC. The RTC will generate periodic interrupts. Requires 32kHz clock to operate.

    while(1)
    {
        nrf_delay_ms(100);
        //saadc_init();
        //nrf_drv_saadc_sample();
        __WFE();                   //These three commands disable the CPU. CPU will wake up again on any event or interrupt.
        __SEV();
        __WFE();
    }
}


/** @} */

Does i am making any mistake while doing this?? Please guide me in this regards...

Related