Сучасна диджитал-освіта для дітей — безоплатне заняття в GoITeens ×
Mazda CX 30
×

Проблема з I2S ADC на ESP32

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

Доброго дня!
Спроба зняття сигналу з АЦП через інтерфейс I2S зазнала невдачі.
Cхоже я не отримую бажану частоту дискретизації (10000 Гц)

 // Initialization of I2S buffer
	uint16_t* i2sReadBuffer = (uint16_t*)calloc(DMA_BUFFER_LEN, sizeof(uint16_t));
	size_t bytesRead;

	while (1) {

		// Read data in the buffer till its not full
		i2s_read(ADC_I2S_NUM, (void*)i2sReadBuffer, DMA_BUFFER_LEN * sizeof(uint16_t), &bytesRead, portMAX_DELAY);

		for (size_t i = 0; i < DMA_BUFFER_LEN; i++) {
			uint16_t value = i2sReadBuffer[i];
            printf("%d\n", value);
		}
	}

Сигнал через UART я отримав і відфільтрував.
Але фільтр адекватно працює тільки з коефіцієнтами, що були задані для частоти дискретизації 1кГц.

Посилання на результат

MatLab код для обробки сигналу:

xlsFile = 'ecg_data.xlsx';

[num, txt, raw] = xlsread(xlsFile);

input = cell2mat(raw);

a = fir1(100, [0.06 0.14], 'stop'); % BandStop фільтр

in = input(:, 2);

filtered = filter(a, 1, in);

y = fft(filtered);

N = length(y);                   % Довжина вектора

f = (0:N - 1 ) * 100 / N;        % Частотний вектор

m = abs(y);                      % Амплітуда
% y(m<1e-6) = 0;
p = unwrap(angle(y));            % Фаза

X_vector = (1:3:N) / ((N - 1) * 1e-3);

title('Частотний аналіз')

subplot(2,2,1)
plot(f,m)
title('АЧХ')
ax = gca;
ax.XTick = X_vector;

subplot(2,2,2)
plot(f,p*180/pi)
title('ФЧХ')
ax = gca;
ax.XTick = X_vector;

subplot(2,2,3)
plot(in)
title('Вхідний сигнал')
xlabel('msec')
ax = gca;

subplot(2,2,4)
plot(filtered)
title('Відфільтрований сигнал')
ax = gca;

Конфігурація I2S

#define SAMPLING_FREQ 10000
#define ADC_CHANNEL ADC1_CHANNEL_4
#define ADC_UNIT ADC_UNIT_1
#define DMA_BUFFER_LEN 1024
#define ADC_I2S_NUM I2S_NUM_0

static void init_i2s_adc(void) {
    i2s_config_t i2s_config = 
    {
        .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN),
        .sample_rate = SAMPLING_FREQ,                                            
        .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,                            
        .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,                              
        .communication_format = I2S_COMM_FORMAT_STAND_MSB, 
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,                                                 
        .dma_buf_count = 8,                                                    
        .dma_buf_len = DMA_BUFFER_LEN,
        .tx_desc_auto_clear = 1,                                            
        .use_apll = 0,                                                       
    };
    adc1_config_channel_atten(ADC_CHANNEL, ADC_ATTEN_11db);
    adc1_config_width(ADC_WIDTH_12Bit);
    i2s_driver_install(ADC_I2S_NUM, &i2s_config, 0, NULL);

    i2s_set_clk(ADC_I2S_NUM, SAMPLING_FREQ, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO);
    i2s_set_adc_mode(ADC_UNIT, ADC_CHANNEL);
    i2s_adc_enable(ADC_I2S_NUM);
}

Чи не означає це те що реально частота дискретизації 1кГц?
Хтось може допомогти виправити цю проблему?

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

1. Додав перевірку на виклик i2s_set_clk — все гаразд.
2. Переписав цикл відносно значення bytesRead, дякую за зауваження
3. Я гадки не маю як отримати реально встановлену частоту дискретизації. Ви б не могли підсказати як її отримати?

Тепер все зрозуміло. Реальна частота була в 16 разів менша.
При такому значенні MATLAB фільтрував частоти 40-80 Гц, що не спотворило криву ЕКГ і при цьому дозволило усунути шум 50-60 Гц.
Красно дякую вам!

Чогось я тут не розумію, передивись цю строчку

f = (0:N — 1 ) * 100 / N;

Це відноситься до перетворення Фур’є. Мене скоріше цікавить чого фільтр працює з параметрами 0.06 — 0.14.

насчет фильтра не понял вопроса. он аппаратный?
но сам код с i2c_read() не имеет смысла, поскольку ты не смотришь на значение

bytesRead

1. Ні, цифровий (50-60 Гц).
2. Якщо передати portMAX_DELAY останнім аргументом, то жодного timeout не буде. Відповідно bytesRead = DMA_BUFFER_LEN.

Підписатись на коментарі