Need help with ESP32 ADC DMA continuous read configuration
Posted: Mon May 02, 2022 11:08 am
Hello,
I am trying to read an analog signal through two ADC1 channels. The signal comes from a frequency generator and the idea is to run an FFT with the data acquired. I am using ESP32 with SDK v4.4.1.
When using continuous ADC, I am able to get a buffer containing the data from both channels (channels 6 and 7). However, the total number of outputs from these channels seems to be stuck to 256. The rest of the buffer is filled with data from Channel 0 with value 0. This is the case no matter how I configure the continuous ADC.
I did my project following adc_dma_exemple, but I can't find an answer in there or in the documentation.
Here is my code to setup everything :
The configuration :
This function is called every 10ms to get the buffer
I then sort the received buffer into two buffers to run through the FFT and obtain the signal characteristics of both channels
I would like to increase the size of the buffer to run more data through the FFT.
I hope any of you have a solution.
Thanks !
I am trying to read an analog signal through two ADC1 channels. The signal comes from a frequency generator and the idea is to run an FFT with the data acquired. I am using ESP32 with SDK v4.4.1.
When using continuous ADC, I am able to get a buffer containing the data from both channels (channels 6 and 7). However, the total number of outputs from these channels seems to be stuck to 256. The rest of the buffer is filled with data from Channel 0 with value 0. This is the case no matter how I configure the continuous ADC.
I did my project following adc_dma_exemple, but I can't find an answer in there or in the documentation.
Here is my code to setup everything :
The configuration :
Code: Select all
#define TIMES 1024
#define SAMPLE_FREQUENCY 80000
#define GET_UNIT(x) ((x>>3) & 0x1)
#if CONFIG_IDF_TARGET_ESP32
#define ADC_RESULT_BYTE 2
#define ADC_CONV_LIMIT_EN 1 //For ESP32, this should always be set to 1
#define ADC_CONV_MODE ADC_CONV_SINGLE_UNIT_1 //ESP32 only supports ADC1 DMA mode
#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE1
#endif
#if CONFIG_IDF_TARGET_ESP32
static uint16_t adc1_chan_mask = BIT(6) | BIT(7);
static uint16_t adc2_chan_mask = 0;
static adc_channel_t channel[2] = {ADC1_CHANNEL_6, ADC1_CHANNEL_7};
#endif
static const char *TAG = "ADC DMA";
static void continuous_adc_init(uint16_t adc1_chan_mask, uint16_t adc2_chan_mask, adc_channel_t *channel, uint8_t channel_num)
{
adc_digi_init_config_t adc_dma_config = {
.max_store_buf_size = 1024,
.conv_num_each_intr = TIMES,
.adc1_chan_mask = adc1_chan_mask,
.adc2_chan_mask = adc2_chan_mask,
};
ESP_ERROR_CHECK(adc_digi_initialize(&adc_dma_config));
adc_digi_configuration_t dig_cfg = {
.conv_limit_en = ADC_CONV_LIMIT_EN,
.conv_limit_num = 250,
.sample_freq_hz = SAMPLE_FREQUENCY,
.conv_mode = ADC_CONV_MODE,
.format = ADC_OUTPUT_TYPE,
};
adc_digi_pattern_config_t adc_pattern[SOC_ADC_PATT_LEN_MAX] = {0};
dig_cfg.pattern_num = channel_num;
for (int i = 0; i < channel_num; i++) {
uint8_t unit = GET_UNIT(channel[i]);
uint8_t ch = channel[i] & 0x7;
adc_pattern[i].atten = ADC_ATTEN_DB_11;
adc_pattern[i].channel = ch;
adc_pattern[i].unit = unit;
adc_pattern[i].bit_width = 12;
ESP_LOGI(TAG, "adc_pattern[%d].atten is :%d", i, adc_pattern[i].atten);
ESP_LOGI(TAG, "adc_pattern[%d].channel is :%d", i, adc_pattern[i].channel);
ESP_LOGI(TAG, "adc_pattern[%d].unit is :%d", i, adc_pattern[i].unit);
}
dig_cfg.adc_pattern = adc_pattern;
ESP_ERROR_CHECK(adc_digi_controller_configure(&dig_cfg));
}
esp_err_t adc_init()
{
esp_err_t error_code;
continuous_adc_init(adc1_chan_mask, adc2_chan_mask, channel, sizeof(channel) / sizeof(adc_channel_t));
error_code = adc1_config_width(ADC_WIDTH_BIT_12);
if(error_code != ESP_OK)
{
return error_code;
}
adc_digi_start();
return ESP_OK;
}
Code: Select all
int IRAM_ATTR read_adc_dma(uint32_t *ret_num, uint16_t *result)
{
esp_err_t ret;
ret = adc_digi_read_bytes(result, TIMES, ret_num, ADC_MAX_DELAY);
return ret;
}
Code: Select all
void sort_dma_data_into_buffers(uint16_t *buff_ch0, uint16_t *buff_ch1, uint32_t ret_num, uint32_t *i0, uint32_t *i1, uint16_t *result)
{
uint32_t n0 = 0;
uint32_t n1 = 0;
for (int i = 0; i < ret_num; i += ADC_RESULT_BYTE) {
adc_digi_output_data_t *p = (void*)&result[i];
// printf("3.1\n");
if(p->type1.channel == ADC1_CHANNEL_6)
{
buff_ch0[n0] = p->type1.data;
n0++;
}
else if(p->type1.channel == ADC1_CHANNEL_7)
{
buff_ch1[n1] = p->type1.data;
n1++;
}
}
*i0 = n0;
*i1 = n1;
}
I hope any of you have a solution.
Thanks !