Разработка buck-преобразователя на STM32F334: принцип работы, расчеты, макетирование

  • Tutorial
В двух своих последних статьях я рассказал о силовом модуле и плате управления на базе микроконтроллера STM32F334R8T6, которые созданы специально для реализации систем управления силовыми преобразователями и электроприводом. Так же был рассмотрен пример DC/AC преобразователя, который являлся демонстрацией, а не завершенной конструкцией. Теперь пришло время сделать что-то простое, но полезное, а главное завершенное.

Большинство вопросов, касающихся проекта и силовой электроники, связаны с конкретными топологиями: кому-то интересно узнать алгоритм управления PFC, кому-то хочется научиться строить LLC полумост, но наиболее популярная топология — это несомненно buck. Ведь buck-преобразователь (он же buck converter) является основной для большинства интересных проектов: это и драйвер для LED светильников, и основа MPPT контроллера для солнечных панелей, и зарядные устройства и вообще много чего еще.

В сети достаточно много информации по buck, в том числе и даташиты, но она разрозненна и мне лично не встречался материал, где подробно описан процесс создания buck-преобразователя с цифровым управлением. Пора это исправить. Математики практически нет, объяснения «на пальцах», поэтому будет интересно всем, кто хоть как-то связан с электроникой.



Введение


Для начала нужно понять, что мы хотим получить в итоге и какие вводные у нас есть. Топология buck является понижающей, то есть позволяет построить понижающий преобразователь напряжения. Как вы увидите далее напряжение на выходе buck-преобразователя практически линейно зависит от напряжения на входе, поэтому необходимо добавить обратную связь. Сегодня я расскажу о простой обратной связи по напряжению (voltage mode), которая является наиболее наглядной и позволит вам понять принцип работы, при этом такой обратной связи вам хватит для реализации большинства задач.

В конце статьи мы получим работающий стабилизированный источник напряжения по топологии «синхронный buck», работающий на достаточно высокой частоте с цифровым управлением, реализованным на STM32F334R8T6 с применение High Resolution PWM (HRPWM). Диапазон входного напряжения — 15...60В, выходное напряжение — 12В, максимальный выходной ток — 2А.

Глава 1. Принцип работы топологии buck


Начну я рассказывать начиная с самых основ и постепенно будем улучшать наш преобразователь, т.к. «синхронный buck» это версия улучшенный вариант с повышенными КПД и сложностью управления. Базовый вариант топологии, который вы наверняка использовали, выглядит следующим образом:



Данная топология используется в маломощных преобразователях напряжения, например, для питания цифровых схем и прочих маломощных приборов. Понижающие dc/dc, которые вы применяете в своих устройствах наверняка реализованы на микросхемах по данной топологии. Пример такой микросхемы LMR16006.

Принцип работы у данной схемы очень простой, на транзистор VT1 подается ШИМ сигнал, сама работа разделяется на 2 этапа, которые чередуются друг за другом:

  • Стадия накопления энергии в LC-контуре. На данном этапе транзистор VT1 открыт и ток протекает через транзистор в нагрузку, попутно накапливая энергию в катушке индуктивности и выходной емкости:

  • Стадия разряда. На данном этапе транзистор VT1 закрывается и тут начинается самое интересное. Дроссель — эта такая штука, которая накапливает энергию если к нему приложить потенциал (открыть VT1) и отдает ее, если потенциал пропал (VT1 закрыли). При этом он стремится не просто отдать энергию, а сохранить значение тока и его направление, поэтому чтобы использовать данное свойство нужно добавить диод VD1, чтобы замкнуть цепь, ведь ток протекает только в замкнутой цепи:


Когда классе в 6-7м я познакомился с данной топологией, то не понял сразу почему диод не проводит ток на 1-й стадии, сейчас это кажется банальным, но думаю стоит упомянуть. Когда VT1 открыт, то на катод диода VD1 прикладывается потенциал +VIN, например, +20В, а на аноде диода соответственно потенциал земли. Чтобы ток через диод протекал должно быть ровно наоборот: потенциал на аноде должен быть больше потенциала на катоде, поэтому в buck-е на стадии накопления энергии диод «закрыт». На стадии разряда диод уже замыкает цепь, на его катод не действует потенциал +VIN и не «запирает» его. Надеюсь понятно объяснил.

Тут у вас должен был возникнуть вопрос: «А какое напряжение будет на выходе, если мы подали на вход 20В?». Как всегда все просто:



Как видно из формулы напряжение на выходе линейно зависит от коэффициента заполнения (duty) ШИМ сигнала, который мы подаем на транзистор VT1. Если кто-то не знает или забыл «коэффициент заполнение (duty)» — это отношение времени, которое транзистор находится в открытом состояние к длительности периода. Данный коэффициент может принимать значение от 0 до 1 или от 0 до 100%. Дальше мы будет оперировать именно этой цифрой при управление преобразователем, но для понимая сути давайте подставим это отношение в формулу:



Частота работы buck-преобразователя величина постоянная и выбирается при проектирование, в процессе работы она не меняется, а значит и период (T) величина постоянная. Получается, что выходное напряжение напрямую зависит двух физических величин:

  • от времени на которое мы открывает верхний транзистор (VT1) — чем дольше он открыт, тем больше энергии успевает накопиться в LC-фильтре и соответственно выше напряжение на выходе;
  • от входного напряжения, например, если мы зафиксировали заполнение на 50% и меняем Vin от 20 до 40В, то на выходе напряжение будет так же меняться от 10 до 20В.

Я думаю у вас начала прорисовываться общая картина и принцип работы, давайте теперь ее закрепим и посмотрим на реальные осциллограммы и проверим данное соотношение на практике. У меня собран макет buck-а, который нагружен светодиодом на 10 Вт. Я задействовал 3 канала осциллографа, которые включены в следующие точки:



Опыт №1 — Входное напряжение (Vin) постоянное 20В, изменяется коэффициент заполнения

  • Vin = 20V, D = 25%, Vout = D * Vin = 0,25 * 20V = 5V

  • Vin = 20V, D = 50%, Vout = D * Vin = 0,5 * 20V = 10V


Как вы можете видеть на осциллограммах — соотношение между выходным напряжение и коэффициентом заполнения верное. Конечно же это был «идеализированный» эксперимент, в реальности напряжение на входе не бывает стабильным и плавает в достаточно широком диапазоне. Давайте теперь посмотрим какова будет зависимость от входного напряжения при фиксированном заполнении.

Опыт №2 — Входное напряжение (Vin) изменяется, коэффициент заполнения постоянный и равен 50%

  • Vin = 15V, D = 50%, Vout = D * Vin = 0.5 * 15V = 7.5V

  • Vin = 20V, D = 50%, Vout = D * Vin = 0.5 * 20V = 10V

  • Vin = 30V, D = 50%, Vout = D * Vin = 0.5 * 30V = 15V


Теперь мы на практике убедились, что выходное напряжение так же линейно зависит от входного при фиксированном коэффициенте заполнения. Поняли уже как будет стабилизировать выход? Принцип стабилизации простой как сама формула — Vout равно 12В и константа, коэффициент заполнения мы можем менять с помощью микроконтроллера, значит если Vin увеличивается, то увеличивается и напряжение выхода и в этот момент мы уменьшаем коэффициент заполнения (duty) пока опять не станет 12В. Соответственно при уменьшение Vin мы начинаем увеличивать коэффициент заполнения пока опять же напряжение Vout не станет 12В.

На что еще хотелось бы обратить внимание в теоретическом разделе… Ах, да! Наверняка вам интересно, как ШИМ с амплитудой 20В после транзистора в итоге превратился в постоянное напряжение с мизерными пульсациями? Действительно, если мы поставим красный щуп осциллографа в исток транзистора VT1, зеленый щуп после LC-фильтра, то увидим такую картину:



Вы можете видеть, как LC-фильтр «смазывает» напряжение переменное в постоянное, а дело все в том, что энергия запасенная в индуктивности и емкости не может мгновенно израсходоваться, следовательно и напряжение не может мгновенно измениться. Получаем, что в момент, когда ШИМ перед дросселем стал 0В напряжение на выходе обеспечивается запасенной в фильтре энергией, которая не рассасывается мгновенно и ее хватает чтобы поддерживать напряжение в момент закрытия VT1. Это все на пальцах разумеется, если интересно углубиться, то как всегда советую для начал книгу Б.Ю. Семенова «Силовая электроника: от простого к сложному», там целая глава по buck (чопперу).

Борьба за КПД


Как я чуть ранее писал — это был базовый вариант топологии. Основной ее минус — высокие потери на запирающем диоде. Какой ток в несложных системах работающих на МК и CPLD? Обычно в пределах 1А, иногда 2А, если имеется какой-то TFT дисплей. В таком случае потери даже при использовании диода Шоттки составят 0,4В * 2А = 0,8 Вт. В принципе терпимо, рассеивать столько на корпусе SMA/SMB можно без проблем, хотя при напряжении 3.3В и 2А потери 0.8В — это все таки 12% КПД!

Теперь представим себе случай, когда ток у нас 20А. Это может быть и MPPT контроллер, и система питания большой FPGA и много чего еще. В таком случае потери составят 0,4В * 20А = 8 Вт! Что это значит? Например, в случае MPPT у вам будет меньше запасаться энергии в АКБ, в случае питания FPGA это будут дополнительные 8 Вт тепла, которые надо куда-то рассеивать и в обоих случаях это несомненно потеря общего КПД. Что можно сделать? А давайте заменим диод VD1 на еще один N-канальный Mosfet и получим вот такую схему:



Теперь транзистор VT2 выполняет роль диода, то есть проводит ток, когда VT1 закрыт. Диод, который был в базовой версии не требовал управления, сейчас же за улучшение характеристик мы вынуждены заплатить дополнительным каналом управления с ШИМ сигналом.

Для начала давайте посчитаем насколько мы уменьшили потери. Сопротивление канала современного mosfet-а составляет несколько мОм. В качестве примера давайте возьмем транзистор из моего силового модуля о котором я рассказывал в прошлых статьях — IPP083N10N5AKSA1 с сопротивление канала 8.3 мОм. Получаем статические потери равные 0,0083 * 20А * 20А = 3,32 Вт. Еще разумеется будут динамические потери, которые с адекватно спроектированным драйвером составят не более 20%, то есть суммарные потери у нас составят 4 Вт. Получаем, что переход от обычного buck-а к синхронному позволяет вдвое уменьшить потери на диоде.

Давайте теперь разберем усложнившееся управление. Как мы уже поняли запирающий диод проводил ток когда был закрыт VT1. Из этого следует, что VT2 должен быть закрыт когда открыт VT1 и соответственно VT2 открыт когда закрыт VT1. Если проще — транзисторы работают попеременно: или один открыт иди другой, если оба транзистора откроются, то возникнет сквозной ток, т.к. они замкнут между собой VIN и GND. Давайте посмотрим какой должен быть сигнал, где «желтый канал» — транзистор VT1 и «зеленый канал» — транзистор VT2:



Как видите, если в желтой канале (на VT1) установлена логическая «1», то в это время обязательно должен быть установлен логический «0» в зеленом канале (на VT2). Получаем, что VT1 накачивает энергию в LC-фильтр, а VT2 замыкает контур на стадии разрядки.

Есть еще один момент о которым вы уже ранее слышали или читали выше — сквозной ток. Дело в том, что реальный, а не идеальный транзистор (mosfet) имеет на затворе определенную емкость, то есть в реальности он не мгновенно переходит из лог.0 в лог.1, да и энергия в транзисторе не рассасывается мгновенно, в результате чего транзисторы на короткое время в момент переключения могут оказаться оба открыты. Это может привести в лучшем случае к повышенным потерям, а значит нагреву и в худшем случае в бабаху, т.к. сквозной ток это обычное короткое замыкание (КЗ). Чтобы этого избежать между выключением одного транзистора и включением другого вводят задержку или так называемый dead-time. Выглядит это следующим образом:



Думаю вы заметили, что на границе переключения сигнала есть небольшой пробел. Я установил его заведомо большой (около 3%), чтобы вы могли его увидеть, в реальности он значительно меньше. Вообще dead-time (далее dt) устанавливается как можно короче, но при этом достаточный чтобы транзисторы успели закрыться. Его можно рассчитать, а можно подобрать опытным путем, лично я считаю и тот и тот вариант нормальным, но бородатые джедаи наверняка скажут вам: «Нужно считать обязательно, а лучше моделировать!». Это конечно правильно, но решайте сами — если не лень моделируйте в LTspice с учетом паразитных индуктивностей и емкостей проводников и компонентов.

Для стенда в данной статья я установил dt равный ~100 нс (на самом деле 104). Мой модуль позволяет установить его значительно меньше, т.к. драйвер очень суровый применен, но наверняка многие из вас будут собирать свой макет без моего модуля, а значит там с большой долей вероятностью будут сопли. Вот чтобы не бахнуло из-за соплей оставлю dt с запасом и если у вас нормальная разводка на плате, то вы сами можете его уменьшить — дальше в главе посвященной коду вы увидите как, а пока смотрим действительно ли есть dt:



Тут видно, что dt длится 2,5 деления и каждое деление 40 нс — значит длительность составляет ~100 нс как и было задумано. Надеюсь вы поняли зачем нужен dt, сколько он должен быть по длительности и как вообще работает преобразователь по топологии buck. Если не поняли, то как обычно вопросы в комментариях, лс и на почту принимаются, пока вроде отвечаю всем.

Глава 2. Расчет основных компонентов


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

Напомню вводные данные:

  • Входное напряжение: 15...30В
  • Выходное напряжение: 12В
  • Номинальный выходной ток: 2А
  • Частота коммутации: 100 кГц

Выходное напряжение 12В выбрано, т.к. в качестве нагрузки планирую использовать светодиод 12В 20Вт, который оказался под рукой и является весьма наглядной нагрузкой. Предвидя вопросы «экспертов» в комментариях — да, я в курсе, что светодиоду нужна стабилизация тока, но мы то делаем стабилизатор напряжения и светодиод просто нагрузка.

Входное напряжение выбрано от балды, можно и 15...60В сделать, поэтому если вам интересен другой диапазон, то можете посчитать для него сами значение компонентов. Номинальный ток 2А выбран чтобы получить мощность на выходе 12В * 2А = 24 Вт, то есть чуть больше, чем нужно для светодиода. Сам светодиод при 12В потребляет около 1,82...1,9А.

Остался самый интересный параметр — рабочая частота преобразователя. Какая она должна быть? Ответить тут придется вам самим, в моем случае это 100 кГц. Выбор основывается на двух тезисах:

  • Увеличение частоты приводит к уменьшению необходимой индуктивности дросселя, входного и выходного конденсатора. Если говорить проще — с увеличением частоты уменьшаются габариты устройства. С уменьшением частоты габариты увеличиваются.
  • Уменьшение частоты приводит к увеличению КПД, т.к. динамические потери при переключение транзисторов уменьшаются. Увеличение частоты увеличивает динамическую составляющую транзисторов и соответственно уменьшает КПД.

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

Шаг 1. Выбор транзисторов

Нас в основном будут интересовать 3 параметра: максимальное напряжение «сток-исток», сопротивление канала в открытом состоянии и емкость затвора. К транзистору прикладывается весь потенциал источника напряжения (Vin), а так же присутствуют выбросы в момент переключения. У вас есть 2 варианта: взять транзистор VT1 и VT2 с запасом по напряжению или повесть RC-снаббер на VT2. В моем случае на силовом модуле стоят транзисторы на 100В, а при входном 30В это огромный запас по напряжению, даже 60В хватило чтобы обойтись без снабберов и обезопасить транзистор от пробоя.

Сопротивление канала — тут чем меньше, тем лучше, но есть одно НО. При уменьшение сопротивления канала мы уменьшаем статические потери (I2*R), но технология такова, что увеличивается емкость затвора, а это приводит к увеличению динамических потерь. Вам предстоит найти золотую середину между «сопротивление канала» и «емкость затвора». Для напряжение до 100В советую обратить внимание на транзисторы серии OptiMOS от Infineon, на большие напряжения уже смотрите сами по параметрическому поиску или даже в сторону IGBT-транзисторов. Последние так же поддерживаются моим силовым модулем и не требуют никаких изменений в драйвере.

Шаг 2. Расчет индуктивности дросселя

Необходимо посчитать минимальное значение индуктивности, которая позволит работать нашему dc/dc преобразователю в режиме неразрывных токов (Lmin):



По переменным я думаю понятно все, кроме — kind. Это допустимые пульсации тока в дросселе, обычно выбирают значение 20...50%, я же практически всегда задаю 30%. Чем меньше пульсация тока, тем дальше мы будем от границы насыщения сердечника на котором намотан дроссель, но как видно из формулы — понадобится большая индуктивность дросселя.

Теперь посчитаем минимальное значение индуктивности, которая понадобится для моих вводных данных, пульсации я заложу 30% как уже выше писал:



Стоит понимать, что это минимальная индуктивность, требующаяся для работы buck-преобразователя в режиме неразрывных токов, но опять есть нюанс. В процессе увеличения тока, действующего в обмотке, несколько уменьшается проницаемость сердечника и индуктивность дросселя БЕЗ тока и С током несколько отличается, у разных материалов это зависимость разная. Чтобы не возникла ситуация, когда при увеличение тока в дросселе индуктивность уменьшилась ниже Lmin и dc/dc не ушел в режим разрывного тока, необходимо несколько увеличить индуктивность, то есть добавить парочку лишних витков при намотке. Увеличения индуктивности на 10-15% будет достаточно для материала Kool Mu, а мой дроссель будет именно на нем.

Шаг 3. Расчет и изготовление дросселя

Я хотел данную процедуру описать в разделе «макетирование», но тогда этап расчета индуктивности остался бы для вас менее понятным, да и по интересным картинкам наверное соскучились, поэтому опишу все здесь. Для изготовления дросселя я возьму дроссель R26/14/11 (R — это кольцо, а цифры — габариты) из материала Kool Mu с проницаемостью 60, скачать документацию на него и купить можно тут — Лэпкос.



Теперь нужно посчитать сколько витков и каким проводом надо намотать. Начнем с количества витков пожалуй. В документации на сердечник есть такой удобный параметр — AL, который равен 75 нГн/виток2. Тут внимательно — витки в квадрате! Чтобы найти индуктивность сердечника необходимо умножить AL на количество витков в квадрате. Отсюда формула для нахождения количества витков выглядит так:



Чтобы получить минимальную необходимую индуктивность необходимо намотать 40 витков, но как мы уже обсудили — необходимо немного увеличить индуктивность, допустим накинем +3 витка. Берем кольцо и наматываем 43 витка, получаем вот такой дроссель:



Теперь ради интереса посчитаем какая индуктивность должна получиться:



И для надежности проверяем индуктивность дросселя пинцетом:



137 мкГн, прекрасно! Результаты сошлись, погрешность в пределах ±8% для AL. Тут стоит лишь заметить — если у вас нет возможности измерить индуктивность, то не покупайте сердечники на алиэкспресс, в ЧиДе, компэле, электронщике и прочих «забегаловках» — там есть вероятность получить сердечник из другого материала или не той проницаемостью, но при правильной маркировке — проверено. Без возможности измерить индуктивность вы не сможете проверить AL и сможете сильно намучиться в поисках причины «бабаха» вашего преобразователя.

Тут появится разумный вопрос — «а хватит ли нам сердечника и его габаритов? Может надо было больше?». Для материала Kool Mu предел магнитной индукции составляет 0.5 Тл, на практике лучше не вылезать за порог выше 0.45 Тл без явно необходимости. Получается, что обмотка намотанная на сердечник не должная создавать индукцию в каждой точке сердечника больше 0.45 Тл, так что проверим:



Как видим значение магнитной индукции 0,06 Тл сильно ниже, чем предельные 0,5 Тл. Из этого можно сделать 2 вывода: во-первых, дроссель не уйдет в насыщение, а во-вторых, сердечник сильно большой и мощно взять кольцо существенно меньшего размера. Я взял кольцо R26 просто потому, что у меня их целая коробка, никакого другого тайного смысла тут нет.

Осталось определить какое сечение провода взять для дросселя. Во-первых, провод с диаметром более 1...1,2 мм я вам брать настоятельно не советую при таких высоких частотах, т.к. скин-эффект уже оказывает существенное влияние и уменьшает эффективное сечение. Во-вторых, плотность тока в проводе нужно выбирать исходя из условий охлаждения и мощности. На малых мощностях (до 10-20 Вт) можно смело закладывать плотность тока 8..10 А/мм2 даже без обдува воздушным потоком. На мощностях до нескольких киловатт лучше закладывать плотность тока в интервале 5...6 А/мм2, а при мощностях от 10 кВт и далее разумно будет снизить плотность тока до 3...4 А/мм2.

У меня под рукой оказался лакированный провод с диаметром 0,8 мм. Его сечение соответственно составляет ~0,5 мм2. При токе в 2А получаем плотность тока в обмотке около 4 А/мм2. Я мог бы использовать провод и вдвое меньшего сечения, но у меня сердечник достаточно большой, поэтому провод большего сечения без проблем влез. Когда же вы оптимизируете свое устройство, то вам придется сначала считать, а потом закупать провод нужного сечения, тогда вы сможете получить оптимальные габариты дросселя.

Шаг 4. Расчет выходного конденсатора

На данном этапе, как и в случае с индуктивностью, мы будем считать минимальное значение емкости, которую необходимо установить в LC-фильтр на выходе buck-преобразователя. Соответственно если установите больше, то будет лучше и дальше увидите почему. Посчитаем емкость:



Разумеется емкость необходимо так же ставить с некоторым запасом, особенно если вы используете только керамику на выходе, т.к. ее емкость сильно уменьшается в зависимости от приложенного к ней напряжения. Еще стоит обратить на зависимость от пульсаций — переменная Vpulse. Это максимальное значение пульсаций на выходе, то есть в идеале при емкости 147,8 мкФ амплитуда пульсаций будет 0,2В, то есть напряжение на выходе будет плавать в диапазоне 11,9...12,1В. Хотите уменьшить пульсации? Тогда уменьшайте их в формуле и значение полученной емкости соответственно увеличится, разумеется лабораторный блок питания вы не получите просто увеличивая выходную емкость. Так же необходимо учесть необходимость низкого ESR, для этого обычно ставят 1-2 электролита параллельно и параллельно им навешивают керамику на несколько мкФ с диэлектриком X7R желательно. Если позволяет бюджет, то можно заменить электролитический конденсатор на полимерный тантал (как в GPU) и так керамика не нужна, ESR у них и так мизерный.

Рассуждения о рабочей частоте

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

  • Как видите в формуле фигурирует частота, чем выше рабочая частота, тем меньшее значение индуктивности дросселя будет требоваться и меньшее количество витков придется мотать — экономим на меди и упрощаем изготовление моточных изделий
  • В формуле вычисления магнитной индукции присутствует индуктивность и количество витков, правда как помните индуктивность имеет квадратичную зависимость от витков, а значит при снижение количества витков в 2 раза индуктивность уменьшится в 4 раза. Из этого следует, что при повышение частоты уменьшается индуктивность и значение магнитной индукции, а значит можно применить сердечник меньшего размера, то есть уменьшаем габариты
  • Теперь посмотрим на формулу выходной емкости, тут тоже все очевидно — она линейно зависит от индуктивности, то есть чем меньше индуктивность, тем меньшая емкость нужна. Габариты уменьшаются!
  • Теперь о плохом… Частота растет, а значит увеличиваются динамические потери транзисторов и это очевидно ведет к снижению общего КПД. На сколько нибудь значительной мощности разумный предел частоты для buck-преобразователя на mosfet-ах составляет 200 кГц и ниже. Хотите большую мощность (сотни ватт) и огромную частоту? Добро пожаловать в мир GaN транзисторов или резонансных топологий

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

Глава 3. Собираем макет buck-преобразователя


Так, самая нудная, но важная, часть закончилась, теперь пойдет железо и код. Давайте соберем макет на котором будем реализовывать теоретические выкладки. Для этого понадобятся два модуля про которые я рассказывал в предыдущих статьях: силовой модуль и модуль управления на STM32F334. Так же вы можете сами на макетной плате собрать полумост из любого подручного мусора типа IR2110, а в качестве управления применить любой МК: STM32-Discovery, LaunchPad, Arduino и просто адаптировать логику работы и код под свой любимый МК, сложного ничего не будет, если вы поняли из первых двух глав как работает buck-преобразователь.

Теперь давайте сделаем нашу структурную схему buck-а более «реалистичной», добавив на нее номиналы всех компонентов и верно отразим количество конденсаторов, а так же отметим какую часть может реализовать мой силовой модуль:



Как видно по схеме модуль уже содержит в себе полумост (два транзистора) для реализации синхронного buck-а и входной конденсатор, он кстати в модуле стоит с огромным запасом — там 3 электролита по 1000 мкФ и 100В, этого хватит чтобы спокойно собрать buck на 500-800 Вт. Нам остается добавить дроссель, который мы уже изготовили и выходные конденсаторы, последние тоже кстати с запасом, т.к. на низкое напряжение я нашел только 4700 мкФ 25В, но они китайские какие-то поэтому еще и решил парочку запараллелить. На самом деле там хватит и 470 мкФ одного, но у меня такой мелочи в выводном исполнение просто не оказалось. Получается вот такая конструкция:



Как ранее было сказано, в качестве нагрузки используется мощный светодиод на 20 Вт. На сколько он светит не знаю, да и не очень интересно, но потребляет он при 12В как раз 21...22 Вт на которые и рассчитан мой buck-преобразователь. Сам светодиод обмазал КПТ-8 и прикрутил к радиатору, его конечно мало, но на 5-7 минут работы его хватает без проблем (греется до +40...50 oC), а большего мне и не нужно. Подключаем от модуля управления 2 сигнала HRPWM, GND и через делитель цепляем выход buck-а на АЦП, в итоге имеем такой стенд:



Глава 4. Пишем ПО и запускаем преобразователь


Теперь у нас есть все необходимое, чтобы начать писать код и оживить наш buck-преобразователь. Для начала давайте посмотрим на pin-out для микроконтроллера STM32F334R8T6, который стоит в модуле управления:



Теперь нам понятно, какие будут использоваться выводы микроконтроллера. На самом модуле мне понадобится всего 1 из 5 каналов для управления силовой части, использовать будем канал «А». У данного канала, как в прочем и у остальных, есть 2 выхода высокоточного ШИМа (HRPWM), 1 вход ошибки (его не используем), GND для объединения земли плат и 2 канала АЦП (будем использовать только один для напряжения).

Немного о HRPWM

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

Я не буду в рамках данной статьи углубляться в теорию данной периферии, поэтому опишу суть. HRPWM или High Resolution PWM — это привычный нам ШИМ модуль, который обладает повышенным разрешением установки коэффициента заполнения (duty) и в дополнение обычно обладает более гибкими настройками.



  • У микроконтроллера STM32F334R8T6 имеется 10 каналов HRPWM, которые объединены в 5 групп по 2 канала. Эти 2 канала внутри группы могут работать как независимо, так образовывать комплементарную пару — последняя нам и нужна;
  • Внутри комплементарной пары между 2-мя сигналами ШИМ можно устанавливать аппаратный dead-time для защиты от сквозного тока;
  • Все 10 каналов тактируются от одного таймера — Master timer, благодаря этому они все синхронизируются между собой и вам не придется вручную настраивать цепочку из таймеров. Достаточно включить мастер и таймеры Timer A...E за тактируются от него;
  • Частота на HRPWM идет удвоенная, то есть при частоте ядра в 72 МГц на HRPWM идет 144 МГц после дополнительного множителя (х2) с PLL. Это дает возможность управлять преобразователями на частоте в сотни кГц;
  • Множество настроек для управления ШИМом, например, по мимо возможности привязать геренерацию ШИМа к началу и концу периода, есть еще 4 настраиваемых события (comp), которые позволяю перевести ШИМ в 0 или 1 в любой момент периода отличный от начала/конец периода;
  • Есть режимы для конкретных топологий, например, режим push-pull, который позволяет реализовать множество двухтактный топологий.

И это лишь малая часть особенностей, на схеме устройства HRPWM вы видите еще возможности синхронизации с кучей событий, ЦАПом, встроенными в МК компараторами, а по мимо данной блок-схемы есть еще множество задокументированных возможностей.

Остался последний вопрос, который нужно осветить — «почему этот ШИМ высокоразрядный?». Для этого рассмотрим простой пример. Представим, что решили использовать МК без HRPWM, допустим STM32F103C8T6, который так же работает на частоте 72 МГц. Нам нужно управлять полумостом на частоте 70 кГц, считаем какой шаг регулирования мы можем получить: 72 000 000 / 1025 шагов = 70 243 Гц. Ага, у нас 1025 шагов и мы можем при регулировке менять напряжение на выходе с теоретическим шагом 1/1025 = ~0,1%. Теперь берем STM32F334, при частоте тактирования 144 МГц и разрядности сдвига таймера в 32 бита мы получаем эквивалентную частоту 144 МГц * 32 = 4,608 ГГц. Для тех, кто испугался и усомнился в цифре:



Нет, это не рабочая частота, это частота эквивалентная. Что нам это дает? Берем эквивалентную частоту 4 608 000 000 Гц / 70 300 Гц = 65 535 шагов. Теперь мы можем регулировать напряжение (или ток) на выходе с шагом 1 / 65 535 = ~0,001%, то есть в 100 раз точнее!

А теперь сделаем так — частота у нас 700 кГц, что является нормально для многофазного buck-а, например. У F103 получится 72 000 000 Гц / 700 000 Гц = 102 шага, что позволяет в лучшем случае получить регулирование 1%, но это 1% для duty, то есть в реальности с таким количество шагов у вас будет напряжение плавать на выходе как будто стабилизации и нет особо. Тогда как для F334 количество шагов будет примерно 6500, что все еще позволяет строить очень точный регулятор напряжения или тока. Получаем, что разрешение (шаг) установки скважности значительно выше/чаще, чем у обычного МК с стандартным ШИМ-модулем внутри.

Настройка системы тактирования

В качестве среды разработки в данной статье я использовал TrueSTUDIO, ибо бесплатная, не такая убогая как Keil или IAR да да, расскажите мне о его чудесном отладчике, кросс-платформенная и пожалуй лучшее решение для новичков и не только. В конце статьи будет архив с проектом именно для этой IDE. Как создавать и настраивать проект я рассказывать не буду, просто оставлю ссылку на видео, где все подробно показано — смотреть.

После того как создали проект и помигали светодиодом, необходимо настроить систему тактирования, а именно с 8 МГц поднять частоту то 72 МГц и подать на ядро, а потом настроить делитель чтобы уменьшить частоту, подаваемую на АЦП:

void StartInitClock (void) {

	RCC->CR |= RCC_CR_HSEON;    // Enable HSE
	while (!(RCC->CR & RCC_CR_HSERDY));

	FLASH->ACR |= FLASH_ACR_LATENCY_1;

	RCC->CFGR  |= RCC_CFGR_PLLMUL9;    // PLL mult x9
	RCC->CFGR  |= RCC_CFGR_PLLSRC;    // Source HSE
	RCC->CFGR2 |= RCC_CFGR2_ADCPRE12_DIV10;    // ADC source AHB/10

	RCC->CR |= RCC_CR_PLLON;
	while((RCC->CR & RCC_CR_PLLRDY) == 0){}

	RCC->CFGR &= ~RCC_CFGR_SW;
	RCC->CFGR |= RCC_CFGR_SW_PLL;    // Select source SYSCLK = PLL
	while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_1) {}    // Wait PLL

}

Тут все просто думаю, алгоритм настройки следующий: переходит на внешний кварц (HSE) -> ждем когда переход завершится и выставится флаг готовности -> подаем на вход PLL сигнал с кварца -> умножаем 8 МГц на 9 -> частоту 72 МГц делим на 10 для тактирования АЦП -> включаем PLL -> ждем пока он включится и выставит флаг готовности -> подаем на системную шину и ядро сигнал с PLL -> ждем пока переключение завершится -> готово.

Настройка HRPWM

Вот тут все несколько сложнее, т.к. функционала у данного модуля очень много, куча всяких настроек и объем документации очень большой, но это и минус и одновременно плюс — за гибкость надо платить.

RCC->CFGR3   |= RCC_CFGR3_HRTIM1SW_PLL;
RCC->APB2ENR |= RCC_APB2ENR_HRTIM1EN;

Нужно указать, что HRTIM тактируется от PLL, множитель х2 по умолчанию уже включен. Дальше просто включаем тактирование для HRTIM, вот тут первая фича — как мы понимаем таймер тактируется от PLL, но включаем для APB2. Это не совсем логично, но в файлике с CMSIS легко ищется или в документации.

	RCC->AHBENR  |= RCC_AHBENR_GPIOAEN;

	GPIOA->MODER   &= ~GPIO_MODER_MODER8;
	GPIOA->MODER   |= GPIO_MODER_MODER8_1;    // Alternative PP
	GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8;    // Very high speed

	GPIOA->MODER   &= ~GPIO_MODER_MODER9;
	GPIOA->MODER   |= GPIO_MODER_MODER9_1;
	GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR9;

	GPIOA->AFR[1] |= 0xDD;    // PA8 and PA9 - AF13

PA8 и PA9 — это выход Timer A, который на моем модуле идет на канал №1, что вы можете видеть на схеме и pin-out. Ноги настраиваются как push-pull с альтернативной функцией, номер самой функции для обеих ног 13-й. Важно так же настроить на максимальную частоту GPIO, а то будет непонятный завал фронта и спада сигнала, что для силовой электроники крайне критично.

HRTIM1->sCommonRegs.DLLCR |= HRTIM_DLLCR_CAL | HRTIM_DLLCR_CALEN;
while ((HRTIM1->sCommonRegs.ISR & HRTIM_ISR_DLLRDY) == RESET);

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

HRTIM1->sTimerxRegs[0].PERxR = PeriodTimerA;    // Period for timer A
HRTIM1->sTimerxRegs[0].CMP1xR = 0;    // Duty for timer A

Вот и пошла гибкость. Во-первых, мы можем задать свою частоту для каждого таймера A...E, тут просто записываем период нашего ШИМа. Во-вторых, по умолчанию у нас выравнивание ШИМа по началу периода, то есть сигнал переходит в лог.1 при начале нового периода, а теперь нам надо выбрать когда он вернутся в лог.0, в данном случае по компаратору №1, то есть я задаю в нем по суть коэффициент заполнения (duty).

Для примера можно переводить ШИМ не по началу периода, а по компаратору №1, а возвращать в лог.0 по компаратору №2 и таким образом аппаратно двигать фазу.

// Deadtime enable
HRTIM1->sTimerxRegs[0].OUTxR |= HRTIM_OUTR_DTEN;   

// Tdtg = 6.94 ns 
HRTIM1->sTimerxRegs[0].DTxR  |= HRTIM_DTR_DTPRSC_0 | HRTIM_DTR_DTPRSC_1; 
  
// Deadtime rising = 15*Ttg = 104 ns 
HRTIM1->sTimerxRegs[0].DTxR  |= HRTIM_DTR_DTR_0 | HRTIM_DTR_DTR_1 | HRTIM_DTR_DTR_2 | HRTIM_DTR_DTR_3;		

// Deadtime falling = 15*Ttg = 104 ns
HRTIM1->sTimerxRegs[0].DTxR  |= HRTIM_DTR_DTF_0 | HRTIM_DTR_DTF_1 | HRTIM_DTR_DTF_2 | HRTIM_DTR_DTF_3;    
HRTIM1->sTimerxRegs[0].DTxR  |= HRTIM_DTR_DTFSLK | HRTIM_DTR_DTRSLK;

На этом этапе мы включаем dead-time и настраиваем его, в принципе в комментариях есть все формулы, их можно так же найти в reference manual. DT длительностью ~100 нс вы уже видели на осциллограмме в теоретической главе данной статьи. Мертвое время можно задать отдельно по фронту и по спаду сигнала. Кстати, [0] — это Timer A, соответственно [1] — это Timer B и так далее.

// Samples in middle of ON time
HRTIM1->sTimerxRegs[0].CMP2xR = PeriodTimerA / 10; 

// ADC trigger 1 update: Timer A   
HRTIM1->sCommonRegs.CR1 |= HRTIM_CR1_ADC1USRC_0;  

// ADC trigger 1 event: Timer A compare 2  
HRTIM1->sCommonRegs.ADC1R |= HRTIM_ADC1R_AD1TAC2;   

Для меня это был самый не очевидный момент. Суть какая — я хочу сделать так, чтобы на 10% длительности периода Timer A генерировалось событие, которое бы запускал преобразование АЦП и измеряло сигнал с обратной связи. Почему 10%? Просто в идеале измерение не должно приходиться на момент перехода ШИМа из 0 в 1 или обратно, т.к. в этот момент в силовой части идут переходные процессы и помехи, а нам их измерять не надо. Поэтому 10% в моем случае оптимально, т.к. при 12В выходном и 30В входном напряжение коэффициента заполнения (duty) не упадет до 10% и момент переключения транзистора точно не совпадет с измерением АЦП.

Теперь нужно посмотреть на систему связи событий между HRTIM и АЦП:



В первой строке мы выбираем когда именно будет срабатывать компаратор, в моем случае это 10% от периода таймера А. Далее выбираем конкретный триггер в АЦП, который свяжется МК, нам доступен 1 или 3-й. Теперь просто указывает какое событие будет отправлять сигнал на АЦП, в моей случае это компаратор №2.

// Enable output PWM for TA1 and TA2
HRTIM1->sCommonRegs.OENR |= HRTIM_OENR_TA1OEN | HRTIM_OENR_TA2OEN;

// Continuous mode
HRTIM1->sTimerxRegs[0].TIMxCR |= HRTIM_TIMCR_CONT;

// Period for master timer
HRTIM1->sMasterRegs.MPER = 65000;

// Enable counter for Master and timer A
HRTIM1->sMasterRegs.MCR |= HRTIM_MCR_MCEN | HRTIM_MCR_TACEN;												

И финальный аккорд! Разрешаем HRTIM выводить сигналы от Timer A на наши GPIO. Теперь выбираем режим, бывает бесконечный (у меня он), а бывает что таймер включился на 1 период и после этого его опять надо запускать. Далее устанавливаем период для Master timer и последним шагом включаем его, он начинает тактировать таймеры каналов и на выходе появляется ШИМ сигнал.

Это была функция настройки, осталось сделать функцию, которая будет задавать коэффициент заполнения (duty), именно с ней мы и будем работать при создании регулятора:

void SetDutyTimerA (uint16_t duty) {
    HRTIM1->sTimerxRegs[0].CMP1xR = duty;
}

Листинг функции настройки и установки коэффициента заполнения
// f = 102,4 kHz
#define PeriodTimerA 	((uint16_t)45000)

void InitHRPWM (void) {

RCC->CFGR3   |= RCC_CFGR3_HRTIM1SW_PLL;
RCC->APB2ENR |= RCC_APB2ENR_HRTIM1EN;

/************************************************
*                             Setting GPIO
***********************************************/

RCC->AHBENR  |= RCC_AHBENR_GPIOAEN;

// Alternative PP
GPIOA->MODER   &= ~GPIO_MODER_MODER8;
GPIOA->MODER   |= GPIO_MODER_MODER8_1;
																		
// Very high speed
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8;																	

GPIOA->MODER   &= ~GPIO_MODER_MODER9;
GPIOA->MODER   |= GPIO_MODER_MODER9_1;
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR9;

// PA8 and PA9 - AF13
GPIOA->AFR[1] |= 0xDD;																						

/************************************************
*                          Setting timer A
***********************************************/

HRTIM1->sCommonRegs.DLLCR |= HRTIM_DLLCR_CAL | HRTIM_DLLCR_CALEN;
while ((HRTIM1->sCommonRegs.ISR & HRTIM_ISR_DLLRDY) == RESET);

// Period for timer A
HRTIM1->sTimerxRegs[0].PERxR = PeriodTimerA;																

// Duty for timer A
HRTIM1->sTimerxRegs[0].CMP1xR = 0;																			

// Deadtime enable
HRTIM1->sTimerxRegs[0].OUTxR |= HRTIM_OUTR_DTEN;
															
// Tdtg = 6.94 ns
HRTIM1->sTimerxRegs[0].DTxR  |= HRTIM_DTR_DTPRSC_0 | HRTIM_DTR_DTPRSC_1;	
								
// Deadtime rising = 15*Ttg = 104 ns
HRTIM1->sTimerxRegs[0].DTxR  |= HRTIM_DTR_DTR_0 | HRTIM_DTR_DTR_1 | HRTIM_DTR_DTR_2 | HRTIM_DTR_DTR_3;		

// Deadtime falling = 15*Ttg = 104 ns
HRTIM1->sTimerxRegs[0].DTxR  |= HRTIM_DTR_DTF_0 | HRTIM_DTR_DTF_1 | HRTIM_DTR_DTF_2 | HRTIM_DTR_DTF_3;		

HRTIM1->sTimerxRegs[0].DTxR  |= HRTIM_DTR_DTFSLK | HRTIM_DTR_DTRSLK;

// Event forces the output to active state for TA1
HRTIM1->sTimerxRegs[0].SETx1R |= HRTIM_SET1R_PER;	
														
// Event forces the output to inactive state for TA1
HRTIM1->sTimerxRegs[0].RSTx1R |= HRTIM_RST1R_CMP1;															

/************************************************
*        ADC trigger intialization (with CMP2 event)
************************************************/

// Samples in middle of ON time
HRTIM1->sTimerxRegs[0].CMP2xR = PeriodTimerA / 10;															

// ADC trigger 1 update: Timer A
HRTIM1->sCommonRegs.CR1 |= HRTIM_CR1_ADC1USRC_0;
															
// ADC trigger 1 event: Timer A compare 2
HRTIM1->sCommonRegs.ADC1R |= HRTIM_ADC1R_AD1TAC2;															

/************************************************
*                           HRTIM start
***********************************************/

// Enable output PWM for TA1 and TA2
HRTIM1->sCommonRegs.OENR |= HRTIM_OENR_TA1OEN | HRTIM_OENR_TA2OEN;
											
// Continuous mode
HRTIM1->sTimerxRegs[0].TIMxCR |= HRTIM_TIMCR_CONT;	
														
// Period for master timer
HRTIM1->sMasterRegs.MPER = 65000;	

// Enable counter for Master and timer A																		
HRTIM1->sMasterRegs.MCR |= HRTIM_MCR_MCEN | HRTIM_MCR_TACEN;												

}

void SetDutyTimerA (uint16_t duty) {

HRTIM1->sTimerxRegs[0].CMP1xR = duty;

}


Теперь давайте выясним правильным ли путем мы движемся. В функции main инициализируем настройку HRTIM и устанавливаем скважность, допустим 22500. При входном напряжение 20В и периоде 45000 наш коэффициент заполнения будет 50% и на выходе будет около 10В. Этого не хватит чтобы раскачегарить светодиод на полную, но загореться он должен и мы поймем работает ли силовая часть, все хорошо ли с dt и прочее. У меня все стартануло с первого раза:



Вы можете видеть, что все предыдущие теоретические выкладки подтвердились. При фиксированном коэффициенте заполнения (duty) в 50% напряжение на выходе просто делилось на 2: 20В -> 10В, 22В -> 11В, 18В -> 9В. Теперь давайте сделаем так, чтобы напряжение на выходе было стабильным и не зависело от входного, то есть добавим обратную связь.

Настройка АЦП и регулятора

Про АЦП в STM32 очень много уже написано до меня, я подробно остановился лишь на настройке триггера привязанного к компаратору HRTIM. Об остальных настройках АЦП я расскажу кратко. Смотрим функцию инициализации:

void InitBasicADC (void) {

RCC->AHBENR |= RCC_AHBENR_ADC12EN;
RCC->AHBENR |= RCC_AHBENR_GPIOCEN;

/************************************************
*                          Calibration 
***********************************************/

ADC2->CR &= ~ADC_CR_ADVREGEN;
ADC2->CR |= ADC_CR_ADVREGEN_0;    // Vref enable
Delay(10);
ADC2->CR &= ~ADC_CR_ADCALDIF;

ADC2->CR |= ADC_CR_ADCAL;    // Start calibration
while (ADC2->CR & ADC_CR_ADCAL);    // Wait end calibration

/************************************************
*              Select event trigger and channel
***********************************************/

// Enable start conversion external trigger
ADC2->CFGR |= ADC_CFGR_EXTEN_0;

// Event 7 - HRTIM
ADC2->CFGR |= ADC_CFGR_EXTSEL_0 | ADC_CFGR_EXTSEL_1 | ADC_CFGR_EXTSEL_2;		

// Select ADC2 channel IN5
ADC2->SQR1 |= ADC_SQR1_SQ1_0 | ADC_SQR1_SQ1_2;									

// Length regular ADC channel = 1
ADC2->SQR1 &= ~ADC_SQR1_L;														

ADC2->IER |= ADC_IER_EOCIE;    // Interrupt enable
NVIC_EnableIRQ(ADC1_2_IRQn);    // enable interrupt ADC1 and ADC2

/************************************************
*                           Start ADC
***********************************************/

ADC2->CR |= ADC_CR_ADEN;    // Enable ADC2
Delay(10);
ADC2->CR |= ADC_CR_ADSTART;
}

Я использую режим регулярных каналов, канал у меня всего один и он выбирается в регистре SQR1. Задействовал АЦП №2, а именно его вход IN5, он является быстрым и может работать на максимальной частоте семплирования, но не в этот раз. Частота выборки равна частоте ШИМа, т.к. 1 период = 1 выборка, в принципе этого более чем достаточно.

Так же нам в регистре CFGR нужно выбрать событие по которому будет запускать преобразование, то есть Event 7, почему именно он? Смотрим в RM:



Trigger 1 от модуля HRPWM приходит на Event 7 для нашего АЦП №2, который в данном случае работает в роли slave, то он управляется от модуля HRPWM. Думаю теперь понятно как связать 2 модуля, в принципе алгоритм аналогичный для любой периферии и любого таймера, отличаться будет разве что название регистра.

При достижения счетчика периода Master timer будет запускаться преобразования, которое спустя примерно 15 циклов (сколько точно смотрите в RM-е) вызовет прерывание и в нем можно будет забрать результат. Именно в этом прерывание мы и организуем алгоритм управления. Да, внутри прерывания что-то массивно лучше не делать, лучше выставлять флаг и передавать выполнение дальше, но я позволю себе такое упрощение, ибо в данном случае мой контроллер ничем особо не загружен и он с вероятностью 146% успеет посчитать и выйти из прерывания до появления нового.

Немного об управление

Представьте, что вы вошли в ванную комнату и решили помыть руки в раковине. Вы чуть приоткрываете воду, трогаете рукой, холодная? Добавляете еще горячей воды, теплее? Хорошо! Добавляете еще горячей воды? Почти то, что надо? Хорошо! Добавим еще горячей воды, пробуем рукой, обжегся? Давай теперь чуть убавим горячую. Хорошо? И так до бесконечности вы будете крутить кран пока температура воды не станет идеальной. Это самый простой регулятор!

Только у нас регулируется не количество горячей воды, а коэффициент заполнения ШИМа. Вместо руки у нас АЦП с измеренным результатом. Остается лишь реализовать логику. Мы посчитаем что должен выдавать АЦП при 12В на выходе, а потом с помощью условия if заставим наш контроллер поддерживать это значение с помощью изменения коэффициента заполнения (duty).

Для начала давайте повесим на выход делитель напряжения, чтобы 12В уменьшить до 2-2,5В к примеру, т.к. АЦП умеет измерять от 0 до +3,3В и если подать 12В, то микроконтроллер сгорит просто. Поэтому я поставлю делитель с номиналами 10 кОм и 2 кОм, который даст коэффициент деления 6 и соответственно наши +12В превратятся в +2В. Наш АЦП будет выдавать результат: adcResult = (Vout / k) / Vref * 212 = (12V / 6) / 3.3 * 4095 = 2481. Теперь пишем код для обработчика прерывания:

void ADC1_2_IRQHandler (void) {

	ADC2->ISR |= ADC_ISR_EOC;

	adcResult = ADC2->DR;

	if (adcResult > 2480) {

		dutyControl = dutyControl - 10;
	}
	else
	{
		dutyControl = dutyControl + 10;
	}

	SetDutyTimerA(dutyControl);
}

Первым делом после попадания в обработчик прерывания нужно сбросить флаг этого самого прерывания, иначе второй раз вы в него уже не попадете. Затем считываем результат и сохраняем его в виде переменной adcResult. Теперь, зная напряжение на выходе, нужно внести корректировку значения коэффициента заполнения для ШИМ, я это реализовал просто через условие if. В каждом периоде ШИМ мы делаем измерение, увеличиваем или уменьшаем коэффициент заполнения и устанавливаем полученный результат для следующего периода. Все просто, быстро и видна суть. Смотрим на результат работы:



Как видите все работает и при изменение входного напряжения сам выход остается стабильным в 12В. Сильно внимательные могут заметить небольшие иголки проскакивающие, тут нужно просто повесить керамику X7R на выход на 1-10 мкФ и они уйдут, мне просто лень уже искать ее и напаивать. Теперь сама осциллограмма, чтобы не портить глаза:



Тут вы можете увидеть как нарастает напряжение на выходе. Дело в том, что из-за алгоритма управления, чтобы заполнение достигло нужно значения от 0 до 10000, например, необходима тысяча периодов или примерно 10 мс. Меня это устраивает ибо софт-старт, если вы хотите сократить время нарастания, то чуть усложните алгоритм и прибавляйте +1000, а не +10, и чем ближе вы будете подбираться к заданным 12В, тем меньше шаг регулирования делайте пока не дойдете до +10. Вообще в плане управления можно сделать много чего, так что поле для экспериментов у вас есть.

Еще интересный момент это колебания в момент выключения, такая «гармошка». Дело в том, что после выключения питания моя цифровая часть продолжает работать от другого БП и она пытается удержать нужное значение на выходе. Откуда берется энергия? Да из входных конденсатор, это те что по 1000 мкФ аж 3 штуки, вот такое интересное явление.

Заключение


Статья вышла не маленькая, но вы же хотели всё и сразу мол давай готовую железку — получите. Надеюсь статья вам понравится, постарался сделать ее скорее не научную, а научно-популярную, чтобы материал был доступен людям с разным уровнем знаний и опыта. Возможно в дальнейшем я разберу аналогично и другие топологии типа boost, full bridge и прочие.

Кстати, данная статья и код послужат для нового MPPT контроллера на 20А, который проектирую. Сейчас жду платы от PCBway, которые собственно и вызвались про спонсировать печатными платами мои открытые проекты, исходники на MPPT так же будут открыты как и на все мои модули.

Самое главное забыл! Держите проект с кодом для TrueSTDIO — RAR.
Поделиться публикацией

Комментарии 104

    0
    PCBway похоже раскидывает сеть. Тоже предлагает.
    А вот нельзя как то индуктивность сделать из печатных плат (была статья на эту тему на хабре) и сразу заказать всё на PCBway? Сильно не хочется катушки искать/мотать. Для частоты 500 КГц например.
      +3
      Соглашайтесь, можно больше своих проектов пилить))
      Учитывая, что про планарника статья мною и написана, то однозначно можно. Правда планарник имеет смысл делать на частотах от 400 кГц и выше. Да и пакет из двухслоек конечно забавно, но кольцо проще намотать в реальности. Заказывать же плату 6-10 слоев под планарник выгодно только на очень большой серии, когда она будет стоить три копейки. В розницу на прототипы плата будет 300-600$ стоит, что как бы неразумно.
      +1
      А чем решение с микроконтроллером лучше какого-нибудь условного трехдолларового Buck controller чипа, вроде LTC3703, который делает все то же самое, но аппаратно?

      И какое именно напряжение подается на high side транзистор в итоге? А то в статье фигурируют 40 В местами, а исток-затвор выбранного транзистора 20 В.
        0
        Причина в конце, mppt алгоритм на LTC не запихнуть, да и 5-ти фазный buck с каналом на 20А тоже не сделать.

        Затворы что на нижнем, что на верхнем ключе имеют по 1-му независимому драйверу и по 1-му развязанному dc/dc на 12-12В, поэтому на затворе всегда там 12В (исток-затвор).
          0
          А почему не транзистор с каким-нибудь открытым коллектором? Или тем же контроллером через диод и резистор открытым коллектором? Ставить dc/dc и драйвер это какой-то адов оверкил, нет?
            +1
            Драйвер развязанный нужен, чтобы из силовой части срач помех не проникал в цифровую часть. Так что тут или dc/dc или бутстрепное питание, но последнее это для дешманских поделок больше подходит или для крупносерийного производства. Поэтому я не вижу оверкила в том, чтобы поставить лишний dc/dc за 1$.
            +3
            Окей, допустим, с MPPT понятно, хотя и такие чипы тоже существуют (LT8490).
            Но если мне как любителю нужен просто Buck на пару Ампер, имеет ли смысл городить микроконтроллер?

            В статье, кстати, ни слова про частотную стабильность петли обратной связи. Это окей?
              0
              Чипы готовые кончаются на 10А, когда обычно токи от 20 до 100А нужны. Готовые микры разве что куда-то в датчики удаленные с питанием от солнца ставить.

              Ради пары ампер конечно же не стоит, МК есть смысл ставить после 20А и далее. В статье я сделал пару ампер, чтобы любой желающих мог собрать на любых соплях и оно работало. Все таки 20А — это уже определенные требования к опыту и трассировке.
                +2
                Ну, есть масса чипов под внешние ключи. Они, обычно, ещё и имеют лучшие возможности по внешнему управлению. Дёшево и сердито, как компромис.
                  +1
                  Дешево это сколько? МК стоит 3$, а сколько стоит микросхемка у Linear или TI? Долларов 10 на digikey и в 1,5 раза дороже в РФ. При этом в нем не будет ни CAN, ни RS485.

                  Опять же — готового камня, который может и управлять силой и имеет специфичный алгоритм не так много. В МК с одного камня могу реализовать и MPPT-алгоритм и заряд для Li-ion сборки и при этом мониторить все подряд и отправлять данные на сервер. Цена будет при это значительно ниже готового решения и главное будет более гибким и понятным.
              0
              И ещё вопрос, а не проще действительно специализированный чип поставить, а потом им рулить через ЦАП контроллера и обратную связь, выбирая напряжение стабилизации?
              Более, того есть такое ощущение, что если управляемый цифровой резистор поставить и им рулить выбирая напряжение стабилизации, то получится проще и лучше за те же деньги, нет?
              Если бы я такое делал, то сначла смотрел бы в сторону специализированных микросхем и ЦАП. Никаких проблем с регулированием, предсказуемые характеристики, низкая сложность схемы и т.п.
                0
                Ох, еще раз… Надо MPPT с входом 15-150В с током 20А и чтобы он еще умел на входе 12/24/48В. Можно увидеть готовую микросхему, которая сможет это? А еще желательно, чтобы умела плеваться данными в RS485 или USB.
                  0
                  Контроллер оставить, но для преобразователя поставить специализированную микросхему, допускающую использование внешних ключей. Напряжение стабилизации задаётся контроллером через цепь обратной связи управляющей микросхемы при помощи ЦАП контроллера или управляемого цифрового сопротивления. Развязанное питание тоже есть ощущение, что избыточно. Как-то так. Очень просто всё получается по схемотехнике и управлению.
                  И никаких танцев с алгоритмами управления ШИМ, частотной стабильностью и т.п.
                    +1
                    Еще раз: в заголовке статьи у вас одно, а в тексте по факту совсем другой девайс разрабатывается. А все вопросы по поводу того, что было заявлено изначально, ведь до последнего абзаца про MPPT ни слова не было.
                    Ток 20 Ампер на много каких серийных чипах реализуется, если их в параллель поставить.
                    Те же ПЛИС почти всегда питают через изолированный мощный DC/DC (Х -> 5 или 12 В) и набор POL конвертеров из 5 или 12 в нужные разные напряжения (1.2 для ядер, 3.3 для периферии и т.д.) и на большие токи. Там обычно даже внешние силовые транзисторы не нужны, все прекрасно интегрируется. И никаких микроконтроллеров)
                      +3
                      1) Статья про расчет buck-а, а не ответ на непонятные вопросы «а почему не взять готовый чип?». Если сделано, значит есть ряд задач, где готовые решения отсутствуют, а они отсутствуют как только речь идет о какой-то вменяемой мощности и алгоритмах. Может мне надо было сделать устройство для изучения, которое не смогут повторить большинство людей? Вот так «tutorial» получился бы))

                      2) Для DSP/FPGA есть инфраструктура, но что делать если вход не 12В, а 12-150В? Городить еще один dc/dc? А если надо не стандартные 3.3/1В, а например, 56.8В для заряда АКБ?
                        0
                        Вся та часть, которая про расчет buck-а, вполне релевантна для расчета конструкции на базе готовых PWM-контроллеров.
                        Если сделано, значит есть ряд задач, где готовые решения отсутствуют
                        Статья стала бы еще полезнее, если бы вы посвятили пару абзацев тому, для каких задач что лучше. А то если кто-то попробует девайсом типа вашего питать другой микроконтроллер, это будет стрельба из пушки по воробьям)

                        но что делать если вход не 12В, а 12-150В?
                        Такие готовые чипы тоже есть. Условный LTC3894 умеет вход от 5 до 150 В и выход до 60 В. Для заряда АКБ там тока, разумеется, не хватит, то есть много и других задач.

                        P.S. Не поймите меня превратно, я не хочу критиканствовать, а, наоборот, хочу лучше разобраться в сферах применения того и другого. У меня сейчас на мониторе как раз схема такого готового чипа для DC/DC преобразования моделируется, поэтому очень интересно посмотреть на него «глазами потенциального потребителя», особенно такого, который применяет конкурирующее решение.

                          +1
                          Верно, по сути силовой части все равно кто ею управляет, а расчет был дли силы.

                          Про пару абзацев учту, мельком в конце упомянул mppt, видимо мало)) Кстати, в статье про модуль управление было несколько подробнее рассмотрено как и чем можно с нее управлять.

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

                          Можете критиковать, даже нужно (критика обоснованная — лучший фидбек), тем более к вашему мнению я всегда с удовольствием прислушиваюсь)) О, новая микросхема отечественная? Это хорошо! Отечественный motor control, про который НПФ Вектор рассказывал, очень понравился и часть новых проектов планируется на них сделать. Главное чтобы dc/dc был доступен для коммерции, а не только ВПК.
                            +2
                            Окажется, что надо заряжать, не до 4.2, а до 4.35 или 3.6 и 90% мелкосхем отваливается…
                  +2
                  Если уже есть микроконтроллер в девайсе, то зачастую проще приделать к нему драйвер с mosfet-ом, диодом и дросселем, чем искать подходящий подо все требования чип. Потому что там у каждого свои ограничения и особенности, да и схема в итоге часто получается проще. В случае же когда нужно заряжать мощный аккумулятор — вообще ничего подходящего не находится.
                    +2
                    А чем решение с микроконтроллером лучше какого-нибудь условного трехдолларового Buck controller чипа, вроде LTC3703, который делает все то же самое, но аппаратно?


                    Так понимаю, это наработка для MPPT контроллёра. Широкий динамический диапазон выходного напряжения (скажем 12В, 24В), с АЦП.
                    MPPT будет на свинцовых АКБ или на литиевых?
                      +1
                      Совершенно верно)) Задача не просто выкатить проект mppt, а перед этим объяснить как работают узлы из которого он будет построен.
                      Свинец + литий точно будет поддерживать, другие типа АКБ вряд ли, но будут открыты исходники и любой сможет самостоятельно добавить алгоритм заряда под свою задачу.
                        +1
                        Будет ли BMS с балансировкой для литиевых AКБ? Как говорят no pressure, просто зацепило как увидел youtube записи людей, делающих свои Powerwall на 18650.
                          0
                          BMS разумеется будет, но отдельным устройством. Мой товарищ по проекту сейчас занимается 12S 200 А*ч ячейкой для инвертора, как будет результат около-финальный, то он напишет статью и будут так же исходники.
                            0
                            Недавно на kickstarter-е появился интересный проект Solar BMS and Digital MPPT for PV electricity and heating.
                            Cхема есть в руководстве (MCU STM32F3 и интересная микросхема ISL94203 от Renesas).
                              0
                              Неплохо реализовано кстати, может быть даже поучаствовать в проекте ради интереса.
                    0
                    А как связать крутизну фронта из даташита и максимальную частоту шим-а? Или га какой ещё параметр смотреть?
                    p.s. половину ваших "-ие" надо заменить на "-ии".
                      0
                      В даташите обычно указывается или заряд в нКл или емкость в нФ. Считаете за сколько она зарядится от импульсного тока вашего драйвера, а затем смотрите какую часть периода составляет время нарастания от 0 до 10В. Если фронт и спад длятся больше 0,5% от длительности периода сигнала, то все плохо и будет горячо.

                      Вообще как считать драйвер, ток необходимый и dc/dc расскажу уже в следующей статье. Если кратко — хотите большую частоту? Выбирайте ключ с как можно меньшей емкостью/зарядом затвора. И не стоит забывать про время восстановления паразитного диода внутри ключа.
                      +1
                      здорово
                        0
                        Вам бы Vref ещё нужно измерять на каждом тике и корректировать результат, т.к. точность этих 3.3 В весьма приблизительная. Про это часто забывают, а даже те, кто помнят, как правило, делают это неправильно (усредняют Vref, измеряют несинхронно и надеятся на высокую точность, и прочие изыски, которые больше вредят, чем помогают).
                          0
                          Верное дополнение, но пока не стал усложнять, чтобы голову не перегружать людям)) В принципе измерение Vref можно добавить вторым в очередь и он будет так же измерять по компаратору на 10% периода. В плане синхронизации с событиями у HRTIM все очень удобно и наглядно.
                            0
                            Можно использовать при расчетах внутренний опорник stm-ки… изначальная погрешность у него не ахти, но дальнейшая стабильность на очень не плохом уровне…
                              0
                              У 3xx и 4xx опорный источник калиброван при выпуске контроллера, а коэффициент калибровки хранится в ПЗУ (VREFINT_CAL). Если всё правильно делать, то начальная погрешность очень неплохая. Со стабильностью тоже всё не плохо, особенно, если правильно аналоговое питание организовать. Не фонтан, конечно, но для большинства применений отлично подходит. Я на АЦП 2xx измерительные приборы с метрологией делал. В том числе и климатические камеры проходили. Когда приходили к тому, что нужно ставить внешний опорный источник, то, обычно, нужно было уже и внешний АЦП ставить, т.к. начинаются пляски со снижением шумов за счёт измерений в спящем режиме и прочая сильная магия.
                            +2
                            о, осталось дождаться статьи про повышайку.
                              +1
                              У контроллера нет аппаратной защиты от сквозного тока.

                              3 электролита хорошо, конечно, но дают ли они нужный импульсный ток? Ну и с фильтром на выходе та же история. Даже если электролиты импульсные. Пара пленочных по 20 мкф может оказаться эффективнее. Правда, они дорогие
                                0
                                Есть dt и вход BKIN и FAULT, которые внутри реализованы обычным логическим элементов и даже если ядро погибло и повисло, то защита все равно отключит выходы ШИМа. Ради интереса можно почитать аппноуты по HRTIM и там это весьма подробно разжевано. TIM1 таймера это кстати тоже касается.
                                0
                                А мостовую схему вы планируете делать? я бы с нетерпением почитал…
                                  +1
                                  Конечно, но уже скорее на новогодних каникулах. Планирую пример «повышалки» 24-400В dc/dc для инвертора к СЭС.
                                  +1
                                  Independent Watchdog в таких решениях обязателен.
                                    0
                                    Это все из разряда «очевидные нюансы», которые не имеют отношения в работе и расчету силовой части. Про общую стабильность и надежность устройств на МК и так много информации в гугле.
                                    0
                                    Ограничение резолюции таймера можно обойти модуляцией значений скважности в прерывании конца цикла тимера или в dma. Например если нужно 9.6 тиков то [ 9 9 9 9 10 10 10 10 10 10] в цикле.Давно пользуюсь подобным трюком, правда для других целей. Так что мне кажется можно и stm32f103 задействовать, благо он дешевле
                                      0
                                      Софтварные костыли — это для «ценителей», а нормальные решения нужно реализовывать аппаратно все таки. К тому же в f103 вроде нет FPU, нет компараторов и прочих прелестей. Ценник 2,5$ в розницу вроде не много, f103 стоит дороже вроде если оригинал, а не с алишки непонятно что, поэтому все относительно))
                                        +1
                                        Сейчас объясню, что лично меня смущает в stm32f334. Для него нужно изготавливать плату. То есть на коленке попробовать навесным монтажом не получится. То есть если нужно не мелкосерийное производство, а разовый проект для дома, то он не очень удобен.
                                        Если делать небольшие серии подобных проектов на заказ (блоки питания и тп) то видимо это неплохой выбор, впрочем это уже не совсем хобби, а те кто занимается этим профессионально и сами знают как делать блоки питания.
                                        в f103 вроде нет FPU, нет компараторов и прочих прелестей

                                        Так Вы их и не используете в данной статье :).
                                        а не с алишки непонятно что

                                        Зато недорого и доступно.
                                          –1
                                          Зато недорого и доступно.
                                          Это при условии, что вы не цените свое время. Лично для меня дорого угробить свое время на какую-то проблему с МК с алишки и в итоге выяснить, что дело не в коде и не в схемотехнике, а в чипе.

                                          Так Вы их и не используете в данной статье :).
                                          А разве на данном МК можно делать только то, что в статье?)) Думаю с float работают все.

                                          Для него нужно изготавливать плату
                                          ЛУТ или фоторезист позволяют изготовить плату за 15 минут. Текстолит с алиэкспресс один раз в год заказать думаю не проблема.
                                            +1
                                            Ну каждый смотрит со своей колокольни. Когда мне нужен float32 на работе, то не спасает ни STM32H750 за $3, ни intel i9, только харкор, только GPU :). А быстро дрыгать ножками в реальном времени или нужно на батарейках — вот тут и STM хорош, впрочем FPGA и быстрее могут. Везде ведь компромисс цена/качество/скорость разработки.
                                            Опять таки, статья мне понравилась именно простотой железа, а китайских f103с8т6 платок у меня валяется избыток, вот и смотрю куда бы их приспособить в домашнем хозяйстве например для поливалки на солнечной батарее, а DC-DC по этой схеме чтобы не перезарядить конденсатор электромагнита водяного крана и суперконденсатор резервного питания.(Если солнце пропадает, а кран таки нужно закрыть)
                                            +2
                                            FPU в реальности очень редко нужен. Software fp отлично работает на Cortex M3/M4. Для M0, там уже чуть хуже, но тоже в большинстве случаев аппаратный FPU не нужен.
                                            Например, у меня есть проект с десятками цифровых фильтров, разложением спектра 10 кГц в реальном времени в прерываниях и прочей сложной математикой на STM32F207 на эмуляции FPU и загрузка CPU там примерно 60%.
                                            Ставите -ffast-math, -ffp-contract=fast, -fsingle-precision-constant, -Wdouble-promotion, не используете double (а он всё равно на аппаратных FPU от ST не поддерживается) и в 99% случаев вам аппаратный FPU не нужен.
                                            Аппаратный FPU это только обработка видео, работа со спектром в реальном времени на частотах более 10 кГц и прочая тажёлая математика.
                                            Компаратор, это да. Но они стоят дешевле, чем разницам между stm32F2xx и 3xx, не говоря уже о сотой серии. А вообще, STM32F0xx, ценой меньше ста рублей за чип даже в России, вот это наше всё.
                                              0
                                              Ага, сколько разница между умножением float 16 без FPU и с ним? Что-то в районе 30 раз по количеству потраченных тактов. Это весьма критично, например, когда у нас трехфазная сеть и нужно налету считать 3 синуса и корректировать форму тока, а если есть PFC перед этим? То еще 3 синуса и 3 вектора тока. И да, разница 1 такт против 30 — это вполне существенно, если мы строим систему с хорошим реал-таймом.

                                              F2, F0 сравнивать с F334 смысла нет, ибо ни у того, ни у того нет столько гибкого ШИМа в виде HRTIM, они максимум подойдут чтобы частотник на них сделать.
                                                +1
                                                Меньше — от 10 до 20 раз между программным и аппаратным FPU для большинства задач.
                                                А вы посмотрите с какой скоростью синусы вычисляются без FPU. Я же привёл реальный пример, у контроллер меня спектр раскладывает на лету в прерываниях, несколько десятков полосовых фильтров считает и ещё кучу мелочёвки, типа RMS, постоянной составляющей и т.п. И всё это тысячи раз в секунду на эмуляции FPU. Пускал с аппаратным FPU на 4xx, но оказалось, что нет смысла.
                                                Даже три десятка синусов несколько тысяч раз в секунду это не нагрузка даже для 2xx серии.
                                                Большинство, кстати, совершенно не представляет, как правильно FPU использовать. Например, если вы не используете "-Wdouble-promotion", то вы совершенно точно делаете что-то не так, так как у вас где-то в коде почти наверняка будет неявное преобразование в double, вся плавающая точка тихо мирно свалится в эмуляцию и никто этого не заметит. И fastmath нужно использовать, иначе даже на аппаратном FPU куча программного кода генерируется а не команды FPU и т.д. и т.п.
                                                При частоте 70 кГц ШИМ на 2xx даст вам шаг регулирования порядка 0.1%. На практике будет раза в четыре больше, т.к. у вас там фильтры на гораздо более низкие частоты среза, а регулировать вы можете хоть каждый шаг. Более того, уж если хочется извратиться, то управляем таймером на глубину 16, например, шагов с dithering (если очень хочется, то можно даже автоматизировать через DMA) и наслаждаемся красивым кодом и стабильным шагом регулирования порядка 0.09% и лучше — куда уже точнее?! И делать это можно даже на нулевой серии. Отлично работает уже не в одном проекте.
                                                Раз уж бросаться в управление преобразователем голыми руками, то почему бы не применить лучшие техники, тем более, что вы рассчитываете на радиолюбителей и хотите низкой цены. HRTIM это барство ;)

                                                P.S. Все читающим — гуру STM32 ищет очень высокооплачеваемую работу.
                                                  0
                                                  Зачем выдумывать эти извращения, когда можно сделать проще, быстрее и дешевле? 0,09% это прекрасно, а если 500 кГц? Вот HRTIM прекрасно позволит получить необходимый шаг и на такой частоте.

                                                  Еще интересный вопрос — вот мне надо 4 комплементарные пары, которые работают на разных частотах, где их в F0 взять то? А если надо сдвинуть фазу придется? Рисовать таблички что ли? Вот это решение от сенсея!))

                                                  Зачем вы double приплели я вообще не понял. F334 — это серия для управления силовыми преобразователями, двигателями и подобным, то есть это работа с float, даже 32-х битные числа тут не нужны.

                                                  P.S. гуру не ищут работу, им ее стабильно предлагают и так.
                                                    –3
                                                    double к тому, что во всех сторонних более-менее сложный проектах, что я видел, были ошибки с неявным приведением к double и откатом к программному FPU.
                                                    P.S. Гуру без работы не сидит и даже типа-директор, но в «Советской России работа работает тебя» и гуру всё время пытаются предложить работу за 40 тысяч и искренне понимают, что не так, и потому немного саморекламы в неожиданных местах не повредит :)
                                        +2
                                        Отличная статья. Прям захотелось обратно в эмбеддед вернуться.
                                        На счет регулировки выходного напряжения, лучше что то вроде ПИД сделать.
                                        Хотя, допустим, светодиодам это не нужно.
                                          0
                                          Спасибо) ПИД наверное перебор, хотя зависит от типа нагрузки, а вот ПИ-регулятор наверное самый популярный и достаточный вариант. Про него расскажу на следующей топологии, вероятно boost.
                                            +1
                                            Ну если сопротивление нагрузки может меняться резко да на несколько порядков, то полный ПИД не помешает. Если она практически постоянная то ПИ вполне сойдёт.
                                          +1
                                          А в токовую поцикловку тот контроллер сможет? Есть ли смьісл несведущему человеку с ним заморачиваться програмировать для одного устройства или лучше по-старинке спецмикруху за ноги дергать?
                                            0
                                            Как всегда отличная статья. А что использовали в качестве драйвера? Готовую ИС или рассыпуху? Что вы думаете об использовании драйверов, и об эффекте опрокидования в драйвере?
                                            (В полевых транзисторах не последнюю роль играет эффект Миллера. Если транзистор коммутируется слишком быстро, а сопротивление цепи управления велико, напряжение на затворе может «подскакивать» на значительную (и даже опасную величину). Затвор, присоединенный к выходу драйвера к тиристорной p-n-p-n-структуре. Если приложенное напряжение окажется выше напряжения питания управляющего каскада, всего на 0,3 В, наступает эффект опрокидывания, паразитной тиристорной структуры, вывод питания замыкается на общий. Защелка не может восстановиться пока драйвер не останется без питания, ну или пока из него весь дым не выйдет.) Ссылка

                                            Может не в тему, но хотел бы спросить что бы вы сделали в следующем кейсе.
                                            Я балк собрал на 12 В до 2А на L7987, Dity до 100%, питаю автомобильным питанием 13.5 — 15 в. Все бы нечего, только в некоторых случаях, когда без АКБ запускают на вход может подаваться выпрямленный диодом по входу полупериод 50гц, амплитудой > 60 вольт. Ненагруженное напряжение с генератора. А надо чтобы железка работала. Я по входу поставил ряд кондеев электролитов, и TVS диод, но по габаритам кондеи больше чем на 50в не поставить. Попробовал специальные суржеры типа LT4356, хорошая защита, но не от перенапряжения, они полевик в лишейник превращают и он греться начинает при привышении напряжения и нагрузке. Все же думаю решать задачу влоб, давить TVS диодом мощным, и надеятся что в отличие от корпуса SMА корпус SMС выдержит.
                                            Может хендмейд преобразователь как у вас собрать до 100 вольт на входе или еще как решить? Что скажите?
                                              0
                                              Схему силовой платы можно посмотреть в предыдущих статьях, он из серии 1ED от Infineon — 1 МГц и 6/-10А + гальваническая индуктивная развязка, по напряжению 1200В ключи может дергать. В данный драйверах печатный транс + комплементарная пара полевиков внутри.

                                              В принципе мощность мелкая, можно поставить ключик на 100В и кондеры и уже проблем не будет, а так решение давить кратковременные выбросы TVS-ом вполне логичное, если не хочется переделывать buck в более высоковольтный.
                                              +1
                                              Урааа!) Долгожданная статья! Все как обычно интересно и просто) С нетерпением ждем продолжения ваших статей. Так же про ютубчик не забывайте!) Так же хотелось бы чтоб Вы напомнили про TMS320, т.к. в структурке упоминалось про DSP…
                                                0
                                                TMS320F28 такой же DSP как F334 на самом деле) Вообще я планирую сделать такой же модуль на TMS320F280049 новеньком, чтобы они были pin-to-pin совместимы и тоже про них рассказать. Правда это будет не завтра, но будет 100%.
                                                +5
                                                Шум на осциллографе — это не следствие отсутствия керамики, с ней кстати будет ещё больше иголок. Это проблема упрощённой системы обратной связи.
                                                Обратная связь для таких преобразователей — это отдельный увлекательный квест, его хватит на несколько публикаций, особенно если планомерно наступать на все известные грабли.
                                                Явная и очевидная грабля — это скорость реакции.
                                                Ну не нужна она тут, с таким громадным отставанием в росте тока на дросселе. Фиксировать напряжение можно и нужно, но вот реагировать на него с подобной скоростью — излишне. Резко реагировать нужно на предельное значение тока и напряжения — выставляется отдельной опцией на самом ацп. Считать обратную связь проще сначала на бумажке, и только потом в цифре.
                                                bsvi.ru/kompensaciya-obratnoj-svyazi-v-impulsnyx-istochnikax-pitaniya-chast-1
                                                В данном случае можно немного схитрить, и считать сумму массива, допустим за 10 отчётов (или больше) — за одну точку «измерения», которая будет воздействовать на глубину шима.
                                                Можно накинуть цифровых фильтров, мк для них и предназначен.
                                                Можно и нужно реализовать программный старт/стоп — там вас тоже ждут откровения.

                                                Общий комплекс мер подавления нежелательного шума должен демонстрировать стабильное потребление тока внешнего источника, при постоянной мощности нагрузки.

                                                И ещё — километры и киловольты не относятся к характеристикам мк, вообще ни как.
                                                  +1
                                                  1) Повешенная керамика отлично спасла от иголок меня, хотя о обратной связи я тоже в статье говорил, но тут это не критично, т.к. характер нагрузки активный.

                                                  2) Вы что-то путаете, с цифровым управлением весь квест сводится к подбору коэффициентов ПИ-регулятора и фильтрации данных с АЦП.

                                                  3) Статью эту видел, только она для аналогового управления, так что не понял к чему она тут. В случае цифры достаточно поставить ФНЧ и дальше отфильтровать с данных АЦП все граничные значения.
                                                    +3
                                                    Статью эту видел, только она для аналогового управления, так что не понял к чему она тут.

                                                    Аналоговое управление — это видимость, тут главное общее — индуктивность в цепи обратной связи. Любая аналоговая схема прекрасно замещается в цифре. Это даже проще и нагляднее чем сразу цифра, или алгоритм.
                                                    Вы что-то путаете, с цифровым управлением весь квест сводится к подбору коэффициентов ПИ-регулятора и фильтрации данных с АЦП.

                                                    ПИ-регулятор — это и есть та самая аналоговая часть в цифровом представлении, с положительными и отрицательными обратными связями, с задержкой, и средой накопления энергии. Вам нужно просто взглянуть на него под немного иным углом.
                                                    Повешенная керамика отлично спасла от иголок меня

                                                    Есть старый хороший анекдот про плача с очень острым топором — а теперь кивни.
                                                    Наличие нижнего транзистора в преобразователе — превращает его в активный трансформатор. Где выходное напряжение жёстко связано с входным через коэффициент шима. Это означает что при условии повышения напряжения на выходе при неизменном шиме — на входе блока будет повышаться напряжение. Обратный процесс однако.
                                                    У вас это дело очень ярко проявляется — ток потребления на бп пляшет.
                                                      +2
                                                      Все, теперь понял о чем вы — buck в обратную сторону это как раз boost же.
                                                      Общий посыл ваш понял, надо будет внимательнее и правда еще посмотреть в статью без скепсиса. Благодарю за аргументированные доводы)
                                                    +1
                                                    Всё правильно, но если описать всё что вы тут изложили на пальцах, то нужна уже не статья а книжка. Надо писать цикл и продвигаться от простого к сложному. Иначе слишком длинно получится, да и у читающего вспухнет мозг от большого количество новой информации. Нужно время, чтобы она в голове уложилась.
                                                      0
                                                      нужна уже не статья а книжка

                                                      Как правило мозг кипит уже на разборе работы ёмкости и индуктивности. Это примитив, самое начало. Но далеко не все могут понять простую вещь — что запасается энергия, а не вольты и амперы.
                                                      Недавно на одном из популярных форумов обсуждался закон ома. Экспертов было огромное количество, каждый со своим мнением. Порвали три баяна, и баню сожгли на деревне. По этому простые вещи нужно подавать как есть. Тем кому интересно — копнут глубже. А огромное количество «экспертов» увидят непонятную длинную формулу, и самопроизвольно поделятся на ноль в своих мнениях.
                                                        –1
                                                        Но далеко не все могут понять простую вещь — что запасается энергия, а не вольты и амперы.

                                                        Ну а что не так, если в формулу энергии в конденсаторе входит напряжение на нём, а в энергию индуктивности — ток? И из закона сохранения энергии начинает следовать стремление конденсатора сохранять напряжение и индуктивности — ток.
                                                        Разверните противоположную точку зрения.
                                                    0
                                                    Спасибо большое, отличная статья! Все наглядно и по полочкам разожено, буду рекомендовать начинающим.
                                                    Добавлю только про мертвое время (dead-time). Особо его подкручивать имеет небольшой смысл в hard-commutated конвертерах. Главное чтобы не было сквозняка или наоборот разрыва выходного тока.
                                                    А в резонансных ZVS конвертерах dead-time имеет гораздо большее значение, потому что именно тогда происходит перезаряд емкостей транзисторов и собственно достигается мягкая коммутация. Для получения предельной эффективности приходится вручную настраивать dead-time в каждой рабочей точке и загонять это все в виде таблиц в микропроцессор. В этим состоит огромное приемущество цифрового управления, что можно реализовывать нелинейные зависимости для достижения оптимальных режимов.
                                                      0
                                                      Отличная статья. Вопрос есть. Судя по картинке, у вас БП Korad. Крутилка нормально работает или начала уже дурить?
                                                        0
                                                        Пока еще проблемы с ним не вылезли, крутилка адекватно работает, использую уже года 2, может чуть дольше.
                                                        +2

                                                        А почему у вас на Vin какие-то пики?


                                                        Еще интересно, какие в итоге получились пульсации и какой шум от переключений транзисторов? На картинках не видно — там графики от нуля. И еще, не описаны процессы, которые происходят в правой части схемы во время dead-time и как это отражается на Vout?


                                                        Когда мне нужен был DC/DC, я пошел на st.com и посчитал его себе в их программе. Там нужно было учитывать устойчивость получившейся схемы. Я в этом разбираться не стал, полагаясь на программу, а у вас вообще в статье про это ничего нет. Может быть, проясните этот вопрос?

                                                          0
                                                          Первое правило клуба частотной стабильности — не писать в статьях о частотной стабильности.
                                                            0
                                                            А что о ней писать?) Аналоговой части тут нет, а в цифре регулятор простейший для примера. Когда про ПИ буду писать, то там вопрос стабильности ОС подробно рассмотрю, там уже без базового матана и ТАУ особо не обойтись.
                                                              +2
                                                              То, что у вас обратная связь сделана с дискретизацией на АЦП, строго говоря, не отменяет необходимости обеспечивать ее стабильность. В большинстве случаев прокатывает, но именно, что в большинстве, а не строго всегда.
                                                              Например, как пишут ниже, при низкой нагрузке. Или могут быть интересные эффекты при коэффициенте заполнения сильно выше 50%.
                                                            +1
                                                            На осциллограммах видно где нули, слева экрана стрелки — это как раз ноль для конкретного канала. Пики на транзисторах в пределах 20В, но это просто от лабораторника до самой платы длинные тонкие провода, а значит там паразитная индуктивность достаточно высокая.

                                                            dt для LC-фильтра особо и не заметен, т.к. во время паузы LC-контур подпирается паразитным диодом нижнего ключа.
                                                              0
                                                              На осциллограммах видно где нули

                                                              где нули то видно, но хочется посмотреть на колебания Vout вокруг 5 вольт, а этого не видно из за масштаба. Вот такого плана картинка меня интересует:

                                                                0
                                                                А понял, пульсации. У меня они были максиму +-122 мВ, если интересное, то завтра или в понедельник могу снять осциллограмму и скинуть. Главное не забыть))
                                                            +2
                                                            Скажите, правильно ли я понимаю, что у вас vt2 открыт всегда, пока что vt1 закрыт? (dead time не учитываем) Если это так, то при коэффициенте заполнения меньше 0.5 кпд преобразователя будет проигрывать классической схеме с диодом, потому что при после открытия vt2 сперва запасенная энергия в дросселе будет отдаваться в нагрузку, а потом ток потечет в обратную сторону, разряжая выходной конденсатор.
                                                              0
                                                              Насколько я понимаю, это нигде не сказано, но подразумевается, что девайс н когда не будет работать на маленькую нагрузку)
                                                              Но в целом да, отдельные чипы buck controller уже довольно давно делаются по схеме current-mode, а не voltage-mode, и там регулировка идёт с учётом пиковых токов как через нижний, так и через верхний транзистор. На самом деле, какой-то обратный ток через нижний транзистор на малых нагрузках допустим, и КПД будет все ещё выше, чем у диода, но контролировать и ограничивать его, конечно же, нужнля если мы говорим об универсальном, а не об узкоспециализированном устройстве.
                                                                0
                                                                Синхронные выпрямители «из коробки» с режимом прерывистого тока вообще не работают, там нужны специальные решения.
                                                                0
                                                                Мелкие придирки.
                                                                УГО диода Шоттки на первых рисунках скорее напоминает УГО двунаправленного стабилитрона. Внутренние диоды МОП транзисторов кстати правильно нарисованы. А в целом статья интересная и популярно изложена.
                                                                Правда если писать статью для начинающих, хорошо бы немного подробнее про снаббер рассказать. Они не обязаны знать что это такое, зачем нужен и как работает.
                                                                  0
                                                                  У двунаправленного стабилитрона «усики» вроде не перпендикулярно линии катода, а под углом 45 градусов, но могу о ошибаться как оно правильно) Про снаббер по хорошему надо статью написать, ибо штука полезная и его надо уметь считать.
                                                                    0
                                                                    со стабилитроном мне кажется наоборот. Обратите внимание как у внутри встроенных МОП транзисторов они стоят в вашей же схеме. Там обычные шоттки используются насколько я знаю.
                                                                      +2
                                                                      Во да, внутри транзистора вроде и неправильно. Внутри действительно Шоттки, надо будет УГО поправить. Я его скопировал с рабочей библиотеки года 3 назад, даже особо внимания не обращал, но таки порядок должен быть)
                                                                        0
                                                                        Согласно нашему ГОСТу вы правы, извиняюсь за беспокойство. Но у буржуев разные обозначения встречал.
                                                                  0
                                                                  Уточню смою мысль: vt2 должен быть открыт только в то время, когда ток через него будет заряжать выходной конденсатор, а не все время пока что закрыт vt1. Именно так работает классический диод, но он плох из-за неустранимого падения напряжения на нем в открытом состоянии. Cхема в нынешнем виде будет иметь никудышный кпд при малом выходном напряжении и малой нагрузке, попробуйте замерить ток потребления преобразователя без нагрузки. Иными словами замена диода на синхронный выпрямитель реализована не корректно, дополнительно требуется контроль направления тока через vt2.
                                                                    +1
                                                                    Уточню смою мысль: vt2 должен быть открыт только в то время, когда ток через него будет заряжать выходной конденсатор, а не все время пока что закрыт vt1.

                                                                    Поскольку всё делается из рассчёта на неразрывность (>0 в любой момент времени, а точнее — пульсации не более 30%) тока дросселя, то ситуация с разрядом выходного фильтра через «нижний» транзистор невозможна в принципе.
                                                                      0
                                                                      Это не так. Запустите представленную схему без нагрузки: U вх=20В, U вых=12, и измерьте ток через vt1. Потом замените vt2 на диод и посмотрите на то, как изменится ток. При использовании диода на холостом ходу ток через vt1 будет около нулевым, а при работе с vt2 он будет вполне ощутимым, при этом схема с точки зрения кпд начинает работать как линейный регулятор.
                                                                        +1

                                                                        Как вы полагаете, почему в классическом step-down внизу используется диод, а не ключ? Очень просто: диодом не нужно управлять, он сам понимает когда закрываться, что бы не было обратного тока. Для полноценной замены диода на ключ в схему последовательно с дросселем нужно добавить шунт и при помощи быстродействующего операционника вычислять время, когда ток на дросселе меняет направление, и в этот момент нижний ключ нужно запирать.

                                                                    0
                                                                    Скажите пожалуйста модель пинцета, что на фото с проверкой индуктивности дросселя.
                                                                      0
                                                                      Smart Tweezer Collibri. Советую смотреть на ebay, там можно купить его в пределах 10к. Я покупал в Финляндии с возвратом налогов за 200 евро, а в отечественных магазинах от стоит 20-25к, что определенно лютая дичь и жадность))

                                                                      Но пинцет стоит своих денег, настолько RLC уже и не помню когда использовал последний раз, этот и удобнее и точности хватает даже индуктивность дорог от 10 нГн измерять.
                                                                        +1
                                                                        Спасибо, нашёл, очень хороший инструмент)
                                                                      0
                                                                      вопрос немного не в тему, извините.
                                                                      задумался как расово-правильно остановить ШИМ

                                                                      void tim1_stop (void)
                                                                      {
                                                                      while ((????????????){ // как здесь правильно дождаться конца счета регистра ARR????
                                                                      TIM1->CCER &= ~TIM_CCER_CC1E;
                                                                      TIM1->CCER &= ~TIM_CCER_CC1NE;
                                                                      TIM1->BDTR &= ~TIM_BDTR_MOE;
                                                                      TIM1->CR1 &= ~TIM_CR1_CEN;
                                                                      }
                                                                      }
                                                                        0
                                                                        Дождаться окончание периода, поймать флаг о данном событие и выключить его. Еще стоит задуматься «а надо ли выключать?», уверен что во многих случаях можно установить duty в ноль, что более рассово-правильно, т.к. вкл/выкл таймера происходит не мгновенно, а запись duty за такт.
                                                                        –3
                                                                        Я про DT в 104 мс как-то не очень уловил. При частоте коммутации в 100 кГц (жёлтая надпись 102.4 кГц — это же как раз частота переключений ключа?) период будет всего 10 мкс, и 1% от этого — примерно 100 нс. Да и на скриншоте цена деления времени 40 нс вроде как (W сверху справа).
                                                                          0
                                                                          Так везде, в том числе и в комментариях кода, написаны наносекунды. Про 40 нс так же и в тексте написано.

                                                                          P.S. если вы увидели опечатку (не вижу ее почему-то), то стоит написать как все в лс, а не загромождать комментарии текстом, который не очень касается основной темы статьи.
                                                                          +1
                                                                          Да, как выше заметили, в статье не хватает расчетов условий когда continuous condution переходит в discontinuous, а также объяснения чем это грозит. А вообще, расчет обратной связи это, пожалуй, самая интересная часть в проектировании, изучение которой вы незаслуженно обошли стороной. Вы удивитесь, но control theory совершенно одинаково работает и для аналога и для цифры, в цифре у нас разве что немного больше возможностей для творчества, пока вычислительная мощность позволяет, конечно же.
                                                                            0
                                                                            Для более подробного ознакомления с DCM и CCM я оставил ссылку на книжку. Не уже ли все настолько ленивые, что мне нужно текст из книжки копипасть в статью?)) Статья и так объемная вышла, а увеличивать ее объем еще в 2 раза смысла не вижу.

                                                                            Я перед собой ставлю задачу лишь заинтересовать тех, кому это нужно, чтобы они пошли дальше и знали что гуглить и про что читать, а не написать Войну и Мир в «кратком изложение».
                                                                            +1
                                                                            Возможно, я не заметил, но не затронута тема времени обратного восстановления диода. Если при включении верхнего транзистора диод еще будет восстанавливаться, то получим КЗ. Диоды Шоттки, условно, имеют время обратного восстановления равное 0, но для высоковольтных сборок это уже не так.
                                                                              0
                                                                              Для высоковольтных сборок есть SiC и частоты там обычно десятки кГц, так что можно пренебречь в простых задачах.
                                                                              0
                                                                              Новичковый вопрос: почему нужно задействовать два канала ШИМ? Нельзя обойтись одним каналом и инвертором?
                                                                                +1
                                                                                Потому что вам не нужны сквозные токи, возникающие в момент, когда один транзистор еще не полностью закрылся, а второй уже начал открываться. Для того, чтобы так не было, нужно, чтобы тайминг двух каналов быть чуть-чуть хитрее, чем меандр и инвертированный меандр.
                                                                                  0
                                                                                  Выше уже ответили. Могу добавить, что на логике обычной можно сделать аппаратный dead-time, но это уже куча рассыпухи, а не один инвертор.
                                                                                    0
                                                                                    У меня получается, если совсем «в лоб», простейший счётчик чёт-нечет (чтобы второй транзистор всегда открывался последним, а закрывался первым) и 30 метров провода для 100нс задержки. Ну да, не совсем то, что хотелось бы, уж очень мнимое упрощение получается.
                                                                                      0

                                                                                      Велосипед уже изобретен, и без 30 метров проводов)
                                                                                      Нижняя схема на рисунке. Делает из одного сигнала два неперекрывающихся. Dead time регулируется числом инверторов или конденсаторами на выходе инверторов.
                                                                                  0
                                                                                  Кстати, stm32f334 discovery уже содержит в себе схему buck-boost преобразователя.
                                                                                  Так что если просто поиграться — то делать ничего не надо.

                                                                                  image
                                                                                    +1
                                                                                    Кому просто поиграться — не покупает узкоспециализированные отладки, а берет плату на f103 с Китая за 100 рублей и играется))

                                                                                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                                  Самое читаемое