ESP32 ADC DMA continuous read configuration
Posted: Mon May 02, 2022 1:44 pm
Hello,
I am trying to use DMA with two ADC channels in order to have two readings of a same signal. It means that the ADC writes the data of both channels into the same buffer in memory. However it seems that this buffer has only 256 slots available for both of these channels and the rest is filled with something from channel 0 (see screenshot). This happens no matter how I set the buffer length in the ADC configuration.
I would like to fill the buffer with only data from the two desired channels but I did not manage to find an answer in the example I base my code on and in the documentation.
Here is my ADC configuration script :
Once I get the buffer, I split it in two according to the corresponding channels to run them through a FFT :
I find that i0+i1 = 256 and I can't get more values for the 2 channels. The idea is to get more periods of a 1.2kHz signal but I can't have more than one.
Thanks for your help !
I am trying to use DMA with two ADC channels in order to have two readings of a same signal. It means that the ADC writes the data of both channels into the same buffer in memory. However it seems that this buffer has only 256 slots available for both of these channels and the rest is filled with something from channel 0 (see screenshot). This happens no matter how I set the buffer length in the ADC configuration.
I would like to fill the buffer with only data from the two desired channels but I did not manage to find an answer in the example I base my code on and in the documentation.
Here is my ADC configuration script :
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 = 4096,
.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
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;
}
Thanks for your help !