Как стать автором
Обновить

Зачем программисту микроконтроллеров тригонометрия? (или Обзор Усилителя Звука из Apple AirTag)

Уровень сложностиПростой
Время на прочтение7 мин
Количество просмотров9.5K

На 12м году опыта программирования микроконтроллеров мне наконец-то пригодилась школьная тригонометрия. Это настолько специфический случай, что я решил написать про это заметку.

Когда Вам надо добавить в устройство звук, то можно воспользоваться микросхемой MAX98357A. Чип этого же семейства MAX98357B можно встретить вообще в Apple AirTag!

Это по сути DAC у которого на входе I2S, а на выходе PWM 330kHz. Меняется только скважность PWM сигнала в зависимости от значений PCM отсчетов в канале I2S.

Главный плюс таких D усилителей - это высокий КПД и высокая энергоэффективность.

В семействе MAX98357x только 2 чипа: MAX98357A, MAX98357B. Вот что значит расшифровка PartName.

Далее я буду работать с MAX98357A.

С точки зрения программиста микроконтроллеров чип выглядит так. Тут можно заметить приемник I2S, цифро-аналоговый преобразователь DAC, усилитель D-класса (по сути генератор PWM), регулятор громкости напряжением. Еще в спеке сказано, что внутри присутствует осциллятор на 330kHz.

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

ASIC примечателен тем, что для него есть специальная отладочная плата. На корпусе микросхемы написано AKK 7AA.

Распиновка PCB отладочной платы

Габариты отладочной платы показаны на рисунке ниже, это 17.7x18.7 мм. Вот чертеж.

Так как чип получает данные по I2S, то приведу подсказку по интерфейсу I2S. I2S это 4х проводной двухканальный синхронный полнодуплексный последовательный интерфейс передачи цифровых данных. Топология соединения Master-Slave. Битовая скорость до 3MBit/s. Интерфейс передает отсчеты DAC/ADC в формате big-endian знаковых чисел в кодировке two's complement integer (PCM). Вот пожалуй всё, что надо знать про I2S в 90% случаев.

В теории так выглядит осциллограмма передачи звука.

А вот так выглядит осциллограмма работающего звука 1kHz на практике. Тут видны PCM семплы со значениями 32, 1, -31, 63. Заполнены оба канала. Звук есть.

Передача 16-битного звука по левому каналу I2S
Передача 16-битного звука по левому каналу I2S

А вот если передавать PCM данные только по правому каналу то звука не будет. Это потому, что у меня сейчас на проводе SD_MODE напряжение 3,3V.

звука нет
звука нет

В чипе MAX98357x выбор канала задается напряжением на пине 4 SD_MODE. Обычно это делается установкой резисторов подтяжки напряжения. Таким образом проводом SD_MODE можно включать или отключать звук даже, если в шине I2S бежит трафик.

Если передавать данные только по левому каналу, то звук снова есть. Это и ожидаемо, ведь на проводе SD_MODE 3.3V.

Очевидно, что сейчас чип MAX98357A выхватывает PCM отсчёты только из левого канала I2S.

А это сигнал на выходе усилка. Тут PWM на частоте 285714 Hz, хотя в спеке заявлено 330 kHz.

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

Вот такой получился прототип. Пришлось соединить все компоненты общей пластмаcской из оргстекла.

Отладка

Как же убедиться, что звуко-излучатель работает на той частоте, которую в самом деле установили?

Вариант №1: Воспроизвести синус.

Надо воспроизвести тестовый звук. Что-нибудь предельно простое, например синус функцию. Затем измерять частоту и сравнить измеренную частоту с воспроизведенной частотой. Если значения совпали, то значит акустическая система воспроизведения работает четко.

Вот таблица предварительно рассчитанных в RAM памяти микроконтроллера PCM семплов

Теперь, когда звук присутствует, можно воспользоваться мобильным приложением Audizr. Это акустический спектро анализатор для мобильных телефонов с OS Andriod. Подразумеваю, что мобильное приложение в real-time вычисляет DFT. Вот на экране мобильного телефона видно, что тон в самом деле 1000 Hz.

Вариант №2: Тестирование звукоизлучателя DTMF интерфейсом

В предыдущем параграфе мы проверили только одну частоту: 1kHz. Однако как проверить остальные частоты? Есть решение.

Можно на микроконтроллере рассчитать двухтональный сигнал и воспроизвести не просто синус, а сумму синусов. То есть DTMF тоны для кнопок 0, 1, 2, 3, ... D, *, #. Затем поднести мобильный телефон с работающим мобильным приложением DTMF Тone Decode и принять цифры. Если в GUI приложения принялись те же числа, что в коде модульного теста, то это значит, что акустическая система полностью исправна.

Вот DTMF частоты, которые соответствуют кнопкам

Надо рассчитать звуковую дорожку для каждой кнопки и воспроизвести её. И тут наступает серьезная проблема.

Сколько отсчетов надо расcчитать для каждого тона DTMF?

Очевидно, что никто не собирается подключать SD карту и всю память записывать гигабайтными однообразными тонами DTFM в *.wav файлах. Надо попытаться найти минимальный период для каждого из 16 тонов.

Эту задачу легко формализовать. Надо просто для каждой пары f1, f2 найти Т. То есть 16 раз решить систему уравнений (1) (2) (3).

\\ y(t) = sin(2 \pi  f_1 t)+sin(2\pi f_2 t) \,\,   (1) \\ y(t)=y(t+T)   \,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\, (2) \\  {y(t)}'={y(t+T)}'      \,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,(3)   \\

Надо как-то выразить T через f1, f2.

T(f_1,f_2)=? \,\,\,\,\,\,\,\,\,\,\,\,\,\,\,       (4)

Решая эту систему уравнений в общем виде, я пришел к выводу, что это как-то слишком сложно. Особенно для таких странных частот как f1=1336, f2=941. Для решения системы уравнений (1-2-3) частоты DTMF это совсем не подарок судьбы. Они даже не в 2 раза отличаются между собой. Сайт Wolfram Alfa даже отказался искать численно решение за бесплатно.

https://docs.google.com/spreadsheets/d/156IrB-d4iHU-ew_3oUJFnV8MYvpMWvZcby_R--UYgXU/edit#gid=0

Поиск периода суммы синусов через решение линейного диофантова уравнения

Можно подойти к задаче с другой стороны. Период суммы синусов это, в сущности, целое число периодов высокой частоты f1 и другое целое число периодов на низкой частоте f2. Эти произведения периодов должны совпадать как показывает уравнение (5)

\\  \frac{N}{f_1 } = \frac{M}{f_2}  \;\;\;\;\;\;\;\;\; (5)

Уравнение (5) вырождается в уравнение (6). А уравнение (6) это не что иное как линейное диофантово уравнение

\\ \frac{N}{f_1 } - \frac{M}{f_2} =0  \;\;\;\;\;\;\;\;\;\;\;\;\; (6)

Его можно решить методом перебора матрицы коэффициентов NxM. Можно найти период суммы синусов, если решить линейной Диофантово уравнение (6). Сделать это можно перебором. Только тут сразу стоит сказать, что обходить матрицу чисел NxM надо зигзагом по диагонали, начиная от верхнего левого угла. Так численный алгоритм быстрее наткнется на решение.

Одно из решений уравнения (6) можно просто угадать. Если каждый период умножить на его частоту, то получается 1 секунда. Однако в микроконтроллере по-любому не хватит никакой памяти, чтобы сохранить дорожки размером в 1 секунду для для всех 16 тонов и всех частот дискретизации. Такая дорожка для 16-битного звука в 2х канальном I2S на частоте 48kHz заняла бы 187.5kByte RAM памяти!

В общем из-за этого у меня было в тот вечер плохое настроение.

Как же быть?

Я решил попробовать найти период DTMF тонов "на глаз". Для этого я написал Python скрипт для, того чтобы самому лично пройтись по звуковой волне.

import matplotlib.pyplot as plt
import math
import numpy as np

f2=770.0
f1=1477.0
Fs=48000
T=0.01
T_fs= 1.0/Fs 

t = np.arange(0, T, T_fs)
Y1 = np.sin(t*2*math.pi*f1)
Y2 = np.sin(t*2*math.pi*f2)
Y =Y1+Y2 

plt.plot(t, Y)
plt.title('signal')
plt.xlabel('Time,[s]')
plt.ylabel('PCM, ')
plt.grid()
plt.xticks(rotation=-90)
plt.show()

Получился вот такой график для тона "5" : 1336 Hz, 770 Hz.

Видишь период DTMF "5"? Вот и я не вижу... А он есть...
Видишь период DTMF "5"? Вот и я не вижу... А он есть...

В результате пришлось пойти на нелегальные действия и выбрать так называемый псевдо период. То есть часть графика, которая хоть как-то визуально повторяется. Для тона 5 получилось значение 9021858 ns=9021.858 us=9.021858 ms.

Для остальных тонов я поступил аналогично. В результате у меня кристаллизировалась вот такая LookUp таблица псевдо периодов для DTMF.

static const DtmfKeyPadFreq_t DtmfKeypadFrequencies[] = {
    {.code = 0x1, .letter = '1', .freq_small_hz = 697, .freq_big_hz = 1209, .min_period_ns=9968000,},
    {.code = 0x0, .letter = '0', .freq_small_hz = 941, .freq_big_hz = 1336, .min_period_ns=7465949,},
    {.code = 0x2, .letter = '2', .freq_small_hz = 697, .freq_big_hz = 1336, .min_period_ns=8362420,}, 
    {.code = 0x3, .letter = '3', .freq_small_hz = 697, .freq_big_hz = 1477, .min_period_ns=8739477,},
    {.code = 0x4, .letter = '4', .freq_small_hz = 770, .freq_big_hz = 1209, .min_period_ns=9095496,},
    {.code = 0x5, .letter = '5', .freq_small_hz = 770, .freq_big_hz = 1336, .min_period_ns=9021858,},
    {.code = 0x6, .letter = '6', .freq_small_hz = 770, .freq_big_hz = 1477, .min_period_ns=9345112,}, 
    {.code = 0x7, .letter = '7', .freq_small_hz = 852, .freq_big_hz = 1209, .min_period_ns=8248412,},
    {.code = 0x8, .letter = '8', .freq_small_hz = 852, .freq_big_hz = 1336, .min_period_ns=8226680,},
    {.code = 0x9, .letter = '9', .freq_small_hz = 852, .freq_big_hz = 1477, .min_period_ns=9446054,},
    {.code = 0xA, .letter = 'A', .freq_small_hz = 697, .freq_big_hz = 1633, .min_period_ns=8583695,},
    {.code = 0xB, .letter = 'B', .freq_small_hz = 770, .freq_big_hz = 1633, .min_period_ns=9155131,},
    {.code = 0xC, .letter = 'C', .freq_small_hz = 852, .freq_big_hz = 1633, .min_period_ns=9255729,},
    {.code = 0xD, .letter = 'D', .freq_small_hz = 941, .freq_big_hz = 1633, .min_period_ns=8546970,},
    {.code = 0xE, .letter = '*', .freq_small_hz = 941, .freq_big_hz = 1209, .min_period_ns=7441866,},
    {.code = 0xF, .letter = '#', .freq_small_hz = 941, .freq_big_hz = 1477, .min_period_ns=7444171,},
};

Я собрал сборку, запрограммировал микроконтроллер и начал испускать DTMF тоны. Каково же было мое удивление, когда мобильное Andriod приложение DTMF Тone Decode в точности распознало звуки, синтезированные по этим псевдо периодам!

Всё здорово, однако мобильный телефон это автоматизированный тест, который подразумевает участие человека оператора. Как же сделать тест полностью автономным?

Есть такой чип как MT8870. Это DTMF Decoding модуль. Чип вычисляет алгоритм Гёрцеля для 8 частот DTMF и устанавливает двоичный код на 4х битном GPIO порте.

У него на выходе 4хбитный GPIO. Можно подключить его к GPIO отладочной платы и им же принимать воспроизводимый сигнал. Тогда не будет нужды в мобильном приложении и человеке-операторе.

Вот так при помощи старого интерфейса DTMF можно тестировать аудиоаппаратуру.

Недостатки MAX98357A

1--Усилители D-класса трудно отлаживать. Тут на выходе меняется скважность. Если вы воспроизводите синус, то вы осциллографом не увидите синус на выходе. Вы его только услышите. Надо еще прикрепить специально рассчитанный фильтра нижних частот.

2--Нет возможности варьировать громкость. Только Вкл.\Откл.

Достоинства MAX98357A

1++ Простота

2++ Дешевизна усилителя (110 RUR).

3++ Высокая энергоэффективность

4++ MAX98357A не нужно отдельное высокочастотное мегагерцовое тактирование для работы подобно тому как это было в ASICе MAX9860.

Итоги

Удалось разработать драйвер для MAX98357A. Для этого понадобилось написать MCAL для подсистемы тактирования микроконтроллера, I2S, GPIO. Также пришлось разработать программный компонент DAC для вычисления сигналов различной формы (синусы, косинусы). Прежде всего sin с разной фазой, частотой и амплитудой.

Интерфейс DTMF отлично подходит для тестирования звукоизлучающей аппаратуры.

Как обычно, чтобы написать систему тестирования, пришлось затратить в 3 раза больше усилий, чем на написание самого функционала.

Если Вы знаете как решить в общем виде систему уравнений (1-2-3), то пишите в комментариях.

Словарь

Акроним

Расшифровка

I2S

Inter-IC Sound

КПД

коэффициент полезного действия

DAC

digital to analog converter

MCAL

Microcontroller Abstraction Layer

DFT

Discrete Fourier transform

MSB

most significant bit

WS

Word Select

ASIC

Application-specific integrated circuit

LRCLK

Left Right Clock

PCM

Pulse-code modulation

IC

integrated circuit

BCLK

Bit Clock

MAX

Maxim Intergated

Links

https://habr.com/ru/companies/vdsina/articles/533492/
https://docs.google.com/spreadsheets/d/1m7vS2bYHUwDMsY2KlE-snnw0ZAD8YeDrgGDN_kSPVAM/edit#gid=1473020946

https://habr.com/ru/companies/skillfactory/articles/554452/

https://habr.com/ru/companies/timeweb/articles/555752/

https://stereo.ru/p/t808p-kak-rabotaet-usilitel-klassa-d-ili-ne-takoy-kak-vse

http://latex.codecogs.com/eqneditor/editor.php

Контрольные вопросы

  1. Как работает усилитель D-класса?

  2. Какой период у DTMF сигнала для символа "1"?

  3. Чем интерфейс I2S отличается от интерфейса TDM?

  4. Как найти период суммы синусов?

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы работали с микросхемой max98357?
12.5% Да8
87.5% нет56
Проголосовали 64 пользователя. Воздержались 6 пользователей.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы работали с интерфейсом I2S?
61.76% да42
38.24% нет26
Проголосовали 68 пользователей. Воздержались 6 пользователей.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы работали с интерфейсом DTMF?
42.65% да29
57.35% нет39
Проголосовали 68 пользователей. Воздержались 4 пользователя.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы работали с усилителями D класса?
69.57% да48
30.43% нет21
Проголосовали 69 пользователей. Воздержались 4 пользователя.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы использовали тригонометрию в программировании микроконтроллеров?
56.06% да37
43.94% нет29
Проголосовали 66 пользователей. Воздержались 5 пользователей.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы работали с интерфейсом TDM?
24.59% да15
75.41% нет46
Проголосовал 61 пользователь. Воздержались 7 пользователей.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы работали с микросхемой MT8870?
6.45% да2
93.55% нет29
Проголосовал 31 пользователь. Воздержались 4 пользователя.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вам приходилось решать диофантовы уравнения при работе программиста микроконтроллеров?
66.67% да2
33.33% нет1
Проголосовали 3 пользователя. Воздержавшихся нет.
Теги:
Хабы:
Всего голосов 23: ↑18 и ↓5+19
Комментарии37

Публикации

Истории

Ближайшие события

19 сентября
CDI Conf 2024
Москва
24 сентября
Конференция Fin.Bot 2024
МоскваОнлайн
30 сентября – 1 октября
Конференция фронтенд-разработчиков FrontendConf 2024
МоскваОнлайн