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

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

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

Lumenjer

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

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

★★★★★★★
14 Авг 2019
4,281
1,306
Москва
Вообще интересный проект. Я делал что то похожее. С 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
3,103
916
Ну это же цикл.
циклом это будет во время выполнения. А во время компиляции программа анализируется последовательно строчка за строчкой и обьявление переменной должно стоять ДО ее использования.
Если бы у вас 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
3,103
916
ещё я не понимаю где точка отсчёта в первом (абслолютные координаты) и втором (относительные) случаях.
в первом точно не уверен - скорее всего ноль координат в том месте, где был мотор при подаче питания
Во втором случае координата каждый раз прибавляется к текущей позиции в момент подачи команды setTarget(
 
  • Лойс +1
Реакции: DAER

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

★★★★★★★
14 Авг 2019
4,281
1,306
Москва
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

DAER

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

попробовал ради тренировки изобразить в коде

C++:
volatile boolean F_START; //логический флаг стартовой инициации
volatile boolean F_KONC_A; //концевик А
volatile boolean F_KONC_В; //концевик В
long distance=0; //обьявили переменную дистанции и присвоили ей 0

void Initial_positionA() {   //ФУНКЦИЯ ОБРАБОТКИ ПРЕРЫВАНИЯ концевик A
  if (millis() - debounce >= 200 && digitalRead(2)) {
    debounce = millis();
    F_KONC_A = 1;
    }
}
void Initial_positionB() {   //ФУНКЦИЯ ОБРАБОТКИ ПРЕРЫВАНИЯ концевик B
  if (millis() - debounce >= 200 && digitalRead(2)) {
    debounce = millis();
    F_KONC_B = 1;
    }
}



void setup() {
F_KONC_A=0;
F_KONC_В=0;
F_START=1;

attachInterrupt(0, Initial_positionA, RISING); //ОБЪЯВЛЕНИЕ ПРЕРЫВАНИЯ А
attachInterrupt(1, Initial_positionB, RISING); //ОБЪЯВЛЕНИЕ ПРЕРЫВАНИЯ B


if (!stepper1.tick() && F_START==1 ){//Если флаг СТАРТ поднят
   stepper1.setRunMode(KEEP_SPEED); //Режим поддержания скорости. Просто едем, пока не нажмём концевик А.
   stepper1.setMaxSpeed(maxspd/2); //С маленькой скоростью
      }
     
       if (F_KONC_A ==1 && F_START==1 &&F_KONC_B==0) //Нажали концевик А, едем к концевику В
        stepper1.brake(); //РЕЗКО тормозим, чтобы не сломать концевик
        stepper1.reverse(); //Инвертируем направление вращения
        stepper1.setMaxSpeed(maxspd/2); //С маленькой скоростью
        stepper1.setCurrent(0);//обнуляем координаты
             
    }
       if (F_KONC_A ==1 && F_START==1 &&F_KONC_B==1) //Нажали концевик В
        stepper1.brake(); //РЕЗКО тормозим, чтобы не сломать концевик
        distance=stepper1.getCurrent(); //Получаем координату и записываем её в переменную distance
        stepper1.setRunMode(FOLLOW_POS);//Устанавливаем режим следования к цели
        stepper1.reverse(); //Инвертируем направление вращения
        stepper1.setMaxSpeed(maxspd/2); //С маленькой скоростью
        stepper1.setTarget(distance/2, Relative);//Устанавливаем координату цели. После остановки она сбросится в 0.
        F_KONC_A=0;
        F_KONC_В=0;
        F_START=0;
             
    }
   
Void loop (){

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


}
 

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

★★★★★★★
14 Авг 2019
4,281
1,306
Москва
Самое главное не написал: получилось ? Вроде не должно работать...
Смотрю код. есть ошибки.

C++:
volatile boolean F_START = 1; //логический флаг стартовой инициации
volatile boolean F_KONC_A = 0; //концевик А
volatile boolean F_KONC_В = 0; //концевик В
long distance = 0; //обьявили переменную дистанции и присвоили ей 0

void Initial_positionA() {   //ФУНКЦИЯ ОБРАБОТКИ ПРЕРЫВАНИЯ концевик A
  if (millis() - debounce >= 200 && digitalRead(2)) {
    debounce = millis();
    F_KONC_A = 1;
  }
}
void Initial_positionB() {   //ФУНКЦИЯ ОБРАБОТКИ ПРЕРЫВАНИЯ концевик B
  if (millis() - debounce >= 200 && digitalRead(2)) {
    debounce = millis();
    F_KONC_B = 1;
  }
}


void setup() {
  attachInterrupt(0, Initial_positionA, RISING); //ОБЪЯВЛЕНИЕ ПРЕРЫВАНИЯ А
  attachInterrupt(1, Initial_positionB, RISING); //ОБЪЯВЛЕНИЕ ПРЕРЫВАНИЯ B

  // в начале F_START всегда 1, это раз. stepper1.tick() - проверять не имеет смысла в setup - итог условие тут не нужно!
  //f (!stepper1.tick() && F_START==1 ){//Если флаг СТАРТ поднят
  stepper1.setRunMode(KEEP_SPEED); //Режим поддержания скорости. Просто едем, пока не нажмём концевик А.
  stepper1.setMaxSpeed(maxspd / 2); //С маленькой скоростью
  //}
  // это не будет работать!
  //if (F_KONC_A == 1 && F_START == 1 && F_KONC_B == 0) //Нажали концевик А, едем к концевику В, и лишние условия ни к чему.
  /*
       Тут не имеет смысла проверять  tick - он всегда будет true т.к. у нас движение с пост. скоростью, а не до места.
       Значит проверяем только на нажатие концевика:
      проверять надо так:
  */
  while (!F_KONC_A) stepper1.tick();



  stepper1.brake(); //РЕЗКО тормозим, чтобы не сломать концевик // тут не резко тормозим, а отменяем движение. Да его и не будет дальше, т.к. движение идет через tick, а его уже нет.
  stepper1.setCurrent(0);//обнуляем координаты // это делаем сразу.
  stepper1.reverse(); //Инвертируем направление вращения
  stepper1.setMaxSpeed(maxspd / 2); //С маленькой скоростью

  while (!F_KONC_B) stepper1.tick();

  // if (F_KONC_A == 1 && F_START == 1 && F_KONC_B == 1) //Нажали концевик В

  stepper1.brake(); //РЕЗКО тормозим, чтобы не сломать концевик
  distance = stepper1.getCurrent(); //Получаем координату и записываем её в переменную distance
  stepper1.setRunMode(FOLLOW_POS);//Устанавливаем режим следования к цели
  stepper1.reverse(); //Инвертируем направление вращения
  stepper1.setMaxSpeed(maxspd / 2); //С маленькой скоростью
  stepper1.setTarget(distance / 2, Relative); //Устанавливаем координату цели. После остановки она сбросится в 0.
  F_KONC_A = 0;
  F_KONC_В = 0;
  F_START = 0;

}

Void loop () {

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


}

Внес кое какие изменения, так работать должно , если ничего не упустил :)

Но есть замечания:
1) Если изначально перепутано направление движения, то снос концевика гарантирован. Ну вернее упор в него.
2) Я на тестовые концевики повесил конденсатор на 0.1мкф, и включил подтяжку PULLUP для данного пина, получил отлично работающую RC цепочку, для гашения дребезга.


Буду продолжать тут:
Т.к. движения симметричные , все происходит относительно середины , то собственно пофиг где будет 0, а где нет. И значение 2-го концевика тоже пофиг, будет оно со знаком + или со знаком -, главное взять переменную ЗНАКОВУЮ.
Тогда на оба пина с концевиками делаем ОДНУ функцию прерывания, которая будет возводить флаг , когда упремся в любой из концевиков.
И тогда код получается такой
0) Устанавливаем нужную скорость, 1 раз%
stepper1.setMaxSpeed(maxspd / 2);
1) Даигаемся в любую сторону, пока не упремся:
F_KONС=0; // на всякий скидываем состояние, если до этого был упор в концевик
while (!F_KONС) stepper1.tick();
2) Делаем место нулем:
stepper1.setCurrent(0);//обнуляем координаты // это делаем сразу.
3) меняем направление:
stepper1.reverse(); //Инвертируем направление вращения
4) Двигаемся пока не упремся:
F_KONС=0; // скидываем состояние, если до этого был упор в концевик
while (!F_KONС) stepper1.tick();
5) Запоминаем положение:
distance = stepper1.getCurrent(); //Получаем координату и записываем её в переменную distance
6) Запускаем движение к середине:
7) Возвращаем направление:
stepper1.reverse(); //Инвертируем направление вращения
stepper1.setTarget(distance / 2, Relative); //Устанавливаем координату цели. После остановки она сбросится в 0.

Вид общего прерывания при условии, что запаян конденсатор и сделано PULLUP.
1640113320950.png
C++:
void Initial_position() {   
    F_KONC= 1;  
}
Да, т.к. прерыания rising -, т.е. по возрастанию, а INPUT_PULLUP притягивает пин к лог. 1, то подключать концевик надо одним концом (COMNON) к земле, а втроым , тем, что NC (NORMAL CLOSE, нормально замкнутый) к пину.
 
Изменено:
  • Лойс +1
Реакции: DAER

Lumenjer

★★★✩✩✩✩
10 Дек 2020
220
112
@DAER, setup() выполняется один раз при включении устройства, далее будет пофиг, какие концевики сработали, а какие нет.

И void loop() с маленькой надо
 

DAER

✩✩✩✩✩✩✩
17 Дек 2021
21
0
Ну так и задумано один раз инициализация и измерение рабочего хода.

У меня пины подтянуты к земле резисторами на 10к. Ну и программно на всякий случай. А концевик подаёт на каждый +.
Без программного устранения дребезг есть. Возможно, из за того, то 2 и 3 пин это прерывания, опрашиваются очень часто.

ЕСТЬ ВОПРОСЫ
1. Если мотор в режиме keep_sped остановился приехал в точку, остановился и двинулся обратно. Что происходит с координатой? Она не обнуляется в момент остановки?

2. В конструкциях
if...
if...
if...

ecли режим мотора (поддерж. скорости) задан в первом иф, он распространяется на все нижележащие? Если в
сетап или раньше был указан другой режим (следования к координате)?
 

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

★★★★★★★
14 Авг 2019
4,281
1,306
Москва
Координата не обнуляется. При движении в одну сторону координата просто увеличивается на 1, в другую уменьшается.

if тут не будет работать - написал вроде выше. Почему ? Потому что по условию if все что подходит выполниться 1 раз и все. А это значит мотор выполни только 1 шаг. И все. Он не будет двигаться, При условии while все что подходит под условие будет работать постоянно пока условие выполняется, до 1-го нарушения. Потом переход далее.

Режим работы мотора сохраняется до тех пор, пока его дальше не изменить.
 
  • Лойс +1
Реакции: DAER

DAER

✩✩✩✩✩✩✩
17 Дек 2021
21
0
см. комментарии

C++:
void setup() {
...
stepper1.setRunMode(FOLLOW_POS); //РЕЖИМ СЛЕДОВАНИЯ К ПОЗИЦИИ
...

}

void loop() {

    ...

    if (F_KONC_A ==1 && F_TIME==1){
        stepper1.brake();
        stepper1.setRunMode(KEEP_SPEED); //Установили режим поддержания скорости
        stepper1.setMaxSpeed(maxspd/2);
        ...
     
    }
     if (F_KONC_B ==1 && F_TIME==1){
                                   //ВОТ ТУТ КАКОЙ БУДЕТ РЕЖИМ МОТОРА???
         stepper1.brake();
        stepper1.setMaxSpeed(maxspd/2);
       ....
    }
}
 

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

★★★★★★★
14 Авг 2019
4,281
1,306
Москва
Вот тут не обязательно! Неизвестно какой концевик (условие) сработает раньше.
Вот эти 2 строки:
C++:
        stepper1.setRunMode(KEEP_SPEED); //Установили режим поддержания скорости
        stepper1.setMaxSpeed(maxspd/2);
]
Нужно делать в setup
А в условиях оставить только stepper1.brake(); и добавить смену направления.
Но логика все равно как то хромает. Я уже перестал понимать что происходит. Изначально было больше осмысленности.
Резюмируя:
У мотора есть некоторые настройки по умолчанию - когда он объявляется в коде уже есть некоторые значения для скорости, для типа движения и т.д.
Если их поменять, например скорость для постоянного движения, то изменение будет сохранено до тех пор, пока не будет другого изменения.
Это касается в данном примере типа движения KEEP_SPEED и выставленной максимальной скорости maxspd/2.
Оставить так можно - ошибки не будет. Вопрос зачем ?

И еще подумал про вчерашний код
В конце идет перемещение используя worksteps , диапазон получился 2*worksteps.
worksteps= (dist*roundstps)/shkiv;
Но при этом теоретически может оказаться ситуация, что worksteps будет больше половины всей дистанции. Тогда он будет тупо лупить по концевиками.
Значит дополнительно надо вычислить максимально возможное значение worksteps и если вычисленное по формуле будет превышать максимальное, то взять именно максимально. Тут очень удобна функция min() которая вернет минимальное значение из 2-х.
 
Изменено:
  • Лойс +1
Реакции: DAER

DAER

✩✩✩✩✩✩✩
17 Дек 2021
21
0
...Я уже перестал понимать что происходит. Изначально было больше осмысленности.
Есть готовый скетч, и он работает. Вот прямо сейчас :) Но есть некоторые для меня непонятные вопросы. Можно на них и забить (ведь работает же), но в этот раз мне хочется понять в этих строчках абсолютно всё! Особенно, еслим учесть, что строчек-то немного. Так что спасибо за помощь :)

В конце идет перемещение используя worksteps , диапазон получился 2*worksteps.
worksteps= (dist*roundstps)/shkiv;
Но при этом теоретически может оказаться ситуация, что worksteps будет больше половины всей дистанции.
Нет. Сейчас у меня между концевиками 75 мм. Рабочий ход - 40 мм ( 40 вперёд, остановка, 40 назад). (тут немного убого сделано, лучше, видимо абсолютная дистанция). roundstps нужен, чтобы удобно было менять деление шага.

А общее резюме - удивительно насколько не совпадает мозг (логика) новичка с тем, что как написано в учебниках, уроках и пр.

ЗЫ: это неудивительно. Возьмите школьный курс иностранного. Учебники, методички, всё утверждено... Столько лет, а что в итоге?

кстати, вот он. Я добавил таймер 10 минут работы 10 минут отдых. Но мне не нравится, что я в каждом IF пишу F_TIME==1
Я понимаю, что IF срабатывает один раз, но из-за того что всё это хозяйство помещено в loop я постоянно путаюсь.


C++:
#include <GyverStepper.h>

//****НАСТРАИВАЕМ РАБОТУ
int dist = 40; //рабочий ход мм
int cycles = 15; //количество циклов в минуту
int center = 35; //расстояние от концевика до центра мм
uint32_t timer_run = 10; //время работы мин.
uint32_t timer_pause = 10; //время паузы мин.


long stp = 64; //деление шага
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; //ускорение движение шаг/с*с
uint32_t timer_rum_millis = timer_run*60000;
uint32_t timer_pause_millis = timer_pause*60000;

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

//*****ФЛАГИ
volatile boolean F_KONC_A; //Флаг концевика А возле мотора
volatile boolean F_KONC_B; //флаг концевика В дальний
volatile boolean F_START; //логический флаг иници
volatile boolean F_TIME; //флаг таймера работы/паузы
uint32_t tmr; //переменная хранения времени

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;
    }
}
//****SETUP***************

void setup() {
F_TIME=1;
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 (millis() - tmr >= (F_TIME ? timer_rum_millis : timer_pause_millis)) {
    tmr = millis();
    F_TIME = !F_TIME;
}

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

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

★★★★★★★
14 Авг 2019
4,281
1,306
Москва
А не надо так писать.
C++:
void loop() {
  // тут все хорошо!
  if (millis() - tmr >= (F_TIME ? timer_rum_millis : timer_pause_millis)) {
    tmr = millis();
    F_TIME = !F_TIME;
  }


  // если работаем то делаем все, что внутри:
  if (F_TIME == 1) {
    if (!stepper1.tick()) {  //Начинаем работать вперёд-назад
      stepper1.setMaxSpeed(maxspd);
      stepper1.setTarget(dir ? worksteps : -worksteps, RELATIVE);
      dir = !dir;
    }


    ...
  }
}
Там где ... дописать остальные проверки. Только понимаю, что условие F_TIME == 1 уже выполнено.
 
  • Лойс +1
Реакции: DAER

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
574
@hiteker75, AccelStepper сжирает в десятки раз больше процессорного времени на участке разгона
 

78125

✩✩✩✩✩✩✩
1 Дек 2019
76
2
Использую gyverstepper Почему то если просто в loop засунуть обновление скорости мотора оно не работает
C++:
ISR(TIMER2_A) { //прерывание по таймеру 2А
MainSt.tick(); //тикаем
}

void loop() {
bus.poll(modbus_array,1);       //Used to receive or write value from Master
if (modbus_array[0] ==0) {
                              MainSt.brake();
                              } else {
                                      MainSt.setSpeed(modbus_array[0]); //обновляем скорость
                                      }
}
А вот если обновлять скорость с задержкой 100 мс например, мотор все отрабатывает.
но для меня задержка в 100 мс критична, что не так с обновлением скорости сразу после принятия по rs485?

C++:
ISR(TIMER2_A) { //прерывание по таймеру 2А
MainSt.tick(); //тикаем
}

void loop() {
bus.poll(modbus_array,1);       //Used to receive or write value from Master
if(millis() - LEDTimer > 100) {
LEDTimer = millis();
if (modbus_array[0] ==0) {
                              MainSt.brake();
                              } else {
                                      MainSt.setSpeed(modbus_array[0]); //обновляем скорость
                                      }
}}
 

poty

★★★★★★✩
19 Фев 2020
3,292
953
Очевидно, скорость меняете чаще, чем срабатывает прерывание. Внутри loop нужно проверять, изменилось ли что-нибудь с момента последнего приёма и изменять скорость только тогда, когда изменилось.
Единица в bus.poll - правильна? Принимается 1 байт?
 

78125

✩✩✩✩✩✩✩
1 Дек 2019
76
2
она точно не меняется чаще. пид выдает новую скорость не чаще чем 400 мс.
 

poty

★★★★★★✩
19 Фев 2020
3,292
953
Так Вы проверьте, сколько раз выполняется цикл за одну секунду. Тогда будет всё понятно.