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

Parents
  • 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.

Reply
  • 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.

Children
  • 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.

  • Ok, the issue is on line #19 of the code snippet. It should be:

    NRF_LOG_INFO("V2=%d\r\n", p_event->data.done.p_buffer[1]);

    instead of:

    NRF_LOG_INFO("V2=%d\r\n", p_event->data.done.p_buffer[2]);

    After this change, the code works as expected.

  • Hi,

    I'm using above code to read SAADC. However, I'm experiencing a strange issue. The SAADC works fine when device is not connected to BLE central device. As soon as it's connected, the saadc_callback function stops executing despite the fact that nrf_drv_saadc_sample(); returns NRF_SUCCESSFUL. 

    I have tried changing the priority of SAADC IRQ in the sdk_config.h from 7 to 3, still no success.

    The code otherwise works fine and at device startup, when it's not connected, SAADC reads values correctly.

  • Hi,

    There should not be any link between the BLE connection and the SAADC. Do you do something else when the connection is established? Could it for instance be that you start doing a lot of work in a higher priority interrupt that blocks the SAADC handling? Or some other logic flaw in the app that prevents SAADC sampling? Can you verify (for instance by breakpoints in the SAADC driver) weather the sampling is actually started and weather an interrupt is triggered?

Related