Управление шаговыми двигателями. Библиотека AccelStepper.
- Войдите на сайт для отправки комментариев
Вс, 29/01/2017 - 21:45
Доброго времени суток! Уважаемые Форумчане, помогите начинающему, пожалуйста. Уже месяц колупаюсь над проектом ( возникла такая необходимость ), начал с нуля... с полного нуля, а уже с неделю не получается вращать двигатели как хотелось бы.
Должно быть так - выбирается управление автомат или ручное. На автомате начинают в паре вращаться myStepper1 и myStepper4 (это работает) потом 2-й (работает) и затем 3-й в паре с 4-м (начались проблемы, вращается только 3-й). Этот цикл должен повторится, ну скажем 5 раз и остановиться. При повторном выборе режима авто должно
все повториться. ВООБЩЕ не получается повторить вращение, только через полное отключение. При вращении двигателей, когда срабатывает кнопка переключения режимов они должны остановиться, пока вращаются 2-й и 4-й это получается а дальше управление теряется. Помогите кто чем может, у меня уже ума не хватает.
Вот код:
#include <AccelStepper.h>
#include <Wire.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd1(31, 32, 33, 34, 35, 36);
LiquidCrystal lcd2(A8, A9, A10, A11, A12, A13);
// Define some steppers and the pins the will use
AccelStepper myStepper1; // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5
AccelStepper myStepper2(AccelStepper::FULL4WIRE, 6, 7, 8, 9);
AccelStepper myStepper3(AccelStepper::FULL4WIRE, 10, 11, 12, 13);
AccelStepper myStepper4(AccelStepper::FULL4WIRE, 14, 15, 16, 17);
const int buttonPinA_M = A4;
const int buttonPinB_1 = A7;
const int buttonPinB_2 = A2;
const int buttonPinB_3 = A3;
const int ledPin5V = 40;
const int ledPinSTOP = 41;
const int ledPinAUTO = 18;
const int ledPinMANUAL = 19;
const int ledPinD_1 = 44;
const int ledPinD_2 = 43;
const int ledPinD_3 = 42;
const int ledPinD_4 = 2;
int A_M = 1;
int flag = 0;
int regim = 0;
int flag_1 = 0;
int regim_1= 0;
volatile int state = LOW;
void setup()
{
myStepper1.setMaxSpeed(300.0);
myStepper1.setAcceleration(200.0);
myStepper1.moveTo(500);
myStepper2.setMaxSpeed(300.0);
myStepper2.setAcceleration(200.0);
myStepper2.moveTo(100);
myStepper3.setMaxSpeed(300.0);
myStepper3.setAcceleration(200.0);
myStepper3.moveTo(100);
myStepper4.setMaxSpeed(300.0);
myStepper4.setAcceleration(200.0);
myStepper4.moveTo(100);
pinMode(buttonPinA_M, INPUT);
pinMode(buttonPinB_1, INPUT);
pinMode(buttonPinB_2, INPUT);
pinMode(buttonPinB_3, INPUT);
pinMode(ledPin5V, OUTPUT);
pinMode(ledPinAUTO, OUTPUT);
pinMode(ledPinMANUAL, OUTPUT);
pinMode(ledPinSTOP, OUTPUT);
pinMode(ledPinD_1, OUTPUT);
pinMode(ledPinD_2, OUTPUT);
pinMode(ledPinD_3, OUTPUT);
Serial.begin(9600);
}
void loop()
{
digitalWrite(ledPin5V, HIGH);
if(digitalRead(buttonPinA_M) == !state && flag == 0)
{
regim ++;
flag = 1;
if(regim > 2) // Если номер режима превышает требуемого
{ // то отсчет начинается с нуля
regim = 0;
}
}
if(digitalRead(buttonPinA_M) == state && flag == 1)
{
flag = 0;
}
// ======= Вполняем задачу при выборе режима =======
// РЕЖИМ 0: OFF
if(regim == 0)
{
Stop();
}
// РЕЖИМ 1: AVTO
if(regim == 1)
{
avto();
}
// РЕЖИМ 2: MANUAL
if(regim == 2)
{ digitalWrite(ledPinMANUAL,HIGH);
manual();
}
}
void motor_x3()
{
digitalWrite(ledPinD_3,HIGH);
myStepper4.run();
myStepper3.runToNewPosition(100);
myStepper3.runToNewPosition(0);
}
void motor_x2()
{
digitalWrite(ledPinD_2,HIGH);
myStepper2.runToNewPosition(100);
myStepper2.runToNewPosition(0);
if (myStepper2.distanceToGo() == 0)
motor_x3();
}
void motor_x1()
{
myStepper1.run();
myStepper4.run();
if (myStepper1.distanceToGo() == 0)
motor_x2();
}
void manual()
{
}
void Stop()
{
digitalWrite(ledPinD_1,LOW);
digitalWrite(ledPinD_2,LOW);
digitalWrite(ledPinD_3,LOW);
digitalWrite(ledPinMANUAL, LOW);
digitalWrite(ledPinAUTO, LOW);
digitalWrite(ledPinSTOP, LOW);
}
void avto()
{
digitalWrite(ledPinD_1,HIGH);
digitalWrite(ledPinMANUAL, LOW);
digitalWrite(ledPinAUTO, HIGH);
motor_x1();
if (myStepper3.distanceToGo() == 0)
digitalWrite(ledPinSTOP, HIGH);
}
когда в функцию manual добавляю
if(digitalRead(buttonPinB_1) == state && flag_1 == 0)
{
regim_1 ++;
flag_1 = 1;
if(regim_1 > 1) // Если номер режима превышает требуемого
{ // то отсчет начинается с нуля
regim_1 = 0;
}
}
if(digitalRead(buttonPinB_1) == !state && flag_1 == 1)
{
flag_1 = 0;
}
// ======= =======
// РЕЖИМ 0: OFF
if(regim_1 == 0)
{
motor_x1();
}
// РЕЖИМ 1: R
if(regim_1 == 1)
{
digitalWrite(ledPinD_1,HIGH);
digitalWrite(ledPinSTOP, HIGH);
}
для ручногоуправления тоже не продолжить движение,
не в паузу перейти.
Заранне благодарю за помощь.
Да и еще, запчасти еще в пути, моделирую в протеусе.
С нетерпением жду ответа.
вы не изучили библиотеку
сначала перепробуйте примеры и разбиритесь в них
надо помнить что в библиотеке некоторые функции блокирующие (в описании на сайте автора указано) и во время их выполнения нифига больше не работает
Все примеры перепробовал. В описании библиотеке сказано для продолжения движения
Stepper.run(); вызвать и здесь вообще непонятносколько не добавляйmyStepper1.run();myStepper1.run();myStepper1.run(); движения нет и цикл пробовал применять, толку нет, или чтото не так делаюсначала научитесь кнопкой управлять одним шаговиком
потом пробуйте наращивать количество двигателей
ну и неполохо бы решить вопрос с дребезгом контактов кнопки
светодиоды потом уже подключайте когда всё будет работать как вам нужно
Защиту от дребезга убрал временно, она никак не влияла. С помощью Stepper.h проблем особых нет и одним управлял и шестью, а вот с акулой никак не разберусь. Одним управлял с помощбю примеров - тупик во всех примерах или один раз крутится или без остановок, не пойму в чем загвоздка, гдето явного не вижу
это хождение покругу уже достало
Защиту от дребезга убрал временно, она никак не влияла. С помощью Stepper.h проблем особых нет и одним управлял и шестью, а вот с акулой никак не разберусь. Одним управлял с помощбю примеров - тупик во всех примерах или один раз крутится или без остановок, не пойму в чем загвоздка, гдето явного не вижу
это хождение покругу уже достало
ну что ещё вам посоветовать - подключать мотор, кнопку и пробовать
блокирующие функции на двух моторах работать не будут
Как успехи? Не разобрались как можно повторять несколько раз одно вращение? Разбираюсь с этой же библиотекой, никак не могу понять логику этой функции (stepper.distanceToGo() == 0)
Как успехи? Не разобрались как можно повторять несколько раз одно вращение? Разбираюсь с этой же библиотекой, никак не могу понять логику этой функции (stepper.distanceToGo() == 0)
Подразобрался немного, как то так
void motor_x1() { myStepper1.run(); if (myStepper1.distanceToGo() == 0) motor_x2(); } void motor_x2() { myStepper2.run(); myStepper4.run(); // без этого currentPosition будет применяться постоянно if (myStepper2.distanceToGo() == 0)//когда двигатель достигнет 0 позиции motor_x3(); } void motor_x3() { myStepper3.runToNewPosition(100); myStepper3.runToNewPosition(0); myStepper1.moveTo(myStepper1.currentPosition()+200);//для продолжения дв-я 1 двиг myStepper2.moveTo(myStepper2.currentPosition()+100);//для продолжения дв-я 2 двиг myStepper4.moveTo(myStepper4.currentPosition()+100);//для продолжения дв-я 4 двиг if (myStepper3.distanceToGo() == 0) count ++; if(count>4)//повторить 5 раз { state = !state; } }Ура! Спасибо, заработало))
Ура! Спасибо, заработало))
Пожалуйста, с этой библиотекой еще разбираться и разбираться, эх, знаний не хватает.
Пока рулит метод научного ТЫКА.
AnLaz - это не то что работать, это даже компилироваться не должно
Уважаемый AnLaz - почитайте про библиотеку stepper. и сделайте несколько простеньких примеров (на 1 двигатель), а потом, если не получится задавайте конкретные вопросы, а не "что-то не учтено". Пока Вы в стадии теоретических рассуждений Вам здесь не помогут.
#include <AccelStepper.h> #include <Bounce2.h>; #define PIN_BUTTON A1 // Создаем объект Bounce debouncer = Bounce(); int lastState = 1; int number_of_regim = 0; AccelStepper Stepper1(1, 13, 12); //использует пин 12 и 13 для dir и step, 1 - режим "external driver" (A4988) const int LedPinGreen = 7; const int LedPinRed = 6; const int LedPinYelow = 5; int ButonPinOut = A0; //---прототипы функций------------- void regim_1(); void regim_2(); int numberRegim(int state); //--------------------------------- void setup() { Serial.begin(9600); pinMode(LedPinGreen, OUTPUT); pinMode(LedPinRed, OUTPUT); pinMode(LedPinYelow, OUTPUT); pinMode(ButonPinOut, OUTPUT); pinMode(PIN_BUTTON, INPUT_PULLUP); // Даем бибилотеке знать, к какому пину мы подключили кнопку debouncer.attach(PIN_BUTTON); debouncer.interval(2); // Интервал, в течение которого мы не буем получать значения с пина //---настройки шагового двигателя---------- Stepper1.setMaxSpeed(2800); //2800устанавливаем максимальную скорость вращения ротора двигателя (шагов/секунду) Stepper1.setAcceleration(100); //устанавливаем ускорение (шагов/секунду^2) } //---------------------------------------------------------------------------------------------------------------- void loop() { // Даем объекту бибилотеки знать, что надо обновить состояние - мы вошли в новый цкил loop debouncer.update(); // Получаем значение кнопки int value = debouncer.read(); numberRegim(value); switch (number_of_regim) { case 0: digitalWrite (7, LOW); digitalWrite (6, LOW); digitalWrite (5, LOW); break; case 1: regim_1(); break; case 2: digitalWrite (6, HIGH); digitalWrite (7, LOW); digitalWrite (5, LOW); void regim_2(); break; case 3: digitalWrite (5, HIGH); digitalWrite (7, LOW); digitalWrite (6, LOW); void regim_3(); break; } } void regim_1() { digitalWrite (7, HIGH); digitalWrite (6, LOW); digitalWrite (5, LOW); if (Stepper1.distanceToGo() == 0) //проверка, отработал ли двигатель предыдущее движение { Stepper1.move(10000); //устанавливает следующее перемещение на N шагов (если dir равен -1 будет перемещаться -1600 -> противоположное направление) } Stepper1.run(); //запуск шагового двигателя. Эта строка повторяется вновь и вновь для непрерывного вращения двигателя } //----------------------------------------------------------------------------------------------------------------------------------------------- void regim_2() { if (Stepper1.distanceToGo() == 0) //проверка, отработал ли двигатель предыдущее движение { Stepper1.move(15000); //устанавливает следующее перемещение на N шагов (если dir равен -1 будет перемещаться -1600 -> противоположное направление) } Stepper1.run(); //запуск шагового двигателя. Эта строка повторяется вновь и вновь для непрерывного вращения двигателя } //---------------------------------------------------------------------------------------------------------------------------------------------------- void regim_3() { if (Stepper1.distanceToGo() == 0) //проверка, отработал ли двигатель предыдущее движение { Stepper1.move(20000); //устанавливает следующее перемещение на N шагов (если dir равен -1 будет перемещаться -1600 -> противоположное направление) } Stepper1.run(); //запуск шагового двигателя. Эта строка повторяется вновь и вновь для непрерывного вращения двигателя } //-------------------------------------------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------- int numberRegim(int state) { if (number_of_regim > 3) { number_of_regim = 0; } if ( state != lastState ) { if (state == 1) { number_of_regim++; } lastState = state; return number_of_regim; } } //-------------------------------------------------------------------------Прошу помощи. По задумке есть три режима у шагового двигателя. На каждом режиме он должен прокрутиться определенное количество шагов. Но при таком составлении скетча он вообще не вращается. Если без дополнительных функций, просто добавить в void loop
{
if (Stepper1.distanceToGo() == 0) //проверка, отработал ли двигатель предыдущее движение
}
то всё работает.
Не пойму почему не запускается мотор.
Нумбер_оф_регим меняется?
В строках #60 и #66 слова void лишние.
Да меняется, у меня светодиоды загораются по очереди.
Согласен void лишний . Но и на первом режиме не работает шаговик.
Надо смотреть через Serial, как distanceToGo() меняется.
... numberRegim(value); Serial.print("Stepper1.distanceToGo -"); // выводим текст 1 раз в секунду Serial.println( Stepper1.distanceToGo()); // выводим текст 1 раз в секунду switch (number_of_regim) { case 0: digitalWrite (7, LOW); digitalWrite (6, LOW); digitalWrite (5, LOW); ... Интересное открытие. После добавления 4 и 5 строчки, мотор завращался на всех режимах, но вращается как то не адекватно, не стой угловой скоростью , как то медленно и с рывками. Но странно что он вообще начал вращаться после добавления этих строк.distanceToGo() меняется от 10000 до 0 после того как начал вращаться.
maxSpeed > 1000 шаг/сек вообще-то к неадекватному поведению должен в аксельстеппере приводить.
Прошу помощи. По задумке есть три режима у шагового двигателя. На каждом режиме он должен прокрутиться определенное количество шагов. Но при таком составлении скетча он вообще не вращается. Если без дополнительных функций, просто добавить в void loop
{
if (Stepper1.distanceToGo() == 0) //проверка, отработал ли двигатель предыдущее движение
}
то всё работает.
Не пойму почему не запускается мотор.
нажали кнопку , запустили мотор и взвели флаг.
после окончания движения
if (Stepper1.distanceToGo() == 0)
флаг опускаем.
при поднятом флаге кнопка не фурычит.
и уменьшите скорость и увеличите ускорение.
когда отработаете - выставите как нужно
Не сильно понимаю как использовать флаги, но буду разбираться. Я ещё в самом начале своего пути программиста. Спасибо за помощь!
Тоже разбираюсь с управлением шаговиков. Хотел бы узнать какие у вас драйверы и схемы подключения к ним?
Что-то типа DRV8825 (у меня такие) и подобных ? Которым нужно подать только один сигнал с импульсами. Один импульс - один шаг и т.д.
Или какие-то другие?
Драйвер у меня из Китая такой TB6600. Ну подключил я как рекомендовал продавец драйвера. Скину фотку , если не понятно напишите я подскажу.
я тоже с аксельстеппером вожусь, документация у него не простая, примеры самые простые, кручу двумя моторами через А4988, в самом простом случае (один мотор крутится постоянно, подстроечником регулируем скорость)
#include <Arduino.h> #include <AccelStepper.h> #define STEPPER1_STEP_PIN 9 #define pot_pin_st1 (A0) //potentiometer speed rotation stepper 1 int16_t val_st_1 = 0; //value speed stepper 1 AccelStepper stepper1(AccelStepper::DRIVER, STEPPER1_STEP_PIN); void setup() { stepper1.setAcceleration(500.0); stepper1.setMaxSpeed(1000); } void loop() { val_st_1 = map(analogRead(pot_pin_st1), 0, 1024, 0, 1000); val_st_1 = constrain(val_st_1, 10, 1000); stepper1.setSpeed(val_st_1); stepper1.run(); }но не могу понять как правильно выставить stepper1.setMaxSpeed , ставлю 1000, мотору явно мало импульсов в режиме 1\16, приходится 1\8 втыкать, а это вибрации сразу.
ставлю 2500, теряется линейность.
runSpeed() отказывается принимать аргументы, видимо я его не умею готовить.
жаль нет примеров применения :( не понимаю в каком контексте те или иные функции и классы используются :(
runSpeed() отказывается принимать аргументы, видимо я его не умею готовить.
жаль нет примеров применения :(
ConstantSpeed.ino
я кажется понял что не так, я использовал stepper1.run(); хотя я не указывал число шагов а указывал скорость движения, и для этого нужно установить stepper1.runSpeed(); , не увидел этого отличия в примерах, спасибо!
Есть подробное описание библиотеки AccelStepper на Русском?