Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async (non-blocking) ADC API (IDFGH-64) #792

Open
HubbyGitter opened this issue Jul 10, 2017 · 4 comments
Open

Async (non-blocking) ADC API (IDFGH-64) #792

HubbyGitter opened this issue Jul 10, 2017 · 4 comments
Labels
Type: Feature Request Feature request for IDF

Comments

@HubbyGitter
Copy link

My wish, if I may say that, would be that a few essential ADC properties be specified / documented and that either the register usage is clarified officially or the ADC API is extended for additional flexibility, namely such that busy waiting for the ADC result can be avoided.

And here now comes the motivation.

Elsewhere, well-known @nkolban described that wantig fast ADC was a symptom of underlying masochism ESP_puff wrote:

The sample frequency is 6KHZ. We have 12-bit SAR ADC up to 18 channels.

Being utterly masochistic, Although I now believe that sampling every 100 µs may be sufficient in my case (still well above 6 kHz), I had read in the Tech Spec that two of the SAR ADC controllers "support high-performance multiple-channel scanning" (emphasis mine) and was really expecting that the ADCs would need around 8 µs and that I should aim at having one sample per 50 µs at least, maybe even 33 µs.

(Suboptimal, but feasible) test recipe:

  • ISR calls vTaskNotifyGiveFromISR()
  • Core-pinned task 1 calls adc1_get_voltage(), calculates moving average, filters and takes sample sequences and calls xQueueSend() (if it fails, it fails)
  • Core-pinned task 2 post processes sampled data
  • @ 240 MHz / "debug" optimisation
  • 12 bit conversion
  • Other tasks are pinned to other core, or else FreeRTOS will try to use the tiny bit of execution time left which will lead to a starving IDLE task.

Turns out that this works down to ~ 50 µs so that made me curious. It looks like:

  • adc1_get_voltage() runs in a little less than 25 µs,
  • deleting the code which claims the ADC back from the RTC domain, leaving the channel selection and conversion, runs in 16 µs,
  • and just starting the conversion and busy waiting for the result (at least I think that's what the last part of the adc1_get_voltage() code does) is finished within 10 µs (mostly busy waiting)..

I would like to reclaim most of the 25 µs,

  • either with just one channel being available for the ADC plus an ISR triggering the conversion now and collecting the result next time,
  • or with an ISR setting the channel now, triggering the conversion next time, and collecting the result (and choosing the next channel) after that.

(Yes the sampled values will be outdated by a few microseconds.)

Because even at one sample per 100 µs, the not strictly necessary 25 µs of adc1_get_voltage() have a pretty big share, and that's not going to get better should this function be changed to correct for the slightly non-linear results as announced by @Spritetm (which I don't want and don't need to deal with at the time of the measurement).

Specific questions are,

  • can one rely on the abovementioned measured conversion times / will they be specified, and
  • will the register usage be officially documented to make this an official approach, and
  • is access to the non-ULP registers acceptable in the ISR.

Thank you!

P.S. @nkolban ...sorry, couldn't resist...

@negativekelvin
Copy link
Contributor

negativekelvin commented Jul 10, 2017

Isn't adc1_get_voltage still using RTC SAR ADC controllers? DIG SAR ADC controllers with DMA are the performance ones but I don't know if there is sufficient documentation to use them. It seem like you have to use together with i2s.

@HubbyGitter
Copy link
Author

HubbyGitter commented Jul 11, 2017

@negativekelvin Interesting point. I didn't think so. adc1_get_voltage() is located in rtc_module.c but uses e.g. SENS_SAR_MEAS_START1_REG. Om the other hand, fast ADC could be much faster than 8 µs. But the CPU's access to the registers could be slow.

Also, according to Tech Spec, section 21.3.2 "Features" says DMA is available only on one controller, while Figure 73 "SAR ADC Depiction" shows DMA for both SAR ADCs.

@negativekelvin
Copy link
Contributor

negativekelvin commented Jul 11, 2017

I think that is because the one controller can scan both ADCs. Even though in other places they are referred to as separate controllers.

@FayeY FayeY changed the title Not waiting for ADC [TW#13911] Not waiting for ADC Jul 12, 2017
@projectgus projectgus changed the title [TW#13911] Not waiting for ADC Not waiting for ADC (IDFGH-64) Mar 12, 2019
@projectgus projectgus changed the title Not waiting for ADC (IDFGH-64) Async (non-blocking) ADC API (IDFGH-64) Apr 30, 2020
@projectgus projectgus added the Type: Feature Request Feature request for IDF label Apr 30, 2020
@projectgus
Copy link
Contributor

This ticket has been opened for a long time, but for the benefit of anyone still wondering about this: The I2S driver now supports a way to read one or two ADC channels directly via DMA at a fixed sample rate, with no CPU overhead at all. This is supported via driver/i2s.h.

This is the way to read ADC channel(s) quickly at a fixed frequency.

There is still probably a good use case for an asynchronous ADC API though, so it's possible to make one function call to start a conversion, and then another function call later to read the result. Keeping this feature request open for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Feature Request Feature request for IDF
Projects
None yet
Development

No branches or pull requests

3 participants