Problem with sampling using ADC via DMA

User avatar
Splendiferous
Posts: 2
Joined: Mon Apr 23, 2018 9:03 pm

Problem with sampling using ADC via DMA

Postby Splendiferous » Thu Apr 26, 2018 11:21 am

Hi All.

I'm trying to acquire a single channel analogue input using the I2S DMA. This is somewhat successful in that I can configure the I2S and read data correctly and it gives me sensible values. However. I seem to be getting two channels of the same measurement, separated by 1/f, instead of one. The full test code can be viewed here.

The config being used is shown below:

Code: Select all

i2s_config_t i2s_config ;
    i2s_config.mode =  i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN);
    i2s_config.sample_rate = SAMPLE_RATE;                           // 120 KHz
    i2s_config.dma_buf_len = NUM_SAMPLES;                           // 512
    i2s_config.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT;         // Should be mono but doesn't seem to be
    i2s_config.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT;
    i2s_config.use_apll = false,
    i2s_config.communication_format = I2S_COMM_FORMAT_I2S;
    i2s_config.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1;
    i2s_config.dma_buf_count = 2;
    //install and start i2s driver
    i2s_driver_install(I2S_NUM_0, &i2s_config, 1, &i2s_event_queue);
    // Connect ADC to I2S
    i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_6);
    //i2s_set_clk(I2S_NUM_0,SAMPLE_RATE,I2S_BITS_PER_SAMPLE_16BIT,I2S_CHANNEL_MONO);    // This doesn't work either
The image below shows some waveforms with their resultant FFTs. The top waveform is a plot of the buffer (with adjustment to remove the DC) assuming it is a single channel (f=120KHz sampling rate) with a signal source of about 10KHz being read by the ADC. The FFT yields 2 major peaks at about 10KHz and at about (f/2)-10KHz. These FFT signals converge until they overlap and then proceed to diverge as the test signal is increased, so they are definitely related to the single signal.

Image

The bottom two are the result of the same data but de-interleaved. The raw measurements (buffer dump of the i2s_read_bytes) can be found here. For these two plots, I am assuming that we have two channels, each sampling at f/2 which yield the expected results.

So it seems I have two interleaved channels, of the same signal, at f/2 sample rate. How do I sample a single channel channel @ 120kHZ instead of 2 channels at 60 kHz?
The most amazing achievement of the computer software industry is its continuing cancellation of the steady and staggering gains made by the computer hardware industry.
(Henry Petroski)

User avatar
Splendiferous
Posts: 2
Joined: Mon Apr 23, 2018 9:03 pm

Re: Problem with sampling using ADC via DMA

Postby Splendiferous » Sun Apr 29, 2018 4:13 pm

OK. As I watched the tumble-weed pass by, I found out what the problem is. However. I'm unsure of the driver behind the behaviour.

It seems that there are indeed two channels sampling the data and channel 2 is "out of phase" by 1/fs. These two channels are then interleaved into the read buffer as if it were a single signal.
By de-interleaving the buffer and then shifting the second signal by 1/fs (delete the first sample from the array of channel 2) and then interleave back, I now get the signal I expect.

Image

Can anyone explain this behaviour? Is there a setting I'm missing?
The most amazing achievement of the computer software industry is its continuing cancellation of the steady and staggering gains made by the computer hardware industry.
(Henry Petroski)

mbalci
Posts: 16
Joined: Fri May 13, 2016 11:54 am

Re: Problem with sampling using ADC via DMA

Postby mbalci » Wed Aug 29, 2018 12:45 pm

in i2s.h file there is such code ;

Code: Select all

typedef enum {
    I2S_MODE_MASTER = 1,
    I2S_MODE_SLAVE = 2,
    I2S_MODE_TX = 4,
    I2S_MODE_RX = 8,
    I2S_MODE_DAC_BUILT_IN = 16,       /*!< Output I2S data to built-in DAC, no matter the data format is 16bit or 32 bit, the DAC module will only take the 8bits from MSB*/
   [color=#FF0000] //I2S_MODE_ADC_BUILT_IN = 32,     /*!< Currently not supported yet, will be added for the [/color]next version*/
    I2S_MODE_PDM = 64,
} i2s_mode_t;
So how is your code works at all ?

esp3233
Posts: 1
Joined: Thu Aug 30, 2018 9:39 pm

Re: Problem with sampling using ADC via DMA

Postby esp3233 » Fri Aug 31, 2018 11:31 am

Hello,

i have exactly the same problem. Did you find a solution meanwhile?

zekageri
Posts: 43
Joined: Mon Sep 03, 2018 11:04 am

Re: Problem with sampling using ADC via DMA

Postby zekageri » Wed Sep 18, 2019 8:04 am

I have got the same problem.
No matter what, i measure the same signal on all the channels of the ADC1 just with more "noise" when i config the ADC to just one channel.These signals are coming from a signal generator with 4Khz. I measure it with 8Mhz.

Code: Select all

.sample_rate = 80000

Code: Select all

i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_0);
Attachments
Képernyőfelvétel (16).png
ADC1_Channel_0
Képernyőfelvétel (16).png (202.79 KiB) Viewed 13700 times
Képernyőfelvétel (14).png
ADC1_Channel_3
Képernyőfelvétel (14).png (192.29 KiB) Viewed 13700 times
Képernyőfelvétel (13).png
ADC1_Channel_4
Képernyőfelvétel (13).png (196.34 KiB) Viewed 13700 times

AlexMa89
Posts: 2
Joined: Fri May 08, 2020 3:58 pm

Re: Problem with sampling using ADC via DMA

Postby AlexMa89 » Fri May 08, 2020 4:20 pm

Hi everyone,

I'm trying to use I2S to read tot samples from channel 4 of adc1 but what i get is always zero.
I attached my code.

If i try to read by calling adc_get_raw i get something different from zero (returned values make sense, at least they are different from zero)

Have i to set something in menuconfig to work with I2S and adc?
Is there anything wrong in my code?

Thanks in advance for help

Alessandro
Attachments
adc_dma.c
(1.11 KiB) Downloaded 677 times

maurogramajo
Posts: 1
Joined: Mon Nov 02, 2020 1:43 am

Re: Problem with sampling using ADC via DMA

Postby maurogramajo » Mon Nov 02, 2020 1:56 am

Hi!

I've got exactly the same problem as AlexMa89, would anyone give us some help?

oliverjrose99
Posts: 2
Joined: Sun Nov 15, 2020 1:32 pm

Re: Problem with sampling using ADC via DMA

Postby oliverjrose99 » Sun Nov 15, 2020 2:00 pm

Hi, i'm yet another person having issues with I2S ADC and DMA. Im trying to use the APLL clock as i need a sample rate of about 44100hz. with use_apll = false i get values returned which are correct but not the correct rate and with use_apll = true all i get returned is 0s. If any devs could post WORKING code that would be great. everything ive tried so far including the offical exampels dont work.

oliverjrose99
Posts: 2
Joined: Sun Nov 15, 2020 1:32 pm

Re: Problem with sampling using ADC via DMA

Postby oliverjrose99 » Sat Nov 21, 2020 2:18 pm

@AlexMa89 @maurogramajo I believe i have fixed the issue thank god. I had to manually power down the apll and then power it up after all the config funcs have been called. the following code can probably be cleaned up and includes optimized but it works.

EDIT: This only seems to work up to 40000 or so frequencey, im gonna try some stuff and reply what I find

Code: Select all

#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "driver/i2s.h"
#include "driver/adc.h"
#include "soc/i2s_reg.h"
#include "soc/syscon_reg.h"
#include "soc/syscon_struct.h"
#include "soc/sens_reg.h"
#include "soc/sens_periph.h"
#include "soc/sens_struct.h"
#include "esp_log.h"

#define SAMPLES 1024
#define SAMPLING_FREQ 44100

static const char* TAG = "MAIN";

void init_i2s_adc()
{
    i2s_config_t i2s_config = {
        .mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN,
        .sample_rate = 44100,
        .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
        .communication_format = I2S_COMM_FORMAT_STAND_I2S,
        .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
        .intr_alloc_flags = 0,
        .dma_buf_count = 2,
        .dma_buf_len = 1024,
        .use_apll = 1,
    };

    // powerdown APLL/PLLA
    SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD_M);
    CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU_M);

    // config adc atten and width
    adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_11db);
    adc1_config_width(ADC_WIDTH_12Bit);

    // set pattern tbl and invert, might not need, double check
    SYSCON.saradc_ctrl.sar1_patt_len = 1;
    SYSCON.saradc_sar1_patt_tab[0] = 0b00001111000011110000111100001111;
    SYSCON.saradc_ctrl2.sar1_inv = 1;

    //install and start i2s driver
    i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
    i2s_set_adc_mode(I2S_NUM_0, ADC1_CHANNEL_0);

    // delay and enable
    vTaskDelay(3000 / portTICK_RATE_MS);
    i2s_adc_enable(I2S_NUM_0);

    // powerup APLL/PLLA
    SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU_M);
    CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD_M);
}

void app_main()
{
    init_i2s_adc();

    int read_len = 1024 * 2;
    uint16_t* read_buff = (uint16_t*) calloc(read_len, sizeof(uint16_t));
    size_t bytes_read;

    while(1) {
        i2s_read(I2S_NUM_0, (void*) read_buff, read_len, &bytes_read, portMAX_DELAY);

        for (int i = 0; i < 64; i++) {
            printf("%hu ", read_buff[i]);
            if (i % 8 == 0) printf("\n");
        }

    }
}


rma-31
Posts: 15
Joined: Sun Oct 08, 2017 5:07 pm

Re: Problem with sampling using ADC via DMA

Postby rma-31 » Fri Nov 27, 2020 8:43 am

Hi,

I am also on the same issue...

Strangely, no matter which ADC Channel I configure, sampling only works on Channel 0 (Sensor VP) (code from last post).

Working from esp-idf master with DevKitC WROVER module...

Anyone else experiencing the same?

Thx :)

Who is online

Users browsing this forum: Corand and 126 guests