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

Rate this item
(0 votes)

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

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

Зачем нужен этот прибор?

Если вы собрались делать робота или машину на радиоуправлении, то вам обязательно понадобится управлять моторами постоянного тока. Рассмотрим классическую платформу управляемого робота на базе Arduino UNO (отладочная плата микроконтроллера ATMEGA).




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

Большая часть, продаваемых плат на рынке, не содержит логики управления моторами, а только предоставляет интерфейс для микроконтроллера. Например, так работает известная плата управления моторами — Arduino motor shield, стоимостью около 600 рублей.


Основной минус данной платы состоит в том, что для управления 4-мя моторами необходимо задействовать много выводов микроконтроллера (почти все выводы Arduino UNO), а также в том, что на микроконтроллер возлагается вся логика управления моторами. В итоге, ресурсов не такого уж мощного микроконтроллера, не хватает на другие задачи — обработку датчиков и основную программу.

Мы будем делать плату управления 4-мя моторами, которая содержит свой собственный микроконтроллер. Он будет управлять всеми моторами, а общение с основным мозгом робота будет производиться по протоколу UART — всего по одному проводу.

Такая технология в настоящее время набирает обороты. В модуль ставится недорогой микроконтроллер, который берет на себя рутинные операции, а основной мозг, освобождается от них. Например, вы можете все чаще встретить LCD экраны на базе встроенного микроконтроллера (драйвера), со своей памятью, что позволяет «свалить» на него формирование текста, графических примитив и даже операций 2D графики (масштабирование и другие). Также устроен SPP bluetooth модуль. В компьютере различные модули периферии (видео карта, wifi карта) тоже имеют свой микроконтроллер или процессор.

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

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

Основные требования к плате моторов

  • Небольшой размер

  • Управление 4-мя моторами постоянного тока одновременно

  • Рабочий ток каждого мотора не более 1.5А, напряжение не более 12В

  • Небольшое собственное потребление тока, для меньшего расхода батареек или аккумуляторов

  • Напряжение питания от 7 до 12В

  • Выход 5В для питания Arduino

  • Управление по одному проводу — протокол UART

  • Независимое управление скоростью и направлением вращения каждого мотора

  • Низкая стоимость

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

{product id=34}

Подбор компонентов

Так как у нас стоит задача управлять скоростью и направлением вращения каждого мотора, то нам понадобится четыре полноценных H-моста. В качестве электронных ключей будем использовать полевые транзисторы (MOSFET). Так как у нас невысокие требования по силе тока и напряжению, то в качестве верхних транзисторов будем использовать P-MOSFET, а в качестве нижних N-MOSFET. Для возможности реализации любой схемы управления будем стараться сделать так, чтобы скорость управления транзисторами была как можно выше, и чтобы оба транзистора были максимально близкие по параметрам. В итоге мы должны иметь возможность подавать ШИМ сигнал на все четыре транзистора каждого H-моста.

Подробно прочитать теорию про управление можно тут.

Подбираем ключевые транзисторы — MOSFET

Выбирать полевой транзистор мы будем по ключевым параметрам, которые обычно указаны в datasheet. Разберём подробно каждый параметр, чтобы научиться подбирать транзисторы. Руководствоваться будем документом Understanding-Modern-Power-MOSFETs.pdf

Rθja — коэффициент зависимости нагрева транзистора от выделяемой им мощности

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




В нашем приборе будет много транзисторов, поэтому выберем минимальный корпус — SOT-23 (u-3). Коэффициент тепловой передачи, при модифицированной площади припаивания, согласно данной таблице, для него составляет 308 градусов на ватт. Запомним данную цифру, она нам будет нужна позже.

Дополнительно стоит отметить, что данная таблица приводится для ОДНОГО транзистора на плате! По сути, часть тепла уходит в воздух через медную площадку, а часть тепла, медная площадка передаёт стеклотекстолиту, и он уже в свою очередь отдаёт тепло воздуху. Если у нас на одну площадку припаяно несколько транзисторов, то нужно считать одновременную выделяемую мощность и общую площадь меди. Например, у нас четыре H-моста. В самой плохой ситуации у нас будет открыто по 2 транзистора на каждый мост. А это значит, что всего у нас будет открыто 8 транзисторов! Если общая площадь меди будет в разы больше 1 дюйма, то все равно надо считать коэффициент не ниже 30 К / Ватт и выбирать максимальное значение нагрева между двумя расчётами. Также, надо учитывать выделяемую мощность при прохождении тока по меди (калькулятор есть в Kicad). И если мощность большая, то требуется напаять шины на дорожки (толстой медной жилой). Мы проведём все эти расчёты когда будем рассматривать финальную плату.

Rds(on) — сопротивление в открытом состоянии

Сопротивление транзистора в открытом состоянии должно быть как можно меньше, это основной источник нагрева транзистора. Согласно закону ома, мощность выделяемая на данном транзисторе в открытом состоянии вычисляется по формуле . Ограничением мощности является максимальный нагрев корпуса, который можно рассчитать, используя коэффициент выше. Рассчитаем минимальное значение Rds(on), которое нам подойдёт.

  1. Максимальный ток равен 1.5А

  2. Температура где будет работать прибор не будет превышать 40 градусов. Максимальный нагрев транзистора — 150 градусов. Значит нагреться транзистор может максимум на 110 градусов (150 — 40 градусов)

  3. При выбранном корпусе, максимальная мощность составляет 110 / Rθja = 110 / 308 = 357 мВт

  4. Теперь можно рассчитать Rds(on) =

  5. Дополнительно надо сделать запас около 30%, таким образом нам подойдёт транзистор с сопротивлением в открытом состоянии меньше 110 мОм

  6. При подборе транзистора, необходимо брать сопротивление Rds(on) при температуре 150градусов!! как правило оно в 1.5 раза выше максимального, приводимого в datasheet для 25 градусов (обычно есть график зависимости сопротивления от температуры).



Vsd - максимальное падение напряжения на внутреннем диоде

Мы будем использовать самый простой вариант ШИМ управления H-мостом — ШИМ сигнал прилагать к нижнему левому (или правому) транзистору, а верхний правый будет постоянно открыт. В этом случае, когда нижний левый транзистор закрывается, то ток ЭДС мотора течет через ВЕРХНИЙ ЛЕВЫЙ транзистор, его паразитный диод. При этом на нем выделяется мощность Pdiode = I * Vsd. Как правило, падение напряжения на диоде MOSFET транзистора составляет 1.2В.

Ток мотора будет пропорционален ШИМ сигналу и самым большим он будет, когда коэффициент заполнения будет больше 90%. При этом диод будет открыт менее 10% всего времени, а значит мощность выделяемая на нем не будет превышать P = 1.2В * 1.5А * 0,1 = 180 мВт. Тем не менее в реальной схеме следует обязательно проверить нагрев верхнего левого транзистора на разных режимах работы мотора. И если он будет перегреваться, то необходимо добавить внешние диоды или сменить схему управления H-мостом. В нашей схеме, мы можем применять ШИМ сигнал к любому из четырёх транзисторов, в том числе реализовать комплементарную схему управления. Применение такой схемы не сильно усложнит код, зато существенно снизит нагрев транзисторов.

Vdss — максимальное напряжение

Мотор является индуктивной нагрузкой. Для индуктивной нагрузки напряжение необходимо брать с запасом - в два раза больше номинального напряжения питания мотора. У нас моторы ограничены 12В, так что, транзистор надо выбирать на напряжение около 20-30В.

VGS(th) — пороговое напряжение открытия транзистора

Так как мы планируем управлять нижними транзисторами напрямую МК, а его питание составляет 5В, то необходимо выбирать логические полевые транзисторы. У них, значение порогового напряжения ниже 2В.

Исходя из этих параметров, уже можно сделать выбор. В качестве N-канального транзистора мы выберем IRLML6244TRPbF (Rds(on) = 21мОм * 1.5 = 31.5), а в качестве P-канального IRLML6402TRPbF (Rds(on)=65мОм * 1.5 = 97.5 мОм).

Схема управления MOSFET

Ещё одна существенная составляющая нагрева транзистора в схемах с управлением ШИМ сигналом - это затраты на его переключение. Они прямо зависят от скорости открытия и закрытия транзистора, а также от частоты переключения. Так как у нас H-мост, то при управлении мостом, надо учитывать время закрытия и открытия, чтобы оба левых транзистора (или правых) не оказались включёнными одновременно (время ожидания окончания переключения называется dead-time). При разработке схемы управления надо не забывать и про время задержки включения и выключения транзистора, которое влияет на время dead-time.

В данном разделе, разберёмся как из параметров, указанных в datasheet, можно получить всю эту информацию, и правильно подобрать драйвер полевых транзисторов. Заметим, что при разработке устройства, лучше дополнительно проверять подобранные значения на симуляторе (например, LTSpice), а потом ещё и на практике с помощью осциллографа!

Практически во всех datasheet на полевые транзисторы приводятся скоростные параметры транзисторах при определённых условиях. К сожалению, их нельзя прямо пересчитать к нужным нам значениям, но можно грубо посчитать то, что необходимо и проверить в симуляторе. Это мы и сделаем. Возьмем один транзистор IRLML6244TRPbF для примера. В datasheet мы имеем следующие значения:


Наиболее полезные:

  • Qg — заряд, который необходимо передать транзистора для полного заряда затвора транзистора

  • td(on) - Время задержки открытия транзистора при указанных условиях

  • tr — Время открытия транзистора при указанных условиях

  • td(off) — Время задержки выключения транзистора

  • tf — Время выключения транзистора

  • Ciss — входная ёмкость затвора транзистора

В идеале, драйвер (схема управления транзистором) должен обеспечивать расчётные условия, указанные в datasheet — производитель указывает оптимальные условия управления. В нашем случае - это Rg = 6.8Ом и Vgs = 4.5В. Затвор полевого транзистора представляет собой конденсатор, и скорость заряда линейно зависит от тока заряда, который в свою очередь зависит от сопротивления перед затвором транзистора. Поэтому, если мы знаем сопротивление, то можно по нему пересчитать приведённые значения. А как же рассчитать данное сопротивление?

Так как мы планируем управлять транзистором напрямую от МК, то один вывод МК не может выдать больше 20мА тока. Исходя из этого ограничения можно рассчитать требуемое сопротивление — 250 Ом. Также надо учесть, что сопротивление внутреннего транзистора в МК в открытом состоянии около 50 Ом. Таким образом внешнее сопротивление необходимо в районе 200 Ом. Ожидаемое время открытия транзистора при таком резисторе будет составлять . Полное время открытия с учётом задержки составит 370 нс, а закрытия ещё больше - 911 нс. Полное время будет необходимо при расчёте времени dead-time. А время открытия и закрытия необходимо для расчёта нагрева транзистора. Для расчёта мощности, которая будет выделяться при переключении используется формула:


её удобнее использовать в виде (с использованием длительности открытия и закрытия транзистора)

В случае с верхним транзистором, необходимо использовать ещё один маломощный транзистор для смещения уровня управления — так как для его закрытия на затворе должно быть напряжение питания двигателей — до 12В, а МК может выдать только 5В. Также необходимо понизить напряжение на базе полевого транзистора через делитель (R3,R5), для его защиты. Можно было бы использовать выход МК в режиме Open Drain, но при напряжении более 5В ток управления составляет менее 1 мА, что приведёт к очень низкой скорости открытия транзистора и большему нагреву. Мы будем использовать для управления N-канальный полевой транзистор 2N7002. Им можно управлять напрямую, без резистора.

В итоге у нас получается вот такая схема управления транзисторами:




Резистор R9 необходим для того, чтобы полевой транзистор был закрыт при подаче питания, когда МК ещё не начал работать. При такой схеме время dead time надо брать около 1-2мкс.

Мы подобрали силовые транзисторы и разобрались со схемой управления ими. Наша плата управления должна замечательно работать с токами до 1.5А на каждый мотор, без всякого радиатора охлаждения. При этом плата должна находится на открытом воздухе, а не в коробке. Стоит также отметить, что силовые элементы платы нельзя покрывать лаком, заматывать изолентой — это сильно снижает теплоотдачу и нарушает все приведённые выше формулы.

Интерфейс общения

Для управления платой моторов будем использовать UART RX — только один провод. Посылка будет очень простая. Будем использовать один байт для скорости, как знаковое число от -127 до +127:

  • от 0 до 127 — скорость вперед

  • от 0 до -127 - скорость назад

Начинаться посылка будет с двух байтов 0x1 и 0x2. В конце посылки передаётся контрольная сумма всех 4 байтов скорости. Такой механизм необходим для контроля посылки, чтобы случайно не получить неверные данные. Если вы используете Arduino, то это позволит не отключать плату моторов на время прошивки Arduino по Serial порту. Для дополнительного контроля, будем считать, что если повторной посылки нет в течение 1 секунды, то требуется остановить все моторы.

Таким образом, у нас будет надёжный протокол управления 4-мя моторами по одному проводу.

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

Для управления 4-мя моторами нужно много выводов. Возьмём микроконтроллер из серии STM8S с 32 выводами. Выберем серию, которая содержит загрузчик для прошивки по UART, в этом случае нам не понадобится ST-Link. Прошить микроконтроллер вы сможете используя любой COM порт (например наш USB UART адаптер, или плату Arduino, или любой другой). Нам подойдёт любой микроконтроллер в корпусе LQFP-32. Это может быть STM8S003Kx, STM8S005Kx, STM8S105Kx, STM8S207Kx, STM8S903Kx. Все эти микроконтроллеры имеют почти одинаковые выводы, так что проект легко можно мигрировать на любой из них. Схему будем составлять так, чтобы работать можно было с любым перечисленным микроконтроллером. Возможность прошивки по UART имеют все эти микроконтроллеры, кроме STMSx03Kx.

Конденсаторы

При управлении моторами с помощью ШИМ сигнала обязательно использование конденсатора на линии питания. Зачем он нужен, где его расположить на плате, как приблизительно рассчитать его ёмкость, какой конденсатор выбрать?

Чтобы разобраться в этом вопросе нам понадобится наглядное пособие — симулятор электрических схем LTSpice. Данная программа разрабатывается компанией Linear Technology и ее бесплатно можно скачать по приведённой ссылке. Программа очень удобная, занимает мало места, работает в Windows и linux под wine. Для понимания необходимости конденсатора составим простую схему. Для упрощения, заменим мотор катушкой индуктивности, а вместо H-моста возьмём один N канальный транзистор. Когда вы моделируете любую схему в симуляторе необходимо обязательно учитывать все паразитные элементы схемы, иначе получится модель далёкая от реальности. Составим следующую схему (её можно скачать с github):


Небольшие пояснения к схеме:

  • V1 — основной источник питания 12В, внутреннее сопротивление 500 мОм

  • L1, L3 — индуктивность проводов, от источника питания до схемы управления мотором

  • V2 — схема управления MOSFET, частота управления 4кГц.

  • M1 — произвольный N канальный MOSFET

  • R1 — сопротивление дорожек платы

  • L2 — наш мотор, небольшие моторы имеют индуктивность в районе 100 мГн, внутреннее сопротивление ставим так, чтобы ток при максимальном ШИМ сигнале ток был около 1.5А * 4 = 6А

  • D1 — любой диод, обязательно необходим для управления двигателем, без него схема будет работать не верно

  • C1,C2 — конденсаторы, в которых нам и надо разобраться

Для максимального приближения к реальности, рассчитаем с помощью данного калькулятора индуктивность проводов. Допустим в качестве источника питания у нас аккумулятор и он подключён многожильными проводами МГТФ-0.14 кв.мм длиной 20см. Индуктивность проводов будет составлять 0.6 нГн — в модели возьмём 1нГн. Теперь уберём конденсаторы, сделаем ШИМ сигнал 99%, для максимального тока и посмотрим график напряжения в точке bat, от которой питается вся схема.




В течение всего лишь 15 нс мы видим высоковольтные всплески — до 72В! Вся проблема в индуктивности проводов. Основное назначение конденсатора - не допустить таких всплесков на линии питания. Данное напряжение, даже на таком коротком интервале может привести к сбою в работе микроконтроллера или вообще вывести его из строя. Чтобы подобрать ёмкость конденсатора, рассмотрим данную схему при 50% ШИМ сигнале и посмотрим на амплитуду напряжения в цепи питания (при 50% ШИМ сигнале она будет максимальная), без конденсатора — 10В:




с конденсатором 1000 мкФ — 300мВ.




Ёмкость конденсатора влияет на колебания напряжения на линии питания — чем они меньше, тем лучше. Соответственно, подбираем ёмкость так, чтобы колебания были в пределах 1 В (лучше 500мВ). Получилось около 100 мкФ. Заметим, что ёмкость зависит от частоты ШИМ, чем она выше, тем меньшая ёмкость нам нужна. Теперь посмотрим, какой ток проходит через конденсатор (около 5А — максимальный и 2.5А средний ток). Максимальный средний ток через конденсатор будет примерно равен половине максимального среднего тока мотора. Так что, нам надо рассчитывать на ток где-то около 4А.


У конденсатора есть такой параметр как ESR — сопротивление на определённой частоте. Это сопротивление основной источник потерь в конденсаторе. Чем оно меньше, тем лучше. Соответственно подбирать сам конденсатор надо по этому параметру. Самое маленькое значение ESR имеют керамические конденсаторы — несколько мОм. Есть специальные алюминиевые LOW ESR конденсаторы — до 100 мОм, есть танталовые конденсаторы LOW ESR — 150 мОм, есть полимерные около 40 мОм. В datasheet на конденсаторы есть параметр Max Ripple Current — можно ориентироваться по этому значению, оно должно быть меньше среднего расчётного тока через конденсатор. Если его превысить, то конденсатор будет перегреваться. Также надо учитывать, что при ШИМ управлении в колебаниях обязательно присутствуют высшие частоты. Алюминиевые конденсаторы имеют высокое сопротивление на этих частотах, так что параллельно им обязательно нужен керамический или плёночный конденсатор небольшой ёмкости. Также надо учитывать, что керамические конденсаторы сильно теряют ёмкость (до 80%) при повышении напряжения. Если у вас напряжение не превышает 20В, то можно использовать керамику, при более высоком напряжении — керамика + алюминиевые конденсаторы. Вы также можете попробовать в модели поменять ESR конденсатора, и посмотреть как оно влияет на схему.

У нас напряжение 12В и нам нужен конденсатор небольшого размера в SMD исполнении и не дорогой. Подойдёт танталовый LOW ESR (85 мОм) конденсатор на 20В 100мкф.

Параллельно необходим керамический LOW ESR 10 мкФ. Также, чтобы срезать совсем высокочастотные колебания, поставить керамический конденсатор 10 нФ (но в данной схеме этого не требуется). Более подробно об этой методике вы можете прочитать здесь.

Подведём итоги, как подбирать конденсатор:

  1. Максимально реально, с запасом учитываем индуктивность проводов

  2. Подбираем ёмкость конденсатора при 50% ШИМ, чтобы колебания напряжения были 5-10%.

  3. Подбираем конденсатор по ESR и Max Ripple Current, чтобы выдержать нужный ток при 50% ШИМ

  4. Желательно параллельно поставить керамические конденсаторы, они будут снижать, в том числе требования к основному конденсатору по току.

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

  6. Размещать конденсатор надо как можно ближе к силовому контуру «питание плюс - MOSFET — MOTOR — питание минус».

Мотор

Нам подойдёт любой мотор постоянного тока рассчитанный на напряжение от 7 до 12 В. Максимальный потребляемый ток мотора должен не превышать 1.5А.

Надо не забывать, что если у вас может быть ситуация стопора мотора, то надо выбирать мотор по току останова. Как правило, в этом случае, потребляемый ток мотором возрастает в разы. Например, мотор R380-2580 имеет максимальный ток под нагрузкой — 1.5А, но ток останова 9А!!! Если такая ситуация не возможна, то по максимальному рабочему току.

Если у вас нет datasheet на мотор, то лучше перестраховаться и подбирать мотор по максимальному току. Для этого достаточно замерить сопротивление его обмоток, и напряжение питания мотора поделить на это сопротивление.

Регулятор питания МК

Для питания МК нам необходимо 5В, так как токи здесь небольшие, то можно использовать линейный регулятор питания. На входе у нас может быть до 12В, плюс возможны помехи — лучше всего использовать автомобильную версию регулятора NCV1117. Он работает до 20В входного напряжения и может выдать ток до 1А. В качестве альтернативы можно использовать регуляторы типа L78, LM78.

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

Основные компоненты подобраны, составляем схему.

Каждым мотором управляет полный H-мост, который состоит из 4 силовых полевых транзисторов, а также схемы управления. Схему управления мы разбирали выше, приведём полную схему одного моста.


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

Так как мы будем использовать программное управление H-мостами, то управляющие выводы можно подключить к любым выводам МК. Выберем наиболее удобные с точки зрения трассировки платы. Для связи платы с внешним миром оставим шины UART, I2C, а также вывод программирования. Все это выведем на внешний разъем.


Линейный регулятор подключаем по схеме из datasheet. В качестве блокирующих конденсаторов у регулятора будем использовать керамические конденсаторы на 10 мкФ на 25В. Для повышения помехоустойчивости МК вывод RESET подключим через резистор 10 кОм на линию питания.

Трассировка платы — силовая часть

Плата в данном приборе совсем несложная, однако, имеет особенности — большие токи управления моторами. В данном разделе разберём подробно трассировку силовой части данного прибора. Большие рабочие токи порождают помехи на линии питании. А вместе с высокой частотой ШИМ они могут вызывать радиочастотные помехи. Все это в итоге может привести к неправильной работе приборе или и вовсе выходу его из строя. Поэтому когда вы разрабатываете плату с импульсным управлением большими токами, то должны строго следовать как минимум этим правилам:

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

  • силовая часть вместе с областью земли должна максимально не пересекаться с зоной МК

  • земля и питание должны быть разведены звездой — то есть от точки подключения питания широкие дорожки на силовую часть и узкие дорожки на схемы питания МК, соединение должно быть в одной точке.

  • провод питания от источника или батареи должны быть как можно короче и обязательно скручен (нельзя допускать островов между плюсом питания и минусом)

  • силовой контур питания должен обязательно иметь на входе LOW ESR конденсаторы, а также керамические конденсаторы 0.1 мкф. При этом рабочее напряжение таких конденсаторов должно быть как минимум 1.5 * Напряжение питания моторов. Например, у нас это будет 18В.

  • силовые линии питания максимально должны идти парой на двух слоях и не образовывать островов (как и провода). То есть если снизу идет силовой плюс, то на другой стороне платы симметрично должна быть силовая земля.

Посмотрим что у нас получилось.




Красным выделен силовой контур в одном из вариантов прохождения тока через силовые транзисторы. На входе стоит LOW ESR танталовый конденсатор. Силовые дорожки должны рассчитаны на общий максимальный общий ток всех 4-ех моторов. Питание МК подключено в одной точке через узкие дорожки. Земля МК не пересекается с силовой землей.




С обратной стороны имеем максимальное покрытие землей, которая опять же отделена от земли МК. На данной плате можно заметить, что схемы управления находятся достаточно далеко от силовых транзисторов — это не очень хорошо! Но так как у нас не высокие скорости переключения транзисторов, то такое вполне допустимо. При более быстрых схемах лучше использовать специальные драйверы управления MOSFET и располагать их максимально близко к силовым транзисторам, образуя замкнутый контур силовая часть и зона управления затворами полевых транзисторов.

Особенности трассировки более мощных регуляторов моторов будут рассмотрены на примере регулятора бесколлекторного двигателя () для квадрокоптера с токами до 30А.

Программа

Общее описание программы

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

  • общение по протоколу UART

  • управление моторами.

Протокол очень простой, в одну сторону, задействована только линия RX. Заголовок пакета данных состоит из двух байт — 0x01 и 0x02, далее следуют 4 байта скорости каждого мотора в формате знакового числа от -127 до 127. Завершает пакет данных контрольная сумма — сумма четырёх байт скорости в виде одного байта. Данный пакет будет защищён от помех, а также позволит передавать прочие данные по тому же UART параллельно, вряд ли встретится такая же последовательность данных. Таким образом UART можно будет использовать например в ARDUINO для прошивки МК не отключая плату моторов. Дополнительно добавим защиту от зависания управляющего МК - если нового пакета не будет получено в течение 3 сек, то все моторы будут остановлены.

Так как у нас 4 полных H-моста, то получить «железный» PWM сигнал на данном типе МК не получится, поэтому будем использовать программный метод генерации PWM. Задействуем таймер TIM1 и его все 4 канала в режиме PWM генерации. А в обработчике прерывания данного таймера будем переключать ножки как нам это необходимо. Для управления моторами будем использовать самую простую схему — верхний транзистор все время открыт, а нижний переключается согласно PWM сигналу. В момент переключения направления вращения мотора будем отключать все транзисторы, выжидать паузу 100мс и потом включать нужный режим. В момент перехода скорости через 0, достаточно выждать 2мс — dead time с запасом. Такая схема решит все вопросы связанные с dead time, а также даст время мотору остановиться в случае смены направления вращения.

Вы можете самостоятельно изменить программу, добавить режим активного торможения, попробовать различные варианты PWM управления H-мостом и другие функции. Также можно возложить на эту плату задачу подсчёта скорости вращения колес, ресурсов МК и свободных выводов для этого достаточно. На плате специально выведен порт I2C — можно настроить управление платой по этому протоколу. В итоге данная плата может полностью закрыть вопрос управления движением 2-4 моторного робота, освободив ресурсы основного «мозга». Также за счёт наличия выводов UART возможно использовать плату сразу как «мозг» простого робота, подключив по UART плату радиоуправления, а по I2C необходимые датчики.

Выбор микроконтроллера

Нам необходимо иметь возможность скомпилировать проект под любой микроконтроллер из серии STM8S. В среде ST VD 8 это делается очень легко. Шаблон проекта содержит настройки под любой МК из серии STM8S. Остаётся только выбрать нужную серию, указать конкретный МК и скомпилировать код под него.




В настройках проекта выбрать конкретный МК и скомпилировать проект.




В коде учтены возможные отличия периферии. Для нашего проекта отличается только номер UART периферии — это может быть UART1 или UART2 или UART3. Делается это с помощью условий препроцессора вида:

  1. #ifdef STM8S003
  2. UART1_DeInit();
  3. UART1_Init((uint32_t)9600, UART1_WORDLENGTH_8D, UART1_STOPBITS_1,UART1_PARITY_NO,
  4. UART1_SYNCMODE_CLOCK_DISABLE,UART1_MODE_TX_DISABLE|UART1_MODE_RX_ENABLE);
  5.  
  6. UART1_ITConfig(UART1_IT_RXNE_OR,ENABLE);
  7. #else
  8. UART2_DeInit();
  9. UART2_Init((uint32_t)9600, UART2_WORDLENGTH_8D, UART2_STOPBITS_1,UART2_PARITY_NO,
  10. UART2_SYNCMODE_CLOCK_DISABLE,UART2_MODE_TX_DISABLE|UART2_MODE_RX_ENABLE);
  11.  
  12. UART2_ITConfig(UART2_IT_RXNE_OR,ENABLE);
  13. #endif
  14.  

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

Частоту работы микроконтроллера устанавливаем в 16 МГц. Кварцевый резонатор не используем, в данном случае в нем нет необходимости. Высокая точность PWM сигнала нам не нужна.

  1. CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);//16mhg
  2.  

На этапе инициализации необходимо настроить милисекундный таймер, он будет необходим для отслеживания таймаутов.

  1. TIM4_TimeBaseInit(TIM4_PRESCALER_128, 124);//Используемпредделитель 128, в этом случае значениетаймера 125 будет соответсвовать 1 мс.
  2. TIM4_ClearFlag(TIM4_FLAG_UPDATE);
  3. TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);
  4.  

Далее необходимо все выводы управления моторами перевести в LOW состояние.

  1. GPIO_Init(GPIOB,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3,GPIO_MODE_OUT_PP_LOW_FAST);
  2. GPIO_Init(GPIOC,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7,GPIO_MODE_OUT_PP_LOW_FAST);
  3. GPIO_Init(GPIOD,GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4,GPIO_MODE_OUT_PP_LOW_FAST);
  4. GPIO_Init(GPIOE,GPIO_PIN_5,GPIO_MODE_OUT_PP_LOW_FAST);
  5.  

Для организации PWM сигнала мы будем использовать таймер 1 и его 4 канала, а управлять выводами будет в прерывании данного таймера. Такой метод более универсальный и позволяет задействовать любые выводы под управление моторами. Но если требуется более быстрое управление моторами то необходимо использовать специальную периферию таймеров. Она позволяет автоматически учесть dead-time и имеет ряд других преимуществ. Настроим сам таймер и все его каналы на 0 скорость.

  1. TIM1_DeInit();
  2. TIM1_TimeBaseInit(0, TIM1_COUNTERMODE_UP, MAXPWM, 0);
  3.  

Используем значение MAXPWM = 4095 для получения частоты PWM сигнала 4 кГц. Использование 16 битного таймера позволяет плавно изменять скорость мотора. Но мы будем использовать более грубую настройку скорости — 127 значений в одну сторону и столько же в другую.

  1. TIM1_CCPreloadControl(DISABLE);
  2. TIM1_BDTRConfig(TIM1_OSSISTATE_DISABLE,
  3. TIM1_LOCKLEVEL_OFF,0,
  4. TIM1_BREAK_DISABLE,
  5. TIM1_BREAKPOLARITY_LOW,TIM1_AUTOMATICOUTPUT_DISABLE);
  6.  
  7. TIM1_OC1Init(TIM1_OCMODE_PWM2, TIM1_OUTPUTSTATE_DISABLE,TIM1_OUTPUTNSTATE_DISABLE,
  8. 0, TIM1_OCPOLARITY_LOW, TIM1_OCNPOLARITY_HIGH,TIM1_OCIDLESTATE_SET,
  9. TIM1_OCNIDLESTATE_RESET);
  10.  
  11. TIM1_OC2Init(TIM1_OCMODE_PWM2, TIM1_OUTPUTSTATE_DISABLE,TIM1_OUTPUTNSTATE_DISABLE,
  12. 0, TIM1_OCPOLARITY_LOW, TIM1_OCNPOLARITY_HIGH,TIM1_OCIDLESTATE_SET,
  13. TIM1_OCNIDLESTATE_RESET);
  14.  
  15. TIM1_CtrlPWMOutputs(DISABLE);
  16.  
  17. TIM1_Cmd(ENABLE);
  18. TIM1_ITConfig(TIM1_IT_UPDATE|TIM1_IT_CC1|TIM1_IT_CC2|TIM1_IT_CC3|TIM1_IT_CC4,ENABLE);
  19.  

Таким образом таймер используется только для генерации прерываний. Наличие 4-х каналов позволяет удобно управлять скоростью каждого мотора независимо. Активируем необходимые прерывания — По переполнению таймера и по сравнению с заданным уровнем PWM сигнала (capture and compare).

В конце блока инициализации настроим UART для управления нашим модулем моторов. Используем только вывод RX и прерывания разрешаем только по приёму данных(наш модуль ничего не передаёт).

  1. UART1_Init((uint32_t)9600, UART1_WORDLENGTH_8D, UART1_STOPBITS_1,UART1_PARITY_NO,
  2. UART1_SYNCMODE_CLOCK_DISABLE,UART1_MODE_TX_DISABLE|UART1_MODE_RX_ENABLE);
  3. UART1_ITConfig(UART1_IT_RXNE_OR,ENABLE);
  4.  

Управление по UART

Для управления всеми 4-мя моторами используется протокол UART. Получение данных выполняется в прерывании модуля UART.

  1. INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18)
  2. {
  3. char c=0;
  4. #ifdef STM8S003
  5. if (UART1_GetFlagStatus(UART1_FLAG_RXNE) != RESET )
  6. c = UART1_ReceiveData8();
  7. #else
  8. if (UART2_GetFlagStatus(UART2_FLAG_RXNE) != RESET )
  9. c = UART2_ReceiveData8();
  10. #endif
  11.  

Если байт получен, то запишем его в переменную «c» и начнем обработку.

  1. //ждем 1 2 с1 с2 с3 с4 (с1+с2+с3+с4)
  2. if (RXready==5) return;
  3.  

Используем переменную RXready для обозначения факта получения корректного пакета данных. Далее этот пакет будем обрабатывать в основном цикле, а до окончания полной обработки в прерывании ничего делать не будем.

  1. if (RXready==2) {
  2. if (RXtek>=4) {
  3. u8 tmp=0;
  4. u8 i;
  5.  
  6. for (i=0;i<4;i++) {
  7. tmp += mot_newscor[i];
  8. }
  9.  
  10. if (tmp == c) RXready = 5;
  11. else RXready = 0;
  12. }
  13.  
  14. mot_newscor[RXtek] = c;
  15. RXtek++;
  16. } else {
  17. if ((RXready==0) && (c==1) ) {
  18. RXready = 1;
  19. }
  20. else if ((RXready==1) && (c==2) ) {
  21. RXready = 2;
  22. RXtek=0;
  23. }
  24. else RXready=0;
  25. }
  26. }
  27.  

После получения двух байт проверим, что это начало посылки — последовательность 0x01 и 0x02. Если да, то следующие 4 байта — это новые значения скоростей моторов. Последний байт — контрольная сумма (просто сумма всех скоростей с переполнением — то есть один байт). Если все хорошо — пакет получен, то выставляем флаг получения новой порции скоростей и обрабатываем его в основном цикле.

  1. if (RXready==5) {
  2. u8 i;
  3. timetest = 3;
  4. changespeed();
  5. RXready=0;
  6. }
  7.  

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

  1. if (timetest==0) {
  2. //все выключаем!
  3. u8 i;
  4. RXready=5;
  5. for (i=0;i<4;i++)
  6. mot_newscor[i]=0;
  7. changespeed();
  8. RXready=0;
  9. timetest = 3;
  10. }
  11. <pre xml:lang="c" lines="true">[code]Если в течение 3 секунд не было пакета— то останавливаем моторы.
  12.  

ШИМ управление моторами

Для генерации PWM сигнала управления моторами используется таймер 1 и его 4-е канала. Каждый канал отвечает за свой мотор. Обработка ведется в прерывании таймера. В каждом H-мосте мы управляем только одним нижним транзистором.Соответственно, при обнулении таймера— включаем данный транзистор (устанавливаемнужный вывод в HIGH), а при достижении установленного значения Capture and Compare выключаем его (устанавливаем вывод в LOW). Используем специальный массив mot_time[i] для блокировки управления моторамина время dead time или время смены направления вращения мотора. Значение в этом массиве уменьшается каждую миллисекунду, и пока оно не равно нулю, обработка выводов не осуществляется.
  1. INTERRUPT_HANDLER(TIM1_UPD_OVF_TRG_BRK_IRQHandler, 11)
  2. {
  3. TIM1_ClearITPendingBit(TIM1_IT_UPDATE); //очищаем битобработки прерывания
  4. //надо включить все нужные нижниевыводы!
  5. //но только если скорость не нулевая!и нет блокировки!
  6. {
  7. u8 i;
  8. for (i=0;i<4;i++) {
  9. if (mot_scor[i] && mot_time[i]==0) {
  10. switch (i) {
  11. case 0:
  12. if (mot_scor[i] > 0) GPIO_WriteHigh(GPIOD,GPIO_PIN_0);//1NL
  13. else GPIO_WriteHigh(GPIOD,GPIO_PIN_2);//1NR
  14. break;
  15. case 1:
  16. if (mot_scor[i] > 0) GPIO_WriteHigh(GPIOC,GPIO_PIN_4);//2NL
  17. else GPIO_WriteHigh(GPIOC,GPIO_PIN_5);//2NR
  18. break;
  19. case 2:
  20. if (mot_scor[i] > 0) GPIO_WriteHigh(GPIOC,GPIO_PIN_6);//3NL
  21. else GPIO_WriteHigh(GPIOC,GPIO_PIN_7);//3NR
  22. break;
  23. case 3:
  24. if (mot_scor[i] > 0) GPIO_WriteHigh(GPIOD,GPIO_PIN_3);//4NL
  25. else GPIO_WriteHigh(GPIOD,GPIO_PIN_4);//4NR
  26. break;
  27. }
  28. }
  29. }
  30. }
  31. }
  32.  

Сами значения скоростей устанавливаются в регистр таймера в процедуре changespeed(). Разберём ее поподробнее.

  1. void changespeed(void)
  2. {
  3. u8 i;
  4.  
  5. for (i=0;i<4;i++) {
  6. if ( mot_scor[i] == mot_newscor[i]) {
  7. //скорость не изменилась, ничего неделаем
  8. continue;
  9. }else if (mot_scor[i]*mot_newscor[i] > 0) {
  10. //тот же знак, просто скорость другая!
  11. //тут ничего не делаем = сделаем ниже
  12.  

Если скорость не поменялась, то ничего не делаем. Если изменилась скорость, но не изменилось направление, то достаточно поменять значение регистра таймера. Сделаем это позже.

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

  1. }else {
  2. //знак разный
  3. //тут надо сначала мотор остановить!
  4. //сменить знаки
  5. //а только потом уже поменять скорости!
  6. if (mot_scor[i]*mot_newscor[i] < 0) {
  7. mot_time[i]=100;//в случае смены направлениявращения заблокируем на 100мс управлениевыводами!
  8. } else mot_time[i]=2;//а здесь достаточнотолько 2мс — dead time.
  9. //выключим нижние транзисторы иверхние!
  10. //нижние сами включаться дальше впрерывании таймера!
  11. //подготовим сразу верхние как надо!!
  12.  
  13. //выключаем нижние транзисторы
  14. switch (i) {
  15. case 0:
  16. GPIO_WriteLow(GPIOD,GPIO_PIN_0|GPIO_PIN_2);
  17. GPIO_WriteLow(GPIOE,GPIO_PIN_5);
  18. GPIO_WriteLow(GPIOC,GPIO_PIN_1);
  19. break;
  20. case 1:
  21. GPIO_WriteLow(GPIOC,GPIO_PIN_4|GPIO_PIN_5);
  22. GPIO_WriteLow(GPIOB,GPIO_PIN_2|GPIO_PIN_3);
  23. break;
  24. case 2:
  25. GPIO_WriteLow(GPIOB,GPIO_PIN_0|GPIO_PIN_1);
  26. GPIO_WriteLow(GPIOC,GPIO_PIN_6|GPIO_PIN_7);
  27. break;
  28. case 3:
  29. GPIO_WriteLow(GPIOD,GPIO_PIN_3|GPIO_PIN_4);
  30. GPIO_WriteLow(GPIOC,GPIO_PIN_2|GPIO_PIN_3);
  31. break;
  32. }
  33. Delay(1);//чтобы исключить deadtime
  34. //теперь включим верхние как нужно!
  35. if (mot_scor[i]>0) {
  36. //xHR правые в случае положительнойскорости
  37. switch (i) {
  38. case 0:
  39. GPIO_WriteHigh(GPIOC,GPIO_PIN_1);
  40. break;
  41. case 1:
  42. GPIO_WriteHigh(GPIOB,GPIO_PIN_2);
  43. break;
  44. case 2:
  45. GPIO_WriteHigh(GPIOB,GPIO_PIN_0);
  46. break;
  47. case 3:
  48. GPIO_WriteHigh(GPIOC,GPIO_PIN_3);
  49. break;
  50. }
  51. } else {
  52. //xHL левые в случае отрицательнойскорости
  53. switch (i) {
  54. case 0:
  55. GPIO_WriteHigh(GPIOE,GPIO_PIN_5);
  56. break;
  57. case 1:
  58. GPIO_WriteHigh(GPIOB,GPIO_PIN_3);
  59. break;
  60. case 2:
  61. GPIO_WriteHigh(GPIOB,GPIO_PIN_1);
  62. break;
  63. case 3:
  64. GPIO_WriteHigh(GPIOC,GPIO_PIN_2);
  65. break;
  66. }
  67. }
  68. }
  69.  

Теперь установим нужные значения в регистр таймера CCRx.

  1. ccrval = (u32)((mot_newscor[i]>0) ? mot_newscor[i] :(-mot_newscor[i]))*MAXPWM/127;
  2.  
  3. switch (i) {
  4. case 0:
  5. TIM1->CCR1H = (uint8_t)(ccrval>> 8);
  6. TIM1->CCR1L = (uint8_t)(ccrval);
  7. break;
  8. case 1:
  9. TIM1->CCR2H = (uint8_t)(ccrval>> 8);
  10. TIM1->CCR2L = (uint8_t)(ccrval);
  11. break;
  12. case 2:
  13. TIM1->CCR3H = (uint8_t)(ccrval>> 8);
  14. TIM1->CCR3L = (uint8_t)(ccrval);
  15. break;
  16. case 3:
  17. TIM1->CCR4H = (uint8_t)(ccrval>> 8);
  18. TIM1->CCR4L = (uint8_t)(ccrval);
  19. break;
  20. }
  21.  
  22. }
  23.  

Сохраним установленные значения скоростей в массив текущих скоростей.

  1. for (i=0;i<4;i++) {
  2. mot_scor[i]=mot_newscor[i];
  3. }
  4. }
  5.  

Вот мы и разобрали всю программу. Остался только обработчик прерывания миллисекундного таймера 4. Но там все просто, он используется для функции Delay() и отслеживания времени блокировки управления моторами.

Как изготовить данный прибор самостоятельно

Делаем плату и все запаиваем

  1. Подготовить все необходимые инструменты: все для пайки, ST-LINK (будет нужен для программирования и отладки МК) или USB-UART адаптер (можно загрузить прошивку по UART).

  2. Внимательно прочитать статьи из раздела Обязательная теория.

  3. Скачать необходимые файлы проекта по данному прибору с github.

  4. Изготовить плату для прибора самостоятельно по нашей инструкции.

  5. Приобрести все необходимые комплектующие и запаять их на плату, смотри наше видео.

  6. Плата готова!

Корпуса данному прибору не нужен, так что как только плата готова — ее необходимо протестировать и можно пользоваться.

Особенности тестирования платы

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

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

  • токи, большие чем рабочие для данного транзистора, например при коротком замыкании

  • неправильная схема управления — слишком долгое открытие и закрытие транзистора

Вот эти два момента и нужно будет дополнительно протестировать. Короткое замыкание возможно при одновременном открытии верхнего и нижнего парного транзистора, например по ошибке в программе. Для тестирования этой ситуации можно воспользоваться лампочкой или специальным блоком питания с защитой от КЗ. В случае с лампочкой все просто — питание к плате подаётся через последовательно включённую лампочку. Далее без мотора пробуем управлять скоростью его вращения (для этого проще в основном цикле программы сделать тестовое изменение скорости от 0 до 100), и если в программе есть ошибки — то лампочка будет загораться!

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

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

Прошивка по UART

Используемый в данном приборе микроконтроллер содержит загрузчик (bootloader), который позволяет загрузить прошивку по UART протоколу. Для этого необходимо использовать специальную программу от ST и обычный USB-UART модуль. Скачать прошивальщик STM8 Flash loader demonstrator (UM0462) можно отсюда.

Приобретённые навыки

Трассировка платы: трассировка силовых плат

Схемотехника: LDO, схема управления MOSFET транзисторами, H-мост

Программирование: программирование PWM сигнала, управление микроконтроллером по UART

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

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

Если добавить SPP bluetooth модуль, то на данной плате можно сделать машину на радиоуправлении без дополнительной платы центрального процессора.

Read 13873 times