Официальный сайт компании Arduino по адресу arduino.cc
Шаговый двигатель (оптимизация)
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Пнд, 25/09/2017 - 15:26
Добрый день! Сделал на базе ардуино и шагового двигателя (28BYJ-48) управления вертикальным жалюзи.
Есть скетч, но есть 3 момента:
1) Можно ли этот код оптимизировать?
2) Не нашел как отключить фиксацию ротора шагового двигателя, движок грееться и расходует лишнюю энергию.
3) Подключить дополнительно дублирующие щаговые двигатели (сколько можно их подключить?) В идеале хочу добиться управления 6ти вертикальных жалюжи, 3(независимое упр)+3 (независимое упр).
/*Программа для шагового двигателя 28BYJ-48 (5V). В схеме есть кнопка и потенциометр. В зависимости от положения кнопки (пол. 1, пол. 2, выключено) мотор вращается либо в одну сторону, либо в другую, либо стоит на месте, а потенциометр влияет на скорость вращения.*/ /*У данного мотора 4 провода (оранж., жёлт., розов., син.), которые мы подключаем к контактам ардуино. Номера контактов указываем в массиве MotorPins, в порядке, соответствующем перечислению цветов, в нашем случае с D12 по D9*/ int MotorPins[4] = {8, 9, 10, 11}; /*Контакты от двух положений кнопки - цифровые*/ const int ButtonOn1 = 5; const int ButtonOn2 = 4; /*Контакт регистрирующий значение потенциометра - аналоговый*/ const int PotenciomData = 0; /*Целочисленная константа, показывающая количество фаз подачи сигналов для одного шага мотора. Для полушагового режима - 8 Для шагового - 4*/ const int OneTurnPhasesCount = 8; /*Целочисленная переменная, показывающая задержку в миллисекундах между фазами подачи сигналов мотору. Для полушагового режима - 2, для шагового - 3*/ int TurnPhasesDelay = 2; /*Целочисленная переменная, показывающая номер текущей фазы*/ int CurrentPhase = 0; //состояние кнопки включено-выключено int ButtonState = 0; /*Целочисленная переменная, показывающая направление вращения мотора: 1 - по часовой стрелке, 0 - против*/ int TurnDirection = 1; /*целочисленная константа, показывающая временную задержку между считыванием состояния кнопки и потенциометра*/ const int CheckButtonDelay = 15; /*Целочисленная переменная показывающая, сколько прошло времени и не пора ли считывать состояние кнопки*/ int CurrentButtonDelay = 0; //Для полушагового режима /*Массив, в котором указано какие сигналы подавать на контакты мотора в той или иной фазе. [фаза][контакт]. Контакты даются в порядке, перечисленном в массиве MotorPins - оранж., жёлт., розов., син. 0 - нет сигнала, 1 - есть сигнал*/ bool MotorTurnPhases[8][4] = { { 1, 1, 0, 0}, { 0, 1, 0, 0}, { 0, 1, 1, 0}, { 0, 0, 1, 0}, { 0, 0, 1, 1}, { 0, 0, 0, 1}, { 1, 0, 0, 1}, { 1, 0, 0, 0} }; /*Функция, в которой происходит инициализация всех переменных программы*/ void setup() { /*перебираем в цикле все контакты массива MotorPins и присваиваем им значение выходных, то есть дающих напряжение в 5В*/ for (int i = 0; i < 4; i++) pinMode(MotorPins[i], OUTPUT); pinMode(ButtonOn1, INPUT); pinMode(ButtonOn2, INPUT); pinMode(PotenciomData, INPUT); } /*Функция-цикл в которой задаётся поведение программы*/ void loop() { if(CurrentButtonDelay >= CheckButtonDelay) { CheckButtonState(); CurrentButtonDelay = 0; } if(ButtonState != 0) { //проверяем индекс текущей фазы CheckLastPhase(); /*подаём напряжения на контакты мотора соответственно фазе, заданной в массиве MotorTurnPhases*/ for (int i = 0; i < 4; i++) { digitalWrite(MotorPins[i], ( (MotorTurnPhases[CurrentPhase][i] == 1) ? HIGH : LOW) ); } //переходим к другой фазе CurrentPhase += TurnDirection; // Пауза между фазами delay(TurnPhasesDelay); } CurrentButtonDelay += TurnPhasesDelay; } /*Функция CheckLastPhase проверяет не вышел ли номер текущей фазы за пределы размера массива MotorTurnPhases, который определяется переменной OneTurnPhasesCount*/ void CheckLastPhase() { if (CurrentPhase >= OneTurnPhasesCount) { CurrentPhase = 0; } if (CurrentPhase < 0) { CurrentPhase = (OneTurnPhasesCount-1); } } /*функция, в которой проверяется текущее состояние кнопки*/ void CheckButtonState() { int CurrentButtonState = 0, CurrentButtonDirection = 0, CurrentTurnPhasesDelay = 0; //считываем данные с положения кнопки I bool readbuttonparam = digitalRead(ButtonOn1); if(readbuttonparam) { CurrentButtonState = 1; CurrentButtonDirection = 1; } //считываем данные с положения кнопки II readbuttonparam = digitalRead(ButtonOn2); if(readbuttonparam) { CurrentButtonState = 1; CurrentButtonDirection = -1; } /*Проверяем, изменилось ли состояние кнопки по сравнению с предыдущим, и если изменилось, то записываем изменения в глобальные переменные*/ if(ButtonState != CurrentButtonState) { ButtonState = CurrentButtonState; } if(TurnDirection != CurrentButtonDirection) { TurnDirection = CurrentButtonDirection; } CurrentTurnPhasesDelay = map(analogRead(PotenciomData), 0, 1023, 2, CheckButtonDelay); if(TurnPhasesDelay != CurrentTurnPhasesDelay) { TurnPhasesDelay = CurrentTurnPhasesDelay; } }
Прошу помочь
(Шаговый двигатель 28BYJ-84, драйвер на основе ULN2003)
1) Можно ли этот код оптимизировать?
Оптимизировать можно всё. Другой вопрос, что Вы не указали цель оптимизации.
А код подробно не глядел, но на первый взгляд выглядит прилично. Стесняюсь спросить ... сами писали?
Брал отсюда http://www.techclub.su/article_arduino06. Цель оптимизации минимальное энергопотребление! Что бы включил в розетку и забыл.
В данный момент при остановке шаговик фиксирует себя и наченает греться, не могу понять как отключить эту функцию.
Так же могу ли я скажем так парралельно добавить шаговый двигатель после драйвера или через ардуионо?
Движок, как правило, отключается подаванием одинаковых уровней на драйвер мотора, читайте доку к своему драйверу. Например, подав HIGH на оба управляющих входа H-моста - можно отключить мотор, при этом ротор будет вращаться руками свободно. Короче - всё зависит от драйвера, смотрите доку по нему.
Нет, это другой драйвер - для 4 ф униполярного шаговика. Там 4 входа и 4 выхода. Дал High- выход на землю (open collector), дал Low- выход болтается. Это просто четверной дарлингтон 2003.
Только с двумя драйверами. Для отключения шд во время паузы подайте LOW на все пины управления драйвером ШД
Просто моргает 1 светодиод на драйвере(
после
напишите
Нет, нет и нет - не делайте так, как только что посоветовали. Да, надо отключить фазы, чтобы зря не гонять, но делать это в каждом шаге нельзя, от слова совсем. Заведите таймер и если фаза не меняется в течении длительнго времени, только тогда отключайте, ну или если нет управляющего воздействия (нет кнопок) - на Ваш выбор, но не в каждом такте.
А по поводу параллельных моторов - да пожалуйста, если они идентичны и скорость шага приемлема для всех сразу.
ButtonState и так уже очищена от дребезга, разве нет?
и задержка уже есть есть
delay(TurnPhasesDelay);
Можно (как вариант) в разрез на драйвер сборку реле 4х канальное. При включении реле замыкает провод. Отработал шаговик - вырубить реле.
Вот когдато писал для себя, может и Вам подойдет
Увы для меня не подходят!
Нашел в просторах ютуба интересный ролик https://www.youtube.com/watch?v=FSIaVWwrMx4&t=147s
https://www.youtube.com/watch?v=B36QTZdG8zs&feature=youtu.be
https://www.youtube.com/watch?v=FSIaVWwrMx4&feature=youtu.be
Вот скетч:
полностью рабочая (проверял) с возможностью переключеня в авто режим (фототранзистор).
Но есть недостаток если потенциометр например в положении 50% (0-100%) при отключении и вновь подачи питания шаговый двигатель прокручивается на определенный шаг сбивается калибровка (т.е может сломать жалюжи). Можно ли доработать данную схему. Ну конечно не бесплатно!
Вот скетч:
NEVEC здравствуй. А библиотеку можно от вас получить. Я так понял ее отдельно писали.