Сразу о главном. Качество звука близко к уровню Hi-End. Нелинейность амплитудно-частотной характеристики в полосе частот от 15 Гц до 30 кГц не более 5 %. Динамический диапазон - не менее 105 Дб. Эффективная выходная мощность - 80 Вт. Отношение сигнал-шум не менее 90 Дб. И что там еще? Да! Губозакаточная машинка идет в комплекте!
Друзья, привет!
Как вы уже поняли, я продолжаю выжимать соки из очень доступных и очень интересных микроконтроллеров из Китая - CH32 на архитектуре RISC-V. Чем дальше я погружаюсь в их архитектуру, тем больше слов благодарности мне хочется сказать разработчикам. Да, они взяли и скопировали архитектуру STM32! Но как скопировали! Творчески! Не постеснявшись впихнуть в наидешевейшие чипы функции от старших братьев STM. Спасибо им за это!
Еще в прошлый раз я упоминал о том, что в моем подопытном CH32V003J4M6, который привлекает меня своим минимализмом, обнаружился встроенный операционный усилитель (ОУ), выход которого может быть связан со входом АЦП. То есть, при необходимости, его можно использовать для усиления или фильтрации сигналов перед под подачей на АЦП. К сожалению, усилитель не обладает программируемым коэффициентом усиления, в отличие, например, от ОУ, встроенного в STM32F300 или STM32G4. Это значит, что его характеристики полностью определяются внешними цепями, но и на том спасибо!
Еще одна вещь, которая несомненно заслуживает внимания - это таймеры микроконтроллера с продвинутыми функциями управления, такими же как и у STM-ов. Здесь мое внимания привлекла возможность управления комплементарными каналами силовых цепей для управления источниками питания, двигателями и другими подобными устройствами, требующими противофазного ШИМ-сигнала. В частности, усилителями класса D!
Так, стоп! Это что же получается? Внутри цифрового, на минуточку, микроконтроллера есть полный набор для создания настоящего усилителя! В самом деле - усилить слабый сигнал, сделав необходимую частотную коррекцию можно? Можно! для этого есть ОУ. Выдать сигнал управления для комплементарного каскада усилителя мощности можно? Можно! Для этого есть таймер. Остается соединить эти два узла между собой при помощи АЦП и мы получаем практически настоящий усилитель мощности класса D! Ну еще пару MOSFET-транзисторов добавить... Ну это так, мелочи! И руки сразу зачесались...
Проектируем усилитель на микроконтроллере CH32V003J4M6
Задачи воспроизведения звука, записанного на флеш-память ваш покорный слуга решал уже неоднократно. Решал даже на этом микроконтроллере.
Но, там звук был, с вашего позволения, так, для галочки. Уже одно то, что 8-битный о многом говорит. А можно ли сделать что-то более путевое? Давайте попробуем. На пути создания усилителя класса D нас ждет несколько задач:
- Звук нужно усилить, доведя его до максимального размаха, чтобы повысить эффективность аналого-цифрового преобразования;
- Звук нужно оцифровать, переведя его из аналоговой в цифровую форму;
- Звук нужно преобразовать в комплементарный (2-канальный с противоположной фазой) ШИМ-сигнал;
- ШИМ-сигнал нужно "раскачать" до требуемой мощности при помощи комплементарного каскада;
- Наконец, ШИМ-сигнал нужно пропустить через фильтр, восстановив исходную форму звукового колебания.
На первый взгляд ничего сложного нет, но, как обычно, дьявол кроется в мелочах. Вот о них дальше и пойдет речь.
Хотел бы сразу оговориться. Я делаю этот проект не для того, чтобы создать высококлассный усилитель. Нет! Я решаю простую задачу - разобрать китайские контроллеры до "исподнего". Сделать это можно только на достаточно амбициозных задачах практического характера. Такие задачи я обычно и выбираю для удовлетворения своей творческо-исследовательской потребности.
Поехали...
Усиливаем звук. То есть, создаем предварительный усилитель. Попробуем для этой цели использовать встроенный операционный усилитель.
Так, стоп! Мужчина в среднем ряду! И еще молодой человек в бейсболке. Что вы говорите? ОУ в цифровом микроконтроллере? Помехи? Так. Покиньте, пожалуйста, аудиторию! Вам в класс меломании или мыломании или еще какой мании... У нас тут серьезные дела. Продолжаем.
Итак ОУ в микроконтроллере подключен к 3-м выводам. Примерно вот так.
Как видно, ОУ занимает сразу 3 ножки контроллера. И все их придется задействовать, охватывая ОУ отрицательной обратной связью, задающей коэффициент усиления и цепями смещения среднего уровня. ПОследние нужны потому, что встроенный АЦП не умеет оцифровывать отрицательные значения напряжения. Шкала только положительная. Значит уровень сигнала надо приподнять на половину шкалы.
Три ножки не всегда себе можно позволить! В предыдущем проекте, в котором я делал устройство записи-воспроизведения звука я, например, этого позволить себе не мог, поэтому пристраивал внешний операционник. Сейчас я такой необходимости не усматриваю, поэтому смело буду пользоваться встроенными возможностями. Заодно и разберусь что там к чему!
Это интересно! В старших STM32 (например, серии STM32G4) встроенные ОУ уже внутри охвачены управляемой обратной связью, позволяющей управлять их усилением. Тогда можно было бы обойтись и одной ножкой, на которую подавать сигнал. Но у нас такой функциональности нет, к сожалению.
Что по усилению? Предположим, что сигнал мы будем подавать с линейного выхода компьютера или телефона. Амплитуда сигнала на таком выходе обычно не превышает 1 Вольта (размах 2 Вольта) и регулируется. Значит, чтобы усилить сигнал с размаха 2 Вольта до размаха 5 Вольт, нужен коэффициент усиления 2,5. Но, чтобы не держать громкость на максимуме, увеличим усиление в несколько раз. Пусть будет 10 раз. Тогда полный размах мы получим на 25% уровня сигнала.
Еще один вопрос - позволяет ли ОУ усиливать сигнал до полного размаха? То есть, является ли он rail-to-rail усилителем? С высокой долей вероятности - да. Иначе зачем он такой нужен! Чтобы не использовать всю шкалу АЦП? Но, кто его знает этих китайцев (не-не, они молодцы)! Придется выяснить экспериментально. Надеюсь, что будет не хуже, чем в STM.
Аналого-цифровое преобразование. Тут все посложнее. Дело в том, что в классических усилителях класса D этого этапа нет. ШИМ сигнал сразу формируется с высокой частотой: сотни килогерц и даже мегагерцы. Но у нас такой возможности нет. И дело тут не в самом АЦП, который, кстати может оцифровывать сигнал с частотой около Мегагерца, а в возможностях ШИМ. Сейчас поясню подробнее. Но для понимания потребуется несколько этапов.
Этап 1. Разрядность АЦП нашего микроконтроллера составляет 10 бит, или иными словами 1024 уровня. Это не много. Современные массовые аудиокарты имеют разрядность 16 бит (около 65000 уровней). То есть точность, с которой мы можем оцифровывать сигнал не так велика (про HiFi речь точно не идет). Точность можно повысить увеличив частоту дискретизации. Увеличение частоты в 4 раза позволяет добавить 1 разряд. Но, нам такой метод не подойдет и вот почему...
Этап 2. ШИМ-сигнал (сигнал одной частоты, но с изменяющейся шириной импульса) в микроконтроллере формируется при помощи таймера. Счетчик таймера считает с определенной частотой. В начале счета на выходе таймера, устанавливается высокий уровень, но как только счет достигает значения, записанного в специальный регистр, уровень устанавливается низкий. Для того, чтобы иметь возможность представить оцифрованный сигнал в виде ШИМ, нам потребуется счетчик на 1024 такта (10 разрядов АЦП). Зная этот факт можно выяснить, с какой частотой нам нужно будет оцифровывать входной звуковой сигнал. Предположим, что счетчик считает с максимальной тактовой частотой процессора (такая возможность есть) - 48 МГц. Тогда периодичность ШИМ-сигнала будет 48000000 / 1024 = 46875 Гц или примерно 47 кГц. Это частота дискретизации входного сигнала и частота ШИМ одновременно. Не густо! Напомню, что в реальных усилителях класса D это сотни килогерц по-меньшей мере. Такую частоту легко отфильтровать. Мы же получили 47 кГц для 10 разрядов. А если увеличить на 1 разряд? Тогда получим 48000000 /2048 = 23438. Уже близко к верхней границе звукового диапазона. Фильтровать будет сложно - раз, да и эффективная полоса звука, которую можно передать в этом случае не превысит (по теореме Котельникова) 10...11 кГц - два. Маловато...
Ну да ладно. Остановимся на том! Итак. Выбираем точность дискретизации сигнала - 10 бит и частоту дискретизации - 46875 кГц. По предварительным расчетам, если настроить фильтр на срез 15...16 кГц, то можно получить подавление ШИМ-сигнала около 18...20 дБ. Не густо, но, что есть. Надеюсь сильно на качестве не скажется, т.к. частота 46 кГц все равно уху не слышна!
Формирование комплементарного ШИМ-сигнала. Похоже тут можно выдохнуть. В микроконтроллерах CH32V003 есть продвинутый таймер - TIM1. Он обладает, поистине, колоссальными возможностями, к которым можно отнести и способность решения нужной нам задачи. Но сначала пару слов о том,зачем все это нужно.
Комплементарный ШИМ-сигнал предназначен для управления нагрузкой при помощи мостовых и полумостовых схем. В простейшем случае комплементарный каскад применительно к усилительной технике выглядит следующим образом.
Два транзистора попеременно открываются сигналами противоположной полярности (комплементарный сигнал). Когда открыт верхний, нижний закрыт, индуктивность и емкость фильтра накапливают заряд через верхний транзистор и нагрузку. Когда открывается нижний, а верхний закрывается, индуктивность и емкость отдают заряд через нижний транзистор и нагрузку.
Кстати, эту схему правильно было бы назвать полумостовой, а не комплементарной. В комплементарной все же используются транзисторы разной проводимости. А вот относительно сигналов - все правильно! Сигналы управления можно назвать комплементарными.
Достоинство схемы - высокий КПД и низкие искажения относительно несимметричных схем. Но есть один нюанс и он самый главный!
Представьте, что случится, если транзисторы окажутся открытыми одновременно! Через них пойдет большой ток от источника питания (сопротивление исток-сток очень маленькое), который их может спалить к такой-то... Ну вы поняли. Это может произойти если один транзистор еще не успел закрыться, а второй уже открылся. И для этого есть все условия. Время закрывания транзистора обычно больше, чем время открывания. Приплыли...
Приплыли бы, если бы не разработчики чипов управления. Которые настраивают управляющие контроллеры так, что сначала закрывается один транзистор и только спустя время открывается другой. Этот временной промежуток носит название "защитный интервал". Такой защитный механизм предусмотрен и в продвинутом таймере (advanced timer) TIM1 нашего контроллера. Вот как это описывается в справочном материале.
На рисунке наглядно видно, что исходный шим сигнал вначале выключает выход OCx и только спустя время задержки delay (настраиваемое, кстати), включает выход OCxN (N - negative, отрицательный).
В общем, за нас уже все придумали и остается только воспользоваться! Шикарно! Та-а-а-ак, какие выводы будем использовать?
Как холодным душем меня окатило когда я посмотрел на структуру выводов 1-го таймера. Внимание! Барабанная дробь...
Как вам? Уловили тонкий юмор китайских разработчиков? Единственная пара комплементарных выводов 1-го таймера (подчеркнуто красным) занимает те же выводы, что и операционный усилитель (синим)! Хорошо, может быть можно комплементарные сигналы взять с разных каналов? Не, нельзя! Китайцы позаботились, потому как единственный "выручательный" канал 1-го таймера T1CH3N оказался, вы будете смеяться, на 8-м выводе, где у нас висит операционный усилитель! Так-то можно было бы его с любым каналом на 7-м выводе попробовать использовать, да не судьба!
Так что, все? Нет, категорически! Начинаем творить по-настоящему!
Решение номер 1. Не использовать комплементарные сигналы, но использовать комплементарные транзисторы (разной проводимости). Я что-то подобное делал в статье про воспроизведение звука на ATtiny13.
Там получилась вот такая схема.
Входные цепи из диодов и резисторов позволяют сделать процесс закрывания транзистора быстрым, а открывания медленным. Можно и так, но мы же контроллер изучаем, а не схемотехнику усилителей! Думаем дальше...
Решение номер 2. Вообще, на оставшихся выводах нам доступен второй таймер - TIM2, а точнее два его канала T2CH2 на 6-м выводе и T2CH4 на 5-м. Что если попробовать сформировать комплементарный сигнал с необходимыми задержками при помощи создания ШИМ разной полярности на этих каналах? Хорошо, думаем в этом направлении.
Сразу отметается несимметричный ШИМ (когда уровень фронта устанавливается в момент начала счета). Здесь установка 1 или 0 будет происходить одновременно. Задержку по фронту не сделать. А вот если использовать симметричный ШИМ, тогда можно устанавливать (или снимать) уровни каналов в нужной последовательности. Как-то так.
Для получения такой картины достаточно в регистр сравнения, который определяет длительность в 4-м канале всегда заносить немного большее значение и не забыть инвертировать сам сигнал. На рисунке период ШИМ равен 10. Регистр сравнения 2-го канала - 4. Регистр сравнения 4-го канала - 5. Получилось похоже на рисунок из даташита!
Теоретически запрограммировать контроллер для такого режима работы несложно, но, не трудно заметить, что частота ШИМ снизилась в 2 раза. Ведь теперь, для формирования нужного сигнала потребуется два периода ШИМ. Это плохо (с грустью вспоминаю теорему Котельникова).
Стоп! А что если снизить разрешение ШИМ с 1024 до 512 уровней? Да, но это значит и снижение разрядности с 10 до 9 бит! Теряем целых 512 уровней! Ну почему теряем? В первом такте ШИМ будет 512 и во втором тоже 512. Да, всего 1024, но из-за осевой симметрии сигнала доступны нам будут все равно только 512 уровней. Можно либо увеличить на 2, либо уменьшить на 2. Верно! Но только, если мы не сможем менять значение в регистре сравнения в момент смены номера такта. А мы сможем? Да!!! Главное его заранее подсунуть в буфер регистра сравнения (во время предыдущего такта), а механизм буферизации (классная штука) сам изменит его в момент апдейта счетчика (вертикальные штрихи сверху рисунка). Это происходит, кстати, каждый такт вне зависимости от вида ШИМ. Проверено экспериментально!
Что, выкрутились? Да. Но не совсем. Что-то еще? Да, есть маленько! Дело в том, что все это хорошо работает только если микроконтроллер работает как часы. А если в нем что-то сломается, сбойнет? Прощай транзисторы? Хм... А для защиты от таких случаев в микроконтроллере предусмотрен алгоритм аварийного аппаратного останова, который при малейшем сбое отключает аппаратные выводы таймера. Беда вот только в том, что поддерживает этот механизм только 1-й таймер! Ладно! Где-то надо остановится. Я решил здесь. В смысле того, что сделаю допущение, что вероятность сбоя микроконтроллера в лабораторных условиях составляет бесконечно малую величину!!!
Раскачка мощности ШИМ-сигнала. Фильтрация. Собственно об этом уже попутно много было сказано. Для усиления сигнала по мощности используем полумостовую схему из двух MOSFET-транзисторов одинаковой полярности, на которую заведем наши комплементарные, защищенные сигналы.
Фильтрация ШИМ-сигнала будет осуществляться стандартным LC-фильтром Баттерворта 2-го порядка, настроенного на передачу максимальной мощности в низкоомную нагрузку. Из-за настройки по критерию передачи максимальной мощности (не напряжения) эффективность таких фильтров чуть ниже чем потенциальная. 8...10 децибелл на октаву вместо 12. Поэтому частоту ШИМ и выбирают в сотни килогерц. Но, 47 килогерц тоже неплохо. По-крайней мере, далеко за гранью слышимости. Поэтому неполная фильтрация ШИМ-сигнала не должна существенно сказываться на качестве звука.
Все, рассуждений достаточно! Переходим к делу.
Схемотехника и конструкция усилителя на микроконтроллере
Схема устройства получилась несложной.
1-я, 3-я и 8-я ножки микроконтроллера - это выводы операционного усилителя. Входной сигнал подается на инвертирующий выход. Коэффициент усиления (примерно 10 раз) определяется делителем на резисторах R1, R2 в цепи обратной связи. На положительный вывод ОУ при помощи делителя R3, R4 подается половина напряжения питания (смещение нулевого уровня).
Схема рассчитана на питание от литий-ионного аккумулятора, подключающегося к разъему H3. Конденсаторы C4, C5 защищают усилитель от импульсных помех по питанию.
Предусмотрен и разъем для программирования микроконтроллера - H4. А еще я на, всякий случай, предусмотрел кнопку KEY1. Мало-ли, думаю, потребуется какие-нибудь режимы переключать в экспериментах. Пока она не задействована.
Выходной каскад собран по полумостовой схеме с фильтром Баттерворта 2-го порядка на элементах L1, C2. Частота среза фильтра около 15 кГц. Подавление на частоте ШИМ-сигнала (47 кГц) должно по моим прикидкам составить 5...7 раз. То есть с 4 Вольт размаха до 0,5...0,8 Вольта. 8-омный динамик подключается к разъему H2. Транзисторы SI2302 недорогие и достаточно быстрые держат ток до 2 Ампер. Этого вполне достаточно. Если совсем по-уму делать, то в цепь питания можно поставить быстрый предохранитель на 1 Ампер, чтобы защитить схему от сквозных токов при сбоях микроконтроллера.
Забегая немного вперед, как я только не издевался над усилителем, мне не удалось сжечь выходные транзисторы! Ток заряда затворной емкости ограничивается резисторами R5, R6. А резисторы R7, R8 служат для разряда этой самой емкости, которая может запоминать заряд и при включении открывать транзистор (выводы контроллера при включении находятся в отключенном (высокоимпедансном) состоянии), поэтому затворная емкость будет определять, закрыт транзистор или открыт.
Кстати, анализ характеристик транзисторов позволил определить время задержки между их переключениями.
Из таблицы видно, что наибольшее время у транзистора уходит на закрывание. Turn-off delay time + Fall time = 60 наносекунд (максимум). За это время второй транзистор на должен открыться. Если таймер работает с частотой микроконтроллера - 48 МГц, то длительность одного такта счета составит 1/48000000 = 21 нс. Значит, задержка при переключении должна составить примерно 3...4 такта. После этого можно открывать второй транзистор.
Для изготовления и экспериментов я изготовил небольшую печатную платку. Плата односторонняя. Всего одна перемычка!
Плата в формате SprintLayout 6.0 доступна для скачивания в архиве, приложенном в конце статьи.
Вот такая она получилась в натуре.
Есть пару отличий от чертежа. Я сначала забыл установить затворные резисторы. Пришлось подпаивать задним числом. И еще на плате есть возможность смешать два входных канала в один. В архиве плата правильная.
А вот так усилитель выглядит в сборе.
Дроссель намотан на 8-миллиметровой гантельке проводом, диаметром 0,4 мм. Количество витков не считал. Намотал побольше и постепенно отматывал пока не получилось 120 мкГн. Высокая точность тут не столь важна. На входе стоит стандартное гнездо под 3,5-миллиметровый аудио-джек. Выходной конденсатор я поставил на 470 мкФ (на схеме - 100 мкФ). Чем больше, тем более низкие частоты должен воспроизводить усилитель. Но здесь разница тоже существенной не будет.
Перемычка оранжевого цвета - жилка от витой пары.
Программное обеспечение и испытания усилителя
Софт, как и ранее написан на Си, в среде VS-Code с установленным расширением PlatformIO. Подробнее об этом я рассказывал здесь.
Сама программа очень проста. Ее основной цикл пустой. Вся основная работа осуществляется в прерывании таймера TIM2. Каждый цикл ШИМ поделен на две фазы. В одной фазе происходи опрос АЦП, вычисление длительности импульса ШИМ и загрузка в регистр сравнения первой части импульса. Во вторую фазу происходит загрузка второй части импульса. Глобальная переменная pwm_first (хранит длительность первой фазы) явно избыточна, но оставлена исключительно для наглядности кода.
Вообще я люблю подробно комментировать код. Для себя очень полезно! Полагаю, что не составит большого труда разобраться с принципом работы программы по моим комментариям. Но, если будут вопросы - пишите, я помогу. Сам код программы будет так же размещен в архиве в конце статьи.
В начале программы стоит 5-секундная задержка до момента когда усилитель включается. Дело в том, что конфигурация выводов микроконтроллера делает его последующую прошивку невозможной. Задержка в начале программы (спасибо подписчику, который подсказал идею !!!) оставляет достаточно времени для перехвата процедурой прошивки внимания контроллера. Пяти секунд вполне достаточно, чтобы подключить контроллер к программатору и запустить процесс прошивки.
В настройке усилителя мне очень помог логический анализатор. Прежде всего, еще не запаивая выходной каскад, я при помощи анализатора убедился, в корректности своих расчетов и правильности функционирования софта. Вот так выглядели реальные временные диаграммы с выходных каналов таймера.
Если присмотреться, то можно увидеть ту самую задержку, которая не дает транзистором ни шанса открыться одновременно.
Только после отладки кода я уже допаял усилитель мощности с фильтром и приступил к испытаниям. Вот испытательный комплект.
Знакомый аккумулятор от вейпа. Вообще, я сам не курю, но прошу всех знакомых вейпы не выбрасывать! Хорошие аккумуляторы. Иногда даже восстанавливать не приходится! Динамик 8 Ом, 3 Ватта из дешевой китайской серии. Звук выдает как из бочки, но другого у меня нет, к сожалению.
Для испытаний я просто заводил сигнал с линейного выхода компьютера на свое устройство и смотрел осциллограммы. Приведу парочку. Лучше было бы конечно использовать генератор. Сигнал с компьютера довольно сильно зашумлен и содержит импульсные помехи. Ну да я ведь не HiFi технику создаю! Кстати, в конце статьи будет ссылка на видеоклип с демонстрацией работы усилителя.
На входном гармоническом сигнале хорошо заметны и шумы и импульсные помехи. Видно, что щуп осциллографа подключен к входному разъему.
А вот так выглядит сигнал на выходе.
Синусоида зашумлена частотой ШИМ. Можно заметить, что ее размах примерно 500 мВ. Тут мои предсказания подтвердились даже избыточно! Это неплохой результат, тем более, что эта частота (47 кГц) находится далеко за гранью слышимости.
А так выглядит синусоида на выходе микроконтроллера. Кстати, если это подать на динамик, то звучит уже очень неплохо!
Собственно, как звучит можно послушать в клипе, который я выложил в нашу группу в ВК-Видео.
И конечно, в завершение выкладываю обещанный архив со всеми материалами, необходимыми для повторения.
Что хотелось бы сказать в заключение. Усилитель мне понравился. Профессиональные решения он не заменит хотя бы из-за небольшого количества уровней квантования, но для радиолюбительских самоделок - вполне! Ну а главное, это конечно же не усилитель, а то, что мы с вами, дорогие читатели стали еще на один шаг ближе к разгадке тайны китайских микроконтроллеров серии CH32!
Спасибо, что читаете-смотрите Terrabyte! Подписывайтесь, если вам интересна радиолюбительская тематика, микроконтроллеры, мини-ПК, необычные компьютерные решения и инновационные разработки! Спасибо всем, кто поддерживает нас с братом своими комментариями и лайками!
Наша группа ВК: https://vk.com/terrabyte
Наш канал на VK-Video: https://vk.com/video/@terrabyte/all
Наши разработки: