Skip to content

Latest commit

 

History

History
258 lines (150 loc) · 13.7 KB

adc_continuous.rst

File metadata and controls

258 lines (150 loc) · 13.7 KB

Analog to Digital Converter (ADC) Continuous Mode Driver

Introduction

The Analog to Digital Converter is an on-chip sensor which is able to measure analog signals from specific analog IO pads.

The ADC on {IDF_TARGET_NAME} can be used in scenario(s) like:

  • Generate one-shot ADC conversion result
  • Generate continuous ADC conversion results

This guide will introduce ADC continuous mode conversion.

Driver Concepts

ADC continuous mode conversion is made up with multiple Conversion Frames.

  • Conversion Frame: One Conversion Frame contains multiple Conversion Results. Conversion Frame size is configured in :cppadc_continuous_new_handle, in bytes.
  • Conversion Result: One Conversion Result contains multiple bytes (see :cSOC_ADC_DIGI_RESULT_BYTES). Its structure is :cppadc_digi_output_data_t, including ADC unit, ADC channel and raw data.

image

Functional Overview

The following sections of this document cover the typical steps to install the ADC continuous mode driver, and read ADC conversion results from group of ADC channels continuously:

Resource Allocation

The ADC continuous mode driver is implemented based on {IDF_TARGET_NAME} SAR ADC module. Different ESP targets might have different number of independent ADCs.

To create an ADC continuous mode driver handle, set up the required configuration structure :cppadc_continuous_handle_cfg_t:

  • :cppadc_continuous_handle_cfg_t::max_store_buf_size set the maximum size (in bytes) of the pool that the driver saves ADC conversion result into. If this pool is full, new conversion results will be lost.
  • :cppadc_continuous_handle_cfg_t::conv_frame_size set the size of the ADC conversion frame, in bytes.

After setting up above configurations for the ADC, call :cppadc_continuous_new_handle with the prepared :cppadc_continuous_handle_cfg_t. This function may fail due to various errors such as invalid argumemts, insufficient memory, etc.

esp32

Especially, when this function returns :cESP_ERR_NOT_FOUND, this means the I2S0 peripheral is in use. See Hardware Limitations for more information.

esp32s2

Especially, when this function returns :cESP_ERR_NOT_FOUND, this means the SPI3 peripheral is in use. See Hardware Limitations for more information.

SOC_GDMA_SUPPORTED

Especially, when this function returns :cESP_ERR_NOT_FOUND, this means there is no free GDMA channel.

If the ADC continuous mode driver is no longer used, you should deinitialize the driver by calling :cppadc_continuous_deinit.

Initialize the ADC Continuous Mode Driver

adc_continuous_handle_cfg_t adc_config = {
    .max_store_buf_size = 1024,
    .conv_frame_size = 100,
};
ESP_ERROR_CHECK(adc_continuous_new_handle(&adc_config));

Recycle the ADC Unit

ESP_ERROR_CHECK(adc_continuous_deinit());

ADC Configurations

After the ADC continuous mode driver is initialized, set up the :cppadc_continuous_config_t to configure ADC IOs to measure analog signal:

  • :cppadc_continuous_config_t::pattern_num, number of ADC channels that will be used.
  • :cppadc_continuous_config_t::adc_pattern, list of configs for each ADC channel that will be used, see below description.
  • :cppadc_continuous_config_t::sample_freq_hz, expected ADC sampling frequency in Hz.
  • :cppadc_continuous_config_t::conv_mode, continuous conversion mode.
  • :cppadc_continuous_config_t::format, conversion output format.

For :cppadc_digi_pattern_config_t:

  • :cppadc_digi_pattern_config_t::atten, ADC attenuation. Refer to the On-Chip Sensor chapter in TRM.
  • :cppadc_digi_pattern_config_t::channel, the IO corresponding ADC channel number. See below note.
  • :cppadc_digi_pattern_config_t::unit, the ADC that the IO is subordinate to.
  • :cppadc_digi_pattern_config_t::bit_width, the bitwidth of the raw conversion result.

Note

For the IO corresponding ADC channel number. Check datasheet to acquire the ADC IOs. On the other hand, :cppadc_continuous_io_to_channel and :cppadc_continuous_channel_to_io can be used to acquire the ADC channels and ADC IOs.

To make these settings take effect, call :cppadc_continuous_config with the configuration structure above. This API may fail due to reasons like :cESP_ERR_INVALID_ARG. When it returns :cESP_ERR_INVALID_STATE, this means the ADC continuous mode driver is started, you shouldn't call this API at this moment.

See ADC continuous mode example peripherals/adc/continuous_read to see configuration codes.

ADC Control

Start and Stop

Calling :cppadc_continuous_start will make the ADC start to measure analog signals from the configured ADC channels, and generate the conversion results. On the contrary, calling :cppadc_continuous_stop will stop the ADC conversion.

ESP_ERROR_CHECK(adc_continuous_start());
ESP_ERROR_CHECK(adc_continuous_stop());

Register Event Callbacks

By calling :cppadc_continuous_register_event_callbacks, you can hook your own function to the driver ISR. Supported event callbacks are listed in :cppadc_continuous_evt_cbs_t - :cppadc_continuous_evt_cbs_t::on_conv_done, this is invoked when one conversion frame finishes. - :cppadc_continuous_evt_cbs_t::on_pool_ovf, this is invoked when internal pool is full. Newer conversion results will be discarded.

As above callbacks are called in an ISR context, you should always ensure the callback function is suitable for an ISR context. Blocking logics should not appear in these callbacks. Callback function prototype is declared in :cppadc_continuous_callback_t.

You can also register your own context when calling :cppadc_continuous_register_event_callbacks, by the parameter user_data. This user data will be passed to the callback functions directly.

This function may fail due to reasons like :cESP_ERR_INVALID_ARG. Specially, when CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is enabled, this error may indicate that the callback functions aren't in internal RAM. Check error log to know this. Besides, when it fails due to :cESP_ERR_INVALID_STATE, this means the ADC continuous mode driver is started, you shouldn't add callback at this moment.

Conversion Done Event

The driver will fill in the event data of a :cppadc_continuous_evt_cbs_t::on_conv_done event. Event data contains a buffer pointer to a conversion frame buffer, together with the size. Refer to :cppadc_continuous_evt_data_t to know the event data structure.

Note

It is worth noting that, the data buffer :cppadc_continuous_evt_data_t::conv_frame_buffer is maintained by the driver itself. Therefore, never free this piece of memory.

Note

When the Kconfig option CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is enabled, the registered callbacks and the functions called by the callbacks should be placed in IRAM. The involved variables should be placed in internal RAM as well.

Pool Overflow Event

The ADC continuous mode driver has an internal pool to save the conversion results. When the pool is full, a pool overflow event will emerge. Under this condition, the driver won't fill in the event data. This usually happens the speed to read data from the pool (by calling :cppadc_continuous_read) is much slower than the ADC conversion speed.

Read Conversion Result

After calling :cppadc_continuous_start, the ADC continuous conversion starts. Call :cppadc_continuous_read to get the conversion results of the ADC channels. You need to provide a buffer to get the raw results.

This function will try to read the expected length of conversion results each time.

  • If the requested length isn't reached, the function will still move the data from the internal pool to the buffer you prepared. Therefore, check the out_length to know the actual size of conversion results.
  • If there is no conversion result generated in the internal pool, the function will block for timeout_ms until the conversion results are generated. If there is still no generated results, the function will return :cESP_ERR_TIMEOUT.
  • If the generated results fill up the internal pool, new generated results will be lost. Next time when the :cppadc_continuous_read is called, this function will return :cESP_ERR_INVALID_STATE indicating this situation.

This API aims to give you a chance to read all the ADC continuous conversion results.

The ADC conversion results read from above function are raw data. To calculate the voltage based on the ADC raw results, this formula can be used:

Vout = Dout * Vmax / Dmax (1)

where:

Vout Digital output result, standing for the voltage.
Dout ADC raw digital reading result.
Vmax Maximum measurable input analog voltage, this is related to the ADC attenuation, please refer to the On-Chip Sensor chapter in TRM.
Dmax Maximum of the output ADC raw digital reading result, which is 2^bitwidth, where bitwidth is the :cpp:member::adc_digi_pattern_config_t:bit_width configured before.

To do further calbration to convert the ADC raw result to voltage in mV, please refer to calibration doc adc_calibration.

Hardware Limitations

  • A specific ADC unit can only work under one operating mode at any one time, either Continuous Mode or Oneshot Mode. :cppadc_continuous_start has provided the protection.
  • Random Number Generator uses ADC as an input source. When ADC continuous mode driver works, the random number generated from RNG will be less random.

esp32s2 or esp32c3 or esp32s3

  • ADC2 is also used by the Wi-Fi. :cppadc_continuous_start has provided the protection between Wi-Fi driver and ADC continuous mode driver.

esp32

  • ADC continuous mode driver uses I2S0 peripheral as hardware DMA fifo. Therefore, if I2S0 is in use already, the :cppadc_continuous_new_handle will return :cESP_ERR_NOT_FOUND.
  • ESP32 DevKitC: GPIO 0 cannot be used due to external auto program circuits.
  • ESP-WROVER-KIT: GPIO 0, 2, 4 and 15 cannot be used due to external connections for different purposes.

esp32s2

  • ADC continuous mode driver uses SPI3 peripheral as hardware DMA fifo. Therefore, if SPI3 is in use already, the :cppadc_continuous_new_handle will return :cESP_ERR_NOT_FOUND.

Power Management

When power management is enabled (i.e. CONFIG_PM_ENABLE is on), the APB clock frequency may be adjusted when the system is in an idle state, thus potentially changing the behavior of ADC continuous conversion.

However, the continuous mode driver can prevent this change by acquiring a power management lock of type :cppESP_PM_APB_FREQ_MAX. The lock is acquired after the continuous conversion is started by :cppadc_continuous_start. Similarly, the lock will be released after :cppadc_continuous_stop. Therefore, :cppadc_continuous_start and :cppadc_continuous_stop should appear in pairs, otherwise the power management will be out of action.

IRAM Safe

All the ADC continuous mode driver APIs are not IRAM-safe. They are not supposed to be run when the Cache is disabled. By enabling the Kconfig option CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE, driver internal ISR handler is IRAM-safe, which means even when the Cache is disabled, the driver will still save the conversion results into its internal pool.

Thread Safety

ADC continuous mode driver APIs are not guaranteed to be thread safe. However, the share hardware mutual exclusion is provided by the driver. See Hardware Limitations for more details.

Application Examples

  • ADC continuous mode example: peripherals/adc/continuous_read.

API Reference

inc/adc_continuous.inc