Метка: 3D принтер

MKS Gen Подключение – Cхема платы управления, распиновка (3D принтер, ЧПУ, лазер)
MKS Gen V1.4. Эта новейшая плата объединяет в себе функционал сразу двух плат Arduino и Ramps, поэтому превосходит их в качестве исполнения, т.к базируется на более дорогих и надежных компонентах!…..

Кулачковая муфта – Размеры и характеристики. Гибкие муфты вала.
Кулачковая муфта вала часто используется для подключения серводвигателя, шагового двигателя, кодирующего устройства, ходового винта, ШВП, платформы станка. Прорезиненная муфта обычно применяется в ЧПУ станках, а также в 3D принтерах и…..

Nema 23 – Размеры и характеристики (чертеж шагового двигателя, таблица)
Шаговые двигатели – один из важнейших узлов ЧПУ оборудования. Поэтому при выборе сборке ЧПУ станка, 3D принтера или же лазерного гравера важно правильно рассчитать и выбрать необходимую модель ШД Nema…..

Драйвер DRV8825 подключение и распиновка, описание (8825 для шагового двигателя)
DRV8825 – самый популярный драйвер для преобразования кода от платы управления (arduino) во вращательное движение шагового двигателя Nema 17 и Nema 23. Драйвер шагового двигателя DRV8825 – подключение будет еще более…..

Драйвер шагового двигателя A4988 подключение, распиновка, описание (а4988)
А4988 – один из базовых и основных драйверов используемых на Arduino платах и модуля. Драйвер шагового двигателя A4988 – подключение будет еще более быстрым и доступным, если пользоваться готовыми схемами (распиновкой)……

Линейные подшипники LM-L (удлиненные) – Размеры и характеристики
Удлиненные линейные подшипники LM-L отличные профессиональные типы подшипников, используемых на 3D принтерах и другом ЧПУ оборудовании. Для ЧПУ станков, 3D принтеров и лазерных граверов часто применяют линейные подшипники следующих типоразмеров:…..

Линейные подшипники LMF и LMK (с фланцем) – Размеры и характеристики
Одни из современных и популярных являются линейные подшипники LMF и LMK, потому что это профессиональные типы подшипников, используемых на 3D принтерах и ЧПУ оборудовании. Для ЧПУ станков, 3D принтеров и…..

Линейные подшипники LM – Размеры и характеристики
Линейные подшипники LM одни из самых популярных профессиональных типов подшипников, используемых на ЧПУ оборудовании. Для ЧПУ станков, 3D принтеров и лазерных граверов часто применяют линейные подшипники следующих типоразмеров: LM6UU, LM8UU, LM10UU, LM12UU, LM13UU, LM16UU, LM20UU, LM25UU, LM30UU, LM40UU, LM50UU……

Nema 17 – Размеры и характеристики (чертеж, таблица)
Шаговые двигатели – один из важнейших узлов ЧПУ оборудования. Поэтому при выборе сборке ЧПУ станка, 3D принтера или же лазерного гравера важно правильно рассчитать и выбрать необходимую модель ШД Nema…..

RAMPS 1.4 подключение – плата управления 3D принтером
Плата совместима с платой драйвера шагового двигателя А4988 или DRV8825 для управления двигателем в микро шаговом режиме. Плата включат в себя: Разъём для подключения драйверов шаговых двигателей и контроля экструдера,…..
Arduino.ru

Необходимо добавить кнопку «Пуск» — двигатель с постоянной скоростью делает N количество оборотов, двигатель останавливается (не в режиме Пауза). Цикл повторяется.
Нужна схема подключения и скетч для arduino nano, драйвер TB6600, двигатель nemo 23 2.5A, lcd дисплей с возможностью ввода количества шагов, скорость оборотов, направление вращения. Принцип такой же что и предыдущий, нажимаем «Пуск», двигатель вращается с заданной постоянной скоростью N количество оборотов и полностью останавливается (не в режиме пауза). Цикл повторяется.
- Войдите на сайт для отправки комментариев
Библиотека для шагового двигателя Arduino v2.2.0

Библиотека обновлена для ЧПУ станков! По вашим многочисленным просьбам сделал удобный инструмент для работы с несколькими моторами. В библиотеке версии 2+ доступны два планировщика траекторий, которые позволяют сделать многоосевой станок с ЧПУ, в котором моторы движутся синхронно к заданным координатам. × Закрыть это предупреждение.
Исправлен баг! С версии 2.0 по 2.1.2 некорректно работал режим FOLLOW_POS в GStepper! Приношу извинения, пропустил буковку. Начиная с 2.1.3 всё работает корректно × Закрыть это предупреждение.
Режим слежения в GStepper2 С версии 2.2.0 GStepper2 может обрабатывать новую точку траектории во время движения с сохранением плавности. × Закрыть это предупреждение.
ТЕОРИЯ
Для подключения шаговых моторов к Arduino нужно использовать драйверы. Очень дешёвые и популярные моторы 28byj-48-5v часто продаются вместе со своим драйвером (транзисторная сборка ULN2003), подключить можно к любым 4-м пинам Ардуино и использовать.
Для работы с большими шаговиками (типа Nema 17) нужно использовать специализированные драйверы, ниже вы найдёте описания и схемы подключения для A4988, DRV8825 и TMC2208, драйверы такого формата подключаются и работают практически одинаково, т.к. разработаны для CNC шилдов и взаимозаменяемы. У этих драйверов нужно настроить ток при помощи крутилки на плате. Это можно сделать “на глаз”, заставив мотор вращаться и регулируя крутилку. Мотор должен вращаться, но не вибрировать как перфоратор и сильно не нагреваться. Лучше настроить ток по опорному напряжению Vref, у каждого драйвера оно считается по своей формуле (см. картинки ниже). Берём ток своего мотора из описания, подставляем в формулу вместо current, считаем, и накручиваем полученное напряжение крутилкой. Для измерения опорного напряжения нужно подключить щупы вольтметра к самой крутилке и пину GND.
Главное преимущество дорогущих драйверов TMC – отсутствие шума/свиста/вибраций при работе, так как драйвер своими силами интерполирует сигнал до микрошага 1/256.






БИБЛИОТЕКА
GyverStepper v2.4
Производительная библиотека для управления шаговыми моторами с Arduino
- Поддержка 4х пинового (шаг и полушаг) и STEP-DIR драйверов
- Автоматическое отключение питания при достижении цели
- Режимы работы:
- Вращение с заданной скоростью. Плавный разгон и торможение с ускорением
- Следование к позиции с ускорением и ограничением скорости
- Следование к позиции с заданной скоростью (без ускорения)
Совместимость
Совместима со всеми Arduino платформами (используются Arduino-функции)
УСТАНОВКА
- Библиотеку можно найти и установить через менеджер библиотек по названию GyverStepper в:
- Arduino IDE (Инструменты/Управлять библиотеками)
- Arduino IDE v2 (вкладка “Library Manager”)
- PlatformIO (PIO Home, вкладка “Libraries”)
ДОКУМЕНТАЦИЯ
Аааа почему так много всего?!
Библиотека содержит набор инструментов для разных сценариев работы с шаговыми моторами- StepperCore.h [класс Stepper]: ядро всех остальных классов, умеет быстро щёлкать пинами (AVR) и делать один шаг для настроенного типа драйвера. Поддерживает 4 фазы шаг/полушаг, а также step-dir драйверы.
- GyverStepper.h [класс GStepper]: основная тяжёлая библиотека, много настроек. Движение одного мотора с ускорением к заданной позиции или вращение с заданной скоростью. Не очень оптимальная работа в прерывании таймера.
- GyverStepper2.h [класс GStepper2]: новая облегченная версия GyverStepper, практически полностью с ней совместима. Более оптимальный целочисленный гибридный алгоритм движения с ускорением, лёгкий вес. Оптимизировано для работы в прерывании таймера.
- GyverPlanner.h [класс GPlanner]: многоосевой планировщик траектории, движение с ускорением (2 порядок). Остановка в каждой точке. Оптимальная работа в прерывании таймера.
- GyverPlanner2.h [класс GPlanner2]: многоосевой планировщик траектории, движение с ускорением (2 порядок). Планирование скорости на маршруте, оптимальное движение по точкам. Оптимальная работа в прерывании таймера.
Документация GStepper
Инициализация
Библиотека поддерживает два типа драйверов:
- STEPPER2WIRE — специализированный 2-х проводной драйвер для шагового мотора с интерфейсом STEP-DIR (+опционально пин EN), например A4988, DRV8825, TMC2208 и прочие.
- STEPPER4WIRE и STEPPER4WIRE_HALF — 4-х проводной фазовый драйвер (+опционально пин EN), т.е. полномостовой (например L298N, L9110S) или транзисторная сборка (например ULN2003).
- STEPPER4WIRE управляет мотором в полношаговом режиме (выше скорость и момент).
- STEPPER4WIRE_HALF — в полушаговом (меньше скорость и момент, но в два раза больше шагов на оборот и выше точность).
При инициализации указывается тип драйвера, количество шагов на оборот и пины:
- GStepper < STEPPER2WIRE>stepper(steps, step, dir); // драйвер step-dir
- GStepper < STEPPER2WIRE>stepper(steps, step, dir, en); // драйвер step-dir + пин enable
- GStepper < STEPPER4WIRE>stepper(steps, a1, a2, b1, b2); // драйвер 4 пин
- GStepper < STEPPER4WIRE>stepper(steps, a1, a2, b1, b2, en); // драйвер 4 пин + enable
- GStepper < STEPPER4WIRE_HALF>stepper(steps, a1, a2, b1, b2); // драйвер 4 пин полушаг
- GStepper < STEPPER4WIRE_HALF>stepper(steps, a1, a2, b1, b2, en); // драйвер 4 пин полушаг + enable
Где steps — количество шагов на один оборот вала для расчётов с градусами, step , dir , a1 , a2 , b1 , b2 — любые GPIO на МК, en — пин отключения драйвера EN, любой GPIO на МК. Пин en опциональный, можно не указывать.
Для 4-х пиновых драйверов: a1 и a2 — первая обмотка (первая фаза), b1 и b2 — вторая обмотка (вторая фаза). При использовании мотора 28byj-48 с родным драйвером нужно поменять крайние пины местами (например, подключаем D2-IN1, D3-IN2, D4-IN3, D5-IN4, но в программе меняем 5 и 2: stepper(2048, 5, 3, 4, 2); , потому что на драйвере фазы выведены через одну, вот картинка). При подключении через мостовой драйвер — подключать и указывать пины по порядку выхода фаз из мотора (см. последнюю схему выше).
Количество шагов на оборот нужно для работы функций, которые устанавливают или читают параметр в градусах. Если они не нужны — количество шагов можно поставить любое (единичку). Если нужно — количество шагов нужно указывать с учётом редукторов и микрошагов:
- Пример 1: есть мотор NEMA 17, он имеет 200 полных шагов на оборот (по документации). Подключен через драйвер с настроенным микрошагом 1/16. При создании объекта библиотеки нужно указать 200*16 шагов.
- Пример 2: есть мотор 28byj-48-5v, имеет 32 полных шага на оборот и редуктор с соотношением 63.68395:1. Подключен через микросхему ULN2003. Итоговое количество шагов на оборот составляет 63.68395*32 == 2038 для режима полного шага ( STEPPER4WIRE ).
- Пример 3: подключим тот же самый мотор 28byj-48-5v, но в режиме полушага ( STEPPER4WIRE_HALF ). Количество шагов на оборот удвоится (32*2 == 64) и, с учётом редуктора, станет равным 4076 .
Время шага [NEW!]
Для драйверов STEP-DIR сделана задержка между переключением состояния пина STEP, эта задержка является минимальной, т.е. она может быть больше, чем нужно, но если будет меньше — возможна нестабильная работа драйвера. По умолчанию она составляет 4 микросекунды, но разным драйверам она нужна разная (для других драйверов см. даташит):
- A4988 — 1 мкс
- DRV8825 — 4 мкс
- TB6500 — 1 мкс
Также увеличение задержки может повысить стабильность работы при использовании длинных неэкранированных проводов от микроконтроллера к драйверу (к пину STEP).
Для изменения величины задержки сделай дефайн DRIVER_STEP_TIME перед подключением библиотеки:
#define DRIVER_STEP_TIME 10 // меняем задержку на 10 мкс #include "GyverStepper.h"
Медленные скорости (new!)
В версии 1.6 скорость во всех режимах может быть задана в виде десятичной дроби (тип float ), то есть меньше одного шага в секунду. Минимальная скорость ограничена разрешением используемой в библиотеке micros() и составляет 1 шаг в час. Для удобного задания медленных скоростей появились макросы degPerMinute() и degPerHour() , которые нужно использовать совместно с setSpeedDeg() и setMaxSpeedDeg() :
stepper.setMaxSpeedDeg(degPerMinute(360)); // скорость 360 градусов в минуту для режима FOLLOW_POS
Тик и тайминги
Самый главный метод библиотеки — tick() , при активной работе мотора его нужно вызывать как можно чаще. Тик имеет встроенный таймер на micros() и работает по нему. Если в коде программы присутствуют задержки на большее время, чем нужно мотору на текущей скорости, скорость мотора будет ограничена этой задержкой.
Узнать минимальный период вызова tick() (при установленной скорости) можно при помощи getMinPeriod() , который вернёт его в микросекундах. Также можно напрямую опрашивать переменную stepTime , в которой хранится текущий период. Эти инструменты можно использовать для организации работы шаговика в прерывании таймера (см. пример timerISR).
Также .tick() возвращает true , если мотор движется к цели или крутится по KEEP_SPEED и false , если мотор остановлен или приехал.
Метод getState() возвращает текущее состояние мотора аналогично tick() .
Смена направления
Можно глобально (для всех режимов) сменить направление вращения мотора при помощи reverse(true) .
Режимы работы
Библиотека имеет два режима работы с мотором, устанавливается при помощи setRunMode(mode) , где mode :
- FOLLOW_POS — режим плавного движения к заданной позиции с ускорением и ограничением скорости.
- KEEP_SPEED — режим вращения с заданной скоростью (знак скорости задаёт направление вращения).
Режим FOLLOW_POS
В этом режиме мотор следует на указанную позицию в шагах или градусах. Для её установки есть следующие методы:
- setTarget(pos) — установка абсолютной целевой позиции в шагах, принимает положительные и отрицательные значения (тип данных long ).
- setTarget(pos, type) — то же самое, но можно указать тип позиции type — абсолютная ABSOLUTE или относительная RELATIVE .
- setTargetDeg(pos) — установка абсолютной целевой позиции в градусах, принимает положительные и отрицательные дробные значения (тип данных float ).
- setTargetDeg(pos, type) — то же самое, но можно указать тип позиции type — абсолютная ABSOLUTE или относительная RELATIVE .
Примечание: абсолютная позиция — говоришь мотору повернуться на 300 шагов, он повернётся на позицию 300. При повторном вызове ничего не произойдёт. Относительная — говоришь повернуться на 300 — он повернётся на 300 относительно текущей позиции. Если вызвать ещё раз через некоторое время — цель сместится относительно текущей позиции вала.
Установленную целевую позицию можно прочитать:
- getTarget() — возвращает тип данных long
- getTargetDeg() — возвращает тип данных float
Дополнительно можно настроить максимальную скорость и ускорение при движении к целевой позиции:
- setMaxSpeed(speed) — установка максимальной скорости по модулю в шагах/секунду, тип данных float . По умолчанию 300.
- setMaxSpeedDeg(speed) — установка максимальной скорости по модулю в градусах/секунду, тип данных float .
- setAcceleration(accel) — установка ускорения по модулю в шагах/сек/сек, тип данных float . По умолчанию 300.
- setAccelerationDeg(accel) — установка ускорения по модулю в градусах/сек/сек, тип данных float .
Примечание: при установке ускорения в ноль 0 мотор будет двигаться к позиции с максимальной скоростью, заданной в setMaxSpeed() .
Также можно вручную установить текущую позицию мотора в шагах и градусах при помощи:
- setCurrent(long pos);
- setCurrentDeg(float pos);
- getCurrent();
- getCurrentDeg();
Режим KEEP_SPEED
В этом режиме мотор просто крутится с заданной скоростью. Скорость задаётся при помощи
- setSpeed(speed) — в шагах/секунду, положительные и отрицательные целые значения, тип данных float .
- setSpeedDeg(speed) — в градусах/секунду, положительные и отрицательные дробные значения, тип данных float .
(New!) Вторым аргументом можно передать включение плавного изменения скорости, по умолчанию стоит false ( NO_SMOOTH ). Смотри пример accelDeccelButton
- setSpeed(speed, smooth) — в шагах/секунду, положительные и отрицательные целые значения, тип данных float . smooth — SMOOTH или NO_SMOOTH
- setSpeedDeg(speed, smooth) — в градусах/секунду, положительные и отрицательные дробные значения, тип данных float . smooth — SMOOTH или NO_SMOOTH
Установленную скорость можно прочитать:
- getSpeed() — возвращает тип данных float
- getSpeedDeg() — возвращает тип данных float
Алгоритм планировщика скорости
В библиотеке реализовано два алгоритма планирования скорости для режима плавного движения к позиции с ненулевым ускорением:
- Мой алгоритм: скорость планируется с фиксированным периодом, что сильно разгружает процессор и позволяет работать на скоростях до 30’000 шагов в секунду (полностью загрузив процессор) без наличия посторонних задержек в коде. Сильная экономия процессорного времени оставляет возможность спокойно выполнять параллельно другой код и управлять несколькими моторами в разных режимах на хороших скоростях, и «ещё останется». Немного «резковат» при торможении. Активен по умолчанию.
- Модифицированный алгоритм из библиотеки AccelStepper: скорость планируется каждый шаг, что очень сильно нагружает процессор и ограничивает скорость до 7’000 шагов в секунду (полностью загрузив процессор) без наличия посторонних задержек в коде (в оригинальной библиотеке — 5’000 шагов/сек). Разгоняется и тормозит максимально плавно. Для активации нужно прописать дефайн #define SMOOTH_ALGORITHM перед подключением библиотеки в коде (см. пример smoothAlgorithm) или раскомментировать данный дефайн в файле библиотеки GyverStepper.h, находится сразу после описания.
Остановка и сброс
- stop() — плавная остановка с заданным в setAcceleration() ускорением от текущего положения мотора. Можно вызвать в режиме KEEP_SPEED для плавной остановки вращения! Смотри пример accelDeccelButton
- brake() — резкая остановка мотора. Если активен autoPower(true) — мотор будет отключен.
- reset() — brake() + сброс текущей позиции в 0 . Удобно для остановки и калибровки начала координат по концевику (смотри пример endSwitch).
Управление питанием
Питанием мотора/драйвера можно управлять вручную при помощи enable() и disable() . Данные методы включают и выключают пин Enable (если он указан при инициализации), а также снимают и возвращают питание на управляющие выводы (для 4х пинового драйвера).
Поведением пина EN (если он указан при инициализации) можно управлять при помощи invertEn(true) и invertEn(false) . По умолчанию установлено enable(false) переводит пин en в низкое состояние.
В библиотеке реализовано автоматическое управление питанием, включается при помощи autoPower(true) , по умолчанию оно отключено. В режиме FOLLOW_POS при достижении целевой позиции мотор будет автоматически отключен (будет вызван disable() ). При дальнейшей установке новой позиции мотор будет автоматически включен (будет вызван enable() ).
Список функций GStepper
// Примечание: далее по тексту под "по умолчанию" имеется в виду "даже если не вызывать функцию" // Здесь происходит движение мотора, вызывать как можно чаще! // Имеет встроенный таймер // Возвращает true, если мотор движется к цели или крутится по KEEP_SPEED bool tick(); // Возвращает то же самое, что tick, т.е. крутится мотор или нет bool getState(); // Инвертировать направление мотора - true (по умолч. false) void reverse(bool dir); // инвертировать поведение EN пина - true (по умолч. false) void invertEn(bool rev); // Установка режима работы, mode: // FOLLOW_POS - следование к позиции setTarget(. ) // KEEP_SPEED - удержание скорости setSpeed(. ) void setRunMode(GS_runMode mode); // Установка текущей позиции мотора в шагах и градусах void setCurrent(long pos); void setCurrentDeg(float pos); // Чтение текущей позиции мотора в шагах и градусах long getCurrent(); float getCurrentDeg(); // установка целевой позиции в шагах и градусах (для режима FOLLOW_POS) // type - ABSOLUTE или RELATIVE, по умолчанию стоит ABSOLUTE void setTarget(long pos); void setTarget(long pos, GS_posType type); void setTargetDeg(float pos); void setTargetDeg(float pos, GS_posType type); // Получение целевой позиции в шагах и градусах long getTarget(); float getTargetDeg(); // Установка максимальной скорости (по модулю) в шагах/секунду и градусах/секунду (для режима FOLLOW_POS) // по умолч. 300 void setMaxSpeed(float speed); void setMaxSpeedDeg(float speed); // Установка ускорения в шагах и градусах в секунду (для режима FOLLOW_POS). // При значении 0 ускорение отключается и мотор работает // по профилю постоянной максимальной скорости setMaxSpeed(). // По умолч. 300 void setAcceleration(int accel); void setAccelerationDeg(float accel); // Автоотключение EN при достижении позиции - true (по умолч. false) void autoPower(bool mode); // Плавная остановка с заданным ускорением void stop(); // Жёсткая остановка void brake(); // Жёсткая остановка + сброс позиции в 0 (для концевиков) void reset(); // Установка целевой скорости в шагах/секунду и градусах/секунду (для режима KEEP_SPEED) void setSpeed(float speed); void setSpeedDeg(float speed); // Получение целевой скорости в шагах/секунду и градусах/секунду (для режима KEEP_SPEED) float getSpeed(); float getSpeedDeg(); // Включить мотор (пин EN) void enable(); // Выключить мотор (пин EN) void disable(); // Возвращает минимальный период тика мотора в микросекундах при настроенной setMaxSpeed() скорости. // Можно использовать для настройки прерываний таймера, в обработчике которого будет лежать tick() (см. пример timerISR) uint16_t getMinPeriod(); // Текущий период "тика" для отладки и всего такого uint16_t stepTime;
Отличие GStepper и GStepper2
Отличия GStepper2
- GStepper2 гораздо легче и сильнее оптимизирована
- GStepper2 больше предназначена для движения по точкам траектории, но «следящий» режим в ней также работает
- GStepper2 оптимизирована для работы в прерывании таймера
- GStepper2 использует плавный алгоритм движения мотора по умолчанию
- GStepper2 скорее всего будет чуть больше нагружать микроконтроллер во время работы, чем GStepper. Но гораздо меньше, чем GStepper в режиме SMOOTH_ALGORITHM
Как работает GStepper
- Быстрый алгоритм (по умолчанию): в библиотеке заведено два таймера: таймер шагов (разный период) и таймер планировщика (10-30 миллисекунд). По таймеру планировщика производится перерасчёт траектории и вычисляется направление движения и текущая необходимая скорость. Из этой скорости получается новый период для таймера шагов.
- Плавный алгоритм (настройка SMOOTH_ALGORITHM): работает один таймер шагов, на каждом шаге производится перерасчёт скорости движения и времени до следующего шага.
Как работает GStepper2
- Плавный профиль (по умолчанию): здесь используется алгоритм плавного движения SMOOTH_ALGORITHM как в GStepper, но оптимизирован и ускорен в 2-3 раза. Все тяжёлые вычисления траектории производятся при задании новой целевой позиции в setTarget. Далее по таймеру шагов мотор шагает и быстро вычисляет новое время следующего шага. Это позволяет тратить минимум времени в прерывании таймера, если оно используется.
- Быстрый профиль (настройка GS_FAST_PROFILE): всё то же самое, но в таймере шагов происходит не вычисление, а выбор периода из заранее посчитанной таблицы, что позволяет двигаться с ускорением вплоть до скоростей 36000 шагов в секунду.
Общие моменты по GStepper2 / GPlanner / GPlanner2
GStepper2, GPlanner и GPlanner2 являются нововведениями в библиотеке и работают чуть иначе, больше ориентированы на движение от точки к точке.
Быстрый профиль скорости (NEW!)
С версии 2.2.0 в GStepper2, GPlanner и GPlanner2 появился новый алгоритм планирования профиля скорости. Для его активации нужно прописать дефайн GS_FAST_PROFILE перед подключением библиотеки:
#define GS_FAST_PROFILE количество
Где количество — количество отрезков, на которые будет разбит участок разгона/торможения. На этих отрезках скорость будет одинаковой, то есть мотор будет разгоняться и тормозить «ступенчато». Чем больше отрезков — тем плавнее будет движение, в принципе можно ставить 10. Каждый отрезок добавляет 8 байт SRAM на экземпляр класса.
Зачем это нужно? Данный алгоритм заранее вычисляет скорость во всех точках траектории и не пересчитывает её на каждом шаге, что сильно снижает нагрузку на процессор и позволяет двигаться на участке разгона/торможения со скоростью до 30’000 шагов в секунду!
Изменение скорости/ускорения
Скорость и ускорение можно задать в любое время, они будут применены после остановки мотора в конечной точке!
Тикер
Движение мотора происходит внутри tick() , который нужно вызывать как можно чаще, например в loop() (или yield() , если в коде есть delay() ) tick() имеет встроенный таймер на micros() и крутит мотор с нужной скоростью.
Также есть не имеющий таймера tickManual() , который делает шаг, считает период и проверяет, не доехал ли мотор до цели. Его нужно вызывать с периодом, который можно получить из getPeriod() в микросекундах.
getPeriod() получает новое значение периода после очередного вызова tickManual() . Конструкция для работы в прерывании таймера может выглядеть так:
if (stepper.tickManual()) setPeriod(stepper.getPeriod()); else stopTimer();
Здесь setPeriod() и stopTimer() — функции смены периода и остановки аппаратного таймера, реализация функций зависит от применяемой платформы и/или библиотек. Пока мотор крутится — таймер перезапускается на новый период, как только мотор приехал — останавливаем таймер.
Режим постоянной скорости
Для запуска режима вращения с постоянной скоростью достаточно вызвать setSpeed(скорость) / setSpeedDeg(скорость) . Скорость может быть отрицательной. Остановить мотор можно при помощи brake() . В данной реализации скорость не меняется плавно, то есть включается сразу на заданную и тормозится в 0 при остановке. В реальном применении этого достаточно для движения к концевику (см. пример homing для всех трёх классов).
Режим движения к позиции
При помощи setMaxSpeed() / setMaxSpeedDeg() задаётся максимальная скорость, которой может достигнуть мотор (суммарная квадратичная скорость по осям для GPlanner) во время движения к следующей точке. Эта настройка не имеет отношения к режиму вращения.
При помощи setAcceleration() можно задать ускорение в шагах/секунду^2, с которым будет меняться скорость. Если поставить ускорение 0 — мотор будет двигаться без ускорения, т.е. сразу с максимальной скоростью.
Для старта движения к позиции достаточно вызвать setTarget(позиция) / setTargetDeg(позиция) (кроме GPlanner2). После выполнения этой функции можно запросить у getPeriod() время до следующего тика и запустить таймер, если мотор работает в прерывании.
Если мотор находится в активном режиме движения к позиции и доезжает до цели — функция ready() однократно вернёт true . В примерах к библиотеке по этому условию «загружается» следующая точка траектории.
Во время движения к позиции можно остановиться:
- brake() — резко остановит мотор
- stop() — плавно остановит мотор с заданным ускорением
- pause() — мотор доедет до заданной позиции, но ready() не вернёт true
Для возобновления движения можно вызвать resume() , траектория мотора будет пересчитана и он двинется к последней заданной в setTarget() позиции.
Текущую позицию мотора (моторов, для GPlanner) можно прочитать как getCurrent() , установить через setCurrent() , а также сбросить в 0 через reset() .
GPlanner2 работает чуть иначе, так как содержит буфер траектории. Подробнее о нём читайте ниже
Документация GStepper2
Инициализация
Такая же как в GStepper
GStepper2 < STEPPER2WIRE>stepper(шаговНаОборот, step, dir); // драйвер step-dir GStepper2 < STEPPER2WIRE>stepper(шаговНаОборот, step, dir, en); // драйвер step-dir + пин enable GStepper2 < STEPPER4WIRE>stepper(шаговНаОборот, pin1, pin2, pin3, pin4); // драйвер 4 пин GStepper2 < STEPPER4WIRE>stepper(шаговНаОборот, pin1, pin2, pin3, pin4, en); // драйвер 4 пин + enable GStepper2 < STEPPER4WIRE_HALF>stepper(шаговНаОборот, pin1, pin2, pin3, pin4); // драйвер 4 пин полушаг GStepper2 < STEPPER4WIRE_HALF>stepper(шаговНаОборот, pin1, pin2, pin3, pin4, en); // драйвер 4 пин полушаг + enable GStepper2 < STEPPER2WIRE, STEPPER_VIRTUAL>stepper; // виртуальный драйвер step-dir GStepper2 < STEPPER4WIRE, STEPPER_VIRTUAL>stepper; // виртуальный драйвер 4 пин
Список функций
// === наследуется из Stepper ==== void step(); // сделать шаг void invertEn(bool val); // инвертировать поведение EN пина void reverse(bool val); // инвертировать направление мотора void disable(); // отключить питание и EN void enable(); // включить питание и EN void attachStep(void (*handler)(uint8_t)); // подключить обработчик шага void attachPower(void (*handler)(bool)); // подключить обработчик питания int32_t pos; // текущая позиция в шагах int8_t dir; // направление (1, -1) // ========= GStepper2 ========== // тикер bool tick(); // тикер движения, вызывать часто. Вернёт true, если мотор движется bool tickManual(); // ручной тикер для вызова в прерывании таймера с периодом getPeriod(). Вернёт true, если мотор движется bool ready(); // однократно вернёт true, если мотор доехал до установленной позиции и остановился // вращение void setSpeed(int16_t speed); // установить скорость в шагах/сек и запустить вращение void setSpeed(float speed); // установить скорость в шагах/сек (float) и запустить вращение // движение к цели void setTarget(int32_t ntar, GS_posType type = ABSOLUTE); // установить цель в шагах и опционально режим ABSOLUTE/RELATIVE void setTargetDeg(int32_t ntar, GS_posType type = ABSOLUTE); // установить цель в градусах и опционально режим ABSOLUTE/RELATIVE int32_t getTarget(); // получить целевую позицию в шагах void setAcceleration(uint16_t nA); // установка ускорения в шаг/сек^2 void setMaxSpeed(int speed); // установить скорость движения при следовании к позиции setTarget() в шагах/сек void setMaxSpeed(float speed); // установить скорость движения при следовании к позиции setTarget() в шагах/сек, float void setMaxSpeedDeg(int speed); // установить скорость движения при следовании к позиции в град/сек void setMaxSpeedDeg(float speed); // установить скорость движения при следовании к позиции в град/сек, float void setCurrent(int32_t npos); // установить текущую позицию int32_t getCurrent(); // получить текущую позицию void reset(); // сбросить текущую позицию в 0 // всякое uint32_t getPeriod(); // получить текущий период тиков void brake(); // резко остановить мотор void pause(); // пауза - доехать до заданной точки и ждать (ready() не вернёт true, пока ты на паузе) void resume(); // продолжить движение после остановки/паузы uint8_t getStatus(); // текущий статус: 0 - стоим, 1 - едем, 2 - едем к точке паузы, 3 - крутимся со скоростью, 4 - тормозим // ===== ДЕФАЙНЫ НАСТРОЕК ===== // дефайнить перед подключением библиотеки #define GS_NO_ACCEL // отключить модуль движения с ускорением (уменьшить вес кода)
Пример
// крутим туда сюда, тикаем в loop #include "GyverStepper2.h" GStepper2 < STEPPER2WIRE>stepper(400, 2, 3); void setup() < Serial.begin(9600); //stepper.enable(); stepper.setMaxSpeed(100); // скорость движения к цели stepper.setAcceleration(200); // ускорение stepper.setTarget(300); // цель >bool dir = 1; void loop() < stepper.tick(); // мотор асинхронно крутится тут // если приехали if (stepper.ready()) < dir = !dir; // разворачиваем stepper.setTarget(dir * 300); // едем в другую сторону >// асинхронный вывод в порт static uint32_t tmr; if (millis() - tmr >= 30) < tmr = millis(); Serial.println(stepper.pos); >>
Документация GPlanner
Многоосевой планировщик траекторий для шаговых моторов и создания станка с ЧПУ
- ОСТАНОВКА В КАЖДОЙ ТОЧКЕ. БУФЕР НА ОДНУ СЛЕДУЮЩУЮ ПОЗИЦИЮ
- Макс. скорость: 37000 шаг/с на полной, 14000 шаг/с на разгоне
- Трапецеидальный профиль скорости (планировщик 2-го порядка)
- Настройка скорости и ускорения
- Любое количество осей. Будут двигаться синхронно к заданным целям
- Быстрая целочисленная модель планирования траектории и скорости
- Режим постоянного вращения для одной оси (для движения к концевику например)
- Тормоз/плавная остановка/пауза на траектории планировщика
- Оптимизировано для работы по прерыванию таймера
- Быстрый контроль пинов шаговика для Arduino AVR
Как работает
Планировщик управляет любым количеством моторов, вращая их к указанной позиции. В данной версии остановка происходит в каждой точке траектории, после чего поднимается флаг ready() и ожидает установки следующей точки.
Инициализация
GPlanner < драйвер, количество осей>planner;
Использование
void addStepper(uint8_t axis, Stepper &stp); // подключить мотор класса Stepper на ось axis // примечание: тип драйвера должен совпадать у планировщика и моторов // НАСТРОЙКИ void setMaxSpeed(float nV); // установка максимальной скорости планировщика в шаг/сек void setAcceleration(uint16_t nA); // установка ускорения планировщика в шаг/сек^2 // ПЛАНИРОВЩИК uint32_t getPeriod(); // возвращает время в мкс до следующего вызова tick/tickManual bool ready(); // true - готов принять следующую точку маршрута void pause(); // пауза (доехать до заданной точки и ждать). ready() не вернёт true, пока ты на паузе void stop(); // остановить плавно (с заданным ускорением) void brake(); // резко остановить моторы из любого режима void resume(); // продолжить после остановки/паузы void reset(); // сбросить счётчики всех моторов в 0 uint8_t getStatus(); // текущий статус: 0 - стоим, 1 - едем, 2 - едем к точке паузы, 3 -крутимся со скоростью // СКОРОСТЬ void setSpeed(uint8_t axis, float speed); // режим постоянного вращения для оси axis со скоростью speed шаг/сек (м.б. отрицателеьной) // ПОЗИЦИЯ void setCurrent(int16_t cur[]); // установить текущее положение моторов void setCurrent(int32_t cur[]); // установить текущее положение моторов int32_t getCurrent(int axis); // получить текущую позицию по оси axis // установить цель в шагах и начать движение. type - ABSOLUTE (по умолч.) или RELATIVE // ABSOLUTE - конкретные координаты точки, куда двигаться // RELATIVE - смещение относительно текущих положений моторов // вернёт true, если цель установлена. false, если цель совпадает с текущей bool setTarget(int32_t target[]); bool setTarget(int16_t target[]); bool setTarget(int32_t target[], type); bool setTarget(int16_t target[], type); int32_t getTarget(int axis); // получить цель в шагах на оси axis // ТИКЕР // тикер, вызывать как можно чаще. Вернёт true, если мотор крутится // здесь делаются шаги как для движения по точкам, так и для вращения по скорости bool tick(); // ручной тикер для вызова в прерывании или где то ещё. Выполняется 20..50 us bool tickManual();
Пример
// базовый пример: как создать и запустить планировщик // при запуске моторы будут отправлены на первую позицию // при достижении - на вторую. После этого движение прекратится // открой плоттер и смотри графики #include "GyverPlanner.h" // создаём моторы класса Stepper с указанием типа драйвера и пинов // МОТОРЫ ДОЛЖНЫ БЫТЬ С ОДИНАКОВЫМ ТИПОМ ДРАЙВЕРА // вот они красавцы Stepper < STEPPER2WIRE >stepper1(2, 3); Stepper < STEPPER2WIRE >stepper2(4, 5); // создаём планировщик, указываем в <> тип драйвера КАК У МОТОРОВ // и количество осей, равное количеству моторов (любое больше 1) GPlanner < STEPPER2WIRE, 2 >planner; void setup() < Serial.begin(115200); // добавляем шаговики на оси planner.addStepper(0, stepper1); // ось 0 planner.addStepper(1, stepper2); // ось 1 // устанавливаем ускорение и скорость planner.setAcceleration(100); planner.setMaxSpeed(300); planner.reset(); // сбрасываем все позиции в 0 (они и так в 0 при запуске) // массив с целевыми позициями осей, размер массива равен количеству осей int target[] = ; // отправляем planner.setTarget(target); > void loop() < // здесь происходит движение моторов, вызывать как можно чаще planner.tick(); // вернёт true, если все моторы доехали if (planner.ready()) < // загружаем новую точку int newTarget[] = ; planner.setTarget(newTarget); > // асинхронно вывожу в порт графики static uint32_t tmr; if (millis() - tmr >= 20) < tmr = millis(); Serial.print(stepper1.pos); Serial.print(','); Serial.println(stepper2.pos); >>Документация GPlanner2
Многоосевой планировщик траекторий для шаговых моторов и создания станка с ЧПУ
- ПЛАНИРОВАНИЕ СКОРОСТИ НА МАРШРУТЕ. НАСТРАИВАЕМЫЙ БУФЕР
- Макс. скорость: 37000 шаг/с на полной, 14000 шаг/с на разгоне
- Трапецеидальный профиль скорости (планировщик 2-го порядка)
- Настройка скорости и ускорения
- Любое количество осей. Будут двигаться синхронно к заданным целям
- Быстрая целочисленная модель планирования траектории и скорости
- Режим постоянного вращения для одной оси (для движения к концевику например)
- Тормоз/плавная остановка/пауза на траектории планировщика
- Оптимизировано для работы по прерыванию таймера
- Быстрый контроль пинов шаговика для Arduino AVR
Как работает
Планировщик управляет любым количеством моторов, вращая их к указанной позиции. В данной версии реализован буфер траектории, который можно наполнять точками, пока available() возвращает true. addTarget() принимает:
- Массив точек указанного при инициализации размера
- Флаг остановки. Если передать 1 — планировщик остановит мотор в этой точке и будет ждать дальнейшей команды resume()
- Тип точки: ABSOLUTE (абсолютная координата) или RELATIVE (относительно предыдущей точки)
Когда планировщик приезжает до точки остановки — он встаёт на паузу (например для включения выключения инструмента), после совершения нужных действий вызываем resume() и он продолжает движение.
В отличие от предыдущего GPlanner, в GPlanner2 реализован просчёт траектории в буфере и планирование скорости для всех точек, что позволяет системе двигаться быстрее и не тормозить в каждой точке.Инициализация
GPlanner2 < драйвер, количество осей >planner; // объявление GPlanner2 < драйвер, количество осей, размер буфера >planner; // + размер буфера (по умолч. 32)
Использование
void addStepper(uint8_t axis, Stepper &stp); // подключить мотор класса Stepper на ось axis // примечание: тип драйвера должен совпадать у планировщика и моторов // НАСТРОЙКИ void setMaxSpeed(float nV); // установка максимальной скорости планировщика в шаг/сек void setAcceleration(uint16_t nA); // установка ускорения планировщика в шаг/сек^2 void setDtA(float newDta); // установить dt смены скорости в повороте, 0.0.. 1.0 по умолч. 0.3 // ПЛАНИРОВЩИК uint32_t getPeriod(); // возвращает время в мкс до следующего вызова tick/tickManual void start(); // начать работу void stop(); // остановить плавно (с заданным ускорением) void brake(); // резко остановить моторы из любого режима void resume(); // продолжить после остановки или конечной точки маршрута void reset(); // сбросить счётчики всех моторов в 0 bool ready(); // флаг достижения точки остановки. После неё нужно вызывать resume bool available(); // true - в буфере планировщика есть место под новю точку uint8_t getStatus(); // текущий статус: // 0 ожидание команды (остановлен) // 1 ожидание буфера // 2 в пути // 3 на паузу // 4 на стоп // 5 крутится setSpeed // СКОРОСТЬ void setSpeed(uint8_t axis, float speed); // режим постоянного вращения для оси axis со скоростью speed шаг/сек (м.б. отрицательной) // ПОЗИЦИЯ // добавить новую точку маршрута. Массив координат, флаг окончания и абсолютный/относительный void addTarget(int32_t tar[], uint8_t l, GS_posType type = ABSOLUTE); void addTarget(int16_t tar[], uint8_t l, GS_posType type = ABSOLUTE); // ABSOLUTE - конкретные координаты точки, куда двигаться // RELATIVE - смещение относительно текущих положений моторов void setCurrent(int16_t cur[]); // установить текущее положение моторов void setCurrent(int32_t cur[]); // установить текущее положение моторов int32_t getCurrent(int axis); // получить текущую позицию по оси axis int32_t getTarget(int axis); // получить текущую цель в шагах на оси axis // ТИКЕР // тикер, вызывать как можно чаще. Вернёт true, если мотор крутится // здесь делаются шаги для движения по точкам, для вращения по скорости, а также перестройка буфера bool tick(); // ручной тикер для вызова в прерывании или где то ещё. Выполняется 20..50 us bool tickManual(); // обработчик буфера. Сам вызывается в tick. Нужно вызывать вручную при работе с tickManual // вернёт true, если планировщик отправил моторы на новую позицию (в этот момент можно запускать таймер) void checkBuffer();
Пример
// пример с записанным в памяти маршрутом // смотри график, а лучше запусти stepperPlot int path[][2] = < , , , , , >; // количество точек (пусть компилятор сам считает) // как вес всего массива / (2+2) байта int nodeAmount = sizeof(path) / 4; #include "GyverPlanner2.h" Stepper < STEPPER2WIRE >stepper1(2, 3); Stepper < STEPPER2WIRE >stepper2(4, 5); GPlanner2 < STEPPER2WIRE, 2 >planner; void setup() < Serial.begin(115200); // добавляем шаговики на оси planner.addStepper(0, stepper1); // ось 0 planner.addStepper(1, stepper2); // ось 1 // устанавливаем ускорение и скорость planner.setAcceleration(500); planner.setMaxSpeed(500); // начальная точка системы должна совпадать с первой точкой маршрута planner.setCurrent(path[0]); planner.start(); >int count = 0; // счётчик точек маршрута void loop() < // здесь происходит движение моторов, вызывать как можно чаще planner.tick(); // если в буфере планировщика есть место if (planner.available()) < // добавляем точку маршрута и является ли она точкой остановки (0 - нет) planner.addTarget(path[count], 0); if (++count >= sizeof(path) / 4) count = 0; // закольцевать > // асинхронно вывожу в порт графики static uint32_t tmr; if (millis() - tmr >= 20) < tmr = millis(); Serial.print(stepper1.pos); Serial.print(','); Serial.println(stepper2.pos); >>Плавность хода, шум и момент шагового двигателя при управлении микроконтроллером
Далее опишу алгоритм управления ШД с помощью микроконтроллера.
Перед тем, как начать описывать задачу, я изложу основы управления ШД, которые будут включать необходимый минимум для рассмотрения, описанных в статье способов управления.
Рассмотрим необходимый минимум основ управления ШД , необходимый для понимания принципа управления, описанного ниже. А именно:
- Способы подключения обмоток, необходимые для осуществления данного режима работы. Полношаговый режим управления при задействовании на один шаг двух фаз.
- Изменение полярности обмотки с помощью Н-моста.
- Принципиальная электрическая схема, включающая в себя 4 драйвера полумоста и 2 Н-моста.
- Способ модуляции синусоидального сигнала с помощью широтно-импульсной модуляции (далее просто ШИМ).
ШД имеют 4,5,6 или 8 выводов обмоток. При подключении к модулю управления ШД в каждом конкретном случае необходимо задействовать определенные выводы. В четырех выводном ШД задействуются все четыре вывода. Пяти выводной ШД не подходит для метода управления, описываемого в этой статье. В шести выводном не задействуются выводы нейтральных точек. В восьми выводном ШД обмотки соединены последовательно (см. рис. 1). Конечно можно задействовать все выводы обмоток, но эти методы управления выходят за рамки статьи.

Описание полношагового режима управления.
Для управления ШД необходимо подавать определенную последовательность сигналов на обмотки ШД . По сути создавая статором бегущую волну, заставляющую синхронно вращаться поле статора и ротора ШД . На рис. 2 над диаграммой схематично показан статор с обмотками. Цвет обмоток указывает на их полярность. В центре находится ротор в виде магнита. Если обратить внимание на диаграмму, то будет видно, что в середине каждого шага идет поочередное изменение полярности обмоток. В след за изменяющимся полем статора, вращается ротор по часовой стрелке. Для изменения вращения двигателя можно поменять местами выводы одной обмотки, и ротор начнет вращаться в противоположную сторону. Но зачем менять подключение обмоток, если можно программным путем поменять местами подаваемые сигналы, что и сделано с А+ и А- на рис.2. При этом ротор также начнет вращаться в противоположную сторону. Для большей наглядности сигнал на диаграмме имеет прямоугольную форму. Далее в статье прямоугольный сигнал будет заменен на сигнал ШИМ, модулирующий синусоиду.

Изменить полярность обмотки можно с помощью Н-транзисторного моста (см. рис. 3). В первом варианте из 4 транзисторов открыты Т1,Т4. Ток, соответственно, течет через них. Поменять полярность можно, открыв транзисторы Т2 ,Т3 и при этом закрыв Т1 И Т4. Таким образом, ток через обмотку потечет в противоположную сторону.

Для управления ШД используют два Н моста чаще всего на основе восьми N-канальных MOSFET транзисторов. Для управления транзисторами используются мостовые или полумостовые драйверы. Напряжение на затворе зачастую должно быть выше напряжения истока транзистора на 5-15В. Для MOSFET транзисторов это делают драйверы.
Кроме того, драйверы силовых ключей, в отличие от простых преобразователей уровня, снабжены множественными механизмами защиты как самого драйвера, так и управляемых ключей. Это позволяет выполнять формирование выходных управляющих сигналов согласно определенным алгоритмам, чтобы предотвратить выход системы из строя в аварийной ситуации.
Механизм встроенного временного промежутка Dead-Time обеспечивает гарантированное закрытие одного силового ключа до момента начала открытия ключа в противоположном плече. Гарантией надежного закрытия противоположного транзистора является встроенная схема, контролирующая состояние ключей и наличие схемы задержки, формирующей промежуток времени, в течение которого закрыты оба транзистора в плечах полумоста.
На рис.4 приведена принципиальная электрическая схема управления ШД, включающая в себя 4 драйвера полумоста IR2104S и 2 Н-моста на основе транзисторов IRF7836. При подаче 0 В на вход SD драйвера IR2104s драйвер переходит в неактивное состояние.
На приведенной схеме сигнал с диаграмм можно подавать на 4 входа. Так на ШИМ1 А+, на ШИМ2 А-, на ШИМ3 В+, на ШИМ4 В- соответственно (Рис.4).

Ниже кратко опишу принцип работы ШИМ, расчет и модулирование синусоиды.
ШИМ или PWM (широтно-импульсная модуляция или pulse-width modulation) – это способ изменения мощности, подаваемой на нагрузку. Управление заключается в изменении ширины импульса постоянной амплитуды, следующих через равные интервалы времени.
На рис.5 видно, как регулируется мощность. Так 20%, 40%, 80%, 100% это время, когда транзистор открыт относительно времени периода. Соответственно среднее напряжение будет приблизительно равно 20%, 40%, 80%, 100% от максимального.

Меняя ширину импульса, можно модулировать различную форму сигнала. Так, по синусоидальному закону, при котором ширина импульсов изменяется следующим образом (рис. 6), максимальна в середине шага, а к началу и концу шага уменьшается. Синусоиду можно увидеть на осциллографе, пропустив ШИМ-сигнал с контроллера через RC фильтр. Для RC фильтра использовал конденсатор 2.2 нФ и резистор 1.5кОм.
На рис. 6 показан пример модуляции одного синусоидального шага, состоящего всего из 4 уровней напряжения. Напряжение питания 12В.

Для формирования модулированного сигнала необходимо рассчитать уровни ШИМ и их количество на один шаг. На рис.7 приведено два примера одного синусоидального шага с разным количеством ШИМ уровней, где ШИМ можно изменять в пределах от 0 до 255, что соответствует напряжению от 0 до 100%. Как видно на рис.7, чем больше уровней ШИМ, тем больше форма модулированного сигнала будет повторять синусоиду. Каждое изменение ШИМ происходит по прерыванию таймера в микроконтроллере. Меняя время срабатывания прерывания, можно регулировать время одного шага соответственно и скорость двигателя.

Формулу для расчета ШИМ уровней можно получить из формулы мгновенных значений синусоидальных функции. U = Um*sin(ω*t + Ψ)

Um — амплитудное значение ω — угловая частота Ψ — начальный фаза, значение фазы в начальный момент t=0 аргумент ω*t + Ψ – называют фазой синусоидальной функции
Для расчета Ψ = 0
Синусоида от 0 до Т/4 повторяет форму половины шага, а от T/4 до Т/2 зеркально отображает вторую половину шага. Поэтому для расчета достаточно взять участок от 0 до Т/4 или от 0° до 90°. ωt – для удобства можно заменить на угол α = 0° до 90°. Um заменим на максимальное значение ШИМ_max в примере 255. U заменим на ШИМ_N. Получается ШИМ_N = ШИМ_maxSIN(α). Количество вычислений уровней ШИМ зависит от величины точности к примеру 16 с шагом угла 90°/16 = 5,625°
Значения ШИМ необходимо округлять, так как оно может быть только целым.
Вычислив уровни ШИМ, можно модулировать синусоиду. Для этого я занес значения уровней в массив по прерыванию от таймера, поочередно подставляя значения от ШИМ_0 до ШИМ_16 в ШИМ контроллера. Так модулируется половина шага. Для модуляции второй половины нужно наоборот подставлять значения от ШИМ_16 до ШИМ_0.
Так модулируется один шаг. Меняя время срабатывания таймера можно менять время шага. Теперь такие синусоидальные шаги можно подавать, заменив прямоугольные шаги на диаграммах (рис.2).
Для удобства я написал небольшую программу для расчета значений ШИМ . Где PWM_MAX присваивается максимальное значение ШИМ, которое настраивается в микроконтроллере, а sampling присваивается количество уровней ШИМ на половину шага. Так как большинство программируют МК на языке С, данную программу я решил написать на этом же языке.
#include #include #define PI 3.14159265 #define QUANTIZATION 255 //максимальное значение ШИМ. #define SAMPLING 16 // количество уровней напряжения на половину шага. int i; int main(); return 0; > 0 25 50 74 98 120 142 162 180 197 212 225 236 244 250 254 255
На этом необходимый минимум основ управления ШД завершается. Далее будет описана поставленная задача, возникшие трудности и их решение.
Задача: Двигатель должен вращать массу около 7кг за 0,7 — 1 секунду на 90°. Угол поворота отслеживает 10 разрядный или 1024 битный абсолютный энкодер AS5040 закрепленный на валу механизма. При достижении 90° необходимо включить режим удержание ШД. При этом необходимо учитывать воздействие руки человека, толкающей механизм по направлению движения или против, либо удерживающей вплоть до остановки. При этом напряжение питания блока управления ограничено двенадцатью вольтами, а габариты двигателя ограничены по ширине 100мм, а по длине 110мм, включая длину вала. В наличии было три двигателя подходящих габаритов.
Осовные характеристики двигателей:
- двигатель №1 Рабочий ток 3,1 А. Активное сопротивление обмотки 1,5 Ом Индуктивность обмотки 3,5 мГн. Момент удержания 0,3 кг*м Величина полного шага 1,8° (200 шагов на один оборот ротора).
- двигатель №2 Рабочий ток 4А. Активное сопротивление обмотки 0,8 Ом. Индуктивность обмотки 3,1 мГн. Момент удержания 0,45 кг*м. Величина полного шага 1,8° (200 шагов на один оборот ротора).
- двигатель №3 не соответствовал характеристикам, заявленным производителем. Производитель утверждал, что он является аналогом двигателя №2. При замере активного сопротивления обмоток выяснилось, что сопротивление не соответствовало заявленным 0,8 Ом, а составляло всего 0,2 Ом. Следовательно, рабочий ток и индуктивность тоже отличались.
Изначально решить поставленную задачу я планировал с помощью готового блока управления ШД. Было испытано около пяти готовых блоков управления ШД разной ценовой категории и разных производителей. У всех были приблизительно одни и те же результаты, которые будут описаны ниже.
При испытании двигатель №3 по шуму и вибрациям отличался от первых двух в худшую сторону. Также было замечено, что все блоки управления с этим двигателем сильно грелись. Было решено больше не использовать этот двигатель.
Проблема №1. Свист двигателя. При уменьшении тока на блоках управления шум становился меньше, двигатель более плавно вращает ротор, и всё-таки шум и плавность вращения оставляли желать лучшего. При увеличении дробления шага на блоках управления до 1/16 шум уменьшился, и плавность хода увеличилась, но эти улучшения были незначительны. Дальнейшее повышение дробления вплоть до 1/512 не привело к улучшению показателей.
Решение проблемы №1. Решил сделать свой драйвер управления ШД на основе микроконтроллера PIC18F2331. Он заточен под управление двигателями. Было задействовано 4 канала широтно-импульсной модуляции для управления 4 драйверами полумоста.
Я начал эксперименты с формой сигнала, модулируемого с помощью ШИМ. Подавал треугольный, прямоугольный, трапециевидный сигналы на обмотки двигателя. Результаты: неутешительные показатели по шуму, вибрации и плавности хода были значительно хуже по сравнению с готовыми блоками управления. Подавая на обмотки двигателя синусоидальный сигнал, плавность хода, начиная от 5 об/мин и выше, стала практически незаметной на глаз. Детали механизма не гремели, но если скорость была ниже 5 об/мин, детали гремели, механизм передвигался рывками, ток потребляемый двигателем рос и выходил за пределы рабочего тока двигателя. Что касается шума, даже при скорости выше 5 об/мин был неприятный шум. Свист похожий на звук, издаваемый зарядными устройствами для телефонов ноутбуков, только гораздо сильнее. Такой же шум я слышал от асинхронных двигателей, управляемых частотными преобразователями. Изучив работу частотных преобразователей, стало ясно, что свист зависит от частоты ШИМ. У меня частота ШИМ составляла 4кГц. При изменении частоты свист менялся, и когда я поднял частоту до 20кГц, шум полностью пропал. Слух человека в большинстве случаев не воспринимает частоту выше 20кГц.Так была решена проблема №1.
Проблема №2. Двигатель ниже 5 об/мин двигается рывками, а ток сильно возрастает, так как у драйвера нет обратной связи по току, соответственно и контроля по перегрузке тоже нет.
Решение проблемы №2. Когда напряжение питания драйвера с 12V снизил до 9V, рывки при передвижении механизма тоже стали меньше, но всё равно недостаточно плавно. Тогда напряжение выставил 12V, а амплитуду ШИМ синусоиды начал уменьшать, и при 20% амплитуды от максимума движение было плавным и тихим.
Проблема №3. Если запустить двигатель сразу на большой скорости без разгона, то момент на валу двигателя будет недостаточным для вращения механизма. Начнется пропуск шагов, сопровождаемый сильным шумом, который распространяется по всему корпусу механизма. Звук напоминал ведро с болтами, которое трясут изо всех сил. Так как необходимо было провернуть механизм на 90° за 0,7 — 1 сек., я решил, что до 45° буду линейно ускоряться, а с 45° до 90° линейно замедляться. Достигнуть даже приближённо времени в 1сек не удалось. Еще было замечено при старте, что первый шаг периодически сопровождался рывком ротора. Это связанно с тем, что зубцы ротора могут находиться не на оси включенной обмотки статора. В следствие чего зубцы ротора стремительно притянутся к обмотке, произойдёт фиксация ротора, сопровождающаяся звуком, похожим на удар. Все последующие шаги будут плавными.
Решение проблемы №3 . Рассматривая график зависимость оборотов двигателя и момента, я заметил, что момент при малых оборотах высокий, а с увеличением оборотов нелинейно падает, и чем меньше напряжение питания, тем хуже зависимость.
Для примера покажу график Рис.9. Взятый из даташита.
На двигатель FL86STH156-6204 ток фазы 6,0 А. Максимальный постоянный ток потребления от источника питания 3,8 А для блока SMD-9.0 Блоки управления SMD-9.0 (напряжение 72В) и SMD-82 (напряжение 220В) Дробление шага ½, источник питания 72 В, 300 Вт.

Чем больше напряжение подается на обмотки ШД, тем быстрее идет нарастание тока в них. Соответственно зависимость момента от скорости улучшается.
В моем случае питание 12В и диапазон допустимых скоростей невысок, так как момент стремительно падает с увеличением скорости.
Так как при равномерном ускорении не удавалось разогнать механизм. Я решил разделить ускорение на три диапазона. Первый при скорости ниже 5 об/мин ускорение максимально, так как момент максимально высокий. Второй диапазон от 5 до 7 об/мин ускорение уже в три раза меньше и последний третий диапазон от 7 об/мин и выше, ускорение в десять раз меньше относительно первого диапазона. Таким образом двигатель набирал максимально быстро скорость в начале пути и укладывался в 1с. Нелинейно разгоняя двигатель, можно значительно сократить время разгона ШД. Замедление механизма проходило в обратном порядке. Так как сохраненной осциллограммы сигнала, подаваемого на драйверы полумостов, у меня не осталось, я нарисовал, как, примерно, должна выглядеть осциллограмма.

При старте, первый шаг периодически сопровождался рывком ротора. Удар можно убрать, путем снижения амплитуды первой половины шага (в моем случае 20% от максимума) и значительно увеличив время первой половины шага по сравнению с другими шагами. Как видно на рис.10, первые половины шагов более вытянуты, чем правые. Это связанно с ускорением. Форма синусоиды искажается, но при этом двигатель работает достаточно плавно и тихо. Как видно на рис.10, ускорение максимально, это заметно по сужению шагов в начале движения. Когда момент максимален, а по мере приближения к максимальной скорости ускорение значительно меньше от изначального. Все диапазоны ускорений подбирались экспериментальным путем. Как регулировать амплитуду и ускорение я описал ранее в этой статье.
Проблема №4. Учет воздействия руки на механизм, если не учитывать воздействие руки, то можно было обойтись парой индуктивных датчиков или оптических датчиков для отслеживания крайних положений и направления вращения. А если учитывать воздействие руки, то без датчика угла поворота (абсолютного энкодера) не обойтись. Если механизм находится в движении, а рука хватает его и удерживает на месте, начинается пропуск шагов и сильный шум. По датчику будет видно, что вал колеблется на месте, и двигатель необходимо отключить и попытаться стартовать через заданный промежуток времени. Эта задача легко решаема. Если рука потянула механизм против направления, по датчику можно легко понять, что механизм вращается в противоположную сторону, и тоже отключить двигатель. И совсем другое дело, воздействие на механизм с увеличением скорости перемещения больше заданной изначально или наоборот притормаживание. Логично было измерять скорость перемещения и подстраиваться, чтобы скорость двигателя совпадала с движением руки, но оказалось, что 10 разрядный датчик as5040 не позволял этого сделать. Предположим, что нужно отслеживать перемещение каждые 1,05° .Так как 10 разрядов это 1024 бита, то вычисляем точность 360°/1024 = 0,35°, количество градусов на один бит возьмём 0,35°3 = 1,05°. Зная время, за которое двигатель проходит 1,05°, можно вычислить скорость. Но не все так просто. У датчика есть погрешность — биение младшего бита, то есть погрешность в один бит, а при измерении скорости нужно сделать два замера пройденного пути. В начале и в конце соответственно погрешность удваивается и составляет 0,35°2=0,7°. Измерить скорость каждые 1,05° невозможно. Логично измерять, например, каждые 0,35°*15=5,25°. Уже можно оценить скорость, но 5,25° это слишком большой угол, двигатель успеет пройти почти 3 шага или более точно 5,25°/1,8°= 2,92.
Решение проблемы №4. Целесообразно для измерения скорости использовать 12 разрядный датчик это 4096 бит. Точность измерения увеличится в четыре раза, что позволит точно подбирать скорость движения механизма под скорость движения руки.
Так была решена последняя проблема.
Думаю, эта статья принесет практическую пользу и поможет читателю лучше понять принципы управления шаговым двигателем.
- шаговый двигатель
- микроконтроллеры