I'm in the early stages of design a project I'm working on for fun - a radar speed detector using a simple Doppler radar module and an Arduino (or possibly another similar microcontroller).

I've gotten the analog side working - displaying a good signal when connected to an oscilloscope and audible when attached to an audio amplifier + speaker (and I've found a plethora of resources on where to improve if my current design on the radar/amplifier side doesn't work well enough). However, I've found much less information on how best to sample this sort of signal with a microcontroller.

I'm looking for a sampling frequency of at least 40 kHz, so I figured looking into audio sampling using microcontrollers would give me a good baseline, and have much more resources available. Most of what I've found has been focused on taking qualitative measurements (measuring an audio spectrum for a spectrum visualizer, for example, where you don't care about the actual frequencies, just the frequency bins, so the sampling frequency doesn't have to be well-defined). I don't need this data to be real-time, and I don't think # of samples/memory available will be an issue.

So far, these two methods from the audio-processing world look promising:

Interrupt-based timing

I'd set up a timer to produce an interrupt on a certain interval, and fill up a buffer with each new ADC sampled value at each interrupt. Once the buffer was full, I'd process the data.

I2S communication

I'd need to get either a microcontroller with a built in I2S ADC (Apparently the ESP32 is able to use it's I2S interface with it's own ADC like this? I'm not finding much documentation for this from Espressif themselves) or an external ADC that can talk to the microcontroller over I2S. This would removing the burden of timing the ADC sampling from the microcontroller.

Let me know if there's anything simpler or more effective I can do with regard to ADC sampling at a constant rate, and if the options I've detailed might work.

  • \$\begingroup\$ I2S is an interface (one of many options) used between an external ADC and an MCU. If you're using an MCU's internal ADC, then the interface is not a relevant spec. \$\endgroup\$
    – brhans
    Commented Aug 2, 2022 at 17:25

3 Answers 3


You need to use an ADC that either times its own conversions (like your I2S one -- but those aren't the only ones), or you need to use an ADC that accepts an external start of conversion pulse, and drive it from a hardware timer.

There are bazzilions of choices out there -- while there are a few ADCs where you can only start a conversion by a command on its communications interface, those are rare.

Basically -- you need to go shopping. Decide what interfaces you can use, decide whether you can get a hardware start-of-conversion pulse out of your microcontroller, decide whether you can process data fast enough with your microcontroller (i.e. -- your Arduino may be too slow), then put all the pieces together.


Let me know if there's anything simpler or more effective I can do with regard to ADC sampling at a constant rate

You don't need to restrict your choice of ADC to ones with an I2S interface. Most serial ADCs use SPI or I2C and a lot of MCUs will be able to interface using this serial method. So, for a pretty-good 16 bit ADC that can sample significantly higher than 40 kHz (or at 40 kHz if you wish) you might look at this one, the AD7985: -

enter image description here

I've used this device more times than I can remember and I could not pick fault with it but, TI have a pin-for-pin equivalent and, there are many others to choose from. Maybe try ADI's select tool.


Assuming the micro's internal ADC will have enough performance to do th job...

What you'd usually do is setup one of the micro's timers to trigger the micro's ADC at the desired sample rate. Most micros that have an ADC offer a way to do this.

Since the start of conversion signal comes from a timer that counts the micro's clock, the accuracy of your sample frequency depends on the accuracy of the micro's clock. So if this is important, use a quartz oscillator, not the internal RC oscillator.

Then, if the micro has a DMA core, you'd set that up to grab ADC samples and write them to a buffer, then trigger an interrupt once enough samples have been acquired. This is the highest performance solution because the CPU doesn't have to do anything, it's all DMA.

If the micro doesn't have DMA, then you'll have to use the ADC end of conversion interrupt to "manually" grab the conversion result and store it.

Note that if you only want to measure the frequency of a signal, it is simpler to convert it to a square wave (for example using a schmitt trigger, comparator, etc) and then use one of the timers to measure the frequency or the period.

  • \$\begingroup\$ I've done the same configuration for the Arduino MKR ZERO as described by @bobflux. Here is the link if it helps github.com/cruelkiddy/MKRZERO-Peripherals-Config/tree/main/… And I have a question myself that why it is better to use DMA for data transfer. Is it because the CPU can do other tasks when the signal is being sampled? (because in my case, the CPU has nothing else to do but process the data when the data buffer is full \$\endgroup\$
    – Jack Black
    Commented Aug 2, 2022 at 22:18
  • \$\begingroup\$ Yes DMA means the CPU is free to do other things like process the data or just sleep to save power. But if the ADC runs at a high sampling rate then you simply can't run it full throttle with interrupts, the cpu is not fast enough to process that many interrupts per second. \$\endgroup\$
    – bobflux
    Commented Aug 2, 2022 at 22:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.