GyverStepper. Обсуждение библиотеки

JSNU

✩✩✩✩✩✩✩
16 Июл 2021
1
0
Привет AlexGyver и всем форумчанам!
Столкнулся с проблемой торможения привода на KEEP_SPEED.
Мотор крутится по кнопке. Ускорение и торможение одинаковые только если привод не успел разогнаться до SetSpeed().
Если держать кнопку, разогнать до SetSpeed и продолжать крутить мотор секунд 10-20, то торможение будет в несколько раз выше ускорения (привод ощутимо быстрее останавливается).
Нашел закономерность, что чем дольше крутить мотор, тем резче будет торможение.
В чем я накосячил?)) подскажите что читать и куда копать?
P.S. в коде много лишнего, смотреть сразу case 2.
C++:
#define SMOOTH_ALGORITHM
#include <GyverStepper.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
GStepper<STEPPER2WIRE> stepper(1000, 14, 15);
int flag = 0;
int c = 0;
int s = 0;
//char a;
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(169, 254, 170, 10);
unsigned int localPort = 6630;
EthernetUDP Udp;
char receivingBuffer[100]; // приемный буфер Udp-пакета
float floatVar; //float градуса

void setup() {
  Ethernet.begin(mac, ip);
  Udp.begin(localPort);
  Serial.begin(9600);
  stepper.setAcceleration(50);
  pinMode (4, INPUT_PULLUP); //концевик
  pinMode (5, INPUT_PULLUP); //кнопка homing
  pinMode (16, OUTPUT); //лампочка homing
  pinMode (6, INPUT_PULLUP); //кнопка по часовой
  pinMode (7, INPUT_PULLUP); //кнопка против часовой
  pinMode (8, INPUT_PULLUP); //вкл/выкл
  pinMode (9, OUTPUT); //лампочка ethernet
  digitalWrite(16, LOW);
}
bool btnState = false;
int i1 = 0;
int i2 = 0;
int i3 = 0;
int h = 0;
void loop() {
  c = 0;

  if (!digitalRead(8)) {  //ЕСЛИ КНОПКА ETHERNET НЕ НАЖАТА
    digitalWrite(9, LOW);
    for (int i = 0; i <= 10 && !digitalRead(5); i++) { //ХОУМИНГ
      //Serial.println(i);
      i1++;
    }
    if (i1 >= 10) c = 1;
    i1 = 0;

    for (int i = 0; i <= 10 && !digitalRead(6); i++) { //ПО ЧАСОВОЙ
      //Serial.println(i);
      i2++;
    }
    if (i2 >= 10) c = 2;
    i2 = 0;

    for (int i = 0; i <= 10 && !digitalRead(7); i++) { //ПРОТИВ ЧАСОВОЙ
      //Serial.println(i);
      i3++;
    }
    if (i3 >= 10) c = 3;
    i3 = 0;
  }
  else digitalWrite(9, HIGH);
  //c = 1;
  //Serial.println(c);

  switch (c) {
    case 1:
      //int h = 0;
      Serial.println(222);
      break;
    case 2:
      Serial.println("HANDTURN CW");
      digitalWrite(16, LOW);
      stepper.setRunMode(KEEP_SPEED);
      //stepper.reset();
      stepper.setSpeed(100, SMOOTH);
      stepper.setAcceleration(50);

      while (stepper.getSpeed() != 0 || !digitalRead(6)) {
        if (!digitalRead(6) && !btnState) {
          btnState = true;
        }
        // кнопка отпущена
        if (digitalRead(6) && btnState) {
          btnState = false;
          stepper.stop();
        }
        stepper.tick();
        if (!stepper.getState()) {
          c = 0;
          break;
        }
      }

    case 3:
      Serial.println(333);
      break;

  }
}
 

vovaself

✩✩✩✩✩✩✩
24 Июл 2019
6
0
Как использовать Motor Shield L293D и управление шаговым двигателем через библиотеку GyverStepper ?
Может у кого-нибудь есть пример ?
Спасибо
 

vovaself

✩✩✩✩✩✩✩
24 Июл 2019
6
0

Вложения

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
574
@vovaself, это шилд на основе сдвиговых регистров, лучше его выбросить и взять обычный нормальный драйвер. Либо возиться в режиме "виртуального драйвера" с ручной упаковкой битов, но это абсолютного того не стоит
 

BLOCKHEAD

✩✩✩✩✩✩✩
6 Окт 2021
3
0
Привки!
А как в режиме Follow_Pos менять скорость в зависимости от положения двигателя?
Вот у меня есть цикл, который катает мотор по координатам вперед и взад между координатами 0 и 35000. У ней внутре неонка:
C++:
                    if (5000 <= stepper.getCurrent() <= 30000) {
                      stepper.setMaxSpeed(1500);
                      } else {
                        stepper.setMaxSpeed(500);
Задумка в том, чтобы мотор замедлялся при смене направления. Но при моем коде он всю дорогу лупит на скорости 1500.
Задавать параметры ускорения тут несподручно, потому что мне нужны конкретные скорости в зависимости от положения. Можно, конечно рассчитать под них ускорение, но тогда мотор будет останавливаться в промежуточных точках, такое не нужно.
К тому же в дальнейшем эту конструкцию кода нужно будет прикрутить ко второму мотору. То есть скорость второго должна зависеть от положения первого.
 

bort707

★★★★★★✩
21 Сен 2020
3,102
916
@BLOCKHEAD, в первой строке вашего кода - ошибка. Почитайте про операции сравнения в Си, язык не поддерживает одновременное сравнение с двумя аргументами, как у вас.
Причем ошибок при компиляции не будет, просто результат этого сравнения будет совсем не тот, что вы думаете.
 
  • Лойс +1
Реакции: BLOCKHEAD

BLOCKHEAD

✩✩✩✩✩✩✩
6 Окт 2021
3
0
@bort707, Почитал. Осознал. Прослезился.

Теперь не работает регулировка скорости второго мотора:
C++:
                    if (stepper.getCurrent() <= 5000) {
                      stepper2.setSpeed(100);}
Второй мотор работает в режиме KEEP_SPEED. При такой конструкции он просто не крутится. Если задать скорость снаружи условия if, то все работает, только скорость, само собой, не меняется. Куда смотреть? Где я налажал в этот раз?
 

Lumenjer

★★★✩✩✩✩
10 Дек 2020
220
112
@BLOCKHEAD, 1. Вы уверены, что ваше условие выполняется? (скорее всего да, возможно есть какие-то баги в библиотеки связанные с этим делом)
2. Подозреваю, что этот код лежит в loop, отсюда вопрос, зачем вам устанавливать одну и ту же скорость при каждом проходе в loop?
Лучше сделать какой-нибудь флаг на проверку условия и по этому флагу выставить скорость 1 раз и все.


C++:
static bool lowCurrent = false;     // флаг для определения условия позиции
static bool settedSpeed = false;    // флаг для проверки, была ли установлена скорость
if (stepper.getCurrent() <= 5000) {
    lowCurrent = true;                // если условие по позиции выполняется, то флаг true
}
else {
    lowCurrent = false;             // если не выполняется, то false
}
if (lowCurrent != speedSetted) {    // проверяем, равен ли флаг позиции флагу нужной скорости
    speedSetted = lowCurrent;        // если не равен, то присваеваем значение флага позиции
    if (speedSetted) {                // проверяем значение флага
        stepper2.setSpeed(100);     // если он true, то настраиваем скорость (это произойдет только 1 раз за проход первого шаговика по позиции от 0 к 5000)
    }
    else {
                                    // если false - выполняем что-то другое (выполнится 1 раз, когда первый шаговик перешагнет за 5000)
    }
}
 
  • Лойс +1
Реакции: BLOCKHEAD

BLOCKHEAD

✩✩✩✩✩✩✩
6 Окт 2021
3
0
@Lumenjer, такая конструкция работает, спасибо.
Условие у меня было не в loop, а в таком цикле:
C++:
         for (long target : targets) {
              stepper.setTarget(target);
                  while (stepper.getCurrent() != target) {
Можете объяснить, в чем была ошибка? Выходит, что программа задавала скорость второму мотору при каждом шаге первого и тем самым перегружала его? А эта штука с булевыми переменными эту проблему решает?
 

Lumenjer

★★★✩✩✩✩
10 Дек 2020
220
112
@BLOCKHEAD, Я стараюсь отталкиваться от принципа, что нет смысла дергать методы\функции\параметры если что-то в них не поменялось. Но как-то на скорую руку тоже проверял работу двух шаговиков, и когда задавал скорость второму, которая зависела от скорости первого то тоже не захотело работать как надо. Подкинул флаги и начал вызывать смену скорости намного реже - заработало.
В дебри библиотеки лезть не хотелось, чтобы разбираться, почему так происходит. Может баг, а может так задумано
 
  • Лойс +1
Реакции: BLOCKHEAD

InterestedStudent

✩✩✩✩✩✩✩
23 Сен 2021
3
0
Очень понравилась данная библиотека.

Можно ли использовать ее компоненты (части, разумеется с указанием автора) для написания своего кода?

Мне бы хотелось использовать прерывания для генерации сигнала STEP.
 

bort707

★★★★★★✩
21 Сен 2020
3,102
916
Мне бы хотелось использовать прерывания для генерации сигнала STEP.
вы думаете, если автор использовал прерывания, то другим уже нельзя?:)

но лучше не "брать части", а разобраться в коде и написать свое по аналогии.
 
  • Лойс +1
Реакции: Lumenjer

InterestedStudent

✩✩✩✩✩✩✩
23 Сен 2021
3
0
вы думаете, если автор использовал прерывания, то другим уже нельзя?:)
Нет :).

Меня интересует разгон-ускорение (методы planner(), smoothSpeedPlanner()), а так же подсчет шагов (лишь некоторые приемы).

Есть желание сделать генерацию шагов на прерываниях таймера (для драйвера шагового двигателя который понимает STEP\DIR), чтобы контролер сам изменял состояния вывода, без необходимости вызывать метод tick.
 

bort707

★★★★★★✩
21 Сен 2020
3,102
916
@InterestedStudent, при постоянной скорости именно так все и делают. Но разгон-торможение при этом усложняются.
 

InterestedStudent

✩✩✩✩✩✩✩
23 Сен 2021
3
0
Мне нужна и постоянная скорость (с режимом ускорения, торможения), для одно из двигателей и подсчет шагов для другого (с режимом ускорения, торможения).

Поэтому и хочу воспользоваться частями уже готового решения.
 

IvGor

✩✩✩✩✩✩✩
21 Апр 2021
8
0
Друзья, можете помочь? Пишу маленький скетч по движению шагового двигателя. Но при настройке скорости вращения регулировка происходит плавно только до определенного предела, потом резкий скачок. В качестве платы Arduino Nano.

C++:
// 1- Двагем мотором с заданной скоростью до первого концевика и останавливаем.
// 2- По нажатию кнопки запускаем программу движения от вехнего концевика до нижнего с возможностью настроййки скорости движения
// 3- При нажатии кнопки происходит остановки двигателя, при повторном нажатии запуск.
// 4- Программа работает до выключения питания. Скорость меняет переменный резистор.
//Версия 2.1


#define DRIVER_STEP_TIME 3
#include "GyverStepper.h"
#include "GyverButton.h"
GStepper< STEPPER2WIRE> stepper(6400, 3, 2, 4);
GButton butt_start(12);
GButton butt_up(7);
GButton butt_down(8);
bool stoped = true;


void setup(){
  stepper.setAccelerationDeg(5000);
  stepper.autoPower(true);
    pinMode(7, INPUT_PULLUP);//--------Кнопка UP
    pinMode(12, INPUT_PULLUP);//--------Кнопка START
    
 

//========= ДВИЖЕНИЕ ДО НАЧАЛЬНОЙ ТОЧКИ ==============================
    
    stepper.setRunMode(KEEP_SPEED);
    stepper.setSpeedDeg(-100);// --------Медленно крутимся Вверх до концевика

  while(digitalRead(7)) {//---------------До нажатия кнопки UP 
    stepper.tick();

    }
  stepper.stop();
//=====================================================================


  butt_start.setDebounce(4);     
  butt_up.setDebounce(4);
  butt_down.setDebounce(4);


}


void loop() {
int mnoj = 1;
int speed = 20000;

pinMode(10, OUTPUT);
butt_start.tick();
butt_up.tick();
butt_down.tick();



if (butt_start.isClick()) {
 
  if(stepper.getState())
  {
    stepper.brake();
    stoped = true;
  }
    else
    {
      stoped = false;
      stepper.setSpeed(speed - analogRead(0)*19, 5000);
      stepper.tick();
    }
  }
//-----------------Концевики ------------------------------
  else if (butt_down.isPress() && !stoped){
  digitalWrite(10, HIGH);
  stepper.disable();
  stepper.stop();
  stepper.reverse(true);
  stepper.setSpeed(speed - analogRead(0)*19, 5000);
  }
  //------------Нижний концевик ---------------------------
  else if (butt_up.isPress() && !stoped) {
  digitalWrite(10, LOW);
  stepper.disable();
  stepper.stop();
  stepper.reverse(false);
  stepper.setSpeed(speed - analogRead(0)*19, 5000);
  }
//---------------------------------------------------------
 

  if (!stoped){
      static uint32_t tmr2;
        if (millis() - tmr2 > 50) {
        tmr2 = millis();
      stepper.setSpeed(speed - analogRead(0)*19, 5000);
    }
  }
  stepper.tick();
}
 

hiteker75

✩✩✩✩✩✩✩
18 Авг 2019
26
1
Друзья, можете помочь? Пишу маленький скетч по движению шагового двигателя. Но при настройке скорости вращения регулировка происходит плавно только до определенного предела, потом резкий скачок. В качестве платы Arduino Nano.
А почему именно эту библиотеку юзаете?
Не проще на AccelStepper ?
Вроде нет проблем с разгоном
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,281
1,306
Москва
А чего тут думать ? тут смотреть надо.
Вот эту часть выводите в монитор порта и смотрите как изменяется при скачке
 

DAER

✩✩✩✩✩✩✩
17 Дек 2021
21
0
У меня каретка совершает движения туда-сюда относительно некоего центра +/- 2000 шагов (worksteps ).
Хочу сделать, чтобы при нажатии концевика
  • мотор остановился;
  • откатился назад на 8000 шагов;
  • возобновил движения +/- 2000 шагов.

Вместо этого получаю
  • мотор останавливается;
  • откатывается на 8000 шагов назад;
  • потом ВОЗВРАЩАЕТСЯ на 8000 шагов вперёд;
  • потом продолжает движение +/- 2000 шагов

Помогите понять, почему он возвращается?
И как сделать, чтобы не возвращался?



C++:
...
volatile boolean F_KONC_A = 0; // ФЛАГ 
void Initial_position() {   //ФУНКЦИЯ ОБРАБОТКИ ПРЕРЫВАНИЯ
    F_KONC_A = 1;
      }
//********************************************************************************
...
void setup() {
attachInterrupt(0, Initial_position, RISING); //ОБЪЯВЛЕНИЕ ПРЕРЫВАНИЯ


//********************************************************************************
void loop() {

 if (!stepper1.tick() && F_KONC_A ==0) {  //это обычное движение туда-сюда
    static bool dir;
    dir = !dir;
    stepper1.setTarget(dir ? !worksteps : worksteps);
  }
if (!stepper1.tick() && F_KONC_A ==1){ //если флаг поднят
    stepper1.reset();
    stepper1.setTarget(-8000);
    F_KONC_A = 0;
}
 
}
 

bort707

★★★★★★✩
21 Сен 2020
3,102
916
Помогите понять, почему он возвращается?
потому что позиция задается в шагах относительно НАЧАЛЬНОГО старта, а не от предыдущего шага.
Вот вы задали мотору следовать к позиции -8000, а потом предлагаете ему качаться между 0 и 2000. Как он должен попасть к позиции 0, если он сейчас на -8к? - конечно вернутся назад на 8 тыс шагов, не иначе

Кстати, уверены ли вы, что правильно понимаете, что у вас происходит в строке 18?
 

Lumenjer

★★★✩✩✩✩
10 Дек 2020
220
112
@DAER, По прибытию на точку возврата (после срабатывания концевика) вам нужно еще раз сбросить текущую позицию на 0, а тогда уже двигаться вперед (но не назад, ясное дело), в общем вам нужно доработать логику после возврата на -8000

C++:
void loop() {

 if (!stepper1.tick() && F_KONC_A ==0) {  //это обычное движение туда-сюда
    static bool dir;
    if (F_KONC_A){ // проверяем, вернулись ли мы после срабатывания концевика, если да
        F_KONC_A = 0; // сбрасываем флаг
        dir = true; // выбираем конкретное направление
    }
    else    // если не было концевика, то тут уже туда-сюда обратно
        dir = !dir;
    stepper1.setTarget(dir ? !worksteps : worksteps);
  }
if (!stepper1.tick() && F_KONC_A ==1){ //если флаг поднят
    stepper1.reset();
    stepper1.setTarget(-8000);
    // F_KONC_A = 0;  - эта строка нам не нужна
}
 
}
 

DAER

✩✩✩✩✩✩✩
17 Дек 2021
21
0
@bort707,

- я пробовал обнулять позицию reset(), но это не помогало. Возможно стоит попробовать нечто "если позиция не равна -8000..."

Кстати, уверены ли вы, что правильно понимаете, что у вас происходит в строке 18?
Это очень правильный вопрос. Я понимаю, что создаётся статическая переменная dir? которая меняет свой знак, соответственно меняются и координаты цели.
НО
я не понимаю, как работает цикл. Откуда мотор решил вернуться сначала в 0? Это скрыто в недрах библиотеки? И почему в Loop конструкции IF работают как циклы...

@Lumenjer,

- Вставил ваш код. При одном нажатии на концевик мотор отъезжает на 8000 шагов, делает паузу ...и отъезжает ещё на 8000 шакгов и так далее. Не происходит возврат к stepper1.setTarget(dir ? !worksteps : worksteps);

И вот это непонятно
if (F_KONC_A){ // проверяем, вернулись ли мы после срабатывания концевика, если да

Что значит "вернулись" ?
 

Lumenjer

★★★✩✩✩✩
10 Дек 2020
220
112
@DAER, внимательно посмотрите на 3ю строку и поймёте, почему так происходит)
А ещё, чтобы все работало нормально, то вам придётся блоки местами поменять
 

bort707

★★★★★★✩
21 Сен 2020
3,102
916
Это очень правильный вопрос. Я понимаю, что создаётся статическая переменная dir? которая меняет свой знак, соответственно меняются и координаты цели.
неправильно понимаете.
Почитайте описание оператора "!" - он вовсе не "меняет знак". И если в строке
C++:
dir = !dir;
у вас случайно получилось то. что надо, то в строке
C++:
(dir ? !worksteps : worksteps)
вы используете этот оператор неправильно, результат будет вовсе не от -2000 до 2000, как вы, вероятно, ожидали.

я не понимаю, как работает цикл. Откуда мотор решил вернуться сначала в 0? Это скрыто в недрах библиотеки?
ну какой библиотеки?! - это элементарная логика.Я ж вам написал - координаты, которые вы задаете - АБСОЛЮТНЫЕ! Если вы после смещения мотора на точку -8к просите его дергаться от 0 до 2000 - то СНАЧАЛА МОТОР ДОЛЖЕН ВЕРНУТСЯ к нулю! Что тут может быть непонятно?
 
Изменено:
  • Лойс +1
Реакции: kostyamat, DAER и Lumenjer