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

DAER

✩✩✩✩✩✩✩
17 Дек 2021
21
0
А чтобы проверить условие, какой метод нам нужно запустить, и что в этом методе происходит?)
Если метод stepper1.tick()
то какая строка его ЗАПУСТКАЕТ?

Вы знаете какое условие должно быть, чтобы каретка отъехала назад, отсюда вопрос, почему у вас F_KONC_A == 1 при вкл?
Это какие-то странности с питанием.
У меня Ардуино запитано +5В иплата драйвера + 12В от одного блока питания. Выключатель отсекает оба питания.
НО Ардуино продолжает питаться через USB.
И если отключить USB то выключение-включение выключателем к глюку не приводит. Всё работает правильно.
А если USB остаётся подключен - то вышеописанный глюк. Надо померять мультиметром напряжение на 2м пине.
 

Lumenjer

★★★✩✩✩✩
10 Дек 2020
220
112
Если метод stepper1.tick()
то какая строка его ЗАПУСТКАЕТ?
Возможно вы не поверите, но эта строка и запускает)))
Да, if проверяет условие, но чтобы получить значение, которое нужно проверить, сначала запускается метод, там происходят все операции и уже он возвращает значение, которое и будет проверять if
Иными словами этот кусок кода
C++:
if (!stepper1.tick()) {   // проверяем условие
    // НО НЕ ДЕЛАЕМ ВООБЩЕ НИЧЕГО
}
И этот
C++:
stepper1.tick();
Грубо говоря по функционалу делает одно и тоже
 
  • Лойс +1
Реакции: DAER

DAER

✩✩✩✩✩✩✩
17 Дек 2021
21
0
C++:
void loop() {
    static bool dir = true;
//IF-1

    if (!stepper1.tick()) {  //это обычное движение туда-сюда
        stepper1.setTarget(dir ? worksteps : worksteps*-1, RELATIVE);
        dir = !dir;
    }

//IF-2
    if (F_KONC_A ==1){ //если флаг поднят
        stepper1.setTarget(-8000, RELATIVE);
        F_KONC_A = 0;
    }
}
Это работает. Можно вставить и забыть, но очень хочу разобраться.
Непонятно вот что...
Если сработал концевик - запускается IF-2
устанавливается цель -8000 и опускается флаг.
Далее работает IF-1
Но ведь в IF-1 не -8000, а worksteps : worksteps*-1
Что же заставляет мотор КРУТИТЬСЯ до -8000 ?
 

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

★★★★★★★
14 Авг 2019
4,201
1,287
Москва
У вас есть 3 д принтер ? При старте печати он нащупывает концевики по осям. Что бы взять точку отсчета. у Вас так же должно быть. Запустили - в setup двинулись к концевику пока на него не нажали. Далее может быть смещение от концевика куда то. скажем в точку начала работы.
А потом уже в дергаться от этой точки куда надо. И еще полезно при движении проверять нажатие на концевик, а то вдруг из за пропусков шагов или руками кто то сдвинул мотор.

И еще меня почему то коробит worksteps*-1. Я бы написал - worksteps
 
  • Лойс +1
Реакции: DAER

Lumenjer

★★★✩✩✩✩
10 Дек 2020
220
112
Далее работает IF-1
Далее не работает ничего, т.к. условия ни того, ни другого не подходят.
Первое условие сработает тогда, когда движок придёт к цели -8000 и остановится. Если движок остановился, то tick() возвращает 0, а !0 == 1
 
  • Лойс +1
Реакции: DAER

DAER

✩✩✩✩✩✩✩
17 Дек 2021
21
0
Далее не работает ничего, т.к. условия ни того, ни другого не подходят.
Первое условие сработает тогда, когда движок придёт к цели -8000 и остановится. Если движок остановился, то tick() возвращает 0, а !0 == 1

Но ведь в этом коде IF2

C++:
    if (F_KONC_A ==1){ //если флаг поднят
        stepper1.setTarget(-8000, RELATIVE);
        F_KONC_A = 0;
    }
нет метода tick()

У вас есть 3 д принтер ? При старте печати он нащупывает концевики по осям. Что бы взять точку отсчета. у Вас так же должно быть. Запустили - в setup двинулись к концевику пока на него не нажали. Далее может быть смещение от концевика куда то. скажем в точку начала работы.
А потом уже в дергаться от этой точки куда надо. И еще полезно при движении проверять нажатие на концевик, а то вдруг из за пропусков шагов или руками кто то сдвинул мотор.

И еще меня почему то коробит worksteps*-1. Я бы написал - worksteps
У меня доска для разработки колен. На неё ставлю ноги и доска их возит туда-сюда.
Начало такое и будет - едем к концевику, нажимаем, и возвращаемся на середину.
Привод ременной.
И т.к. это ноги - всегда нога может попасть между или надавить сильнее, или вообще сорвать мотор и съехать до упора. Это "авария". У меня стоит два упора, а рядом с ними концевики. И при аварии надо тожде отработать в центр.
Я думал сделать линейный энкодер, чтобы не привязывался мотор к шагам. Точность мне не нужна. Но не потяну умом.

И так, спасибо большое, что отвечаете и помогаете!

И ещё предстоит добавить таймер, чтобы 10 минут работало, 10 минут отдыхало. Но сначала закончу с концевиком.
 

DAER

✩✩✩✩✩✩✩
17 Дек 2021
21
0
@Старик Похабыч,

Шаговый двигатель NEMA 17HS4401. Драйвер шагового двигателя TMC2209 . Деление шага 1/64. Управление джамперами через плату расширения.

C++:
void loop() {
    static bool dir = true; //объявили переменнную dir и присвоили ей TRUE
    if (!stepper1.tick()) {  //если мотор остановлен...
        stepper1.setTarget(dir ? worksteps : worksteps*-1, RELATIVE);//...а dir сейчас TRUE, устанавливаем  координату "worksteps" ОТНОСИТЕЛЬНУЮ
        dir = !dir; //инвертируем dir в FALSE и переходим к шагу...?
    }
а к какому шагу мы переходим?
Если к 2, то что, опять присваиваем dir - TRUE?
 

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

★★★★★★★
14 Авг 2019
4,201
1,287
Москва
Не уверен что нужно такое дробление. И я бы брал мотор мощнее, 23-ий немо и еще драйвер после сменить на какой то промышленный. Ну типа https://compacttool.ru/drajver-shagovogo-dvigatelya-dm556 (для примера исключительно).

А тесты уже были сделаны с нагрузкой ?
 
  • Лойс +1
Реакции: DAER

DAER

✩✩✩✩✩✩✩
17 Дек 2021
21
0
@Старик Похабыч,
Одно из условий - тишина.
Когда жужжит целый день - крыша едет.
Тесты делал. Всё собрано уже. Ремень 6мм шкив 16 зубьев. Вес двух ног около 15 кг. Усилие на сдвиг требуется меньше 1 кг.
Так вот, если встать очень аккуратно, то доска таскает меня, когда я на ней стою. А это 80 кг. :)
Но ели дёргнуть резко, то гораздо меньше требуется усилие, чтобы сорвать мотор.

Я буду пробовать разное дробление.
Сделал так, чтобы было удобно менять.

C++:
//****НАСТРАИВАЕМ РАБОТУ
int dist = 5; //рабочий ход мм
int cycles = 20; //количество циклов в минуту


long stp = 64; //деление шага
int shkiv = 32; //мм за один оборот мотора
long roundstps = stp*200; //чилсо шагов на оборот в полном шаге
long worksteps= (dist*roundstps)/shkiv; //шагов в рабочем ходе в одну сторону
long spd; //скорость движение шаг/с
long maxspd =(dist*2*cycles*roundstps)/60/shkiv; //мкс скорость движение шаг/с
long accel =maxspd*2; //ускорение движение шаг/с*с
 

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

★★★★★★★
14 Авг 2019
4,201
1,287
Москва
Доска по каким направляющим двигается ? Рельсы ?
Если не сложно и не секретно сделайте фото общего вида, оч. любопытно посмотреть.
 
  • Лойс +1
Реакции: DAER

DAER

✩✩✩✩✩✩✩
17 Дек 2021
21
0
Направляющие мебельные, пришлось переделать (чтобы шариков было на всю длину). Нужна минимальная высота от пола.
изображение_viber_2021-12-18_16-54-31-504.jpg
 

DAER

✩✩✩✩✩✩✩
17 Дек 2021
21
0
В общем пока так:

C++:
void loop() {

if (!stepper1.tick() && F_START==0){ //сделал флаг F_START и установил его в ноль. Проверка флага.
   stepper1.setTarget(centersteps*2, RELATIVE); //если флаг ноль - едем в сторону концевика на какое-то ужасно большое расстояние (ЧТО МНЕ НЕ НРАВИТСЯ, потому, что тупо!)
      }
static bool dir = true;
    if (!stepper1.tick()) {  //это обычное движение туда-сюда
        stepper1.setTarget(dir ? worksteps : worksteps*-1, RELATIVE);
        dir = !dir;
    }
    if (F_KONC_A ==1){ //Концевик нажат (флаг F_START тоже стал 1)
        stepper1.setTarget(-centersteps, RELATIVE); //отъезжаем назад на вычисленное число шагов до центра. Флаг F_START не тррогаем, так и будет 1 до перезагрузки.
        F_KONC_A = 0;
    }
}
осталось примастырить второй концевик.
 

Lumenjer

★★★✩✩✩✩
10 Дек 2020
220
112
нет метода tick()
И что? Оно есть в условии, которое выше, а оно будет проверяться с каждым проходом loop, значит шаговик будет работать (если у него есть цель)
Когда сработает концевик, то со следующим заходом в loop движок поедет обратно и будет ехать до тех пор, пока не приедет на точку.
if (!stepper1.tick()) - эта часть выполняется всегда, она должна выполняться, чтобы проверить условие

{ //это обычное движение туда-сюда
stepper1.setTarget(dir ? worksteps : worksteps*-1, RELATIVE);
dir = !dir;
}
- а эта, только если сработало условие (!tick() вернул 1)
 
  • Лойс +1
Реакции: DAER

DAER

✩✩✩✩✩✩✩
17 Дек 2021
21
0
И что? Оно есть в условии, которое выше, а оно будет проверяться с каждым проходом loop, значит шаговик будет работать (если у него есть цель)
Когда сработает концевик, то со следующим заходом в loop движок поедет обратно и будет ехать до тех пор, пока не приедет на точку.
if (!stepper1.tick()) - эта часть выполняется всегда, она должна выполняться, чтобы проверить условие

{ //это обычное движение туда-сюда
stepper1.setTarget(dir ? worksteps : worksteps*-1, RELATIVE);
dir = !dir;
}
- а эта, только если сработало условие (!tick() вернул 1)
тут начинает проясняться

а вот тут ещё непонятно...
 

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

★★★★★★★
14 Авг 2019
4,201
1,287
Москва
О как... А у меня в голове было что колени из сторны в сторну, а не вперед назад. И диапазон перемещения думал больше будет. Теперь понял.
 
  • Лойс +1
Реакции: DAER

Lumenjer

★★★✩✩✩✩
10 Дек 2020
220
112
@DAER, после dir = !dir возвращаемся в начало loop() (если ничего ниже нет). А далее все время будет вызываться tick(), до тех пор, пока мотор не остановиться и не выполниться условие, где запустится мотор в другую сторону и поменяем dir ещё раз, и так по кругу
 
  • Лойс +1
Реакции: DAER

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

★★★★★★★
14 Авг 2019
4,201
1,287
Москва
Вообще интересный проект. Я делал что то похожее. С 2-мя концевиками. В самом начале я двигал до одного концевика, потом до другого и считал кол-во шагов. Получал длину , записывал ее в память. а потом по нажатии кнопки двигал из одного места до другого, замедляясь при приближении к к краю.
 
  • Лойс +1
Реакции: DAER

DAER

✩✩✩✩✩✩✩
17 Дек 2021
21
0
@DAER, после dir = !dir возвращаемся в начало loop() (если ничего ниже нет). А далее все время будет вызываться tick(), до тех пор, пока мотор не остановиться и не выполниться условие, где запустится мотор в другую сторону и поменяем dir ещё раз, и так по кругу
Я вот чего не могу пока понять, у нас после dir=!dir
стоит static bool dir = true;
а....
постойте, это обьявление переменносй с присваиванием, присваивание действует только единожды?
А я вижу лишь dir = true; ...
Вот, друзья, вам и в голову не могло прийти, что можно думать вот так, а новички так и думают. Поэтому и книжки такие непонятные, что пишущие подразумевают знание "элементарных вещей". Но они на самом деле не элементарные.

В общем, спасибо большое за терпение.

скетч целиком пока такой

C++:
#include <GyverStepper.h>

//****НАСТРАИВАЕМ РАБОТУ
int dist = 40; //рабочий ход мм
int cycles = 30; //количество циклов в минуту
int center = 45; //расстояние от концевика до центра мм


long stp = 8; //деление шага
int shkiv = 32; //мм за один оборот мотора
long roundstps = stp*200; //чилсо шагов на оборот в полном шаге
long worksteps= (dist*roundstps)/shkiv; //шагов в рабочем ходе в одну сторону
long centersteps=(center*roundstps)/shkiv; //шагов от концевика до центра
long spd; //скорость движение шаг/с
long maxspd =(dist*2*cycles*roundstps)/60/shkiv; //мкс скорость движение шаг/с
long accel =maxspd*2; //ускорение движение шаг/с*с

GStepper< STEPPER2WIRE> stepper1(roundstps, 12, 10, 4);

//*****ФЛАГИ
volatile boolean F_KONC_A;
volatile boolean F_KONC_B;
volatile boolean F_START;
volatile uint32_t debounce;
void Initial_positionA() {   //ФУНКЦИЯ ОБРАБОТКИ ПРЕРЫВАНИЯ концевик A
  if (millis() - debounce >= 200 && digitalRead(2)) {
    debounce = millis();
    F_KONC_A = 1;
    F_START = 1;
    }
}
void Initial_positionB() {   //ФУНКЦИЯ ОБРАБОТКИ ПРЕРЫВАНИЯ концевик B
  if (millis() - debounce >= 200 && digitalRead(3)) {
    debounce = millis();
    F_KONC_B = 1;
    }
}
//********************************************************************************
void setup() {
F_KONC_A==0;
F_KONC_B==0;
F_START==0;
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
digitalWrite(2, LOW);
digitalWrite(3, LOW);
attachInterrupt(0, Initial_positionA, RISING); //ОБЪЯВЛЕНИЕ ПРЕРЫВАНИЯ А
attachInterrupt(1, Initial_positionB, RISING); //ОБЪЯВЛЕНИЕ ПРЕРЫВАНИЯ B


stepper1.setRunMode(FOLLOW_POS);
stepper1.setMaxSpeed(maxspd);
stepper1.setAcceleration(accel);


Serial.begin(9600);
Serial.println("Hello World!"); // отправить
Serial.println(worksteps);        // дистанция в шагах
Serial.println(maxspd);       // скорость
Serial.println(accel); // ускорение
Serial.println(roundstps); //шагов в одном обороте
Serial.println(centersteps); //шагов до центра

}
 
void loop() {

if (!stepper1.tick() && F_START==0){//Если флаг СТАРТ поднят
   stepper1.setMaxSpeed(maxspd/2);
   stepper1.setTarget(centersteps*2, RELATIVE);//Едем ДАЛЕКОоо вперёд. Костыль такой.
      }
static bool dir = true;
    if (!stepper1.tick()) {  //Начинаем работать вперёд-назад
      stepper1.setMaxSpeed(maxspd);
        stepper1.setTarget(dir ? worksteps : -worksteps, RELATIVE);
        dir = !dir;
    }
    if (F_KONC_A ==1){ //если флаг А поднят
        stepper1.brake(); //РЕЗКО тормозим, чтобы не сломать концевик
        stepper1.setMaxSpeed(maxspd/2);
        stepper1.setTarget(-centersteps-(worksteps/3), RELATIVE); //Едем в центр
        F_KONC_A = 0; //Флаг А снова готов к труду и обороне
       
    }
     if (F_KONC_B ==1){ //если флаг В поднят
        stepper1.brake(); //опять же тормозим резко
        stepper1.setMaxSpeed(maxspd/2);
        stepper1.setTarget(centersteps-(worksteps/2), RELATIVE); //Тут едем в центр но немного ближе, т.к. следующий шаг туда же
        F_KONC_B = 0;//Опускаем флаг В
        
    }
}
Вообще интересный проект. Я делал что то похожее. С 2-мя концевиками. В самом начале я двигал до одного концевика, потом до другого и считал кол-во шагов. Получал длину , записывал ее в память. а потом по нажатии кнопки двигал из одного места до другого, замедляясь при приближении к к краю.
Такой вариант мне нравится тем, что при смене деления шага или если упоры сдвигаются (концевики), то всё рассчитывается само. Это круто. Интересно, как это выглядит в коде.
 
Изменено:

DAER

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

Ну это же цикл. Значит после dir=!dir следующая строчка №2, как я понимаю.

C++:
void loop() {
static bool dir = true;
    if (!stepper1.tick()) {  //Начинаем работать вперёд-назад
      stepper1.setMaxSpeed(maxspd);
        stepper1.setTarget(dir ? worksteps : -worksteps, RELATIVE);
        dir = !dir;
    }
}
 

bort707

★★★★★★✩
21 Сен 2020
2,924
868
Ну это же цикл.
циклом это будет во время выполнения. А во время компиляции программа анализируется последовательно строчка за строчкой и обьявление переменной должно стоять ДО ее использования.
Если бы у вас dir=!dir стояло ДО static bool dir = true; и это бы компилировалось - это означало бы. что у вас две переменные dir
 
  • Лойс +1
Реакции: DAER

DAER

✩✩✩✩✩✩✩
17 Дек 2021
21
0
циклом это будет во время выполнения. А во время компиляции программа анализируется последовательно строчка за строчкой и обьявление переменной должно стоять ДО ее использования.
Если бы у вас dir=!dir стояло ДО static bool dir = true; и это бы компилировалось - это означало бы. что у вас две переменные dir
Понимание медленно, но приходит.
Вообще эта конструкция dir=!dir
не совсем удачная в моём случае... т.к. с ней имеет значение количество нажатий концевика. Одно нажатие - dir будет TRUE, два нажатия подряд - FALSE
Не критично, т.к. стоит два концевика, ну ткнётся в один два раза, всё равно вернётся потом в центр. Но сточки зрения программиования - коряво, т.к. процесс не предсказуемый.

И ещё я не понимаю где точка отсчёта в первом (абслолютные координаты) и втором (относительные) случаях.
1.

C++:
void loop() {
static bool dir = true;
    if (!stepper1.tick()) {  //Начинаем работать вперёд-назад
      stepper1.setMaxSpeed(maxspd);
        stepper1.setTarget(dir ? worksteps : -worksteps); //АБСОЛЮТНЫЕ ПОЗИЦИИ
        dir = !dir;
    }
}
2.
C++:
void loop() {
static bool dir = true;
    if (!stepper1.tick()) {  //Начинаем работать вперёд-назад
      stepper1.setMaxSpeed(maxspd);
        stepper1.setTarget(dir ? worksteps : -worksteps, RELATIVE); //ОТНОСИТЕЛЬНЫЕ ПОЗИЦИИ
        dir = !dir;
    }
}
В общем понимаю пока так:
Если в обоих случаях привести каретку в центр рукой и включить, то двигаться она будет одинаково, как в первом, так и во втором случае.
Но если отталкиваться от концевика, до которого отцентра 8000 шагов, а рабочий ход +2000 -2000, то в случае абсолютных координат будет
stepper1.setTarget(dir ? 8000+2000: 8000-2000);
а в случае относительных
stepper1.setTarget(dir ? 2000: -2000); Движение кончилось, координата обнулилась.
 
Изменено:

bort707

★★★★★★✩
21 Сен 2020
2,924
868
ещё я не понимаю где точка отсчёта в первом (абслолютные координаты) и втором (относительные) случаях.
в первом точно не уверен - скорее всего ноль координат в том месте, где был мотор при подаче питания
Во втором случае координата каждый раз прибавляется к текущей позиции в момент подачи команды setTarget(
 
  • Лойс +1
Реакции: DAER

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

★★★★★★★
14 Авг 2019
4,201
1,287
Москва
stepper1.setCurrent(0); Устанавливает текущее положение в 0. Или в другое указанное положение.

@DAER,
Так код не сложный. Напишу алгоритм:
1) Устанавалиаем относительно небольшую скорость.
2) Устанавливаем setRunMode(KEEP_SPEED); - движение с постоянной скоростью.
3) Начинаем цикл движения до тех пор пока не будет нажат один из концевиков (тут не важно какой)
4) При нажатии на концевик останаваливаемся и начинаем дивжение в обратную сторону пока концевик не отпустится. Это быстро.
5) Запоминаем текущее положение как 0.
6) Запускаем движение в ту же сторону с постоянной скоростью пока опять не будет нажатия на концевик. Т.к. двигаемся от 1-го концевика, то нажатие точно будет на 2-ой
7) при нажатии оять же смещаем направление, получаем координаты getCurrent - имеем 0 на 1-ой точке, и сколько то на 2-ой.
8) Далее можно двинуться по абсолютному на середеину и установить ее как 0.
9) Для колебания с амплитудой в 4000 шагов попеременно менять setTarget(2000) и setTarget(-2000)
 
  • Лойс +1
Реакции: DAER