
На 12м году работы программистом-микроконтроллеров мне наконец-то пригодились комплексные числа из школьной математики. Где они тут нужны? Начнем из далека.
Есть много организаций, которые так или иначе разрабатывают и производят оборудование со звукоизлучателями. Очевидно, что между производством и продажей это аудио оборудование надо тестировать. Я был свидетелем как тест аудиосистемы выполняли вручную. Выглядело это так. Дама-тестировщик берёт электронную плату, нажимает на кнопку воспроизведения и потом нажимает на другую кнопку для подтверждения, что она в самом деле услышала звук. Недостаток такого метода тестирования заключается в том, что нужно постоянное присутствие человека. Плюс человеческий фактор приводит к тому, что из-за усталости, человек машинально подтверждает звук, которого на самом деле не было!
В этом тексте я написал про то как делать авто тест для звуковых систем. Очевидно, что нужен микрофон. Сейчас самые современные микрофоны это MEMS микрофоны с двухпроводным цифровым интерфейсом PDM.
В качестве экземпляра микрофона рассмотрим к примеру MP23DB01HP. ASIC MP23DB01HP - это MEMS микрофон с PDM интерфейсом для испускания данных. Это очень простой чип. Вся его спецификация - это 16 страниц.
Что надо из оборудования?
# | оборудование | Пояснение |
1 | отладочная плата с MP23DB01HP | для преобразования звука в электрический сигнал |
2 | смартфон c Android | для воспроизведения звука |
6 | логический анализатор Saleae | для разбора осциллограмм |
3 | отладочная плата с nrf5340 | для сохранения звуковой дорожки |
4 | Перемычки вилка-вилка | для соединения микрофона и отладочной платы |
5 | Перемычки вилка-гнездо | для соединения микрофона и отладочной платы |
Вот внешний вид SMD микрофона MP23DB01HP.

На корпусе маркировка S2203 5681.

C точки зрения программиста-микроконтроллеров MEMS микрофон выглядит так.

Расспиновка микросхемы

Вот типичная схема подключения микрофона.

Сам по себе микрофон абсолютно бесполезная вещь. Нужна какая-то PCB плата - переходник для подключения этого крохотного микрофона к другим электронным платам. Вот что-то такое

А это та же плата переходник в составе шлейфа

Распиновка PCB модуля c MEMS микрофоном:
№ | пин | Пояснение | цвет провода |
2 | 3.3V | Питание | оранжевый |
3 | DATA | данные | зелёный |
1 | CLK | тактирование | красный |
4 | GND | заземление | желтый |
Вот образцовая осциллограмма PDM трафика. Тут данные выхватываются по отрицательному перепаду на проводе тактирования CLK.

Тактирование микрофона происходит на частоте 1MHz
Программная часть
Что надо из софтвера?
№ | Утилита | Пояснение |
1 | Мобильное приложение SimpleToneGenerator | Для генерации тонального звука с заданной частотой |
2 | TeraTerm | Для подключения к прошивке по serial порту |
3 | Logic 2.3.53 | Клиент для логического анализатора Slaeae |
Особенность PDM модуляции в том, что она однобитная. Это по сути выход Delta Sigma ADC. Одновременно с этим, звук, по своей природе, аналоговый сигнал. Значит надо его представить как последовательность много битных чисел. В программах звук представляется как последовательность знаковых целых чисел (PCM) в массиве. Поэтому необходим какой-то программный или аппаратный компонент, который будет преобразовывать PDM сигнал в PCM сигнал. К счастью, мне повезло и в микроконтроллере nrf5340 заложена электрическая цепочка, которая преобразует PDM в PCM. Это целый цифровой CIC фильтр, который делает эту работу.
Также Vendor NordicSemiconcuctor предоставил MCAL для высокоуровнего доступа к регистрам в физических адресах карты памяти SoC(а).
Я взял смартфон, запустил на исполнение мобильное приложение SimpleToneGenerator, включил воспроизведение синусоиды на частоте 1000 Hz.

Затем поднес звуко-излучатель своего смартфона к микрофону MP23DB01HP и набрал в TeraTerm, подключенной к UART-CLI консоли в прошивку старт авто теста для PDM микрофона.
Вот я записал коротенькую звуковую дорожку всего в 500 семплов (1000 байт).

Вот можно даже явно в TeraTerm выделить один период.

Когда мы записали массив PCM семплов надо пропустить его через дискретное преобразование Фурье. Вот тут-то и появляются комплексные числа!
#include "dft.h"
#include <complex.h>
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include "log.h"
bool dft_calc(const SampleType_t* const signal, uint32_t n_big, double complex* const dft_out, uint32_t out_len,
double t_big) {
LOG_INFO(DFT, "Calc %u samples", n_big);
bool res = false;
if(signal) {
res = true;
uint32_t k = 0;
for(k = 0; k < n_big; k++) {
dft_out[k] = 0.0 + 0.0 * I;
uint32_t n = 0;
for(n = 0; n < n_big; n++) {
dft_out[k] += ((double)signal[n]) * (cos(TWO_PI_VAL * ((double)k * n) / ((double)n_big)) -
sin(TWO_PI_VAL * ((double)k * n) / ((double)n_big)) * I);
}
dft_out[k] = 2.0 * dft_out[k] / ((double)n_big);
}
}
return res;
}
double ft_find_freq(double complex* X, uint32_t len, double period_s,double * const max_freq ) {
uint32_t i = 0;
//bool res = false;
double freq_range = 1.0 / period_s;
LOG_INFO(DFT, "FindMaxFreq, Size %u, SamplePeriod %f S, %f Hz",len, period_s,freq_range);
Spectr_t cur_spectr = {0};
Spectr_t max_spectr = {0};
for(i = 0; i < len; i++) {
cur_spectr.freq = ((double)i) / (period_s * ((double)len));
if(cur_spectr.freq < (freq_range / 2.0)) {
cur_spectr.amplitude = cabs(X[i]);
if(max_spectr.amplitude < cur_spectr.amplitude) {
if(0.001 < cur_spectr.freq){
max_spectr=cur_spectr;
*max_freq=cur_spectr.freq;
LOG_INFO(DFT, "UpdateMaxFreq %f Hz, Amp %f",cur_spectr.freq,cur_spectr.amplitude );
}
}
} else {
break;
}
}
return max_spectr.freq;
}
В результате получили вот такой спектр записанного сигнала

Видно явный максимум на частоте 1024 Hz. Это как раз соответствует тому сигналу который был воспроизведен в утилите Simple Tone Generator на смартфоне. Успех!
Вот график звуковой дорожки от тона на 3kHz.

можно даже построить график зависимости спектра от чаcтоты на Python
import matplotlib.pyplot as plt
import csv
Freq = []
Amp = []
with open('tone_700.csv', 'r') as datafile:
plotting = csv.reader(datafile, delimiter=',')
for ROWS in plotting:
Freq.append(float(ROWS[1]))
Amp.append(float(ROWS[5]))
print ('Type Freq {} '.format(type(Freq)))
print ('Type Amp {} '.format(type(Amp)))
plt.plot(Freq, Amp)
plt.title('DFT')
plt.xlabel('Freq,[Hz]')
plt.ylabel('Amp,[PCM]')
plt.grid()
plt.show()
Вот спектр синус-сигнала на 700 Hz, который вычислен по данным из реального MEMS микрофона.

Достоинства PDM микрофона
1--Всего два провода: частота и данные.
2--малые габариты: 3.5 x 2.65 x 0.98 мм
Недостатки PDM микрофона
1--Если отвалится провод питания, то прошивка никак этого не сможет понять.
2--Надо преобразовывать данные из PDM в PCM а это много вычислений.
Идеи проектов на основе микрофонов
Так как PDM интерфейс поддерживает стерео то можно сделать звуковую ориентацию. Эта технология называется AngleOfArrival (AoA). Можно распознавать направления на источник звука (откуда стрельба или ориентация PTZ камер на источник звука).
диктофоны.
датчики шума.
тестирование аудио-оборудования: колонки, LapTop(ы).
голосовое управление.
Беспроводной прием бинарных данных из модулированного звука. Микрофон может принимать DTMF интерфейс и прошивка может преобразовывать нимблы в байты. В теории можно по DTMF обновить прошивку через микрофон.
телефоны, рации.
медицинские приборы для автоматического измерения пульса (электронный статоскоп).
По эффекту Доплера можно микрофоном определять скорость движения движущихся источников звука (поезда, роботы и прочее). При условии, что Вы изначально знаете частоту излучаемого сигнала на неподвижном предмете. При чем не обязательно звенеть в слышимом диапазоне волн.
Вывод
Как видите, дискретное преобразование Фурье (или FFT) отлично подходит для авто-тестов аудиосистемы. Казалось бы, чтобы протестировать простенькую пищалку надо подключать микрофон, записать PDM, преобразовать PDM в PCM, высчитывать преобразование Фурье, найти максимум, сравнить максимум с настройками изначального воспроизведения и выдать результат. При этом я тут еще не писал саму программную реализацию цифрового CIC фильтра для преобразователя PDM в PCM. Это вообще тема из высших спец. разделов математики (ЦОС). То что микроконтроллер nrf5340 преобразует PDM-PCM это приятная случайность.
В связи с этим общее правило автоматического тестирования таково
Разработка авто тестов всегда в несколько раз дороже разработки самого продукта для которого предназначены эти авто тесты.
Если Вы затратили на разработку продукта N рублей, то на разработку стенда авто тестов Вы потратите минимум 3N рублей. Тут вариантов нет. При этом разрабатывать систему авто тестов должны более квалифицированные инженеры и программисты, чем те кто разрабатывают сам продукт. Вот так.
Словарь
Акроним | Расшифровка |
VDD | Питание |
MEMS | micro-electromechanical systems |
GND | Ground |
AoA | Angle of Arrival |
DTMF | Dual tone multi-frequency |
PCB | printed circuit board |
SoC | System on a chip |
CIC | Cascaded integrator–comb |
SMD | surface mount device |
DFT | discrete Fourier transform |
PDM | Pulse-density modulation |
ST | STMicroelectronics |
MCAL | MicroController Abstraction Layer |
IC | Integrated circuit |
PCM | pulse code modulation |
Links
https://docs.google.com/spreadsheets/d/1M4_rhUz_ULNsZfSdtrAyq4UJ-e8K5sVsdoTFWnLDiFo/edit#gid=0
https://www.st.com/en/mems-and-sensors/mp23db01hp.html
https://en.wikipedia.org/wiki/Pulse-density_modulation
https://en.wikipedia.org/wiki/Cascaded_integrator–comb_filter
https://habr.com/ru/articles/505942/
https://habr.com/ru/companies/yandex/articles/503920/
Контрольные вопросы
В чем недостатки авто тестов?
Как преобразовать битовый поток PDM в PCM семплы?
Сколько проводов нужно PDM интерфейсу?
Как устроен MEMS PDM микрофон внутри?