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

nRF52832 SAADC

Hello,

I'm using nRF SDK 15.0. I'm trying to use SAADC peripheral in my code. My primary code is based on "ble_app_template". I have added several services which are working fine. 

I have copied the SAADC code from the saadc example in the peripheral folder of SDK. The code is as it is. I can compile the SAADC example individually but when try to use this code in the BLE project, it gives errors (as below). 

Kindly let me know what needs to be changed/adjusted. I need at least two analog inputs.


Compiling ‘main.c’
implicit declaration of function 'saadc_init'; did you mean 'gatt_init'? [-Wimplicit-function-declaration]
'Output/xxx_s132_nrf52832 Debug/Obj/SEGGER_RTT.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/SEGGER_RTT_Syscalls_SES.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/SEGGER_RTT_printf.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/ble_advdata.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/ble_advertising.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/ble_conn_params.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/ble_conn_state.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/ble_srv_common.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/gatt_cache_manager.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/gatts_cache_manager.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/id_manager.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/nrf_ble_gatt.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/nrf_ble_qwr.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/peer_data_storage.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/peer_database.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/peer_id.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/peer_manager.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/pm_buffer.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/pm_mutex.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/security_dispatcher.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/security_manager.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/ble_bas.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/nrf_sdh.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/nrf_sdh_ble.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/nrf_sdh_soc.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/cue_service.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/rgb_service.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/bat_service.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/cmd_service.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/cue_driver.o' is up to date
'Output/xxx_s132_nrf52832 Debug/Obj/rgb_driver.o' is up to date
Output/xxx_s132_nrf52832 Debug/Obj/adc_driver.o does not exist.
Compiling ‘adc_driver.c’
nrfx.h
nrfx_saadc.h
nrf_drv_saadc.h
adc_driver.c
'NRFX_TIMER0_INST_IDX' undeclared here (not in a function); did you mean 'NRFX_TIMER3_INST_IDX'?
in definition of macro 'NRFX_CONCAT_3_'
in expansion of macro 'NRFX_CONCAT_3'
in expansion of macro 'NRFX_TIMER_INSTANCE'
in expansion of macro 'NRF_DRV_TIMER_INSTANCE'
Build failed

  • You've probably missed configuring something in the sdk_config.h ...

  • I forgot to add header file in the main.c. However after adding header file, I get following error:

    Building ‘xxx_s132_nrf52832’ from solution ‘xxx_s132_nrf52832’ in configuration ‘Release’
    Output/xxx_s132_nrf52832 Release/Obj/thumb_crt0.o does not exist.
    Assembling ‘thumb_crt0.s’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_log_backend_rtt.o does not exist.
    Compiling ‘nrf_log_backend_rtt.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_log_backend_serial.o does not exist.
    Compiling ‘nrf_log_backend_serial.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_log_backend_uart.o does not exist.
    Compiling ‘nrf_log_backend_uart.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_log_default_backends.o does not exist.
    Compiling ‘nrf_log_default_backends.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_log_frontend.o does not exist.
    Compiling ‘nrf_log_frontend.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_log_str_formatter.o does not exist.
    Compiling ‘nrf_log_str_formatter.c’
    Output/xxx_s132_nrf52832 Release/Obj/app_button.o does not exist.
    Compiling ‘app_button.c’
    Output/xxx_s132_nrf52832 Release/Obj/app_error.o does not exist.
    Compiling ‘app_error.c’
    Output/xxx_s132_nrf52832 Release/Obj/app_error_handler_gcc.o does not exist.
    Compiling ‘app_error_handler_gcc.c’
    Output/xxx_s132_nrf52832 Release/Obj/app_error_weak.o does not exist.
    Compiling ‘app_error_weak.c’
    Output/xxx_s132_nrf52832 Release/Obj/app_scheduler.o does not exist.
    Compiling ‘app_scheduler.c’
    Output/xxx_s132_nrf52832 Release/Obj/app_timer.o does not exist.
    Compiling ‘app_timer.c’
    Output/xxx_s132_nrf52832 Release/Obj/app_util_platform.o does not exist.
    Compiling ‘app_util_platform.c’
    Output/xxx_s132_nrf52832 Release/Obj/crc16.o does not exist.
    Compiling ‘crc16.c’
    Output/xxx_s132_nrf52832 Release/Obj/fds.o does not exist.
    Compiling ‘fds.c’
    Output/xxx_s132_nrf52832 Release/Obj/hardfault_implementation.o does not exist.
    Compiling ‘hardfault_implementation.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_assert.o does not exist.
    Compiling ‘nrf_assert.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_atfifo.o does not exist.
    Compiling ‘nrf_atfifo.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_atflags.o does not exist.
    Compiling ‘nrf_atflags.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_atomic.o does not exist.
    Compiling ‘nrf_atomic.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_balloc.o does not exist.
    Compiling ‘nrf_balloc.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_fprintf.o does not exist.
    Compiling ‘nrf_fprintf.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_fprintf_format.o does not exist.
    Compiling ‘nrf_fprintf_format.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_fstorage.o does not exist.
    Compiling ‘nrf_fstorage.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_fstorage_sd.o does not exist.
    Compiling ‘nrf_fstorage_sd.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_memobj.o does not exist.
    Compiling ‘nrf_memobj.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_pwr_mgmt.o does not exist.
    Compiling ‘nrf_pwr_mgmt.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_section_iter.o does not exist.
    Compiling ‘nrf_section_iter.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_strerror.o does not exist.
    Output/xxx_s132_nrf52832 Release/Obj/sensorsim.o does not exist.
    Compiling ‘sensorsim.c’
    Compiling ‘nrf_strerror.c’
    Output/xxx_s132_nrf52832 Release/Obj/app_pwm.o does not exist.
    Output/xxx_s132_nrf52832 Release/Obj/ses_nRF_Startup.o does not exist.
    Assembling ‘ses_nRF_Startup.s’
    Compiling ‘app_pwm.c’
    Output/xxx_s132_nrf52832 Release/Obj/ses_nrf52_Vectors.o does not exist.
    Assembling ‘ses_nrf52_Vectors.s’
    Output/xxx_s132_nrf52832 Release/Obj/system_nrf52.o does not exist.
    Compiling ‘system_nrf52.c’
    Output/xxx_s132_nrf52832 Release/Obj/boards.o does not exist.
    Compiling ‘boards.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_drv_clock.o does not exist.
    Compiling ‘nrf_drv_clock.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_drv_uart.o does not exist.
    Compiling ‘nrf_drv_uart.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrfx_clock.o does not exist.
    Compiling ‘nrfx_clock.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrfx_gpiote.o does not exist.
    Compiling ‘nrfx_gpiote.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrfx_power_clock.o does not exist.
    Compiling ‘nrfx_power_clock.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrfx_prs.o does not exist.
    Compiling ‘nrfx_prs.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrfx_uart.o does not exist.
    Compiling ‘nrfx_uart.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrfx_uarte.o does not exist.
    Compiling ‘nrfx_uarte.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrfx_saadc.o does not exist.
    Compiling ‘nrfx_saadc.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrfx_timer.o does not exist.
    Compiling ‘nrfx_timer.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrf_drv_ppi.o does not exist.
    Compiling ‘nrf_drv_ppi.c’
    Output/xxx_s132_nrf52832 Release/Obj/nrfx_ppi.o does not exist.
    Compiling ‘nrfx_ppi.c’
    Output/xxx_s132_nrf52832 Release/Obj/bsp.o does not exist.
    Compiling ‘bsp.c’
    Output/xxx_s132_nrf52832 Release/Obj/bsp_btn_ble.o does not exist.
    Compiling ‘bsp_btn_ble.c’
    Output/xxx_s132_nrf52832 Release/Obj/main.o does not exist.
    Compiling ‘main.c’
    main.c
    unknown type name 'nrf_timer_event_t'; did you mean 'app_timer_event_t'?
    unknown type name 'nrf_drv_saadc_evt_t'; did you mean 'nrf_sdh_state_evt_t'?
    main.c
    storage class specified for parameter 'm_gatt'
    in definition of macro 'NRF_BLE_GATT_DEF'
    ble_srv_common.h
    main.c
    expected declaration specifiers or '...' before '_Static_assert'
    in definition of macro '_SELECT_ASSERT_FUNC'
    in expansion of macro 'STATIC_ASSERT_MSG'
    in expansion of macro 'STATIC_ASSERT'
    in expansion of macro 'NRF_SDH_BLE_OBSERVER'
    in expansion of macro 'NRF_BLE_GATT_DEF'
    expected declaration specifiers or '...' before '_Static_assert'
    in definition of macro '_SELECT_ASSERT_FUNC'
    in expansion of macro 'STATIC_ASSERT_MSG'
    in expansion of macro 'STATIC_ASSERT'
    in expansion of macro 'NRF_SDH_BLE_OBSERVER'
    in expansion of macro 'NRF_BLE_GATT_DEF'
    nrf_section_iter.h
    nrf_sdh.h
    main.c
    storage class specified for parameter 'm_gatt_obs'
    in definition of macro 'NRF_SECTION_ITEM_REGISTER'
    in expansion of macro 'NRF_SECTION_SET_ITEM_REGISTER'
    in expansion of macro 'NRF_SDH_BLE_OBSERVER'
    in expansion of macro 'NRF_BLE_GATT_DEF'
    section attribute not allowed for 'm_gatt_obs'
    in definition of macro 'NRF_SECTION_ITEM_REGISTER'
    in expansion of macro 'NRF_SECTION_SET_ITEM_REGISTER'
    in expansion of macro 'NRF_SDH_BLE_OBSERVER'
    in expansion of macro 'NRF_BLE_GATT_DEF'
    ble_srv_common.h
    main.c
    'used' attribute ignored [-Wattributes]
    in definition of macro '_SELECT_ASSERT_FUNC'
    in expansion of macro 'STATIC_ASSERT_MSG'
    in expansion of macro 'STATIC_ASSERT'
    in expansion of macro 'NRF_SDH_BLE_OBSERVER'
    in expansion of macro 'NRF_BLE_GATT_DEF'
    main.c
    expected ';', ',' or ')' before '=' token
    in expansion of macro 'NRF_SDH_BLE_OBSERVER'
    in expansion of macro 'NRF_BLE_GATT_DEF'
    Output/xxx_s132_nrf52832 Release/Obj/SEGGER_RTT.o does not exist.
    Compiling ‘SEGGER_RTT.c’
    Output/xxx_s132_nrf52832 Release/Obj/SEGGER_RTT_Syscalls_SES.o does not exist.
    Compiling ‘SEGGER_RTT_Syscalls_SES.c’
    Output/xxx_s132_nrf52832 Release/Obj/SEGGER_RTT_printf.o does not exist.
    Compiling ‘SEGGER_RTT_printf.c’
    Build failed

  • Hi,

    You should always start with the first error. Here, the first errors are about missing objects, which is because the linker is trying to find objects which has not been compiled. That typically has one of two reasons:

    • Either the .c file implementing them is not compiled
    • or the relevant parts of the file is not compiled due to the preprocessor removing them, typically because of missing sdk_config.h configuration in the nRF5 SDK.

    To fix this:

    • Add missing files (such as nrf_log_backend_rtt.c)
    • Add missing configurations in sdk_config.h (such as NRF_LOG_BACKEND_RTT_ENABLED and NRF_LOG_ENABLED).
    • Alternatively, if you don't want logging in the first place, remove the code from your application and the linker will no longer look for this, as it is not used.

    Lastly, you might find it simpler to start off with an example that has most of what you want. You should also refer to another example with RTT logging (if that is what you want), so that you can see which files, included and sdk_config.h parameters it needs.

  • Hello,

    I have changed the SAADC code a little bit. Here is the code:

    #include "nrf_drv_saadc.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    
    #define SAMPLES_IN_BUFFER 2
    
    static nrf_saadc_value_t m_buffer[2][SAMPLES_IN_BUFFER];
    
    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;
    
            err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
            APP_ERROR_CHECK(err_code);
            
            NRF_LOG_INFO("V1=%d", p_event->data.done.p_buffer[0]);
            NRF_LOG_INFO("V2=%d\r\n", p_event->data.done.p_buffer[2]);
        }
    }
    
    void saadc_init(void)
    {
        ret_code_t err_code;
        nrf_saadc_channel_config_t channel_config_1 
            = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1);
        nrf_saadc_channel_config_t channel_config_2 
            = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
    
        err_code = nrf_drv_saadc_init(NULL, saadc_callback);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_channel_init(1, &channel_config_1);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_saadc_channel_init(2, &channel_config_2);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_buffer_convert(m_buffer[0], SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_saadc_buffer_convert(m_buffer[1], SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
    
        // Analog PIN assignments
        // P0.02/AIN0
        // P0.03/AIN1 --> Drive_V
        // P0.04/AIN2 --> Batt_V
    }
    
    void saadc_voltage_get(){
    
        NRF_LOG_INFO("SAADC Getting voltage");
        nrf_drv_saadc_sample();
    }

    With above code I'm able read the first channel correctly. For second channel, I get random values and if a known voltage is applied, only random values are printed by log. Below is the log:

    <info> app: Battery Level timeout event
    <info> app: Getting SAADC values...
    <info> app: SAADC Getting voltage
    <info> app: V1=53
    <info> app: V2=74

    V1 belongs to "channel_config_1". I have applied different voltage and reading are correct. V2 belongs to "channel_config_2". It never gives accurate value. No matter if I change the Analog channel above in definition.

    saadc_voltage_get() is called by main function on regular timer intervals.

    Can you guide me what's happening?

  • What board are you using?

    If not a Nordic DK, have you checked it on a Nordic DK?

    Don't know if it matters, but you're numbering your ADC channels from 1 - what happens if you number from zero ... ?

    Note that you don't need a separate initialisation structure for each channel.

Related