Print this page

Беспроводная акустическая система

Rate this item
(2 votes)

Содержание[Показать]

Прежде чем начать

Прежде чем читать эту статью рекомендуем тебе ознакомится со следующей теорией:

Как сделать качественную bluetooth колонку в домашних условиях

Сейчас все делают bluetooth колонки из компонентов с aliexpress. В интернет очень много различных инструкций, youtube завален видео. К сожалению все эти поделки не удовлетворяют даже базовым параметрам Hi-Fi звука. В них обычно используются устаревшие компоненты и технологии звука. Только использование самых современных компонент позволит в домашних условиях сделать переносную Hi-Fi акустику. Перечислим основные пункты, которые приведут нас у успеху:

  • Весь звуковой тракт должен быть цифровым. Аналоговый сигнал очень капризен к трассировке платы, качеству сборки и требует настройки на специальном оборудовании. Цировой же сигнал наоборот, практически не требователен к трассировке, спокойно относится к "кривым рукам". Bluetooth модуль должен быть подключен только по цифровому каналу.
  • Обязательно нужен DSP процессор. Получить мощный звук в компактном корпусе очень сложно. DSP процессор позволит расширить акустический диапазон акустики, особенно в области низких частот. Дополнительно, новейшие разработки в этой области, сделают процесс настройки очень простым, а звук качественным на любом уровне громкости.
  • В домашних условиях очень сложно сделать качественный, красивый корпус. На помощь приходит 3D печать. Качество 3D печати на домашних принтерах сейчас очень высоко. Современные пластики позволяют получить прочный, стильный корпус. Самостоятельная разработка модели позволяет учесть все особенности расположения компонент и обеспечить быстрый доступ к ним.
  • Динамики - сердце нашей системы. Только брендовые компоненты позволят получить натуральный мощный звук. Обязательно использование 2-ух динамиков: Широкополосный - НЧ и СЧ диапазона и ВЧ динамик. Также для малого корпуса просто необходим пассивный динамик. Динамики обязательно должны иметь паспорт и документацию, график АЧХ, без этого сложно будет произвести их точную настройку без специального оборудования, а его как правило дома нет.
  • Вся переносная акустика работает на аккумуляторах, поэтому экономичность и эффективность энергопотрбления всех компонент не на последнем месте. В следствие этого усилитель должен быть D-класса с максмимально высоким кпд. Большую часть времени вы будете слушать акустику на среднем уровне громкости - именно в этом режиме колонка должна работать очень долго. Для получения мощного звука нужен большой ток, а значит нужны высокомощные литиевые аккумуляторы.

Какой Hi-Fi нам нужен

В этой статье в разделе "Что такое хайфай" отлично написано, что же такое Hi-Fi и какой он бывает. Не буду повторять всю статью, напишу только итоговые выводы. Hi-Fi бывает 4 видов:

  • Абсолютный или полный – 20-20 000 Гц, 0,03% (–70 дБ), 90 дБ (в 31 600 раз), 1 дБ (в 1,12 раза), 2 дБ (в 1,25 раза).
  • Высокий или тяжелый – 31,5-18 000 Гц, 0,1% (–60 дБ), 75 дБ (в 5600 раз), 2 дБ, 3 дБ (в 1,41 раза).
  • Средний или базовый – 40-16 000 Гц, 0,3% (–50 дБ), 66 дБ (в 2000 раз), 3 дБ, 6 дБ (в 2 раза).
  • Начальный – 63-12 500 Гц, 1% (–40 дБ), 60 дБ (в 1000 раз), 6 дБ, 12 дБ (в 4 раза).

Качество звука определяется воспроизводимым диапазоном частот, а также отклонениями АЧХ в этом диапазоне. Учитывая, что на переносных колонках практически невозможно воспроизводить нижние частоты (ниже 60 Гц обязательно нужен сабвуфер, а он тяжелый и "кушает" много энергии), нашей целью будет базовый уровень Hi-Fi с небольшими "доработками" - диапазон частот сместим в область высоких частот. Будем стремиться к диапазону 60 - 20 000 Гц с нелинейностью 3 дБ, а на краях диапазона 6 дБ. Это чуть-чуть не дотягивает до высокого уровня Hi-Fi, но для переносной акустики - это супер хорошо.

К сожалению, в домашних условиях качественно замерить АЧХ колонки не получится, так что будем довольствоваться расчетными величинами и своими ушами для оценки того, что у нас получится.

Постановка задачи, требования к прибору

Вот какие получаются требования к нашей переносной акустической системе:

  • Компактный размер (конечно все относительно, кто-то назовет это лошадью) - не более 40х15х15см
  • Вес до 3 кг (больше - уже тяжело носить с собой)
  • сумарная мощность звука 40-60 Вт (это то что нужно! меньше не годится, больше уже будет другой размер и вес)
  • Hi-Fi звук "высокого уровеня" - 60-20 000 Гц с нелинейностью 3дБ и с КНИ < 1%
  • Цифровой тракт bluetooth, протокол Apt-X
  • Цифровой стерео усилитель звука 48кГц, 16бит
  • DSP процессор со встроенными эффектами
  • Режим пауер банк (неприятно когда телефон, передающий музыку сел)
  • Режим mp3, flac плейра, со встроенной sd карты (очень удобный режим, меньше потребление тока, чем bluetooth и телефон не нужен)
  • Проигрывание mp3 с внешней флешки
  • FM-радио - иногда приятно в дороге или на пикнике послушать радио
  • Цветомузыка на основе RGB светодиодов - сейчас это модно и выглядит красиво - must have
  • Качественные динамики, двух-полосная акуситическая система, пассивные динамики
  • Подключение колонки по USB, удобно "озвучить" компьютер по проводам, линейный вход уже устарел
  • Литиевые аккумуляторы минимум 2000 mAh - долгое время работы просто необходимо
  • Wi-Fi модуль для управления плеером с телефона и получения обратной связи от колонки

Схема основных модулей колонки

Переносная акустика это сложный прибор. Тут точно будет не одна печатная плата, да и одной плате будет много "модулей". Чтобы ничего не забыть, отобразим на схеме ее устройство

Глядя на данную иллюстрацию, начинаем понимать, что работа предстоит большая.

Подбор компонентов для изготовления прибора своими руками

Аудио компоненты

Динамики

Сначала я решил сделать ход конем и купить автомобильные динамики со встроенной вч головкой - ESX QE32. Но качество звука в области НЧ расстроило - бас они "не прокачивали". У них совсем не большой ход диффузора, и в общем и целом они рассчитаны на средние частоты.

Потом стал изчуать форумы и нашел тут подробнейший анализ динамиков для переносной акустики. Вот то что нужно! Прочитав форум до конца я понял, что самый правильный выбор - это AURA NS3-193 (НЧ-СЧ диапазон). А в качестве высокочастотных - Хейлы Dayton Audio AMT Mini-8. Пассивные радиаторы - Peerless_SDS-P830878. Вот замечательная тройка:

Aura и Peerless купил на сайте madisound. Это оказалось не сложно, пришли очень быстро. А вот ВЧ купил на aliexpress. Если будете выбирать другие, то следите чтобы на динамики была документация, как минимум параметры Тиля Смола, они в дальнейшем будут нужны для настройки DSP процессора. Конечно их можно замерить, но я как то больше доверяю производителю.

Усилитель звука и DSP процессор

Когда я подбирал усилитель для колонки, то изучил рынок продаваемых колонок (JBL и другие). Коротко опишу базовую схему всех этих агрегатов. Цифровой звук по стандарту I2S поступает на DSP процессор (конечно его роль может выполнить мощный микроконтроллер, но писать софт довольно сложно), далее на DAC (цифроаналоговый преобразователь) и с него уже на усилитель D-класса. Как видно цепочка длинная и самое не приятное место в ней - DAC. Качественный DAC требует грамотной трассировки платы, двухполяного питания и много дополнительного обвеса. И тут я случайно наткнулся на новый чип от компании TI - TAS5782m. Прочитав datasheet, я сразу понял - это то что нужно! Что особенно понравилось:

  • однополярное питание
  • высокая мощность - до 60 Вт звука
  • все внутри одной микросхемы - DSP, DAC и усилитель
  • мощный DSP со SMART функциями, и все это на частоте сэмплов до 96 кГц
  • услитель D-класса работает на очень высокой частоте - 768 кГц, что позволяет снизить размеры выходных LC фильтров
  • минимальный нагрев при работе благодаря 90 мОм транзисторам на выходе - возможность работать без радиатора совсем
  • удобный корпус для домашней пайки
  • минимальный обвес - в основном только конденсаторы и резисторы
  • отличная документация
  • удобный софт по настройке DSP и настройка в два клика

В общем, лучшего решения на текущий момент нет! Скажу наперед - к нему вообще нет претензий, завелся сразу, паять легко, ставлю твердую пять. Единственный момент - купить в России сложно, заказывал напрямую у TI.

Bluetooth модуль

Лучшее что смог найти - модуль на базе чипа CSRA64215. На aliexpress продается под маркировкой BTM625. Вот как он выглядит.

Сам чип очень продвинутый, в интернет есть программа для его программирования, есть отдельный софт на Android для управления им - громкость, эквалайзер и другие настройки. Но самое главное - цифровой выход звука I2S (при покупке будьте внимательны - есть версия под аналоговый выход - придется ее препрограммировать) 48 Кгц 16Бит, наличие кодека Apt-X - существенно улучшаюшего качество звука и задержку (можно смотреть кино).

FM радио

В качестве радиоприемника используется модуль на базе чипа TEA5767. Звук с него подается напрямую на ADC микроконтроллера.

Скажу сразу - чип работает, но качество приема у него среднее. В качестве антенны используется провод от наушников (как в сотовом телефоне). В квартире ловится хорошо, но иногда стерео теряется. Также стоит отметить, что выход звука на данном чипе соответсвует уровню 0.7в по размаху. И он напрямую передается на оцифровку в МК. В итоге имеем очень низкое разрешение звука - всего 8бит. В следующей версии планируется заменить этот модуль на цифровой вариант на базе чипа Si4705 с выходом I2S - это лучшее что я нашел.

Центральная плата

Микроконтроллер

В этом приборе будем использовать мощный микроконтроллер STM32F466, от уже известной нам компании ST. На него будет возлагаться много задач:

  • управление зарядкой
  • управление цветомузыкой
  • декодирование mp3 и flac Сразу выбирал процессор с поддержкой DSP инструкций и float вычислений. Эта модель отлично подходит по всем параметрам, в том числе и по цене.

Wi-Fi модуль

Колонка имеет встроенный Wi-Fi модуль ESP-12F. Зачем он здесь? Через bluetooth модуль можно передавать только звук, использовать его для управления колонкой не получится. Так как в колонке будет mp3 плейер со встроенной флешкой, то хотелось иметь возможность управлять плейлистами, получать информацию о проигрываемой песни и т.д. Этот модуль отлично подойдет для этих задач.

Преобразователи DC-DC

Для питания колонки используется 4S аккумулятор напряжение которого составляет 15В. Базовое питание всех схем - 5В. Для преобразования нужна специальная микросхема DC-DC преобразователь. Будем использовать отличный проверенный чип NCP3170B (версия B работает на частоте 1МГц). Высокая частота - малый размер конденсаторов и индуктора. Микросхема имеет низкое энергопотребление в спящем режиме, встроенные MOSFET транзисторы - нужен только индуктор. В колонке два таких - для питания подсветки и режима пауербанка, а второй для основного питания цифровой части.

Светодиодная подстветка

Управляемые светодиоды RGB - правильный выбор. Решение на базе чипа WS2812b подойдет (можно конечно найти что-то более современное, если найдете - то переписать код в прошивке будет не сложно). Покупал такие - на плате. Удобно паять и меньше нагреваются.

Самое главное в этих светодиодах - управление по одному проводу. Почти вся лицевая панель колонки будет состоять из светодиодов - используется около 100 штук. Это позволяет создать шикарные эффекты цветомузыки, а также выводить с помощью светодиодов служебную информацию.

Корпус

В интернет можно почерпнуть много идей по изготовлению корпуса для колонки, вот несколько примеров:

И еще:

Вдохновившись ими первую колонку я выпилил из МДФ:

Впоследствие изучив различные программы для расчета корпуса акустики (особенно понравилась bass6 pro и dev) я понял, что для получения более мощных басов нужен больший объем корпуса или пассивные излучатели. Для выбранных динамиков нужен объем минимум 2л на каждый. Я сделал комбинированный корпус - текстолит + 3д печать. Супер прочно, легко, но не компактно:

В итоге от этого корпуса я отказался (потеряв в басах) и разработал новый, по размеру как первый, на базе 3Д печати. Этот вариант полностью меня устроил.

3Д печать повозволила учесть все нюансы расположения компонент. Удобство модернизации и ремонта - это главное. Вес корпуса получился около 600гр. Пластик для печати использовал PETG. Специально проверял и расчитывал прочность - на высоте. Корпус легко печатается (нет поддержек), состоит из большого количества деталей, которые склеиваются между собой (я клеил на суперклей Cosmofen).

На этом фото из 3D редактора отлично видно как он устроен.

Для корректной работы пассивного динамика корпус должен быть герметичным. Поэтому все электронику, вместе с аккумулятором, вынес в отдельный отсек. Для упрощения печати (без поддержек) основная часть раделена на 6 частей. После печати они склеиваются суперклеем. Площадь склеивания большая, поэтому соединение получается очень прочным (прочнее чем сама печать). Центральная плата установлена в специальной нише корпуса, сверху она закрывается блоком с акумулятором, вч динамиками и светодиодным экраном. Специальные вставки со светодиодами фиксируют основные динамики болтами. Крышка с отверстиями под разъемы завершает лицевую панель. С обратной стороны вставляется пассивный излучатель, который прижимается крышкой. Для защиты динамиков используются металлические сетки (заказывал на aliexpress).

Составляем схему колонки

Схема колонки довольно сложная. Многие части взяты из datasheet на компоненты. В этом разделе рассмотрим только сложные моменты, над которыми пришлось поломать голову. Весь проект в Kicad доступен в полной версии статьи.

Начнем с кнопок. Кнопок будет 6. Чтобы было меньше проводов - подключим их по схеме с участием ADC и делителей на резисторах. В итоге получается по одному проводу сразу 5 кнопок и одна кнопка для включения питания - с ней все просто.

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

Управление зарядкой на базе классического понижающего DC-DC:

Частота работы DC-DC - 250 кГц. Такая высокая частота выбрана специально для снижения требования к индуктивности, что позволяет минимизировать ее размер. Входное напряжение - 18V. Для управления мосфетом используется биполярный драйвер с очень неплохими характристиками zxgd3003e6. Единственный его минус - небольшое смещение напряжения постоянно присутсвующее на базе мосфета. Из-за него выбирать мосфет с повышенным напряжением отпирания завтора. Такая схема отлично работает с токами до 3А без существенного нагрева. Реально зарядка идет током не более 2А (ограничено программно, потому что аккумуляторы 2000mAh). Емкости везде используются керамические, для уменьшения толщины печатной платы. На выходе DC-DC стоит пара мосфетов Q3A Q3B для аварийного отключения процесса зарядки от аккумулятора.

Для анализа тока заряда и разряда аккумулятора используем rail-to-rail операционный усилитель подключенный к шунту, у которого делителями задано смещение нуля:

Такая схема позволяет измерять ток в двух направлениях - заряд и разряд. Смещение настроено в сторону большего тока разряда. Измерять ток заряда необходимо для контроля процедуры заряда, а ток разряда - для анализа оставшейся емкости аккумулятора.

Байпас внешнего питания - класическая схема на диоде и мосфете.

Максимальный средний ток в такой схеме не превышает 5А. При использовании диода шотке с очень малым падением напряжения 0.3В его нагрев будет минимальным. Во всех схемах компоненты подобраны для работы без радиатора, что существенно уменьшает размеры и упрощает сборку прибора.

Схема усилителя полностью из datasheet, поэтому приводить не буду. А вот над разделением потоков I2S пришлось подумать. Данные с Bluetooth модуля поступают на усилитель через управляемый буфер, там есть различие в уровнях напряжения, а также есть необходимость отключать bluetooth модуль от усилителя. Прямо с микроконтроллера сигнал I2S также идет на усилитель. Здесь важно чтобы одновременно не включились буферы и выход микроконтроллера, это обеспечивается програмно. Усилитель позволяет вывести результирующий сигнал I2S на отдельный вывод (для работы двух усилителей в связке) - заведем его на МК, чтобы анализировать звук для цветомузыки.

Печатная плата

Трассировка платы выполнена по рекомендациям используемых микросхем. Специально для изготовления в домашних условиях по нашему методу увеличен диаметр переходных отверстий до 1.6мм. Минимальное расстояние между дорожками - 0.25мм, минимальная ширина дорожек 0.25мм. Для удобства размещения в корпусе вся электроника разбита на три платы:

  • центральная
  • кнопки
  • разъемы
  • плата балансировки аккумулятора

В полную версию статьи включен проект в Kicad и вы можете модернизировать платы, если это необходимо. Толщина центральной платы с учетом двухсторонней компоновки составляет всего 10мм, что позволило разместить ее в компактном корпусе. Все платы не сложные в сборке. В основном используются SMD компоненты размера 0603. Только в модуле усилителя есть конденсаторы размером 0402. Паять их нужно очень аккуратно, желательно под увеличительным стеклом. Также сам усилитель имеет площадку для отвода тепла, для его пайки можно исопльзовать (паяльный фен) или просверлить отверстия с обратной стороны, залудить площадку на микросхеме и припаять к ней проводки для лучшего теплоотвода. В таком варианте микросхема отлично работает без радиатора.

В первой версии платы я допустил ошибку. Жжелая съэкономить на деталях, решил управлять высовольтными P-мосфетами сразу от микроконтроллера. Так делать нельзя. В итоге пришлось добавить маломощные N-канальные транзисторы для смещения уровня напряжения на отдельной мини плате и припаять все проводами. Во второй ревизии платы - это было исправлено.

Отметим также, что в случае расположения на плате RF модулей необходимо оставлять место на текстолите без меди для корректной работы встроенной антенны. Это можно видеть на плате около модуля bluetooth, и еще одно место - модуль Wi-Fi.

Для сборки проводов в жгуты очень удобно на плате делать петельки из провода или медной жилы:

Плата балансировки описана в отдельной статье.

Сборка колонки

Решил написать отдельное руководство по сборке. Весь процесс оказался нетривиальным.

Необходимые инструменты и всякая мелочовка

Для сборки колонки тебе понадобяться следующие инструменты и дополнительные материалы:

  • ST-link - для программирования и отладки микроконтроллера
  • мощный паяльник (минимум 60 Вт) для сборки аккумуляторов (или нужно использовать аккумуляторы с приваренными контактами)
  • провод МГТФ 0.05 мм2 - как основной сигнальный, 0.14 мм2 - как основной силовой, желательно 0.2мм2 для аккумуляторов
  • витая пара или одножильный провод диаметром жилы 0.5 мм - для шин питания подсветки
  • микро коаксиальный провод 75 Ом для вывода антенны радио на внешний разъем
  • термоусадочная трубка диаметром 3мм - для изоляции разъемов и соединений
  • герметик - Soudal Fix ALL Turbo (только он хорошо клеится к PETG пластику) - для герметизации краев и стыков
  • краска резиновая Super Decor Rubber - для герметизации корпуса изнутри - полная окраска изнутри
  • винты диаметр 3мм различной длины и гайки к ним
  • оплетка для снятия припоя - ее отлично можно использовать для соединения аккумуляторов в сборку
  • разъемы JST-RCY 2 - используется для подключения аккумуляторов (хорошие высокотовые разъемы - до 10А)
  • листовой пвх пластик 3мм куски - как вспомогательный элемент для фиксации различных элементов
  • аллюминиевый профиль П образный 40см 10мм х 1.5мм х 8мм - для усиления конструкции в районе крепления ручки
  • кусочки фольгированного текстолита - для формирования контактных площадок для проводов
  • кусок текстолита без меди толщиной 1.5мм 15см х 4см - для ребра жесткости под аккумулятор и по крепления ручки
  • фиксатор резьбы Локтайт синий (слабый) для фиксирования болтов крепления ремешка
  • фоамиран 2мм - прокладки для герметизации посадочных мест динамика

Печатаем и склеиваем корпус

Про саму печать на 3Д принтере рассказывать нечего. Тут особенностей нет. Пластик используем PETG - он самый экологичный и прочный. Вы можете скачать все детали в формате stl, а также рекомендации по параметрам печати в полной версии статьи.

Для склеивания деталей используется супер клей. Перед склеиванием нужно зашкурить детали мелкой шкуркой и проверить на плотное примыкание. Если стык неплотный, то лучше сначала нанести на углубления супер клей и посыпать стружкой PETG пластика (предварительно наточив например мелким надфилем от ненужных кусочков) и выровнять напильником. Склеивание нужно проводить в хорошо провертриваемом помещении, в защитных очках и желательно респираторе (в большом объеме супер клей сильно испаряется, а его испарения вредны). Важно не забыть перед приклеиванием последней детали вставить внутрь корпуса аллюминиевый профиль для крепления ручки.

После склеивания основного корпуса необходимо укрепить швы пластиковыми заплатками - кусок пластика 1мм толщиной длиной 3см и шириной 1см - поперек шва. Изнутри корпуса.

Точно также склеиваем остальные элементы, которые были разрезаны для удобства печати. В некоторых местах нужно обработать детали надфилем, чтобы они входили в замок.

Собираем все до конца

Полная сборка колонки делается в несколько этапов:

  • прикручиваем на винт М4 крепления для ремешка к корпусу
  • Собираем все платы, соединяем их проводами и проверяем работу электроники. Удобно, что усилитель работает от 5В - то есть можно проигрывать музыку питая всю схему от 5В
  • Делаем сборку аккумулятора 4S
  • Собираем центральный блок - вставляем ВЧ динамики, припаиваем к ним разъемы, вставляем аккумулятор, фиксируем все текстолитом
  • Вставляем в специальные отверстия в корпусе провод для подключения динамиков и герметизируем эти отверстия вместе с проводом
  • Клеим на центральную плату специальные блоки для фиксировования платы в корпусе - можно на обычный герметик
  • Приклеиваем на герметик или клей момент распечатанные колпачки-кнопки
  • Клеим на супер клей фиксаторы платы разъемов - предварительно выравняв плату с помощью пвх пластика (его потом легко срезать)
  • Вставляем светодиоды в распечатанные экраны и припиваем их согласно схеме, на концах припаиваем разъемы
  • Вставляем сеточки в блоки подсветки динамиков и фиксируем точечно герметиком
  • Вставляем модуль светодиодов центрального экрана и припаиваем его к плате разъемов
  • Подключаем аккумулятор и все проверяем
  • Фиксируем центральную часть винтами побокам
  • Устаналиваем фиксаторы динамиков и все собираем

Подробный фото отчет, который поможет в этом процессе есть в полной версии статьи.

Программирование DSP процессора

Встроенный DSP процессор очень мощный и имеет отдельный софт для настройки. В этой статье подробно описано зачем вообще он нужен в переносной акустике. Здесь же приведем основные опции, которые используются в этой колонке. Немного про сам софт, установку и как им пользоваться.

После покупки микросхемы у TI по запросу они дают доступ к скачиванию софта. Установка элементарная. Далее принцип работы примерно такой - делаем в софте нужные настройки, сохраняем выгрузу регистров в Си формате. Копируем эти данные в проект STM32 IDE и при инциализации системы загружаем эти данные в регистры DSP по I2C. Важный момент - загружать регистры необходимо только тогда, когда на DSP уже идет стабильный клок сигнал по I2S, чтобы он мог автоматически определить частоту и настроить внутренние делители. Если так не сделать, то никаких ошибок не будет, но настройки не применятся. Следует отметить что прямо в режиме он-лайн менять какие либо параметры не получится, но можно сделать готовые предустановки и их менять по кнопке или по Wi-Fi. Задача DSP сделать звучание максимально натуральным для именно этой акустической системы, а не постоянно менять настройки под настроение. Хорошо настроенная система одинаково отлично играет любую музыку. Перейдем к описанию настроек, которые необходимо сделать.

Начнем с основного режима. Будем Использовать Smart Amp Processing 48k - в этом режиме настройка максимально простая и автоматическая.

Чтобы смарт режим работал идеально необходима специальная тестовая плата от TI, она позволяет снять характеристики динамика, проводить тесты в он-лайн режиме и многое другое. Но покупать ее для разового проекта смысла нет. У TI есть отличный документ application report (SLAA737B), в нем полностью описан процесс настройки DSP. Читать обязательно. В итоге руководствуясь этим документом я проводил все настройки в слепую, используя данные из datasheet на динамики (вот тут они и пригодились) и на сам усилитель. Полученный результат меня полностью устроил. Для корректной работы необходимо задать следующие параметры:

  • параметры Тиля Смола на основной динамик
  • параметры на пассивный динамик
  • внутренний объем корпуса (в пересчете на один динамик)
  • максимальную RMS мощность динамика
  • пиковый ход диффузора динамика
  • измерить напряжение на динамиках на максимальной громкости обычным вольтметром (мерял на половине громкости и пересчитывал)
  • снятое АЧХ на динамик для использования эквалайзера для нормализации АЧХ (делал без нее)

Самая нужная и важная для переносной акустики функция - Смарт Бас. Основная фишка этого режима состоит в том, чтобы обеспечить максимальный бас на любой громкости и не испортить динамик. Скажу сразу - это действительно работает на твердую пять. Функция очень интересная, посмотрим как она работает. Для этого изучим график АЧХ нашего основного динамика из datasheet.

Как мы видим на графике, ниже 120 Гц начинается падение звукового давления. Это типичная характеристика всех динамиков на границах диапазона. Посмотрим в самое начало нашей статьи - какой Hi-Fi нам нужен. Нижний диапазон 60Гц с падением не ниже 3 Дб - это наша цель. Если взять по графику уровень 80 db за нулевую отметку, то динамик имеет на частоте 60Гц - (-5 ДБ) от нулевого уровня. Но это еще не все. Данный график - динамик без оформления. Если же мы его засунем в наш малюсенький корпус, то получим вот такой график в нижнем диапазоне частот (мне понравилась программа для расчета корпуса акустики внутри эксель файла (UniBox) - просто и наглядно):

тут видно, что на частоте 60Гц - спад еще больше (-10 Дб). Покажу как бы было хорошо этому динамику в большом корпусе:

почти 3 Дб разницы - это много. Но компактность тоже нужна. Так что работаем с тем, что имеем, а вот DSP пусть старается и помогает добиться нужного результата. Итак, для получения нужного эффекта необходимо усилить звук в области низких частот на 7 Дб (по мощности это в 5 раз!). Когда акустика работает не на полную громкость у нас есть запас для увеличения мощности баса, а вот при увеличении громкость он теряется. Функция смарт бас делает усиление автоматически на максимально возможную величину, в зависимости от композиции, громкости, хода динамика и это звучит реально очень сильно. Самое главное она делает это сама - нужно только задать требуемую частоту, параметры динамика и коэффициенты динамики переходных процессов и все! Вот как выглядит диалог настройки функции смарт бас:

Для правильной настройки этой функции (у нас нет спец платы для настройки звука) необходимо создать несколько пресетов и слушать их на колонке, переключая кнопками или по Wi-Fi. Нужно выбрать тип фильтра, коэффициент морфинга, скорость морфинга, коэффициент гармоник. Суть этих параметров описана в документе от TI, а также методика настройки. Скажу сразу - сделать для любого динамика 60 Гц неполучится. Основное препятствие - ход диффузора, чем он меньше, тем частоту придется задавать все выше и выше. Общее правило примерно такое - DSP должен увеличивать мощность не более чем на 10 db.

Вторая очень полезная для нашего проекта функция - моно бас. Она позволяет разместить два динамика в одном общем корпусе и использовать один пассивный радиатор на два динамика. Это очень удобно. Чтобы динамики в области низких частот не работали в противофазе, звук из стерео делается автоматически монофоническим. Так динамики не мешают друг другу, а работают вместе. Можно задать частоту среза - я сделал 300 Гц.

Высокочастотные динамики в корпусе расположены слишком близко друг к другу, что снижает стерео базу, поэтому добавим эффект расширения стерео зоны. Ну и напоследок необходимо выровнять чувствительность динамиков СЧ и ВЧ. У ВЧ чувствительность заметно выше, именно поэтому мы взяли ВЧ на 8 ом, а основной динамик на 4 ом. Но этого все равно мало, ВЧ без корректировки слишком много. По расчетам нужно около (-5Дб) на частоты выше 4000 гЦ - это и выставим с помощью эквалайзера. Можно поднять громкость еще за счет снижения качества (можно снизить THD до 5%), но я этого делать не стал и тебе не советую. Громкости мне хватает. Отмечу здесь, что если бы питание колонки было бы от 5S то можно было бы получить еще большую пиковую мощность - до 80 Вт (но все это выше 150 Гц, поэтому делать этого не стал)!

На этом тюнинг закончен. Далее можно на базе этой настройки строить уже свои пресеты с помощью эквалайзера - работа дома, на улице, больше баса, больше голоса и т.д.

В этом подразделе стоит сказать и про аккумулятор. Беда заключается в том, что один полностью заряженный аккумулятор имеет напряжение 4.2В, а полностью разряженный 2.8В. Для 4-х аккмуляторов размах еще больше целых 5.6В. Если рассчитывать работу DSP от самого низкого напряжения, то мы потеряем часть мощности на полностью заряженном аккумуляторе, а если на самое большое - то при просадке емкости будем иметь сильные искажения на полной громкости. В итоге правильное решение - динамическое изменение максимальной выходной мощности от текущего минимального напряжения аккумулятора.

Для этого программа анализирует минимум напряжения и задает снижение громкости в последнем каскаде работы DSP - output crossbar

Как видно на схеме, за счет управления громкостью получить данный эффект нельзя. Нужна регулировка в самом последнем каскаде - выходном. Во время работы колонки, анализируется минимальное значение напряжение и на текущий сеанс (до выключения колонки) снижает выходную громкость. Получается максимальная громкость на каждому уровне напряжения. Все расчеты DSP в этом случае нужно производить для максимального уровня напряжения.

Программа для микроконтроллера

Программа написана в среде STM32 Cube IDE. Все исходники доступы в полной версии статьи. Здесь рассмотрим ключевые моменты кода.

Общая логика работы программы

  1. При включении проводим инициализацию всех подсистем микроконтроллера и отображаем на несколько секунд на переднем экране состояние аккумулятора. Если в течение этого времени кнопку не отпустили, то подпираем включенное состояние ножкой микроконтроллера и переходим в рабочий режим. Аналогичное решение было в приборе Мини пирометр. Если же кнопку отпустили - то колонка выключается. Получается такой быстрый вариант проверки заряда колонки.
  2. С помощью ADC мониторим (через прерывание) все внешние процессы, связанные с питанием. Автоматически идет определение подключения внешнего источника питания, определение начала и окончания процесса зарядки, определение слишком низкого уровня заряда аккумулятора. В зависимости от этих ситуаций МК может переключаться в различные режимы.
  3. Если аккумулятор заряжен, внешний БП не подключен, то колонка переходит в основной режим - проигрывание музыки по bluetooth. Включается bluetooth модуль, потом устанавливается средний уровень громкости и включается аудиоусилитель. Ожидаем стабилизации сигнала I2S от модуля, после получения 512 пакетов инициализируем DSP процессор и устанавливаем громкость на 100%. Далее все управление идет по bluetooth с телефона, компьютера и т.д.
  4. Если аккумулятор разряжен то колонка ожидает начала зарядки.
  5. Если проигрывается музыка по bluetooth, то идет анализ полученного потока и работает цветомузыка. Отдельная процедура управляет сложными эффектами. Выделяются три области подсветки - центральный экран, и два круга вокруг основных динамиков. На экране отображаются в случайном порядке различные эффекты, которые начинаются в такт музыки в среднем диапазоне частот. Одновременно над динамиками светодиоды меняют цвет на случайный.
  6. При однократном нажатии второй кнопки меняется режим работы колонки по кругу - Bluetooth, радио, mp3 плейер, USB device.
  7. В режиме радио приемник настраивается на фиксированную стануцию, указанную в прошивке и включается на уровень громкости 60%. Кнопками 4,5 производится поиск радиостанций вниз и вверх.
  8. В режиме mp3 плейер выбирается случайный трек и начинается проигрывание с внутренней sd карты. Кнопками 4,5 можно включать следующий или предыдущий трек.
  9. В режиме USB device проигрываем аудиопоток полученный по USB.
  10. Во всех режима кнопки 3,6 управляют громкостью.
  11. Если подключен внешний БП, то колонка переходит в режим зарядки. На экране отображаются столбиками напряжение и ток заряда.

Инициализация

Инициализация микроконтроллера делается визуальными средствами в STM32 Cube. Используемую периферию и ее настройку ты можешь посмотреть в визуальном редакторе. Перечислим ключевые параметры и опишем зачем они были сделаны именно так, а не иначе:

  • Частота работы микроконтролера - максимальная 168 МГц. Чем быстрее тем лучше.
  • ADC работает на частоте 21 Мгц. Один сэмпл - 84 такта (в связи с большими сопротивлениями на входе ADC). Центральный ADC делает последовательно 6 измерений в непрерывном цикле - получается частота одного измерения около 40 кГц.
  • I2S (SAI) работает на частоте 48 кГц, 16 бит. Используется встроенный PLLI2S на частоте 49.142857 МГц - это позволяет получить 48 Кгц с минимальной ошибкой 0.1%. Так как I2S в зависимости от режима работает на передачу или чтение, а в Cube можно настроить только один, то делаем "хитрый" ход. Настраиваем один режим - генерируем проект. Копируем настройки в свою функцию. Потом настраиваем второй режиме - и опять в свою функцию. В итоге имеем готовый код инциализации для каждого случая.
  • Таймеры. TIM2 - ШИМ управления зарядкой, TIM3 - 96Кгц оцифровка радио в режиме over sampling.
  • I2C1 - управление усилителем, I2C3 - управление радио и балансировкой. Тут настройки стандартные.
  • SDIO - sd карта. Шина 1 бит, частота 48 МГц.
  • SPI2 - управление RGB светодиодами. Частота 2.625 MBit\s - подобрана специально чтобы 3 бита попадали в тайминг управления светодидом.
  • UART3 - 115200, подключен к WI-FI модулю, можно использовать для его прошивки через USB.
  • USB 1 в режиме OTG - чтение флешек.
  • USB 2 в режиме USB device - работа в качестве AUDIO device , mass storage, serial port. Настройки делаются также как с I2S. Включаем один режим - формируем проект, записываем все в функцию и т.д. Очень удобный подход.

При старте идет подготовка всех массивов и настройка радио модуля - тут ничего интересного нет.

Для меньшего потребления тока во время выключения колонки, усилитель звука подключен через P-Mosfet. На самом усилителе стоит около 100 мкФ емкостей с очень низким ESR (керамические кондерсаторы). Поэтому при включении колонки нужно не просто включить данный мосфет, а делать это в режиме PWM с очень короткими импульсами включения. Для выбранного транзистора (IRF9321) подходит режим 3мкс вкл \ 50мкс выкл. Полная зарядка емкостей происходит за 10-20 циклов. Вот программа которая это делает:

  HAL_GPIO_WritePin(spk_reset_GPIO_Port,spk_reset_Pin,GPIO_PIN_RESET);

  CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
  DWT->CTRL = DWT_CTRL_CYCCNTENA_Msk;

  //soft start
  for (int i=0 ; i< 100;i++) {
        GPIOD->BSRR = pvdd_on_Pin;//set PIN
        DWT->CYCCNT = 0; while(DWT->CYCCNT < 500) {}; //3 us
        GPIOD->BSRR = (uint32_t)pvdd_on_Pin<< 16U;//RESET PIN
        DWT->CYCCNT = 0; while(DWT->CYCCNT < 8330) {}; //50 us
  }
  HAL_GPIO_WritePin(pvdd_on_GPIO_Port,pvdd_on_Pin,GPIO_PIN_SET);

В начале выключаем усилитель через вывод RESET (на всякий случай). Далее запускаем таймер отладки (он считает каждый такт, то есть при частоте 168 МГц - около 6нс на одно значение) и используем его для генерации микросекундных задержек. В папке проекта есть моделирование заряда емкостей для этого случая в LT-Spice.

Зарядка аккумулятора

Заряд литиевого аккумулятора довольно сложный процесс. Программа обязательно должна уметь отслеживать различные сбои и во время отключать аккумулятор от процесса зарядки. В противном случае возможно возгорание аккумулятора или выход его из строя. Краткое описание процедуры заряда:

  • ADC постоянно измеряет три показателя: напряжение на аккумуляторе, ток заряда, напряжение на внешнем БП. Измерение происходит на частоте 40кГц. Это слишком много, поэтому к данным измерениям применяется скользящее усреднее с размером окна в 32 сэмпла. Этого вполне достаточно для принятия решений. В процедуре обработки прерывания ADC отрабатываются все "опасные" ситуации зарядки, и в случае их возникновения процесс тут же прекращается. Само управление зарядкой идет в основном цикле.
  • В основном цикле программа простая. Пока напряжение на аккумуляторе не достигло 16.2V (пока нет программы балансировки заряжаю чуть ниже, чтобы не контролировать напряжение на каждой банке) или ток заряда не превышает 2A - повышаем время включения DC-DC через таймер TIM3. Если же наступило превышение - то понижаем. При этом понижение происходит каждые 5мс, а повышение раз в 200мс. Так организуется стабилизация работы DC-DC. PID регулятор не используется.

Посмотрим как это выглядит в коде на Си.

newz = (int32_t)adcbuff[ADC_IBAT]-1468;
newz = newz * 411 * (int32_t) KV / 100;
adcbuff_sr[ADC_IBAT] = get_newsamplewindow_current(newz);

Измеряем значение тока, переводим его в мА. Коэффициенты пересчета предварительно были расчитаны согласно схеме, а потом уточнены прямо в режиме отладки. Это обязательно нужно сделать, так как используются не высокоточные резисторы в делителях. При запуске платы без аккумулятора имеем нулевой ток заряда\разряда аккумулятора. При такой схеме легко посчитать смещение нуля. Для более точного расчета коэффициента усиления необходимо подключить потребитель тока, который мы знаем сразу после шунта. Я включал точно измеренный резистор на 50 Ом к источнику питания 5В (ток 100 мА) и таким образом можно легко уточнить коэффициенты усиления внешнего операционного усилителя. После измерения значение передается в функцию которая осуществляет оконное усреднение и возращает новое усредненное значение тока.

Если идет процес заряда и мгновенный ток (а не усредненный) по какой то причине превысил максимальный ток заряда на 30% - выставляем флаг ошибки и сразу снижаем на 40 единиц ШИМ DC-DC. Частота измерения ADC довольно высокая, поэтому все ошибки прогоняем через фильтр - ошибка должна повторится 10 раз, тогда зарядка будет прекращена, а тип ошибки зафиксирован и будет отображен на экране.

if (mode == MODE_CHARGE) {
   if (newz < -1000) {
       chgte=1; //тип ошибки
       fault=1;
       if (TIM2->CCR3 > 40) {
                TIM2->CCR3 -= 40;

}}}

Аналогично проверяются ошибки на превышение максимального напряжения на аккумуляторе (более 16.8V), и дополнительный контроль на падение входного напряжения ниже 17V.

Процедура в главном цикле, которая контролирует процесс заряда выглядит так:

if (timecharge == 0) {
        if (adcbuff_sr[ADC_VBAT] > 16800) {
                //stop
                TIM2->CCR3--;
                timecharge_numplus=0;
        }
        else if (adcbuff_sr[ADC_VIN] < 17200) {
                //stop
                TIM2->CCR3--;
                timecharge_numplus=0;
        }
        else if (adcbuff_sr[ADC_IBAT] < -2000) {
                //stop
                TIM2->CCR3--;
                timecharge_numplus=0;
        } else {
                timecharge_numplus++;
                if (timecharge_numplus>40) {
                        timecharge_numplus=0;
                        TIM2->CCR3++;
        }
}

В случае возникновения ошибки в процессе заряда выйти из нее можно по нажати кнопки 2 или выключив и включив заново колонку. По окончанию зарядки - когда ток заряда упадет до 50 мА и напряжение на аккумуляторе будет больше 16V, колонка выключается.

Балансировка в текущей прошивке еще не реализована. Плата балансировки может по команде I2C автоматически проводить балансировку на одной ячейке, чье напряжение максимальное. Процесс зарядки нужно поменять на контроль не общего напряжения, а максимального на одной ячейке. При этом если ячейка достигла 4.2В нужно включить балансировку. В следующей версии этот процесс будет реализован. Пока процесс балансировки не работает нужно обязательно контролировать напряжение на ячейках вручную, иначе аккумулятор может выйти из строя, вплоть до самовозгорания! Ячейки в моей сборке оказались очень в хорошем состоянии, без балансировки они работают идеально. Расхождения до сих пор нет.

Цветомузыка

Для цветомузыки используется 90 RGB управляемых светодидов. Расположены они в трех областях: Т-образный экран в центре и два круга на месте динамиков. Для управления светодиодами используется периферия SPI. В этой статье подробно описана методика управления светодиодами. Функция setsvet устанавливает нужный цвет светодиоду с указанным номером. Далее по SPI сформированные данные по всем светодиодам отправляются через DMA режим.

Рассмотрим подробнее как реализована анимация. Начнем с центрального Т-образного экрана. Для удобства работы со светодиодами используется специальный двумерный массив 11х8 элементов, который перекодирует номер светодиода в квадратной сетке экрана в его порядковый номер.

const uint8_t ekrandecode0[8][11] = {
        {0,0,0,1,2,3,4,5,0,0,0},
        {0,0,0,10,9,8,7,6,0,0,0},
        {0,0,0,11,12,13,14,15,0,0,0},
        {0,0,0,20,19,18,17,16,0,0,0},
        {0,0,0,21,22,23,24,25,0,0,0},
        {36,35,34,33,32,31,30,29,28,27,26},
        {37,38,39,40,41,42,43,44,45,46,47},
        {74,73,72,71,70,69,68,67,66,65,64}
};

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

void setsvet_xy(int ekran,int x,int y,cvetstruct cvet) {
        int num;

        if (ekran ==0) {
                if (x > 7) x=7;
                if (y > 10) y=10;
                num = ekrandecode0[x][y];
                if (num==0) return;
                ekranram[x][y] = cvet;
        } else {
                if (x > 1) x=1;
                if (y > 15) y=15;
                num = ekranDindecode0[x][y];
                if (num==0) return;
                ekranDinram[x][y] = cvet;
        }

        setsvet(num+3,cvet.red,cvet.green,cvet.blue);
}

Используется два виртуальных экрана - центральный и круги вокруг динамиков. Второй экран представляется как две линии длиной 16 светодиодов.

const uint8_t ekranDindecode0[2][16] = {
        {63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48},
        {75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90}
};

В основном цикле программы каждые 40мс вызывается функция screenAnimate(), которая отрабатывает следующий шаг анимации экрана. Анимация реализована по следующему алгоритму:

  • каждому эффекту анимации соответствует шаблон (по сути рисунок) размером 11х8, где каждому светодиоду указан номер шага анимации, на котором он должен быть включен
  • дополнительно к шаблону существует структура, которая описывает состояние одного эффекта: скорость, цвет новой точки, координаты центра эффекта и другие параметры
  • одновременно может быть активно не более 10 эффектов
  • под экран выделен массив точек в оперативной памяти (на каждую точку хранится текущий цвет RGB) и каждый вызов функции screenAnimate() яркость каждой точки с ненулевым цветом уменьшается на 10 единиц
  • каждый шаг согласно шаблону, зажигаются новые точки номер которых совпадает с номером шага, а старые гаснут с некоторой скоростью (в итоге имеем эффект плавного затухания и шлейфа)
  • сами шаблоны генерируются в момент определения максимума в музыке. В этот момент определеяется случайный цвет, координаты эффекта и другие его параметры

Данная схема позволяет сделать любое количество шаблонов, анимация которых выглядит очень красиво. Шаблоны также используются для отображения иконок режимов работы колонки.

Разберем как работает определение ритма в музыке.

В качестве представления энергии звука используется сумма всех значений порции данных с I2S взятых модулю.

        for (i=0l;i<N_WAVE;i++) {
                if (musicbuff[i]<0)
                        tekenergy -= (float)musicbuff[i];
                else tekenergy += (float)musicbuff[i];
        }

Таким образом, базовая частота потока данных для цветомузыки снижается с 48кГц до 93Гц. Каждое полученное новое значение энергии проходит через функцию peakdetector, которая на выходе возвращает - обнаружен новый пик или нет. Если пик найден, то генерируется случайный цвет для эффекта, ищется свободный слот (из 10-ти эффектов) и запускается новый эффект.

Функция peakdetector работает чуть сложнее. Сначала накладывается НЧ-фильтр на поток данных с параметром peakA.

        x[1] = peakA * newdata + (1-peakA)*x[0];

Далее накладывается ВЧ-фильтр с параметрами peakB и peakB2.

        y[peakMod-1] = peakB2 * x[1] + peakB * (y[peakMod-2]-x[0]);

После этого данные приводятся к ступенькам - максимум на участке 10 значений (peakMod). И уже после этого определяется пик.

        for (int z=0;z<peakMod-1;z++) {
                y[z] = y[z+1];
        }

        if (nummod % peakMod == 0) {
                float tmpmax=0;
                for (int z=0;z<peakMod;z++) {
                        float tyz = (y[z]>0)?y[z]:-y[z];
                        if (tyz>tmpmax) tmpmax = tyz;
                }
                if (tmpmax < 3) tmpmax = 0;

                zmax[2] = tmpmax;

                if ((zmax[0]<zmax[1]) && (zmax[1]>zmax[2])) {
                        peak = 1;
                }

                zmax[0] = zmax[1];
                zmax[1] = zmax[2];
        }

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

Хочется сказать, что удобнее настраивать все фильтры не на самом микроконтроллере, а в программе Sci-lab (бесплатный аналог matlab). Там можно использовать wav файл как поток данных и графически смотреть результаты работы фильтров. Это сильно ускоряет разработку процедур обработки и анализ данных в музыке. В исходниках вы найдете файлы формата sci-lab и сможете самостоятельно "поиграть" с параметрами.

Управление FM-радио

Для FM радио используется мини модуль на базе чипа tea5767, купленный на aliexpress. Выход у него аналоговый, управление по I2C. Для управления чипом нужно передать последовательно 5 байт данных, в которых определенные биты отвечают за различные команды и режимы. Для получения информации от чипа - читаем 5 байта. Все просто. Хочется отметить, что в такой схеме очень удобно использовать битовые структуры в Си. Вот как выглядит определение структуры на запись данных в чип:

struct
{
        // REGISTER R1
        uint8_t PLL_13_8 : 6;
        uint8_t SM: 1;
        uint8_t MUTE : 1;

        // REGISTER R2
        uint8_t PLL_7_0;                        // PLL[7:0] setting of synthesizer programmable counter after search or preset

        // REGISTER R3
        uint8_t SWP1 : 1;
        uint8_t ML : 1;
        uint8_t MR : 1;
        uint8_t Mono : 1;
        uint8_t HiLo: 1;
        uint8_t SSL: 2;
        uint8_t SUD: 1;


        // REGISTER R4
        uint8_t SI: 1;
        uint8_t SNC: 1;
        uint8_t HCC: 1;
        uint8_t SMUTE: 1;
        uint8_t XTAL: 1;
        uint8_t BL: 1;
        uint8_t STBY: 1;
        uint8_t SWP2: 1;

        // REGISTER R5
        uint8_t R5_dummy :6;                            // Reserved for future extensions; these bits are internally set to logic 0
        uint8_t DTC :1;                         // Reserved for future extensions; these bits are internally set to logic 0
        uint8_t PLLREF :1;                              // Reserved for future extensions; these bits are internally set to logic 0
} TEA5767WriteRegister;

а так выглядит структура на чтение:

struct
{
        // REGISTER R1
        uint8_t PLL_13_8 : 6;           // PLL[13:8] setting of synthesizer programmable counter after search or preset
        uint8_t BLF : 1;                        // Band Limit Flag:if BLF = 1 then the band limit has been reached; if
                                                                // BLF = 0 then the band limit has not been reached
        uint8_t RF : 1;                         // Ready Flag:if RF = 1 then a station has been found or the band limit
                                                                // has been reached; if RF = 0 then no station has been found

        // REGISTER R2
        uint8_t PLL_7_0;                        // PLL[7:0] setting of synthesizer programmable counter after search or preset

        // REGISTER R3
        uint8_t PLL_IF : 7;                     // PLL[13:8] IF counter result
        uint8_t STEREO : 1;                     // Stereo indication:if STEREO = 1 then stereo reception;
                                                                // if STEREO = 0 then mono reception

        // REGISTER R4
        uint8_t Dummy : 1;                      // this bit is internally set to logic 0
        uint8_t CI : 3;                         // CI[3:1] Chip Identification:these bits have to be set to logic 0
        uint8_t LEV : 4;                        // LEV[3:0] level ADC output

        // REGISTER R5
        uint8_t R5Data;                         // Reserved for future extensions; these bits are internally set to logic 0
} TEA5767ReadRegister;

Пользоваться такими структурами очень удобно. Делаем две функции - записать данные и прочиать. Осталось устанавить нужные значения через структуру и записать данные в чип. Вот как выглядит настройка на нужную станцию вместе с функциями чтения и записи.

void tea5767_write(void) {
        HAL_I2C_Master_Transmit(&hi2c3,(uint16_t)0xC0,(uint8_t *)&TEA5767WriteRegister,5,1000);
}

void tea5767_read(void) {
        HAL_I2C_Master_Receive(&hi2c3,(uint16_t)0xC0,(uint8_t *)&TEA5767ReadRegister,5,1000);
}

void tea5767_setfreq_base(uint32_t freq) {
        //106800  in kgz
        uint32_t pll;
        if (TEA5767WriteRegister.HiLo) {
                pll = 4 * 1000 * (freq+225) / 32768;
        } else {
                pll = 4 * 1000 * (freq-225) / 32768;
        }

        TEA5767WriteRegister.PLL_7_0 = pll & 0xff;
        TEA5767WriteRegister.PLL_13_8 = (pll>>8) & 0x3f;

        tea5767_write();
        HAL_Delay(30);
        tea5767_read();
}

void tea5767_setfreq(uint32_t freq) {
        //106800  in kgz
        uint32_t pll;
        int lev1,lev2;

        TEA5767WriteRegister.HiLo = 1;
        tea5767_setfreq_base(freq+450);
        HAL_Delay(30);
        tea5767_read();
        lev1 = TEA5767ReadRegister.LEV;

        tea5767_setfreq_base(freq-450);
        HAL_Delay(30);
        tea5767_read();
        lev2 = TEA5767ReadRegister.LEV;

        if (lev1 > lev2) TEA5767WriteRegister.HiLo = 0;

        tea5767_setfreq_base(freq);
        HAL_Delay(30);
        tea5767_read();
}

При чтении данных важный параметр - показания ADC (качество приема) - LEV. На него нужно ориентироваться при настройке на станцию, он отражает качество приема. Все управление модулем идет в основном цикле, после получения команд с кнопок.

Звук с модуля поступает на входы ADC микронтроллера, оцифровывается и передается по I2S на усилитель. Разберем как это делается.

Оцифровка звука идет на удвоенной частоте для повышения качества - 96 кГц. Далее применяется НЧ-фильтр настроенный на частоту 24 кГц и поток преобразуется к 48 кГц. И только теперь передается на I2S. Ведущем в этом процессе является поток I2S.

ADC непрерывно захватывает данные и помещает их через DMA в кольцевой буфер. Частоту захвата регулирует таймер TIM3 (Все настройки сделаны в STM32Cube - так что вы их легко можете посмотреть в исходниках). Поток I2S непрерывано передается из кольцевого буфера в памяти. Используются два прерывания - половина буфера передана и весь буфер передан. Когда срабатывает прерывание I2S, анализируем счетчик переданных байт DMA потока ADC и определяем в какое место в буфере сейчас пишутся данные. С данного места отсчитываем нужное колво байт назад (в кольцевом буфере ADC) и их передаем на кодирование (фильтр и т.д.). Полученную новую порцию записываем в буфер I2S в начало. В это время на I2S передается вторая половина буфера. Когда она передана, то делаем тоже самое - но перезаписываем вторую половину данных. Частоту работы ADC нужно настроить так, чтобы скорости были максимально равны - это можно сделать расчетным путем или подобрать частоту таймера в отладчике.

Посмотрим код.

void SAI1_halfcomplete() {
        //from usbd_audio_if.c
        uint32_t tekposadc = hdma_adc2.Instance->NDTR;

        convertRadionew(&saibuff[0], tekposadc);
}

void SAI1_fullcomplete() {
        uint32_t tekpos = hdma_adc2.Instance->NDTR;

        convertRadionew(&saibuff[256], tekpos);
}

В прерывании I2S "половина буфера передана" получаем позицию буфера ADC и передаем на конвертацию, перезаписывая начало буфера. Тоже самое в конце.

void convertRadionew(uint16_t* buff,uint32_t tekposadc) {
        //simple decimation //middle
        int pos = (512*2 + 512*2 - tekposadc - 512) % 1024;

        lastdelta = (1024 + lastpos - pos)%1024;
        lastpos = pos;

        for (int i=0;i<256;i=i+2) {
                uint16_t templ=0;
                uint16_t tempr=0;

                templ = filtrleft24(adcradiobuff[pos]);
                pos = (pos + 1) % 1024;
                tempr = filtrright24(adcradiobuff[pos];
                pos = (pos + 1) % 1024;
                templ += filtrleft24(adcradiobuff[pos]);
                pos = (pos + 1) % 1024;
                tempr += filtrright24(adcradiobuff[pos]);
                pos = (pos + 1) % 1024;

                buff[i] = (templ-2040);
                buff[i+1] = (tempr-2040);
        }
}

При обработке буфера отдельно обрабатываем левый и правый канал. Размер буфера ADC в два раза больше. Переменная lastdelta позволяет получить колво отсчетов ADC за время срабатывания прерывания - оно должно быть максимально приближено к 512, тогда потоки будут работать синхронно. В отладчике легко сделать это меняя ARR таймера 3. Код фильтров удобно брать из программы WinFilter. Используется IIR фильтр 2 порядка. Громкость увеличивать смысла нет - это можно сделать с помощью громкости усилителя. Отметим последние две строки - вычитаем 2040. Это необходимо для получения знакопеременного потока данных - по сути вычитаем среднее значение потока данных. Так как у нас в схеме не используются точные резисторы, то это значение нужно вычислить для каждого канала отдельно в отладчике измеряя среднее потока за длительный интервал - 10 секунд.

Работа с USB Device

Колонка может подключаться по micro USB разъему к компьютеру и работать при таком подключении в трех режимах: audio device, UART, mass storage (предоставляя доступ к внутренней флешке). На данный момент реализован только режим audio device. Остальные режимы несложно дописать самостоятельно. С audio device тоже все несложно. Но все же напишу несколько слов. Вся настройка делается средствами STM32 cube. В статье описано как все это работает. Единственное что нужно дописать после инициализации - связку USB и I2S. Как это сделать? Разберемся подробнее.

Вся работа ведется в файле "usbd_audio_if.c". В этом файле есть уже ряд готовых функций, в которые нужно дописать код. Первая функция: "AUDIO_AudioCmd_FS", она вызывается при получении команд по usb протоколу. Нам нужны команды START и PLAY:

static int8_t AUDIO_AudioCmd_FS(uint8_t* pbuf, uint32_t size, uint8_t cmd)
{
  /* USER CODE BEGIN 2 */

        if (mode != MODE_USBAUDIO) {
                return (USBD_OK);
        }

        switch(cmd)
        {
                case AUDIO_CMD_START:
                HAL_SAI_Transmit_DMA(&hsai_BlockA1,pbuf,size);
                break;

                case AUDIO_CMD_PLAY:
                HAL_SAI_Transmit_DMA(&hsai_BlockA1,pbuf,size);
                break;
        }

        return (USBD_OK);
  /* USER CODE END 2 */
}

При получении этих команд нужно передать указанный буфер на I2S через DMA, что и делаем. Для синхронизации потока USB и I2S необходимо вставить специальные вызовы из прерываний полученных при передаче половины буфера и полного буфера I2S. Добавляем вызовы из прерываний и туда прописываем нужные функции.

void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
{
  /* Manage the remaining file size and new address offset: This function
     should be coded by user (its prototype is already declared in stm32446e_eval_audio.h) */
if (mode == MODE_USBAUDIO) {
        TransferComplete_CallBack_FS();
} else {
        SAI1_fullcomplete();
}
}

Как видно по комментарию, Пример работы с USB audio есть в документации к плате stm32446e_eval. Многое взято оттуда. Так как у нас I2S (он же SAI) используется не только в USB режиме, то проверяем это и вызываем нужные функции. Аналогично поступаем с половиной буфера.

void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
{
  /* Manage the remaining file size and new address offset: This function
     should be coded by user (its prototype is already declared in stm32446e_eval_audio.h) */
  if (mode == MODE_USBAUDIO) {
                HalfTransfer_CallBack_FS();
        } else {
                SAI1_halfcomplete();
        }
}

На этом настройка USB AUDIO закончена. Подключаем колонку, появляется звуковое устройство - проигрываем через него файл и наслаждаемся музыкой. Дополнительно отмечу, что при работе с USB активно используются динамические буферы, поэтому нужно в настройках STM32 cube увеличить размер heap и stack. Также, в этом файле можно вставить команды управления громкостью, но я этого делать не стал.

Как сделать колонку своими руками

Если ты решил сделать себе такую же колонку, то необходимо прочитать полную версию этой статьи, купить все необходимые компоненты и инструменты. Выделить побольше времени. Будет непросто, но очень интересно. Это один из сложных проектов на этом сайте. Если у тебя нет отпыта - то лучше начать с более простых приборов.

В файле приложенном к статье BOM.xls ты сможешь найти полный перечень компонент, чтобы оценить то, что нужно будет купить.

Самостоятельная работа

На текущий момент еще не все задумки реализованны в прошивке, так что тебе будет чем заняться. Итак, чего еще нет (но возможно скоро появится):

  • mp3 плейер пока не готов, разработка ведется (есть процедура чтения и декодирования файла)
  • цветомузыка - бесконечное расширение эффектов, задействование преобразования фурье для анализа частот
  • управление по Wi Fi - смена различных режимов работы DSP, управление плеером, анализ показателей колонки (есть пример общения с Wi-Fi модулем)
  • процесс зарядки с учетом балансировки (есть пример кода получения данных с платы балансировки)
  • FM-радио - сейчас реализован пример прослушивания радио на одной фиксированной радиостанции и поиск каналов
  • USB-device - не реализованы режимы копирования файлов на SD карту по usb и usb serial

Как ты видишь - проект очень большой, и тебе точно будет чем заняться. Это же твоя колонка! Сделай себе такую же, реализуй нужные тебе функции. Получи уникальный продукт высочайшего качества.

Read 4782 times