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

Calibrating SAADC on nrf52832

Hi,

I am using an nRF52832 with S132 and SDK v15.0.0 and already read in the forum about issues related to the SAADC calibration (inlcuing the erratum  [86]). The problem I have is that the ADC constantly (not only once!) delivers wrong data after I call the calibrate_offset function.

The stuff that happens over time is basically:

-> The SAADC is initialised

-> the channels (2) are initialised

-> the buffer_convert function is called

-> (because the buffer-convert funtion was already called and the SAADC is in IDLE although no START or SAMPLE task was triggered yet) -> the nrfx_saadc_abort() function is called

This is the first point, where somthing goes wrong since sometimes the nrfx_saadc_abort() itself hangs when waiting for the SAADC to become IDLE again. Do I have to do a dummy TASK_SAMPLE before calling the abort function so that a conversion is in progress? it seems that simply aborting without issuing a SAMPLE before fails in waiting for "NRFX_WAIT_FOR((m_cb.adc_state != NRF_SAADC_STATE_IDLE), HW_TIMEOUT, 0, result);". (But I have to call the abort function to get into IDLE after calling buffer_convert?)

->  nrfx_saadc_calibrate_offset() is called

-> The values i get from this time by calling TASK_SAMPLE  are wrong

Besides of the concrete problem, I have the following questions, wo which I did not yet find an answer to.

1.) I am NOT using SAADC in LP Mode. Is the workaround for the erratum [86] still necessary for SDK V15.0.0 or is ia patch alredy somehow included in v15?

2.) I am unsure about how to implement the workaround. It is described as Stopping the SAADC after calibration, but stopping seems to invole waiting for an STOPPED EVENT. Do i have to wait and therefore somehow poll for that event? What is an easy way to do that?

3.) In all the SAADC examples, I see that the event handler checks for the NRFX_SAADC_EVT_DONE event and gets the data from the buffer. Why is that done, when there is explicitly stated that this event does not guaratee that the samples are already in RAM? Why not waiting for the END event? The p_buffer->type does not even seem to expose the END event? Why is that?

4.) I see that in examples, in the Event handler the occurence of the event CALIBRATEDONE is used to again call buffer_convert to set up the buffer again. If i call the calibrate_offset function before a call to buffer_convert, i guess thats a problem because in the event handler the buffer is set to the last one used, but there is no (useful) "last" buffer in this case?)

5.) Could someone provide a minimal working example (minimal main program plus callback) for just initialising the ADC / the ADC channels, perform calibration and set up the buffer for a "real" conversion directly after a startup? All the examples I found use cyclic turning on/off or inti / uninits that make things a bit unclear for a basic understanding.

Thanks a lot!

Parents
  • Hi Kenneth,

    Thanks for the reply.

    According to the numbering of my initial questions:

    3.) Good to know, so it is no problem with IR processing because the delay until the IR is handled, is big enough in any case?

    4.) Will have to check where in the forum I saw it, I will come back to that.

    5.) Well there is one thing I want to ask about this example which is also somthing I did not understand in another example: How is the call to err_code = nrf_drv_saadc_init(NULL, saadc_callback); supposed to work?

    I use nrfx_saadc_init(NULL,saadc_callback); according to the new API in SDK V15, but there is a line in the function "nrfx_saadc_init(NULL,saadc_callback);" that obviously returns immediately if the function is called with a NULL pointer. What is the reason for nto initialising with a proper "ADC config structure" ?

    Thanks

  • About 5) What file and line number are you referring to?

    Kenneth

  • It is example code so please change this as you see fit, but basically using NULL will set default settings from sdk_config.h

    __STATIC_INLINE ret_code_t nrf_drv_saadc_init(nrf_drv_saadc_config_t const * p_config,
                                                  nrf_drv_saadc_event_handler_t  event_handler)
    {
        if (p_config == NULL)
        {
            static const nrfx_saadc_config_t default_config = NRFX_SAADC_DEFAULT_CONFIG;
            p_config = &default_config;
        }
        return nrfx_saadc_init(p_config, event_handler);
    }

  • Hi Kenneth,

    Well sorry, I could have found out that for myself. My program crashed around the line, where the ADC is initilaised with "NULL", so I was a bit blinded but actually, the crash happened somwhere else.

    However, back to the main topic of my question: I still have troubles using the offset calibration. My program does essentially the same as your provided example code and more specifically, it uses the exact code of the "calibrate_saadc" function.

    Unfortunately, when i have the call to the calibrate function in my code (right after nrfx_saadc_init), the program hangs in "nrfx_saadc_sample()" with "NRFX_ERROR_INVALID_STATE" after the first adc conversion (1 sample per CH) is complete.

    This does not happen when I comment the line with the call to the calibrate function during adc initialisation.

    Any hints?

  • Hi Kenneth,

    It´s been some time. any update to this?

  • I am not sure what more debugging that can be done from here, but looking at the code it seems that nrfx_saadc_sample() will report NRFX_ERROR_INVALID_STATE if m_cb.adc_state != NRF_SAADC_STATE_BUSY.

    So maybe your first task is to set a breakpoint when err_code = NRFX_ERROR_INVALID_STATE; in nrfx_saadc_sample() to find the actual value of m_cb.adc_state. And then you can add a log output every time m_cb.adc_state is set to the specific value to find which function is called that set it to !NRF_SAADC_STATE_BUSY in this case.

    Best regards,
    Kenneth

  • Problem was the missing workaround of PAN86, among one additional code bug.. closed

Reply Children
  • Hi Franz:
    I have used the example code for calibrate_saadc() and having the same NRFX_ERROR_INVALID_STATE problem you reported earlier. Could you give some more details about how you solved this?
    How can calibration be so hard? Looks like it's time for Nordic to add a library on top of the driver to support this kind of stuff...

  • Hi!

    I would have to check next week since I do not remember the exact code that I used to get rid of the described error. I only remeber that I changes my ADC code to only have one channel enabled at a time. I can send you the piece in a few days if you whish. One BIG word of caution, though.

    Although I managed to get rid of the error and calibration in regular interval does not throw errors, I have the feeling that calibration does not work at all on the 52832. Of course I cannot prove that or be sure, but  we invested a lot of time to measure the code the adc delivers on a number of boards under controlled thermal conditions and we had one devkit with nrf52832 where the calibration even made things worse than without any calibration.

    I had another private ticket open on a similar topic because of confidential code, but we never managed to get rid of problems with bad performance of calibration (we have "jumps" in the signal of about 6 LSB12b, which might be ok from a datasheet perspective, but does defeat the purpose of the calibration unless you use a very wide temperature range).

    BR

  • Thanks for sharing your experiences. Indeed, as you found, I can get calibration to run successfully once at startup (but not again), but I too am not observing much improvement. Without calibration, I am measuring GROUND at -1 to -2 raw value (10-bit). Calibration will sometimes bring this to zero, but sometimes not. Have not tried yet under temperature variations.

    If you are able to dig up the old code, it might be of use to me & others using this ticket in the future. It seems to come up pretty high in search results :-)

Related