Вы находитесь на странице: 1из 23

08.02.

2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

Разработка Администрирование Дизайн Менеджмент Маркетинг Гиктаймс Разное Войти Регис

NordicEnergy 15 ноября 2017 в 15:31

DC/AC инвертор: принцип работы, схемотехника, встроенное ПО


Программирование микроконтроллеров, Схемотехника, Производство и разработка электроники, Электроника для начинающих

Из песочницы

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

Думаю многие из вас наверняка видели рекламу, либо читали статьи, где была фраза «чистый синус». Вот именно о нем и пойдет речь, но
маркетинговой составляющей, а о исключительно технической реализации. Я постараюсь максимально понятно рассказать о самих принци
работы, о стандартных (и не очень) схемотехнических решениях и самое главное — напишем и разберем ПО для микроконтроллера STM3
которое и сформирует нам необходимые сигналы.

Почему STM32? Да потому, что сейчас это самый популярный МК в СНГ: по ним много обучающей русскоязычной информации, есть куча
примеров, а главное эти МК и средства отладки для них — очень дешевые. Скажу прямо — в коммерческом проекте я бы поставил только
TMS320F28035 или подобный DSP из серии Piccolo от TI, но это уже совсем другая история.

Важно одно — STM32 позволяет стабильно управлять простыми «бытовыми» силовыми преобразователями от которых не зависит судьба
работа какой-нибудь АЭС или ЦОДа.

Вот такую картину управляющих сигналов необходимо получить, чтобы превратить ток постоянный в переменный. И да — тут именно сину
том фильме: «Видишь суслика? — Нет. — А он есть...»

Интересно узнать каким образом формируется синус? Хочется узнать как все-таки качают нефть киловатты энергии? Тогда добро пожалова
кат!

1. Топологии для формирования синусоидального сигнала


Если спросить у толпы электронщиков: «Как можно сформировать синусоидальный сигнал?», то посыпятся предложения с десятком разли
методов, но какой нужен нам? Давайте оттолкнемся от изначальной задачи — нам нужно превратить, например, 380В 10А в переменное
напряжение 230В. В общем это «классический» случай, его мы можете увидеть в любом хорошем on-line UPS или инверторе. Получается н
надо преобразовать мощность около 4 кВт да еще и с хорошим КПД, не слабо, да? Я думаю подобное условие поубавит количество вариа
«рисования» синуса. Так что же нам остается?

В силовых преобразователях до 6-10 кВт применяется две основные топологии: полный мост и «полумост» со сквозной нейтралью. Выгляд
следующим образом:

https://habr.com/ru/post/358172/ 1/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр
1) Топология со сквозной нейтралью

Данная топология очень чаще всего встречается в бюджетных ИБП с синусом на выходе, хотя и такие авторитеты как APC и GE не брезгую
применять ее даже на достаточно больших мощностях. Что же их побуждает к этому? Давайте рассмотрим достоинства и недостатки данно
топологии.

Плюсы:
Минимально возможное количество силовых транзисторов, а значит потери в 2 раза меньши и стоимость устройства тоже ниже

Сквозной ноль. Это упрощает процесс сертификации, особенно CE и ATEX. Связано это с тем, что сквозной ноль позволяет системам
защиты по входу (например, УЗО) срабатывать так же при возникновение аварии в выходных цепях после преобразователя

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

Минусы:
Необходимость двухполярного источника питания. Как видите на схему инвертора надо подавать ±380В и еще ноль

Удвоенное количество высоковольтных конденсаторов. Высоковольтные конденсаторы большой емкости и с малым ESR на мощностя
кВт начинают составлять от 20 до 40%
стоимости компонентов

Применение электролитических конденсаторов в «делителе». Они сохнут, подобрать конденсаторы с одинаковыми параметрами практ
нереально, а если учесть, что параметры электролитов меняются в процессе эксплуатации, то и бессмысленно. Заменить на пленку м
но дорого

Основные плюсы и минусы определены, так когда необходима это топология? Мое субъективное мнение: на мощностях до 500-1000 Вт, ко
основополагающим требованием является стоимость, а не надежность. Явный представитель такого ширпотреба — это стабилизаторы от
электроника»: дешево, кое-как работает да и ладно. Для 60% потребителей в нашей стране этого достаточно и доступно по цене. Делаем
выводы.

2) Мостовая топология

https://habr.com/ru/post/358172/ 2/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

Мостовая топология… наверное самая понятная и самая распространенная топология в силовых преобразователях, а главное доступная
разработчикам даже с небольшим опытом. После 10 кВт вы не встретите ничего другого кроме моста одно- или трехфазного. За что же его
любят?

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

Входная емкость требуется в разы, а то и на порядок меньше. Необходимо лишь обеспечить расчетное значение ESR. Это позволяет
использовать пленочные конденсаторы при сохранение себестоимости. Пленочные конденсаторы — не сохнут, лучше ведут в суровых
температурах, рабочий ресурс на порядок выше, чем у электролитов

Минимальные пульсации напряжения на транзисторах, а значит можно применить транзисторы на меньшее напряжение

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

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

Повышенная сложность драйвера, особенно при требованиях к наличию гальванической развязки

Как видите из реальных минусов мостовой топологии лишь повышенное требование к охлаждению транзисторов. Многие подумают: «Тепл
выделяетсябольше — значит КПД ниже!». Не совсем так… За счет уменьшенных выбросов ЭДС и более «жесткой» системы управления КП
двух приведенных топологий примерно равный.

В 70% случаев мне приходится применять мостовую схему не только в DC/AC инверторах, но и в других преобразователях. Это связано с т
что проектирую в основном промышленные решения и все чаще для европейских заказчиков, а там принято на дорогие промышленные
устройства давать гарантию 5-15 лет. Классическое требование: «Хотим железку, чтобы можно было давать гарантию 10 лет», тут уже выб
не приходится. Конечно, когда люди хотят устройство с минимальной ценой, то тут необходимо уже отталкиваться от конкретной задачи пр
выборе топологии.

Небольшой итог: в данной статье будет приведено ПО для работы мостового преобразователя (Н-мост или Full Bridge), но сам принцип
формирования синуса одинаковый для всех топологий. Код можно будет также адаптировать и под 1-ю топологию, но это вы уже сами.

2. Формирование переменного тока с помощью мостового преобразователя

https://habr.com/ru/post/358172/ 3/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

Для начала давайте разберем как вообще работает мостовой преобразователь. Смотрим на схемку и видим транзисторы VT1-VT4. Они
позволяют нам подавать на нашу абстрактную нагрузку (резистор, например) тот или иной потенциал. Если мы откроем транзисторы VT1 и
то получится следующее: VT4 один конец нагрузки подключит к минусу (GND), а транзистор VT1 подключит к +380В, на нагрузке появится
разность потенциалов «380В — 0В», которая не равна нулю, а значит через нагрузку начнет протекать ток. Я думаю все помнят, что ученые
договорились — ток протекает «от плюса к минусу». Получаем такую картину:

Что мы получили открыв VT1 и VT4? Мы подключили нашу нагрузку к сети! Если резистор заменить на лампочку, то он она бы просто загор
И еще мы не просто включили нагрузку, а определили направление тока, протекающего через нее. Это очень важно! А что было в это врем
и VT3? Они были закрыты… совсем… намертво… Что будет если все таки VT2 или VT3 были так же открыты? Смотрим:

https://habr.com/ru/post/358172/ 4/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

Предположим, что открылись транзисторы VT1, VT4 и VT2. Вспоминаем закон Ома, смотрим сопротивление канала у высоковольтных
транзисторов, например, IPP60R099P7XKSA1 и видим 0.1 Ом, у нас их 2 последовательно — значит сопротивление цепи VT1 и VT2 у нас о
0.2 Ом. Теперь посчитаем ток, которые пойдет через эту цепь: 380В / 0.2 Ом = 1900А. Думаю всем понятно, что это КЗ? Так же думаю всем
понятно почему VT2 и VT3 должны быть закрыты?

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

Зачем же нужны тогда транзисторы VT2 и VT3? Помните я писал, что очень важно направление тока? Давайте вспомнит что такое перемен
ток. Собственно это ток, который имеет что-то переменное, в данном случае направление тока. У нас в розетке протекает ток, который мен
свое направление 100 раз в секунду. Давайте теперь закроем VT1 и VT4, а затем откроем транзисторы VT2 и VT3 и получим такую картину

https://habr.com/ru/post/358172/ 5/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

Как видите направление тока (обозначено стрелками) изменилось на противоположное. Использование моста позволило нам менять
направление тока, о чем это говорит? Да, мы получили переменный ток!

Прошу обратить внимание, что у моста есть как бы 2 диагонали: первая диагональ образована VT1+VT4, а вторая диагональ образована с
помощью VT2+VT3. Данные диагонали работают по очереди, коммутирую ток сначала в одну сторону, а потом в другую.

Вот мы получили переменный ток, скажите вы, но не все так просто… У нас есть стандарт — сетевое напряжение. Оно нормируется двумя
основными параметрами: напряжение и частота. Давайте пока разберемся с частотой, ибо вопрос напряжения простой и чисто схемотехни

И так частота… что о ней известно — она 50 Гц (бывает 60Гц в Штатах). Период сигнала равен 20 мс. Синусоида штука симметричная в да
случае, а значит наши 2 полуволны (положительная и отрицательная) имеют одинаковую длительность, то есть 10 мс + 10 мс. Надеюсь тут
понятно.

Что это значит в физическом смысле? Да то, что нам нужно менять направление тока в нагрузке каждые 10 мс. Получаем, что сначала у на
открыта 10 мс диагональ VT1+VT4, а затем она закрывается и на следующие 10 мс открывается диагональ VT2+VT3.

Что значит открыть транзистор и какой сигнал на него подавать

И так, для того, чтобы у нас мост менял направление тока каждые 10 мс нам нужно подать на него ШИМ сигнал, период которого равен 20
скважность 50%. Это значит, что у нас из 20 мс плечо половину времени (10 мс) открыто и проводит ток, а другую половину закрыто. Подав
такой ШИМ нам надо на все ключи, но с одним условием — на диагональ VT1+VT4 мы подаем прямой ШИМ, а на диагональ VT2+VT3 уже
инверсный. Если говорить более по-умному, то сигнал, подаваемый на диагонали должен иметь сдвиг 1800. Я думаю в этот момент у вас го
закипела в попытках понять текст, поэтому смотрим на его визуальное представление:

https://habr.com/ru/post/358172/ 6/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

Теперь все понятно? Нет? Тогда подробнее… Как видите я отметил специально моменты открытия и закрытия транзисторов: открываются
«плюсе» и закрываются на «минусе». Также сигналы противоположны, то есть инверсные: когда синий сигнал «плюс», то зеленый сигнал
«минус». Синий сигнал мы подаем на один на одну диагональ, а зеленый сигнал на другую — как видно на осциллограмме, наши диагонал
никогда не открываются одновременно. Переменный ток готов!

Смотри на период. Специально показал осциллограмму с выходов контроллера, чтобы мои слова не были абстракцией. Период сигнала
составляет 20 мс, одна диагональ открыта 10 мс и создает положительную полуволну, другая диагональ так же открывается на 10 мс и созд
уже отрицательную полуволну. Теперь надеюсь всем понятно, а кто и сейчас не понял — пишите в ЛС, проведу для вас индивидуальное за
на пальцах. В подтверждение моих слов осциллограмма показывает наши заветные 50 Гц! Только расслабляться рано…

Мы получили переменный ток с частотой 50 Гц, но в розетке у нас синусода, а тут меандр — не дело. Формально можно подавать меандр н
выход и питать им большинство нагрузок, например, импульсному блоку питанию все равно: синус или меандр. То есть для включения ноут
телефонов, телевизоров, телефонов и прочего вам уже хватит, но если вы подключите двигатель переменного тока, то все будет очень пло
он начнет греться и КПД его ощутимо меньше, а в итоге скорее всего сгорит. Вы думаете у вас нет двигателей дома? А компрессор холодил
А циркулярный насос отопления? Последние вообще горят как будто из дерева сделаны. Такая же ситуация с глубинными насосами для ск
да и вообще много с чем. Получается, что синусоидальный сигнал на выходе инвертора, стабилизатора или ИБП все таки бывает важен. Ч
— надо его создать! Сейчас начнется совсем взрыв мозга…

3. Формирование синусоидальной формы сигнала с помощью ШИМ


Если говорить откровенно, то я не знаю как данный раздел преподнести на доступном языке. Вдруг кто не поймет, то прошу вас или погугли
дополнительно, или написать в комментарии или ЛС — попытаюсь персонально вам объяснить. Глаза боятся, а руки делают…

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

https://habr.com/ru/post/358172/ 7/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

Видим 2 оси: одна ось с периодом пи, пи/2 и далее, вторая с амплитудой от -1 до +1. В нашей задаче период измеряется в секундах и соста
20 мс или 10 мс на каждую полуволну. Тут все просто и понятно, а вот с амплитудой веселее — просто примите как аксиому, что амплитуда
от 0 до 1000. Это значение скважности, которую устанавливает микроконтроллер, то есть 100 — это 10%, 500 — 50%, 900 — 90%. Логика д
понятна. В следующей главе вы поймете почему от 0 до 1000, а пока перестроим наш график под наши значения:

https://habr.com/ru/post/358172/ 8/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

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

По оси Х у нас время, а по оси Y скважность нашего ШИМ-сигнала. Нам нужно нарисовать синус с помощью ШИМа. Вспоминаем геометрию
школе, как мы строили графики? Правильно, по точкам! А сколько точек? Давайте построим синус по нескольким точкам О1(0,0) + О2(5,100
О3(10,0) + О4(15, -1000) + О5(20, 0) и получаем такой синус:

https://habr.com/ru/post/358172/ 9/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

Построили и видим, что в принципе данный сигнал больше похож на синус чем обычный меандр, но это все равно не синус пока что. Давай
увеличим количество точек. Это кстати называется «дискретность сигнала» или в данном случае «дискретность ШИМа». А как узнать коорд
этих точек? С крайними то просто было…

Расчет значений для формирования синуса


Как выше я говорил — синус у нас вполне себе симметричный. Если мы построим 1/4 периода, то есть от 0 до 5 мс, то дублируя этот кусок
дальше — мы можем строить синус бесконечно долго. И так формула:

И так по порядку:

n — значение скважности в данной дискретной точке

A — амплитуда сигнала, то есть максимальное значение скважности. У нас это 1000

pi/2 — 1/4 периода синуса попадает в pi/2, если считаем 1/2 периода, то pi

x — номер шага

https://habr.com/ru/post/358172/ 10/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

N — количество точек

Давайте для примера сделаем удобно условие, что у нас 5 точек. Получается у нас 1 шаг = 1 мс, это позволит легко график построить. Шаг
дискретизации считается просто: период в котором строим график (5 мс) делим на количество точек. Давайте приведем формулу к человеч
виду:

Получаем шаг дискретизации 1 мс. Формулу для вычисления скважности оформим, например, в excel и получим следующую таблицу:

Теперь вернется к нашему графику синуса и построим его снова, но уже для большего количества точек и посмотрим как он изменится:

https://habr.com/ru/post/358172/ 11/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

Как видим сигнал куда больше похож на синус, даже с учетом моего мастерства в рисовании, а точнее в уровне лени)) Я думаю результат н
требует объяснений? По результатам построения выведем аксиому:

Чем больше точек, чем выше дискретизация сигнала, тем идеальнее форма синусоидального сигнала

И так, сколько же точек будем использовать… Понятно, что чем больше, тем лучше. Как посчитать:

1. Использую для статьи старенький микроконтроллер STM32F100RBT6 (отладка STM32VL-Discovery), его частота 24 МГц.

2. Считаем сколько тактов будет длиться период 20 мс: 24 000 000 Гц / 50 Гц = 480 000 тиков

3. Значит половина периода длится 240 000 тиков, что соответствует частоте 24 кГц. Хотите повысить несущую частоту — берите камень
шустрее. 24 кГц наши уши все таки услышат, но для тестов или железки, стоящей в подвале пойдет. Чуть позже я планирую перенести
F103C8T6, а там уже 72 МГц.

4. 240 000 тиков… Тут логично напрашивается 240 точек на половину периода. Таймер будет обновлять значение скважности каждые 100
тиков или каждые 41,6 мкс

С дискретностью ШИМа определились, 240 точек на пол периода с запасом хватит, чтобы получить форму сигнала как минимум не хуже, ч
сети. Теперь считаем таблицу, так же в excel как самый простой вариант. Получаем такой график:

https://habr.com/ru/post/358172/ 12/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

Исходник таблицы и значений можно взять по ссылке — тут.

4. Управление мостовым преобразователем для формирования синуса


Мы получили таблицу синуса и что с ней делать? Нужно передавать эти значения с определенным шагом дискретизации, который у нас изв
Все начинается с того, что таймер инициализировался — время 0, скважность ноль. Далее мы отсчитываем шаг дискретизации 41,66 мкс и
записываем в таймер значение ШИМа из таблицы 13 (0,13%), отсчитываем еще 41,66 мкс и записываем 26 (0,26%) и так далее все 240 зна
Почему 240? У нас 120 шагов на 1/4 периода, а нам надо нарисовать 1/2 периода. Значения скважности те же, только после того как они до
1000 мы записываем ее в обратной последовательность и получаем спад синуса. На выходе мы будем иметь вот такую осциллограмму:

Как видите мы получили кучу значений ШИМа в четко заданном периоде и его длительность составляет: 240 шагов х 41,66(!) мкс = 9998,4 м
9,9984 мс ~ 10 мс. Мы получили половину периода для частоты сети 50 Гц. Сигнала как видите опять два и они в противофазе, как раз то, ч
нужно для управления диагоналями моста. Но позвольте, где же синус спросите вы? Настал момент истины! Давайте теперь сигнал с выхо

https://habr.com/ru/post/358172/ 13/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр
микроконтроллера подадим на ФНЧ, я сделал простой ФНЧ на RC-цепочки с номиналами 1,5 кОм и 0,33 мкФ (под рукой просто были) и пол
такой результат:

Вуаля! Вот он наш долгожданный синус! Красный луч осциллографа — это сигнал до ФНЧ, а желтый луч — сигнал уже после фильтрации.
обрезал все частоты выше 321 Гц. У нас остался основной сигнал 50 Гц, ну и конечно его гармоники с небольшой амплитудой. Если хотите
идеально очистить сигнал, то сделайте ФНЧ с частотой среза около 55-60 Гц, но пока это не важно, нам надо было лишь проверить получи
у нас синус или нет. Кстати… у меня синхронизация осциллографа включена по желтому лучу (стрелка справа экрана) и мы видим внизу эк
его частоту — идеальные 50 Гц. Что еще можно пожелать? Пожалуй все, осталось определиться какой сигнал и куда подавать. Давайте
рассмотрим такую картинку:

Если вы обратите на саааамую первую осциллограмму в статье, то увидите, что сигнал в желтом и синем лучше имеют одинаковую фазу, т
они в одно время становятся положительными и открывают транзисторы. Эти 2 сигнала открывают диагональ VT1+VT4. Соответственно 2
сигнала так же имеют одинаковую фазу и открывают другую диагональ. Теперь мы не просто меняем направление тока, но и задаем ампли
помощью ШИМ таким образом, чтобы она изменялась по синусоидальному закону. Теперь рассмотрим эту же схемку, но уже с токами:

https://habr.com/ru/post/358172/ 14/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

Как видим ток через нагрузку протекает в противоположную сторону, меняя направление с частотой 50 Гц, а модулированный ШИМ, подава
на транзисторы VT1 и VT2 позволяет нарисовать синусоидальную форму сигнала на полуволнах.

ФНЧ (фильтр низкой частоты) выполнен на индуктивности L1 и конденсаторе C2. Частоту среза для данного фильтра советую считать мене
Гц, это позволит минимизировать пульсации напряжения по выходу.

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

5. Борьба со сквозными токами


Я думаю не для кого не секрет, что нет ничего идеального? Тоже самое и с Mosfet-ами, у них есть ряд недостатков и мы рассмотрим один и
— большая емкость затвора. То есть, чтобы нам открыть транзистор надо не просто подать напряжение, но и этим самым напряжением за
конденсатор, поэтому фронт и спад сигнала затягивается. Это приводит к тому, что на границе сигналов может возникать момент времени,
один транзистор еще полностью не закрылся, а другой уже начал открываться.

Подробнее о данном явление советую почитать, например, в этой статье. Я лишь расскажу как с ним бороться. Чтобы транзисторы успели
нормально закрыться до открытия следующего плеча между управляющими сигналами вводят dead-time или проще говоря — временную
задержку. У нас такая задержка будет введена между управляющими сигналами на транзисторах VT3 и VT4, т.к. именно они обеспечивают
коммутацию полуволн. На транзисторах с модулируемым ШИМом (VT1 и VT2) такие задержки уже есть — синус начинается со скважности
заканчивается тоже 0%. Эта задержка длиной в 1 шаг дискретизации, то есть 41.6 мкс.

И так — надо реализовать мертвое время между синим и зеленым лучом/сигналом. На любом контроллере такую задержку можно сделать
программным способом, но это не есть хорошо — программа подвиснет или задержится и пыщ-пыщ ваше устройство и квартира уже объят
огнем. Поэтому в силовой электронике стоит применять только аппаратные средства. На всех специализированных motor control аппаратны
deadtime предусмотрен на всех выходах ШИМа и каналах, но STM32 это все таки МК общего назначения, поэтому тут все проще, но нашу
функцию он выполнит.

Нам понадобится таймер TIM1, только он умеет вставлять аппаратную задержку между сигналами, в разделе про написание ПО я расскаж
это сделать, а сейчас смотрим на результат и на то, что вообще должно быть:

https://habr.com/ru/post/358172/ 15/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

Чтобы увидеть задержку «растягиваем» сигнал на осциллографе, т.к. он имеет небольшую длительность около 300 нс. Необходимое время
длительности deadtime необходимо рассчитывать для каждой конкретной задачи, чтобы защитить транзисторы от сквозных токов. Длитель
задержки настраивается при иннициализации (настройке) таймера TIM1. Данная задержка присутствует и на фронте и на спаде сигнала.

6. Написание встроенного ПО для микроконтроллера STM32


Вот мы и подошли наверное к самой важной и интересной части. Физику процесса мы разобрали, принцип работы вроде понятен, необходи
минимум защит тоже определен — осталось только все это реализовать в реальном железе. Для этого я использую платку STM32VL-Disco
получил ее кстати еще в 2011 году во времена, когда ST раздавали отладки бесплатно на своих конференциях и с тех пор она лежала
запакованная — открыл упаковку всего пару месяцев назад, вроде срок годности не прошел))) Выглядит мой «стенд» для написание кода в

https://habr.com/ru/post/358172/ 16/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

Теперь пройдемся по подключению. Так как мне необходимо формировать два сигнала с разной частотой, то пришлось задействовать вых
ШИМ на разных таймерах. TIM1 формирует сигнал, который задает основную частоту 50 Гц и подает их на транзисторы VT3 и VT4. Исполь
канал ШИМа №3 + его комплементарный выход. Да да, в STM32 аппаратный deadtime можно настроить только между обычным и
комплементарным выходом одного канала, что мне сильно не понравилось. Сам процесс формированию синуса передан таймеру TIM2, ту
не нужна задержка (ранее писал почему) и он вполне сгодится для формирование модулированного сигнала на VT1 и VT2.

Используемые выходы:
PA10 — обычный выход ШИМ, канал №3 таймера TIM1, который генерирует 50 Гц на транзистор VT3

PB15 — комплементарный выход канала №3 таймера TIM1, который подается на транзистор VT4

PA0 — выход ШИМ канала №1 таймера TIM2. Подает модулированный сигнал на VT1

PA1 — выход ШИМ канала №2 таймера TIM2. Подает модулированный сигнал на VT2

Проект реализован в среде Keil 5, он будет в конце статьи прикреплен к архивом. Рассказывать как создавать проект и подобные очевидны
надеюсь не стоит, если такие вопросы возникают, то советую посмотреть как это делать в гугле или на youtube. Весь код написан на CMSIS
(регистры), т.к. использовать в системе управления преобразователем какие-либо дополнительные уровни абстракции просто грех! У ST эт
библиотеки SPL и более актуальные HAL. Для интереса поработал и с теми и с теми, вывод — хлам полный. HAL так вообще безумно
тормознутый и для приложений с жестким реал-таймом просто не подходит от слова совсем. В некоторых критичных моментах регистры бы
разы быстрее, об этом кстати нашел не одну статью на просторах интернета.

Некоторые наверняка спросят: «А почему не задействовать DMA?» Сделать это можно и нужно, но данная статья носит скорее ознакомите

https://habr.com/ru/post/358172/ 17/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр
характер, да и сам МК не делает ничего сложного в плане вычислений, поэтому в производительность ядра тут точно не упереться. DMA —
хорошо, но без DMA можно обойтись без каких-либо потенциальных проблем. Давайте уточним, что нам нужно сделать в программе:

1. Создать массив с нашими 240 точками синуса

2. Настроить цепи тактирования на частоту 24 МГц, выбрав источник внешний кварцевый резонатор

3. Настроить таймер TIM1 на генерацию ШИМ 50 Гц с включенным deadtime

4. Настроить TIM2 на генерацию ШИМ с несущей частотой 24 кГц

5. Настроить таймер TIM6, который генерирует прерывания с частотой 24 кГц. В нем мы будем отправлять следующее значение скважно
таблицы в таймер TIM2, а также чередовать генерацию полуволн

Ничего сложного, правда? Тогда поехали…

6.1. Создание таблицы синуса


Тут все просто, обычный массив. Единственное, что стоит помнить — у нас 120 точек от 0 до 1000. Нам нужно добавить в таблицу еще 120
но в обратной последовательности:

uint16_t sin_data[240] =
{13,26,39,52,65,78,91,104,117,130,143,156,169,182,195,207,220,233,246,258,
271,284,296,309,321,333,346,358,370,382,394,406,418,430,442,453,465,477,488,500,
511,522,533,544,555,566,577,587,598,608,619,629,639,649,659,669,678,688,697,707,
716,725,734,743,751,760,768,777,785,793,801,809,816,824,831,838,845,852,859,866,
872,878,884,891,896,902,908,913,918,923,928,933,938,942,946,951,955,958,962,965,
969,972,975,978,980,983,985,987,989,991,993,994,995,996,997,998,999,999,999,1000,
999,999,999,998,997,996,995,994,993,991,989,987,985,983,980,978,975,972,969,965,
962,958,955,951,946,942,938,933,928,923,918,913,908,902,896,891,884,878,872,866,
859,852,845,838,831,824,816,809,801,793,785,777,768,760,751,743,734,725,716,707,
697,688,678,669,659,649,639,629,619,608,598,587,577,566,555,544,533,522,511,500,
488,477,465,453,442,430,418,406,394,382,370,358,346,333,321,309,296,284,271,258,
246,233,220,207,195,182,169,156,143,130,117,104,91,78,65,52,39,26,13};

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


Настройка тактирования в STM32 весьма гибкая и удобная, но есть несколько нюансов. Сама последовательность выглядит следующим
образом:

1) Переключаемся на тактирование от встроенной RC-цепочки (HSI) на внешний кварц (HSE), дальше ждем флага о готовности

RCC->CR |= ((uint32_t)RCC_CR_HSEON); // Enable HSE


while (!(RCC->CR & RCC_CR_HSERDY)); // Ready start HSE

2) Flash память контроллера работает несколько медленнее, чем ядро для этого настраиваем тактирование флеши. Если этого не сделать
программа запустится, но будет периодически падать: пара кВт и нестабильное ПО — вещи несовместимые.

FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY; // Cloclk Flash memory

3) Выставляем делители для системной шины тактирования (AHB) и для шин периферии, коих аж две штуки: APB1 и APB2. Нам нужна
максимальная частота, поэтому ничего не делим и коэффициенты деления делаем равными 1.

RCC->CFGR |= RCC_CFGR_HPRE_DIV1; // AHB = SYSCLK/1


RCC->CFGR |= RCC_CFGR_PPRE1_DIV1; // APB1 = HCLK/1
RCC->CFGR |= RCC_CFGR_PPRE2_DIV1; // APB2 = HCLK/1

4) Настраиваем множитель частоты (PLL) предделитель, который стоит перед ним и делит частоту кварца на 2. Получаем, что 8 МГц подел
2 и получили 4 МГц. Теперь надо их умножить на 6, чтобы на выходе были 24 МГц. Перед записью регистров предварительно сотрем их
содержимое на всякий случай.

https://habr.com/ru/post/358172/ 18/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

RCC->CFGR &= ~RCC_CFGR_PLLMULL; // clear PLLMULL bits


RCC->CFGR &= ~RCC_CFGR_PLLSRC; // clearn PLLSRC bits
RCC->CFGR &= ~RCC_CFGR_PLLXTPRE; // clearn PLLXTPRE bits

RCC->CFGR |= RCC_CFGR_PLLSRC_PREDIV1; // source HSE


RCC->CFGR |= RCC_CFGR_PLLXTPRE_PREDIV1_Div2; // source HSE/2 = 4 MHz
RCC->CFGR |= RCC_CFGR_PLLMULL6; // PLL x6: clock = 4 MHz * 6 = 24 MHz

5) Теперь надо включить множитель частоты (PLL) и дождаться флага о готовности:

RCC->CR |= RCC_CR_PLLON; // enable PLL


while((RCC->CR & RCC_CR_PLLRDY) == 0) {} // wait till PLL is ready

6) И наконец-то настраиваем источник тактирования для системной шины (AHB) выход нашего множителя частоты, на котором заветные 24
Предварительно содержимое регистра чистим, устанавливаем нужный бит и ждем флага готовности:

RCC->CFGR &= ~RCC_CFGR_SW; // clear SW bits


RCC->CFGR |= RCC_CFGR_SW_PLL; // select source SYSCLK = PLL
while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_1) {} // wait till PLL is used

В итоге у нас получается вот такая функция настройки тактирования:

void RCC_Init (void){

RCC->CR |= ((uint32_t)RCC_CR_HSEON); // Enable HSE


while (!(RCC->CR & RCC_CR_HSERDY)); // Ready start HSE

FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY; // Cloclk Flash memory

RCC->CFGR |= RCC_CFGR_HPRE_DIV1; // AHB = SYSCLK/1


RCC->CFGR |= RCC_CFGR_PPRE1_DIV1; // APB1 = HCLK/1
RCC->CFGR |= RCC_CFGR_PPRE2_DIV1; // APB2 = HCLK/1

RCC->CFGR &= ~RCC_CFGR_PLLMULL; // clear PLLMULL bits


RCC->CFGR &= ~RCC_CFGR_PLLSRC; // clearn PLLSRC bits
RCC->CFGR &= ~RCC_CFGR_PLLXTPRE; // clearn PLLXTPRE bits

RCC->CFGR |= RCC_CFGR_PLLSRC_PREDIV1; // source HSE


RCC->CFGR |= RCC_CFGR_PLLXTPRE_PREDIV1_Div2; // source HSE/2 = 4 MHz
RCC->CFGR |= RCC_CFGR_PLLMULL6; // PLL x6: clock = 4 MHz * 6 = 24 MHz

RCC->CR |= RCC_CR_PLLON; // enable PLL


while((RCC->CR & RCC_CR_PLLRDY) == 0) {} // wait till PLL is ready
RCC->CFGR &= ~RCC_CFGR_SW; // clear SW bits
RCC->CFGR |= RCC_CFGR_SW_PLL; // select source SYSCLK = PLL
while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_1) {} // wait till PLL is used
}

6.3. Настройка таймера TIM1 и «мертвого времени»


Я приведу общую настройку таймера, она подробно описана в reference manual — назначение каждого регистра советую почитать. Да и ба
статьи по работе с ШИМ в интернете есть. Сам код у меня весьма неплохо прокомментирован, поэтому привожу сразу код функции
инициализации таймера TIM1, а самые интересные моменты разберем:

void PWM_50Hz_Init (void){

RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // enable clock for TIM1


RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // enable clock for port A
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; // enable clock for port B
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // enable clock for alternative gpio

/****************************** Setting PA10 **************************************/

https://habr.com/ru/post/358172/ 19/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр
GPIOA->CRH &= ~GPIO_CRH_CNF10; // setting out alternative push-pull for PWM
GPIOA->CRH |= GPIO_CRH_CNF10_1;

GPIOA->CRH &= ~GPIO_CRH_MODE10;


GPIOA->CRH |= GPIO_CRH_MODE10; // gpio speed 50 MHz

/***************************** Setting PB15 ***************************************/

GPIOB->CRH &= ~GPIO_CRH_CNF15; // setting complementary for CH3N


GPIOB->CRH |= GPIO_CRH_CNF15_1;

GPIOB->CRH &= ~GPIO_CRH_MODE15;


GPIOB->CRH |= GPIO_CRH_MODE15; // gpio speed 50 MHz

/************************** Config PWM channel ************************************/

TIM1->PSC = 480-1; // div for clock: F = SYSCLK / [PSC + 1]


TIM1->ARR = 1000; // count to 1000
TIM1->CR1 &= ~TIM_CR1_CKD; // div for dead-time: Tdts = 1/Fosc = 41.6 ns
TIM1->CCR3 = 500; // duty cycle 50%

TIM1->CCER |= TIM_CCER_CC3E | TIM_CCER_CC3NE; // enable PWM complementary out


TIM1->CCER &= ~TIM_CCER_CC3NP; // active high level: 0 - high, 1 - low

TIM1->CCMR2 &= ~TIM_CCMR2_OC3M;


TIM1->CCMR2 |= TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1; // positiv PWM

TIM1->BDTR &= ~TIM_BDTR_DTG; // clear register


TIM1->BDTR |= TIM_BDTR_DTG_2 | TIM_BDTR_DTG_1 | TIM_BDTR_DTG_0; // value dead-time
TIM1->BDTR |= TIM_BDTR_MOE | TIM_BDTR_AOE; // enable generation output

/*******************************************************************************/

TIM1->CR1 &= ~TIM_CR1_DIR; // count up: 0 - up, 1 - down


TIM1->CR1 &= ~TIM_CR1_CMS; // aligned on the front signal
TIM1->CR1 |= TIM_CR1_CEN; // start count

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

TIM1->CCR3 = 500; // duty cycle 50%

Длительность паузы «мертвого времени» зависит сильно от временной параметра TDTS, которое настраивается тут:

TIM1->CR1 &= ~TIM_CR1_CKD; // div for dead-time: Tdts = 1/Fosc = 41.6 ns

Его длительность составляет 1 тик тактовой частоты. Если посмотреть в reference manual, то можно увидеть, что биты CKD могут, наприме
сделать Tdts равным 2, 8 тикам и прочее.

Самое же время паузы устанавливается тут:

TIM1->BDTR |= TIM_BDTR_DTG_2 | TIM_BDTR_DTG_1 | TIM_BDTR_DTG_0;

Если отроете reference manual RM0041, то увидите вот такие формулы для расчета DT. Как видите параметр Tdts там основнополагающий:

https://habr.com/ru/post/358172/ 20/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

6.4. Настройка таймера TIM2, формирующий синус


Тут все еще проще, объяснять что-то в настройке наверно нет смысла, ибо комментарии и так избыточны. Если будут вопросы — жду их в
комментариях.

void PWM_Sinus_Init (void){


RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // enable clock for TIM2
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // enable clock for port A
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // enable clock for alternative gpio

/****************************** Setting PA0 ***************************************/

GPIOA->CRL &= ~GPIO_CRL_CNF0; // setting out alternative push-pull for PWM1_CH1


GPIOA->CRL |= GPIO_CRL_CNF0_1;

GPIOA->CRL &= ~GPIO_CRL_MODE0;


GPIOA->CRL |= GPIO_CRL_MODE0; // gpio speed 50 MHz
/****************************** Setting PA1 ***************************************/

GPIOA->CRL &= ~GPIO_CRL_CNF1; // setting out alternative push-pull for PWM1_CH1


GPIOA->CRL |= GPIO_CRL_CNF1_1;

GPIOA->CRL &= ~GPIO_CRL_MODE1;


GPIOA->CRL |= GPIO_CRL_MODE1; // gpio speed 50 MHz

/*************************** Config PWM channel ***********************************/

TIM2->PSC = 0; // div for clock: F = SYSCLK / [PSC + 1]


TIM2->ARR = 1000; // count to 1000
TIM2->CCR1 = 0; // duty cycle 0%
TIM2->CCR2 = 0; // duty cycle 0%

TIM2->CCER |= TIM_CCER_CC1E; // enable PWM out to PA8


TIM2->CCER &= ~TIM_CCER_CC1P; // active high level: 0 - high, 1 - low

TIM2->CCER |= TIM_CCER_CC2E; // enable PWM complementary out to PA9


TIM2->CCER &= ~TIM_CCER_CC1P; // active high level: 0 - high, 1 - low

TIM2->CCMR1 &= ~(TIM_CCMR1_OC1M | TIM_CCMR1_OC2M);


TIM2->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 |
TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1; // positiv PWM1_CH1 and PWM1_CH2

/*******************************************************************************/

TIM2->CR1 &= ~TIM_CR1_DIR; // count up: 0 - up, 1 - down


TIM2->CR1 &= ~TIM_CR1_CMS; // aligned on the front signal: 00 - front; 01, 10, 11 - center
TIM2->CR1 |= TIM_CR1_CEN; // start count

https://habr.com/ru/post/358172/ 21/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

6.5. Настройка прерываний от таймера TIM6


Настраиваем сам таймер на частоту 24 кГц:

void TIM6_step_init (void){

RCC->APB1ENR |= RCC_APB1ENR_TIM6EN; // enable clock for basic TIM6

TIM6->PSC = 1-1; // div, frequency 24 kHz


TIM6->ARR = 1000; // count to 1000
TIM6->DIER |= TIM_DIER_UIE; // enable interrupt for timer
TIM6->CR1 |= TIM_CR1_CEN; // start count

NVIC_EnableIRQ(TIM6_DAC_IRQn); // enable interrupt TIM6_DAC_IRQn

6.6. Реализация основного алгоритма управления


Основные события происходят в генерируемом таймером TIM6 прерывании. Прерывание генерируется каждые 41,66 мкс, если помните эт
шаг дискретизации. Соответственно в прерывании записывается значение скважности из таблицы в регистр CCRx. Также в данном прерыв
определяется какая диагональ в данный момент времени отрисовывается, путем инверсии флага sin_status после каждого полупериода. М
выводим 240 точек, инвертируем флаг, что вызывает переход управления к другому каналу, когда уже и он отрисовал, то флаг опять
инвертируется и все повторяется. Код основного алгоритма:

void TIM6_DAC_IRQHandler(void){

TIM6->SR &= ~TIM_SR_UIF;

if(sin_status == 0){TIM2->CCR1 = sin_data[sin_step];}


if(sin_status == 1){TIM2->CCR2 = sin_data[sin_step];}

sin_step++;

if(sin_step >= 240){


sin_step=0;
sin_status = sin_status ? 0 : 1;
}
}

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

https://habr.com/ru/post/358172/ 22/56
08.02.2020 DC/AC инвертор: принцип работы, схемотехника, встроенное ПО / Хабр

Одну из своих схем моста я чуть ранее выложил в PDF-ке можете пользоваться сколько угодно, надеюсь она вам поможет в освоение сило
электроники.

Также в проект я натянул FreeRTOS. Конечно средствами RTOS нельзя реализовывать подобные задачи по управлению, т.к. простое
переключение между задачами длится от 4 до 18 мкс и это если код хорошо написан и работе планировщика ничто не помешает. Это не
позволяет получить систему управления, работающую в жестком реал-тайме. FreeRTOS я поставил для другого: интерфейсы связи (RS-48
Modbus RTU), регулировка выходной амплитуды напряжения, пересчет таблицы, синхронизация с сетью 230В и прочее. Все эти плюшки я т
попробую реализовать на STM32, а возможно и напишу продолжение тематики статьи, если получатся интересные результаты и будет чем
поделиться.

Надеюсь статья вам понравилась. Если у вас возникли вопросы по применению данного кода в реальном железе, то буду рад ответить на н
Также прошу не воспринимать данный код как что-то готовое, это ядро преобразователя, которое реализует основную функцию. Все «плюш
прочую избыточность вы можете добавить сами. Голое ядро проекта позволит вам понять как оно работает и не тратить кучу времени на ра
кода.

Материалы

UPD1: хотелось бы поблагодарить пользователя @ sleip за ряд найденных ошибок, в основном в таблице синуса — она изменена. Те, кто
использовали код или саму таблицу прошу скопировать ее снова, в статье уже исправленный вариант.

Теги: stm32, микроконтроллеры, силовая электроника, чистый синус, C/C++

+65 409 100k 259

147,2 0,6 667 3


Карма Рейтинг Подписчики Подписки

Илья @NordicEnergy
Шаман 6 разряда

Поддержать автора Отправить ден

Поделиться публикацией

ПОХОЖИЕ ПУБЛИКАЦИИ

https://habr.com/ru/post/358172/ 23/56