Gyver Stepper, вопросы по библиотеке

Aschas

✩✩✩✩✩✩✩
15 Авг 2020
20
0
Вот я Rez понял как результат. Но после пояснения стало понят, что это именно разрез. Но тогда разрез это не какое то мгновенное действие, а процесс, который занимает определенное время. Больше вопросов чем ответов
А выдержка времени в 1 сек

Пусть это будет не рез любая реакция на достижение целевой точки.
 

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
569
Я делал что то подобное на AccelStepper только рез делал тоже шаговиком и всё работало как часы
C++:
if(Schet==Stopa){
  Schet=0;
  mystepper_1.setAcceleration( Speed*50);
  mystepper_1.setSpeed( Speed*10);
  mystepper_1.setCurrentPosition(0);
  mystepper_1.runToNewPosition(Lenta);
if(mystepper_1.distanceToGo()==0){
  delay(100);
  mystepper.setAcceleration(Speed_1*50);
  mystepper.setSpeed(Speed_1*10);
  mystepper.setCurrentPosition(0);
  mystepper.runToNewPosition(200);
сейчас хотел попробовать на Gyver Stepper
Потому что у Аксель степпер есть блокирующие функции, вроде тот же runtoposition. Если тебе нужно так упростить код - пишешь
stepper.setTarget(1234);
while (stepper.tick());
Код не пойдет дальше пока мотор не приедет
 

Aschas

✩✩✩✩✩✩✩
15 Авг 2020
20
0
И всё же если использовать setTarget(1234, RELATIVE ), как определить момент достижения целевой позиции,чтобы использовать как событие
 

Aschas

✩✩✩✩✩✩✩
15 Авг 2020
20
0
C++:
 #include "GyverStepper.h"
 #include "GyverTimer.h"
 #include "GyverButton.h"
 GStepper<STEPPER2WIRE> stepper2(96, 4, 5);
#define BTN_PIN 13
#define REZ     24
GButton butt1(BTN_PIN);
long Shag=384;
GTimer myTimer(MS);
void setup() {
  Serial.begin(9600);
  pinMode(REZ, OUTPUT);
  digitalWrite(REZ, HIGH);
}

void loop() {
 butt1.tick();
if (butt1.isPress()) {
    stepper2.setRunMode(FOLLOW_POS);
  stepper2.setMaxSpeed(100);
  stepper2.setAcceleration(10000);
  stepper2.setTarget(Shag,RELATIVE);
  Serial.print(stepper2.getCurrent());
 }
    if (!stepper2.tick()){
 digitalWrite(REZ, LOW);
 Serial.println("REZ");
  myTimer.setTimeout(1000);
 if (myTimer.isReady()) {
  Serial.println("Timeout");
  digitalWrite(REZ, HIGH);
  }
  }
 stepper2.tick();
}
таже вакханалия REZ лупит сразу после загрузки и никакое вращение не нужно
 

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
569
C++:
 #include "GyverStepper.h"
#include "GyverTimer.h"
#include "GyverButton.h"
GStepper<STEPPER2WIRE> stepper2(96, 4, 5);
#define BTN_PIN 13
#define REZ     24
GButton butt1(BTN_PIN);
long Shag=384;
GTimer myTimer(MS);
void setup() {
  Serial.begin(9600);
  pinMode(REZ, OUTPUT);
  digitalWrite(REZ, HIGH);
}

void loop() {
butt1.tick();
if (butt1.isPress()) {
    stepper2.setRunMode(FOLLOW_POS);
  stepper2.setMaxSpeed(100);
  stepper2.setAcceleration(10000);
  stepper2.setTarget(Shag,RELATIVE);
  Serial.print(stepper2.getCurrent());
}
    if (!stepper2.tick()){
digitalWrite(REZ, LOW);
Serial.println("REZ");
  myTimer.setTimeout(1000);
if (myTimer.isReady()) {
  Serial.println("Timeout");
  digitalWrite(REZ, HIGH);
  }
  }
stepper2.tick();
}
таже вакханалия REZ лупит сразу после загрузки и никакое вращение не нужно
Естественно лупит, ты ведь так и написал. tick() у тебя возвращает false, условие if (!tick()) постоянно выполняется. Если нужно однократно - вводи свой флаг
 

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

★★★★★★★
14 Авг 2019
4,200
1,287
Москва
Потому что начальная позиция не должна соотв. позиции реза. А тут имеем просто неподвижный мотор.
Но я уже объяснял этот случай, повторяться не буду.
 

Aschas

✩✩✩✩✩✩✩
15 Авг 2020
20
0
Извините if (stepper2.tick()) работает, моя ошибка, я проверял условие if (!stepper2.tick())
 

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
569
Если ты хочешь перейти с Аксель степпер без сильных изменений в коде - оберни tick() в while(), как я писал выше
 

Aschas

✩✩✩✩✩✩✩
15 Авг 2020
20
0
Но .tick действительно тикает т.е. выдаёт им пульсы, а не прямую или не так поясните
 

Aschas

✩✩✩✩✩✩✩
15 Авг 2020
20
0
Ну так уже открывал но решения не нашёл.
В примере не рассматривается относительные перемещения когда .tick тикает в Loop
 

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
569
Ну так уже открывал но решения не нашёл.
В примере не рассматривается относительные перемещения когда .tick тикает в Loop
Там тик тикает именно в луп.... В общем понятно, больше практики и все получится
 

Aschas

✩✩✩✩✩✩✩
15 Авг 2020
20
0
И всё же хоть какой то примерчик с setTarget(val, RELATIVE )
 

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
569
Изменено:

Deiman12

✩✩✩✩✩✩✩
26 Сен 2020
4
0
Здравствуйте!
Столкнулся с такой проблемой, решение которой от меня все ускользает.
Ситуация такова:
Строю станочек и уже победил панель кнопок и экран (почему-то думал, что это самое сложное... ошибался), остался PID и Шаговик. С PID еще все впереди, (оставил на мякотку на потом), а вот шаговик, не смотря на кажущуюся простоту, мне не дается прям вообще. А если конкретнее, то пробелам в одной детали, нужно менять скорость вращения в шагах. У меня есть переменная SPS, она меняется в большую и меньшую сторону кнопками вверх и вниз, меняется она 100%, ибо это видно на экране. .setSpeed(SPS) ну никак не влияет на скорость двигателя. Код прикладываю весь что сейчас есть, проблемные места находятся между комментариями отражающими мой крик.
Я конечно подозреваю, что это из-за того, что я первый раз кодить 3 дня назад начал, но не уверен.
Если нужно будет пояснить места говнокода, то это я смогу.

C++:
#include "GyverStepper.h" // инициализация библиотеки шагового двигателя
#include <LiquidCrystal.h>  // инициализация LCD библиотеки

#define steps 1600 // 1600 - шагов на оборот с учетом деления шага
#define STEP 2
#define DIR 5
#define EN 8
    GStepper< STEPPER2WIRE> stepper1(steps, STEP, DIR, EN); //Настройка портов для библиотеки шаговых двигателей

    LiquidCrystal lcd(9, 10, 3, 4, 6, 7);  // Пины смещены, что-бы не пересекатся с платой расширения для шаговика


// Имена кнопок клавиатуры на дисплее
#define btnUP   1
#define btnDOWN 2
#define btnLEFT 3
#define btnRIGHT 4
#define btnSELECT 5
#define btnNONE 10


// Условия разбивки одного порта на 5 кнопок
int detectButton() {
  int keyAnalog =  analogRead(A0);
  if (keyAnalog < 100) {
    // Значение меньше 100 – нажата кнопка right
    return btnRIGHT;
  } else if (keyAnalog < 200) {
    // Значение больше 100 (иначе мы бы вошли в предыдущий блок результата сравнения, но меньше 200 – нажата кнопка UP
    return btnUP;
  } else if (keyAnalog < 400) {
    // Значение больше 200, но меньше 400 – нажата кнопка DOWN
    return btnDOWN;
  } else if (keyAnalog < 600) {
    // Значение больше 400, но меньше 600 – нажата кнопка LEFT
    return btnLEFT;
  } else if (keyAnalog < 800) {
    // Значение больше 600, но меньше 800 – нажата кнопка SELECT
    return btnSELECT;
  } else {
    // Все остальные значения (до 1023) будут означать, что нажатий не было
    return btnNONE;
  }
}

#define btnRST 11  // Присвоение имени и пина кнопке Reset

// Начальные значения коэффициентов

 int SPS = 1600; // Начальное количество шагов в секунду
 int SPSMin = 950; // Минимальные обороты двигателя
 int SPSMax = 10000; //  максимальные обороты двигателя
 int AccelerationStepper = 30000; // ускорение двигателя
 int revStepperSpeed = 10000; // Скорость реверса
 int tempIn = 0;  // Температура с датчика
 int tempS = 320; // Начальная целевая температура
 int tempMin = 20; // минимально устанавливаемая температура
 int tempMax = 360; // максимально устанавливаемая температура

 long posStepper = 2147483600; // крайняя позиция двигателя, после чего будет остановлен



// Флажки кнопок
 boolean btnUP_flag = 0;   // для задержки срабатывания кнопки UP
 boolean btnDOWN_flag = 0; // для задержки срабатывания кнопки DOWN
 boolean btnRIGHT_flag = 0; // для задержки срабатывания кнопки RIGHT
 boolean btnLEFT_flag = 0; // для задержки срабатывания кнопки LEFT
 boolean btnSELECT_flag = 0; // для задержки срабатывания кнопки SELECT



boolean btnRSTS;   // храним состояния кнопок (S - State)
boolean btnRSTF;   // флажки кнопок (F - Flag)
boolean btnRSTR;   // флажки кнопок на отпускание (R - Release)
boolean btnRSTP;   // флажки кнопок на нажатие (P - Press)
boolean btnRSTH;   // флажки кнопок на удержание (многократный вызов) (H - Hold)
boolean btnRSTHO;  // флажки кнопок на удержание (один вызов при нажатии) (HO - Hold Once)
boolean btnRSTD;   // флажки кнопок на двойное нажатие (D - Double)
boolean btnRSTDP;  // флажки кнопок на двойное нажатие и отпускание (D - Double Pressed)

unsigned long btnRST_timer; // таймер последнего нажатия кнопки
unsigned long btnRST_double; // таймер двойного нажатия кнопки

// Задержки кнопок
 unsigned long button_timer; // Счетчик для замера времени удержания
 

// задержки кнопок
 #define double_timer 150   // время (мс), отведённое на второе нажатие
 #define hold 500           // время (мс), после которого кнопка считается зажатой
 #define debounce 100       // (мс), антидребезг и уменьшение скорости набора
 #define pause_timer 2000    // Долгое нажатие для переключения режима

// Скорости изменения коэффициентов
#define spsSpeed 100      // скорость изменения SPS (шагов  в секунду)
#define tempSSpeed 1    // скорость изменения целевой температуры

 
 boolean stopStepper = 0; // вкл и откл двигателя. в норме выключен при включении питания
 boolean revStepper = 0; // Обратный ход шаговика

 boolean stopTerm = 0; //вкл и откл нагревателя. в норме выключен при включении питания

 void setup() {

  pinMode (btnRST, INPUT); // режим кнопки Reset
 

  pinMode(btnRST, INPUT_PULLUP);

// Для экрана
  Serial.begin(9600);
  lcd.begin(16, 2);
 
// ААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААА
stepper1.setRunMode(KEEP_SPEED); // режим поддержания скорости
  stepper1.setSpeed(666);        //
// ААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААА

}

 void loop() {

  Serial.print(SPS);
// ААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААА
stepper1.tick();
  // сделаем таймер на 50 мс и будем опрашивать потенциометр
  // менять скорость чаще нет смысла
  static uint32_t tmr2;
  if (millis() - tmr2 > 50) {
    tmr2 = millis();
    // ставим новую скорость (-512.. 512 шагов в секунду)
    // будет крутиться в разные стороны
    stepper1.setSpeed(SPS);
    stepper1.tick();
    }
// ААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААА

  //-------опрос кнопок--------
  btnRSTS = !digitalRead(btnRST);
  buttons(); //отработка кнопок
  //-------опрос кнопок--------

  // отработка режимов (опускание флага обязательно!)
  if (btnRSTP) {
    Serial.println("pressed");
    btnRSTP = 0;
  }
  if (btnRSTD) {
    Serial.println("double");
    btnRSTD = 0;
  }
  if (btnRSTH && btnRSTHO) {
    Serial.println("hold once");
    Serial.println(revStepper);
    Serial.println(stopStepper);
    btnRSTHO = 0;
      }

      

 


 
// Отображение преременной SPS на экране
  lcd.setCursor(0, 0);
        lcd.print("SPS ");
        lcd.print(SPS);
  // Часть кода убирающая
    if (SPS < 10) {
        lcd.print(" ");
  }
    else if (SPS >= 10 && SPS < 100) {
        lcd.print(" ");
        }
    else if (tempS >= 100 && tempS < 1000) {
        lcd.print("   ");
  }
 
 
  // Отображение целевой температуры на нагревателе
  lcd.setCursor(0, 1);
        lcd.print("Ts ");
        lcd.print(tempS);
    if (tempS < 10) {
        lcd.print(" ");
  }
    else if (tempS >= 10 && tempS < 100) {
        lcd.print(" ");
    }


   // Отображение Текущей температуры с термистора
  lcd.setCursor(7, 1);
        lcd.print("T ");
        lcd.print(tempIn);
    if (tempS < 10) {
        lcd.print(" ");
  }
    else if (tempS >= 10 && tempS < 100) {
        lcd.print(" ");
    }
    // отбражение текущего режима двигателя
  lcd.setCursor(13, 0);
       if (stopStepper == 0 && revStepper == 0) {
        lcd.print("off");}
        if (revStepper == 1 && stopStepper == 0){
         lcd.print("rev");}
       else if (stopStepper == 1 && revStepper == 0){
         lcd.print("on "); }
      

      // отображение текущего состояния нагревателя
  lcd.setCursor(13, 1);
       if (stopTerm == 0) {
        lcd.print("off");}
       else if (stopTerm == 1){
         lcd.print("on "); }
        
 
// Обработчик нажатий кнопок подключенных к пину А0. Необходим, т.к. подключено 5 кнопок к ожному пину
  int button = detectButton();

  switch (button) {
    case btnUP:
      if (btnUP_flag == 0 && millis() - button_timer > debounce && tempS < tempMax) // Значекние button_timer задает скорость изменение переменной путем задержки между нажатиями
         {
           tempS += tempSSpeed; // Увеличение Целевой температуры на величину tempSSpeed
           btnUP_flag = 1;
           button_timer = millis();
     }
     if (btnUP_flag == 1 && millis() - button_timer > debounce) //Благодаря этой части, код выполняется постоянно пока нажата кнопка
        {
           btnUP_flag = 0;
        }
  break;



    case btnDOWN:
      if (btnDOWN_flag == 0 && millis() - button_timer > debounce && tempS > tempMin) // Значекние button_timer задает скорость изменение переменной путем задержки между нажатиями
        {
           tempS -= tempSSpeed; // Уменьшение Целевой температуры на величину tempSSpeed
           btnDOWN_flag = 1;
           button_timer = millis();
        }
     if (btnDOWN_flag == 1 && millis() - button_timer > debounce)
        {
           btnDOWN_flag = 0;
        }
     break;
    
    case btnLEFT:
      if (btnLEFT_flag == 0 && millis() - button_timer > debounce && SPS > SPSMin) // Значекние button_timer задает скорость изменение переменной путем задержки между нажатиями
        {
           SPS -= spsSpeed; // уменьшение SPS (Скорости двигателя) на величину spsSpeed
           btnLEFT_flag = 1;
           button_timer = millis();       
        }
     else if (btnLEFT_flag == 1 && millis() - button_timer > debounce) {
           btnLEFT_flag = 0;
      }
     break;
 
    case btnRIGHT:
      if (btnRIGHT_flag == 0 && millis() - button_timer > debounce && SPS < SPSMax) // Значекние button_timer задает скорость изменение переменной путем задержки между нажатиями
        {
           SPS += spsSpeed; // увеличение SPS (Скорости двигателя) на величину spsSpeed
           btnRIGHT_flag = 1;
           button_timer = millis();
        }
      if (btnRIGHT_flag == 1 && millis() - button_timer > debounce)
         {
           btnRIGHT_flag = 0;

         }
  break;

    case btnSELECT:
           if (btnSELECT_flag == 0 && millis() - button_timer > pause_timer) /* Значекние button_timer задает скорость изменение переменной путем задержки между нажатиями
           pause_timer - необходим доя медленной смены значений флажков, при малом значении сменяется слишком быстро*/
        {
           stopTerm = !stopTerm;   // переключение состояния нагревателя
           btnSELECT_flag = 1;
           button_timer = millis();
        }
     if (btnSELECT_flag == 1 && millis() - button_timer > pause_timer)
        {
           btnSELECT_flag = 0;
        }
  break;

    default:
      //printDisplay("Press any key");
      break;     
  }
}

// обрабортчик кнопки RST. делает одинарное/двойное/удержание
void buttons() {
  //-------------------------btnRST--------------------------
  // нажали (с антидребезгом)
  if (btnRSTS && !btnRSTF && millis() - btnRST_timer > debounce) {
    btnRSTF = 1;
    btnRSTHO = 1;
    btnRST_timer = millis();
  }
  // если отпустили до hold, считать отпущенной
  if (!btnRSTS && btnRSTF && !btnRSTR && !btnRSTDP && millis() - btnRST_timer < hold) {
    btnRSTR = 1;
    btnRSTF = 0;
    btnRST_double = millis();
    
  }
  // если отпустили и прошло больше double_timer, считать 1 нажатием
  if (btnRSTR && !btnRSTDP && millis() - btnRST_double > double_timer) {
    btnRSTR = 0;
    btnRSTP = 1;
    stopStepper = !stopStepper; // переключение состояния рабоы двигателя on/off
  }
  // если отпустили и прошло меньше double_timer и нажата снова, считать что нажата 2 раз
  if (btnRSTF && !btnRSTDP && btnRSTR && millis() - btnRST_double < double_timer) {
    btnRSTF = 0;
    btnRSTR = 0;
    btnRSTDP = 1;
  
  }
  // если была нажата 2 раз и отпущена, считать что была нажата 2 раза
  if (btnRSTDP && millis() - btnRST_timer < hold) {
    btnRSTDP = 0;
    btnRSTD = 1;
    btnRST_timer = millis();
    revStepper = !revStepper; // переключение залипания реверса при двойном клике
  }
  // Если удерживается более hold, то считать удержанием
  if (btnRSTF && !btnRSTD && !btnRSTH && millis() - btnRST_timer > hold) {
    btnRSTH = 1;
    revStepper = !revStepper; // Включение реверса при зажатой кнопке
  }
  // Если отпущена после hold, то считать, что была удержана
  if (!btnRSTS && btnRSTF && millis() - btnRST_timer > hold) {
    btnRSTF = 0;
    btnRSTH = 0;
    revStepper = !revStepper; // отключение удержания реверса при отпускании кнопки
    btnRST_timer = millis();
  }
}
Ах да, забыл уточнить. Пробовал разные режимы работы, FOLLOW_POS и KEEP_SPEED, результат - отсутствует.

UPD: Оказалось, что такое непонятное вращение и-за вывода информации на экран. (Скорость всё-равно не понятно меняется, но хотя бы меняется)
Теперь не понятно как выводить информацию, если добавляю код вывода на экран в void loop (), перестает нормально работать двигатель.
 

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
569
@Deiman12, повесить обработчик мотора (тик) на прерывания таймера, как в примерах
 

Deiman12

✩✩✩✩✩✩✩
26 Сен 2020
4
0
@Deiman12, повесить обработчик мотора (тик) на прерывания таймера, как в примерах
Я же говорил, что я не грамотный. Немного не понял куда его воткнуть.
Использую немного измененную версию тестового кода, и двигатель раскручивается и меняется скорость, если не выводить ничего на дисплей, но максимальная скорость ограничена. Если полностью очистить loop и оставить только код двигателя, то вращается лучше. Любое добавление в loop подтормаживает двигатель.
Насколько я понял, из-за последовательность обработки команд тормозит.
Думал попробовать на FreeRTOS.




UPD: Уже повтыкал везде stepper1.tick(); скорость стала немного выше но все-равно очень медленно. Втыкал после каждой команды

C++:
// ААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААА


  stepper1.enable();
  stepper1.autoPower(true);
  // установка ускорения в шагах/сек/сек
  stepper1.setAcceleration(1200);
  stepper1.setRunMode(KEEP_SPEED);
// ААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААА

}
bool btnState = false;
 void loop() {


// ААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААА
 
  // кнопка нажата
  if (btnRST && !btnState) {
    btnState = true;
    stepper1.setSpeed(10000);
  }
  // кнопка отпущена
  if (btnRST && btnState) {
    btnState = false;
    stepper1.stop();
    }
  
  //АААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААА
 

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
569
  • Лойс +1
Реакции: Deiman12

Deiman12

✩✩✩✩✩✩✩
26 Сен 2020
4
0
@Deiman12,

ну я же пишу, как в примере. Подробнее о прерываниях по таймеру можно почитать в уроках, там всё максимально подробно расписано
Спасибо большое, все заработало как надо, работают все функции которые нужно.
При частоте прерывания в 45000 Гц все норм работает, при частоте выше 50000 Гц стабильнее набор высоких оборотов и они немного выше, но перестает отвечать код отвечающий за экран и кнопки. Но мне такой результат пока устраивает.
Надеюсь ПИД все не сломает.

Еще раз благодарю!
 

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

★★★★★★★
14 Авг 2019
4,200
1,287
Москва
1 000 000 / 45 000 = 22.2 мкс
Это время одного шага . Если взять для примера мотор 28byj-48, который имеет 2048 шагов, и заявленную скорость в 15 оборотов в минуту, то можно рассчитать, что: 1) 1 оборот делается за 4 секунды, тогда на шаг нужно 2 мкс. Значит максимальная скорость достигнута не будет, для макс. скорости нужна частота 500кГц. Однако мой мотор не смог достигнуть такой скорости. максимум , что вышло адекватно получить это 9 оборотов в минуту с копейками. Что тоже вполне укладывается в 22.мкс. Но , как автор уже заметил, повышение частоты уменьшает время на обработку всего остального кода. Тут уже упираемся в пределы ардуины.
 

AlexGyver

★★★★★★✩
Команда форума
30 Июл 2018
359
569
@Deiman12, нужно брать мотор с меньшим количеством шагов на оборот (х редуктор), чтобы работать на более низких скоростях прерываний, или лезть ковырять уже библиотеки дисплеев и кнопок, чтобы оно все работало в условиях частых прерываний на мотор. Пид - чисто математика, он будет работать в любом случае)
 

Deiman12

✩✩✩✩✩✩✩
26 Сен 2020
4
0
1 000 000 / 45 000 = 22.2 мкс
Это время одного шага . Если взять для примера мотор 28byj-48, который имеет 2048 шагов, и заявленную скорость в 15 оборотов в минуту, то можно рассчитать, что: 1) 1 оборот делается за 4 секунды, тогда на шаг нужно 2 мкс. Значит максимальная скорость достигнута не будет, для макс. скорости нужна частота 500кГц. Однако мой мотор не смог достигнуть такой скорости. максимум , что вышло адекватно получить это 9 оборотов в минуту с копейками. Что тоже вполне укладывается в 22.мкс. Но , как автор уже заметил, повышение частоты уменьшает время на обработку всего остального кода. Тут уже упираемся в пределы ардуины.
Тут еще напряжение двигателя нужно смотреть. Для высоких оборотов нужно достаточно высокое напряжение, на меньшем не успевают перемагничиваться обмотки. Есть даже упрощенная формула расчета напряжения U = 32 * корень индуктивности обмотки. Из нее видно что, для полноценной работы на высоких скоростях с нормальным моментом нужно достаточно высокое напряжение.


@Deiman12, нужно брать мотор с меньшим количеством шагов на оборот (х редуктор), чтобы работать на более низких скоростях прерываний, или лезть ковырять уже библиотеки дисплеев и кнопок, чтобы оно все работало в условиях частых прерываний на мотор. Пид - чисто математика, он будет работать в любом случае)
Для больших скоростей могу просто уменьшить деление шага.