I'm new in this forum so please forgive me if I'm making any mistake creating this post.
I'm developing a system on ESP32 in order to sample a signal and I need an high sample rate (around 51200Hz). Fort this reason I'm using the I2S-ADC mode.
The input signal is composed by a dc value that is generated by an ESP's dac pin and an ac signal from outside.
So, at the adc pin, at least is possible to measure the dc value due to the dac pin.
Sometimes, when the board start for the first time and I initialize the I2S - ADC section, I'm not able to read the data from the dma. To be more specific, I read a zero value buffer.
When I have this problem, I try a re-init of I2S-ADC section but I continue to see this problem. The only solution is to turn off the board, wait some seconds and the turn on. This solution, clearly, is not acceptable.
Somebody know where is the problem and how to solve it?
Some code:
Code: Select all
static void adc_i2s_init(void)
{
esp_err_t ret = ESP_OK;
i2s_config_t adc_i2s_config =
{
.mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN,
.sample_rate = SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.communication_format = I2S_COMM_FORMAT_I2S_MSB,
.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT, // one channel
.intr_alloc_flags = 0,//ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = DMA_BUF_COUNT,
.dma_buf_len = DMA_BUF_LEN,
.use_apll = false,
.tx_desc_auto_clear = true
};
//install and start i2s driver
ret = i2s_driver_install(I2S_UNIT, &adc_i2s_config, 1, &adc_i2s_event_queue);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "i2s_driver_install operation error = %i", ret);
}
//init ADC pad
#if ADC_DUAL_CHANNEL
adc_gpio_init(ADC_UNIT, ADC_VOLTAGE_CHANNEL);
adc_gpio_init(ADC_UNIT, ADC_CURRENT_CHANNEL);
ret = i2s_set_adc_mode_custom(ADC_UNIT, ADC_VOLTAGE_CHANNEL, ADC_VOLTAGE_WIDTH, ADC_VOLTAGE_ATTEN_DB, ADC_DATA_INV);
#elif VOLTAGE_CHANNEL_EN
ret = i2s_set_adc_mode_custom(ADC_UNIT, ADC_VOLTAGE_CHANNEL, ADC_VOLTAGE_WIDTH, ADC_VOLTAGE_ATTEN_DB, ADC_DATA_INV);
#elif CURRENT_CHANNEL_EN
ret = i2s_set_adc_mode_custom(ADC_UNIT, ADC_CURRENT_CHANNEL, ADC_CURRENT_WIDTH, ADC_CURRENT_ATTEN_DB, ADC_DATA_INV);
#else
ESP_LOGE(TAG,"NO CHANNEL SELECTED");
#endif
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "i2s_set_adc_mode_custom operation error = %i", ret);
}
vTaskDelay(2000);
}
static void adc_i2s_enable(void)
{
esp_err_t ret = ESP_OK;
#if ADC_DUAL_CHANNEL
ret = i2s_adc_enable_custom(I2S_UNIT, ADC_VOLTAGE_CHANNEL, ADC_VOLTAGE_WIDTH, ADC_VOLTAGE_ATTEN_DB, ADC_DATA_INV);
//Enable Multipattern scanning
SYSCON.saradc_ctrl.sar1_patt_len = 3;
SYSCON.saradc_sar1_patt_tab[0] = ADC_DUAL_CHANNEL_PATTERN_TABLE;
// SYSCON.saradc_sar1_patt_tab[0] = 0x7F6F7F6F; // Vref 3.6V
#elif VOLTAGE_CHANNEL_EN
ret = i2s_adc_enable_custom(I2S_UNIT, ADC_VOLTAGE_CHANNEL, ADC_VOLTAGE_WIDTH, ADC_VOLTAGE_ATTEN_DB, ADC_DATA_INV);
#elif CURRENT_CHANNEL_EN
ret = i2s_adc_enable_custom(I2S_UNIT, ADC_CURRENT_CHANNEL, ADC_CURRENT_WIDTH, ADC_CURRENT_ATTEN_DB, ADC_DATA_INV);
#else
ESP_LOGE(TAG,"NO CHANNEL SELECTED");
#endif
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "i2s_adc_enable_custom operation error = %i", ret);
}
}
static void adc_i2s_disable(void)
{
i2s_adc_disable(I2S_UNIT);
}
static void adc_i2s_restore_sampling(void)
{
adc_i2s_disable();
adc_disable_function();
vTaskDelay(100);
adc_power_on();
adc_i2s_init();
adc_i2s_enable();
}
static void adc_task(void *pvParameter)
{
esp_err_t ret = ESP_OK;
i2s_event_t adc_i2s_evt;
size_t bytes_read;
/* Reset ADC */
adc_disable_function();
/*********************/
adc_i2s_init();
adc_i2s_enable();
while ( 1 )
{
if(xQueueReceive(adc_i2s_event_queue, (void * )&adc_i2s_evt, (portTickType)portMAX_DELAY))
{
if(adc_i2s_evt.type == I2S_EVENT_RX_DONE)
{
/*
* Read data from I2S bus, in this case, from ADC.
* With DMA_BUF_LEN = 1024, DMA_BUF_COUNT = 2 and NUM_SAMPLES = 1024 it takes 2887 cycles to complete the operation.
*/
ret = i2s_read_custom(I2S_UNIT, (char*)adc_data_buf, NUM_SAMPLES*2, &bytes_read, portMAX_DELAY);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "i2s_read operation error = %i", ret);
}
if(((adc_data_buf[0]) == 0) && ((adc_data_buf[1]) == 0) && ((adc_data_buf[2]) == 0))
{
// If the adc reads zero values, it means it hasn't been started correctly. Restart it again to fix this problem.
adc_i2s_restore_sampling();
}
else
{
// Do Something
}
}
}
}
adc_i2s_disable(); // Unreachable
}