Управление шаговыми двигателями. Библиотека AccelStepper.

Vasilii
Offline
Зарегистрирован: 29.01.2017
Доброго времени суток! Уважаемые Форумчане, помогите начинающему, пожалуйста. Уже месяц колупаюсь над проектом ( возникла такая необходимость ), начал с нуля... с полного нуля, а уже с неделю не получается вращать двигатели как хотелось бы. 
 Должно быть так - выбирается управление автомат или ручное.  На автомате начинают в паре вращаться 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);
     
      
         
    }
для ручногоуправления тоже не продолжить движение,
не в паузу перейти.
Заранне благодарю за помощь.
 
Да и еще, запчасти еще в пути, моделирую в протеусе.
 
Vasilii
Offline
Зарегистрирован: 29.01.2017

С нетерпением жду ответа.

vvadim
Offline
Зарегистрирован: 23.05.2012

вы не изучили библиотеку

сначала перепробуйте примеры и разбиритесь в них

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

Vasilii
Offline
Зарегистрирован: 29.01.2017

Все примеры перепробовал. В описании библиотеке сказано для продолжения движения  Stepper.run(); вызвать и здесь вообще непонятно 

сколько не добавляй  myStepper1.run();

 myStepper1.run();
 myStepper1.run(); движения нет и цикл пробовал применять, толку нет, или чтото не так делаю
vvadim
Offline
Зарегистрирован: 23.05.2012

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

потом пробуйте наращивать количество двигателей

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

светодиоды потом уже подключайте когда всё будет работать как вам нужно

Vasilii
Offline
Зарегистрирован: 29.01.2017

Защиту от дребезга убрал временно, она никак не влияла. С помощью Stepper.h проблем особых нет и одним управлял и шестью, а вот с акулой никак не разберусь. Одним управлял с помощбю примеров - тупик во всех примерах или один раз крутится или без остановок, не пойму в чем загвоздка, гдето явного не вижу
это хождение покругу уже достало

vvadim
Offline
Зарегистрирован: 23.05.2012

Vasilii пишет:

Защиту от дребезга убрал временно, она никак не влияла. С помощью Stepper.h проблем особых нет и одним управлял и шестью, а вот с акулой никак не разберусь. Одним управлял с помощбю примеров - тупик во всех примерах или один раз крутится или без остановок, не пойму в чем загвоздка, гдето явного не вижу
это хождение покругу уже достало

ну что ещё вам посоветовать - подключать мотор, кнопку и пробовать

блокирующие функции на двух моторах работать не будут

         
Евгения
Offline
Зарегистрирован: 12.05.2016

Как успехи? Не разобрались как можно повторять несколько раз одно вращение? Разбираюсь с этой же библиотекой, никак не могу понять логику этой функции (stepper.distanceToGo() == 0)

Vasilii
Offline
Зарегистрирован: 29.01.2017

Евгения пишет:

Как успехи? Не разобрались как можно повторять несколько раз одно вращение? Разбираюсь с этой же библиотекой, никак не могу понять логику этой функции (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;
      
    }
}

 

Евгения
Offline
Зарегистрирован: 12.05.2016

Ура! Спасибо, заработало)) 

Vasilii
Offline
Зарегистрирован: 29.01.2017

Евгения пишет:

Ура! Спасибо, заработало)) 

Пожалуйста, с этой библиотекой еще разбираться и разбираться, эх, знаний не хватает.

Vasilii
Offline
Зарегистрирован: 29.01.2017

Пока рулит метод научного ТЫКА.

AnLaz
Offline
Зарегистрирован: 23.04.2019
Управление двумя двигателями.
Не знаю, как здесь писать, не получается в формате скетча....
Я попытался написать код для программы. Но боюсь, что тут не все учтено.
Это моя первая попытка решения задачи. Я постарался в комментариях написать неясные вопросы.
Прошу уважаемых форумчан помочь по возможности.
 
//Управление двумя моторами
 
const int stepsPerRevolution1 = 2000;//Количество оборотов
const int stepsPerRevolution2 = 4000;//Количество оборотов
int Button1=7;
int Button2=6;
Stepper myStepper1(stepsPerRevolution1, 8,9,10,11); //подключение к пинам 8…11 на Ардуино
Stepper myStepper2(stepsPerRevolution2, 2,3,4,5); //подключение к пинам 2…5 на Ардуино
void setup() {
pinMode(Button1,INPUT);
pinMode(Button2,INPUT);
myStepper1.setSpeed(60); //установка скорости вращения ротора 1
myStepper2.setSpeed(60); //установка скорости вращения ротора 2
 
}
 
void loop(){// Первая операция: выход и спуск
if(digitalRead(Button1==HIGH)){/*Функция ожидает, пока поступит команда кнопки (здесь нужно, как то                поставить антидребезг)*/
myStepper1.step(stepsPerRevolution1);//Запускаем процесс вращения на 2000 оборотов первого двигателя 
delay(1000);//Ждем 1 секунду
}
 
{myStepper2.step(stepsPerRevolution2);//Запускаем процесс вращения на 4000 оборотов второго двигателя 
delay(1000);//Ждем 1 секунду
}
{/* Вторая операция: подьем и возврат Нужно запустить двигатели в обратном направлении (может быть нужно ввести дополнительные константы типа const int stepsPerRevolution2 = -4000)*/
if(digitalRead(Button2==HIGH)){//Функция ожидает, пока поступит команда кнопки
myStepper2.step(stepsPerRevolution2);/*Запускаем процесс вращения на 4000 оборотов второго двигателя В          ОБРАТНОМ НАПРАВЛЕНИИ*/
delay(1000);//Ждем 1 секунду
myStepper1.step(stepsPerRevolution1);/*Запускаем процесс вращения на 2000 оборотов второго двигателя В          ОБРАТНОМ НАПРАВЛЕНИИ*/
delay(1000);//Ждем 1 секунду
}
b707
Offline
Зарегистрирован: 26.05.2017

AnLaz - это не то что работать, это даже компилироваться не должно

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Уважаемый AnLaz - почитайте про библиотеку stepper.  и сделайте несколько простеньких примеров (на 1 двигатель), а потом, если не получится задавайте конкретные вопросы, а не "что-то не учтено". Пока Вы в стадии теоретических рассуждений Вам здесь не помогут.

mutaborxxx
Offline
Зарегистрирован: 07.12.2019
#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;

  }
}
//-------------------------------------------------------------------------

 

mutaborxxx
Offline
Зарегистрирован: 07.12.2019

Прошу помощи. По задумке есть три режима у шагового двигателя. На каждом режиме он должен прокрутиться определенное количество шагов. Но при таком составлении скетча он вообще не вращается. Если без дополнительных функций, просто добавить в void  loop

  {

if (Stepper1.distanceToGo() == 0) //проверка, отработал ли двигатель предыдущее движение

  {
 
    Stepper1.move(15000); //устанавливает следующее перемещение на N шагов (если dir равен -1 будет перемещаться -1600 -> противоположное направление)
  }
  Stepper1.run(); //запуск шагового двигателя. Эта строка повторяется вновь и вновь для непрерывного вращения двигателя

}

то всё работает.

Не пойму почему не запускается мотор.

sadman41
Offline
Зарегистрирован: 19.10.2016

Нумбер_оф_регим меняется?

В строках #60 и #66 слова void лишние.

mutaborxxx
Offline
Зарегистрирован: 07.12.2019

Да меняется, у меня светодиоды загораются по очереди.

Согласен void лишний . Но и на первом режиме не работает шаговик.

sadman41
Offline
Зарегистрирован: 19.10.2016

Надо смотреть через Serial, как distanceToGo() меняется.

mutaborxxx
Offline
Зарегистрирован: 07.12.2019
... 
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 после того как начал вращаться.

 

 

sadman41
Offline
Зарегистрирован: 19.10.2016

maxSpeed > 1000 шаг/сек вообще-то к неадекватному поведению должен в аксельстеппере приводить.

vvadim
Offline
Зарегистрирован: 23.05.2012

mutaborxxx пишет:

Прошу помощи. По задумке есть три режима у шагового двигателя. На каждом режиме он должен прокрутиться определенное количество шагов. Но при таком составлении скетча он вообще не вращается. Если без дополнительных функций, просто добавить в void  loop

  {

if (Stepper1.distanceToGo() == 0) //проверка, отработал ли двигатель предыдущее движение

  {
 
    Stepper1.move(15000); //устанавливает следующее перемещение на N шагов (если dir равен -1 будет перемещаться -1600 -> противоположное направление)
  }
  Stepper1.run(); //запуск шагового двигателя. Эта строка повторяется вновь и вновь для непрерывного вращения двигателя

}

то всё работает.

Не пойму почему не запускается мотор.

 

нажали кнопку , запустили мотор и взвели флаг.
после окончания движения 
if (Stepper1.distanceToGo() == 0)
флаг опускаем.
при поднятом флаге кнопка не фурычит.

и уменьшите скорость и увеличите ускорение.
когда отработаете - выставите как нужно

mutaborxxx
Offline
Зарегистрирован: 07.12.2019

Не сильно понимаю как использовать флаги, но буду разбираться. Я ещё в самом начале своего пути программиста. Спасибо за помощь!

Drakon88
Offline
Зарегистрирован: 05.02.2020

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

Что-то типа DRV8825 (у меня такие) и подобных ? Которым нужно подать только один сигнал с импульсами. Один импульс - один шаг и т.д. 

Или какие-то другие? 

mutaborxxx
Offline
Зарегистрирован: 07.12.2019

Драйвер у меня из Китая такой TB6600.  Ну подключил я как рекомендовал продавец драйвера. Скину фотку , если не понятно напишите я подскажу.

darknew
darknew аватар
Offline
Зарегистрирован: 01.11.2017

я тоже с аксельстеппером вожусь, документация у него не простая, примеры самые простые, кручу двумя моторами через А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, теряется линейность.

sadman41
Offline
Зарегистрирован: 19.10.2016
    /// Sets the desired constant speed for use with runSpeed().
    void    setSpeed(float speed);
 
Смешиваете два разных способа управления.

 

darknew
darknew аватар
Offline
Зарегистрирован: 01.11.2017

runSpeed() отказывается принимать аргументы, видимо я его не умею готовить.

жаль нет примеров применения :( не понимаю в каком контексте те или иные функции и классы используются :(

 

sadman41
Offline
Зарегистрирован: 19.10.2016

darknew пишет:

runSpeed() отказывается принимать аргументы, видимо я его не умею готовить.

жаль нет примеров применения :( 

ConstantSpeed.ino

darknew
darknew аватар
Offline
Зарегистрирован: 01.11.2017

я кажется понял что не так, я использовал stepper1.run(); хотя я не указывал число шагов а указывал скорость движения, и для этого нужно установить stepper1.runSpeed(); , не увидел этого отличия в примерах, спасибо!