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

working with 2 saadc configurations does not work

hello Nordic

i am working with nrf52840, sdk 16.0 

i am building my project over the peripheral app_ble_blinky example 

i whish to have 2 seprate configs for saadc

i call the following init function twice (with 2 different saadc_configs (different naming as well) ):

err_code = nrf_drv_saadc_init(&saadc_config, saadc_sample_event_handler);
    APP_ERROR_CHECK(err_code);

it does not seem to be working.. is there a way to initialize 2 saadc configs

best regards

Ziv

Parents
  • No, you have to uninit the driver beforehand. 

    What is it that you are trying to do exactly?

  • No, you have to uninit the driver beforehand.

    ok .. i found out that saadc has bass address in the instantiation table, so to my understanding there can be only one operational 'nrf_drv_saadc_config_t' at a time, so it brings the question of how is it possible to read all the AIN0-7 channels when one instance can have only 4 channels if i am not wrong.

    anyway, so i configure one 'nrf_drv_saadc_config_t' lets call 1_saadc_config and configure a second 'nrf_drv_saadc_config_t' 2_saadc_config,

    then i call for nrf_drv_saadc_init(&1_saadc_config,... some handler)

    then when sampling is done i call nrf_dev_saadc_uninit();

    then i call for nrf_drv_saadc_init(&2_saadc_config, .. some other handler)

    and when sampling is done i call nrf_drv_saadc_uninit();

    i do not re-init the channel or try to convert the buffers again

    i did not test it yet but i hope you can concur the above logic

    What is it that you are trying to do exactly?

    i need to read 2 analog inputs, each at a different time in the program's flow, so there is no collision there. each analog read requires different configurations in resolution and oversampling. 

    hope to read from you soon

    best regards

    Ziv

  • ziv123 said:
    why do i need to reconfigure the buffers and channels if i use 2 different saadc config in every init ?

     In your case it seems like you will be done with processing the saadc buffers before you need to re-configure the saadc, in that case you don't need to reconfigure the buffers. 

    Just use the uninit and inint functions and you should be fine. 



  • hello again Slight smile

    must say your site is running quite low speed today and i have to rewrite all this message again because it didn't load ): 

    i have 2 modules, in each module's init function i configure the saadc.

    the first run fine the second give error 17, BUSY when i try to init the channel , i read in the forum that this type of error might have something to do with conversion of the buffers, don't realy understand why it matters in my case since i am using different buffers for each module's saadc. here is the codes:

    //  //Initialize SAADC
    //    err_code = nrf_drv_saadc_init(&hydr_saadc_config, hydr_saadc_callback);
    //    APP_ERROR_CHECK(err_code);
      
      //Initialize SAADC channel
        err_code = nrf_drv_saadc_channel_init(3, &hydr_channel_config);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_buffer_convert(hydr_buffer_pool[0], HYDR_NUMBER_OF_ADC_SAMPLES);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_buffer_convert(hydr_buffer_pool[1], HYDR_NUMBER_OF_ADC_SAMPLES);
        APP_ERROR_CHECK(err_code);

    //    err_code = nrf_drv_saadc_init(&audio_saadc_config, audio_saadc_callback);
    //    APP_ERROR_CHECK(err_code);
    
        audio_channel_config.pin_p = AUDIO_PIEZO_ADC_INPUT_PIN; 
        err_code = nrf_drv_saadc_channel_init(0, &audio_channel_config);
        APP_ERROR_CHECK(err_code);
    
        audio_channel_config.pin_p = AUDIO_MIC_ADC_INPUT_PIN;
        err_code = nrf_drv_saadc_channel_init(1, &audio_channel_config);
        APP_ERROR_CHECK(err_code);
    
        audio_channel_config.pin_p = AUDIO_PIEZO_ADC_INPUT_PREAMPLYFIER_INPUT_PIN;
        err_code = nrf_drv_saadc_channel_init(2, &audio_channel_config);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], CONVERTED_ADC_SAMPELS_BUFF_SIZE);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], CONVERTED_ADC_SAMPELS_BUFF_SIZE);
        APP_ERROR_CHECK(err_code);

    what will be the right way to handle this error ?

    what i have done that solved it (though i am not sure its the best way) is to take the buffer conversions and put it after i call the nrf_drv_saadc_init() each time i call it and after i finish with this module i call the saadc uninit function

    another question is that i see i start getting saadc sampling events right after calling the init even if i don't use the nrf_drv_saadc_sample()

    which is not good for me cause i want the sampling to start at a certain point and i want to have just one oversampled sample, what do i need to change ?

    my saadc init look like this now :

    err_code = nrf_drv_saadc_init(&hydr_saadc_config, hydr_saadc_callback);// TBD - need to make sure, maybe global volatile flag that
                                                                       // the other modul did not initialize the saadc WITHOUT UNINITIALIZING IT
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_buffer_convert(hydr_buffer_pool[0], HYDR_NUMBER_OF_ADC_SAMPLES);
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_saadc_buffer_convert(hydr_buffer_pool[1], HYDR_NUMBER_OF_ADC_SAMPLES);
    APP_ERROR_CHECK(err_code);
                    

    and my callback:

    static void hydr_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, HYDR_NUMBER_OF_ADC_SAMPLES);
            APP_ERROR_CHECK(err_code);
    
            hydration_sample_buff[count_of_10_min_sample_events] /*hydr_val*/ = p_event->data.done.p_buffer[0];// + p_event->data.done.p_buffer[1] + p_event->data.done.p_buffer[2] + p_event->data.done.p_buffer[3])/4;        
            measurments_state = MEASURE_STATE_DONE;
            nrf_drv_saadc_uninit();
        }
    }

    [later today i edit] - apperntly i was working at release mode while debugging, returning to debug mode created some assertion issues.. in specific i don't get this assertion:

      // Oversampling can be used only with one channel.
        NRFX_ASSERT((nrf_saadc_oversample_get() != NRF_SAADC_OVERSAMPLE_DISABLED) ||
                    (m_cb.active_channels == 0));

    it says oversampling can be only when working with one channel but if over sampling is disabled and i have more then one channel it asserts .. so what should i do???, also this assertions comply me to init the saadc before the channels initiation and change the way i thought of working before .. don't know the all over consequences of this debug vs release head hack 

    hope to read you soon and hope this reply will be uploaded properly so i will not have to re-write it again ): 

    best regards

    Ziv

  • Hi,

    It may be easier to just have only one buffer at any time, so:

    1. First init by saadc_init()
    2. Prepare buffer by nrf_drv_saadc_buffer_convert()
    3. Then at some time in future execute sample by nrf_drv_saadc_sample()
    4. 
    Wait for NRF_DRV_SAADC_EVT_DONE event and handle saadc data
    5. Prepare buffer by nrf_drv_saadc_buffer_convert()
    Repeat from 3.

    If you want to change saadc configuration, then uninit saadc and re-init saadc again, but make sure you clear potential adc channels that may have been used earlier. Also make sure you don't do this between step 3 and 4 above.

    If you do any calibration of the saadc this should be done between 4 and 5 due to an errata, or between step 1 and 2.

    You are right that oversampling can only be done if 1 channel is configured, this is a hardware limitation, so don't have any good workaround here; you could just sample the channels faster and discard those measurement that you don't want.

    Best regards,
    Kenneth

  • Hi Kenneth

    sorry to say but this is not very clear and does not seem to help

    my main hold back at the moment is that moving from debugging in release mode back to debug mode bring up all sort of assertions, one of them which currently holds me back is this one:

      // Oversampling can be used only with one channel.
        NRFX_ASSERT((nrf_saadc_oversample_get() != NRF_SAADC_OVERSAMPLE_DISABLED) ||
                    (m_cb.active_channels == 0));

    it says oversampling can be only when working with one channel but if over sampling is disabled and i have more then one channel it asserts .. so what should i do???

    after we can figure out why this is happening and how to fix it i will continue with other issues

    basically just to remind, i use 2 saadc instances at different times in the program, each has its own definitions and its own channels (with different numbers for each channels - there is no overlapping there) 

    i init each of the saadc and its channels and then its buffers every time i wish to sample them and then uninit the saadc and reinit the other saadc and its channels and convert the buffers (each saadc has its own buffers)

    hope you can help me and that my problem is better understood now

    hope to read you soon

    best regards

    Ziv

Reply
  • Hi Kenneth

    sorry to say but this is not very clear and does not seem to help

    my main hold back at the moment is that moving from debugging in release mode back to debug mode bring up all sort of assertions, one of them which currently holds me back is this one:

      // Oversampling can be used only with one channel.
        NRFX_ASSERT((nrf_saadc_oversample_get() != NRF_SAADC_OVERSAMPLE_DISABLED) ||
                    (m_cb.active_channels == 0));

    it says oversampling can be only when working with one channel but if over sampling is disabled and i have more then one channel it asserts .. so what should i do???

    after we can figure out why this is happening and how to fix it i will continue with other issues

    basically just to remind, i use 2 saadc instances at different times in the program, each has its own definitions and its own channels (with different numbers for each channels - there is no overlapping there) 

    i init each of the saadc and its channels and then its buffers every time i wish to sample them and then uninit the saadc and reinit the other saadc and its channels and convert the buffers (each saadc has its own buffers)

    hope you can help me and that my problem is better understood now

    hope to read you soon

    best regards

    Ziv

Children
  • I can't see from your code where you are calling nrf_drv_saadc_channel_uninit() for previous configured channels?

    In hardware there is only one SAADC instance, so you will need to manually disable all ADC channels that is no longer in use. I do not think the uninit function of the driver does this for you.

    Edit: Looking at nrfx_saadc_uninit() I can see this is done. Will need to look at this closer then.

    Edit2:It doesn't make any sense that this should assert:

      // Oversampling can be used only with one channel.
        NRFX_ASSERT((nrf_saadc_oversample_get() != NRF_SAADC_OVERSAMPLE_DISABLED) ||
                    (m_cb.active_channels == 0));

    Both these are cleared during nrf_drv_saadc_init()->nrfx_saadc_init() by:

    nrf_saadc_oversample_set(p_config->oversample);
    m_cb.active_channels      = 0;

    Are you 100% sure that p_config->oversample is false when calling nrfx_saadc_init()?

    Kenneth

  • Are you 100% sure that p_config->oversample is false when calling nrfx_saadc_init()?

    this assertion does not happen in the saadc init function, it happens when i try to init the second channel 

    1. i init saadc_1 

    2. int saadc_1 channels

    3. convert buffers

    4. sample 

    5. un-init saadc

    6. init saadc_2

    7. init saadc_2 channels -> here first channel init goes fine, in the second channel init i get the assertion 

  • I understand that the assertion does not occur in saadc init function, however the values that is checked in NRFX_ASSERT() when channel init, is set during saadc init. 

    Hope that make sense,
    Kenneth

  • yes the oversampling is something related to saadc init but as can be seen in my configurations:

      //Configure SAADC
        audio_saadc_config.resolution = NRF_SAADC_RESOLUTION_14BIT;       //Set SAADC resolution to 12-bit. This will make the SAADC output values from 0 (when input voltage is 0V) to 2^12=2048 (when input voltage is 3.6V for channel gain setting of 1/6).
        audio_saadc_config.oversample = NRF_SAADC_OVERSAMPLE_DISABLED;    //DIABLED - //Set oversample to 4x. This will make the SAADC output a single averaged value when the SAMPLE task is triggered 4 times.
        audio_saadc_config.interrupt_priority = APP_IRQ_PRIORITY_LOW;     //Set SAADC interrupt to low priority.
        audio_saadc_config.low_power_mode = NRFX_SAADC_CONFIG_LP_MODE;
    	

    the oversampling is disabled 

    still i get this assertion.. does it has anything to to with the previous configuration  ?

    if not then any idea for solving the problem ?

    i will also add, maybe it matters, this 2 variables that one of them goes in the saadc init are global variables in each of the modules using the saadc

    static nrf_drv_saadc_config_t audio_saadc_config;
    static nrf_saadc_channel_config_t audio_channel_config;

    static nrf_drv_saadc_config_t hydr_saadc_config;
    static nrf_saadc_channel_config_t hydr_channel_config;

    best regards

    Ziv

  • Hi,

    Are you able to find which of the two are causing the assert in the first place?

    NRFX_ASSERT(nrf_saadc_oversample_get() != NRF_SAADC_OVERSAMPLE_DISABLED);

    NRFX_ASSERT(m_cb.active_channels == 0);

    Are you able to make a simple example where you switch between the two that I can run on an nRF52840-DK?

    Kenneth

Related