Параллельный процессы при нажатие кнопки

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

Добрый день,

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

Первый код не работает, когда запускаю двигатель, то не могу его остановить. Должно быть: нажал на кнопку один раз он запустился, второй раз он остановился. Если не сложно, то помогите понять в чем проблема.

#include <StaticThreadController.h>
#include <Thread.h>
#include <ThreadController.h>
#include <Servo.h>
#include <Keypad.h>
#include <plcLib.h>

int dirPin = 8;
int stepperPin = 9;
Servo servo;
Thread runstep = Thread();
Thread runservo = Thread();

char keyMap[4][4] = {
 {'1','2','3', 'A'},
 {'4','5','6', 'B'},
 {'7','8','9', 'C'},
 {'*','0','#', 'D'}
};
 
byte rowsPins[4] = { 50, 48, 46, 44 };
byte colsPins[4] = { 42, 40, 38, 36 };
 
Keypad key = Keypad( makeKeymap(keyMap), rowsPins, colsPins, 4, 4 );
 
int agle = 85;
String message = "";
void setup()
{
 pinMode(dirPin, OUTPUT);
 pinMode(stepperPin, OUTPUT);
 setupPLC();
 servo.attach(7);
 servo.write(85);

 runstep.onRun(rotstep);
 runstep.setInterval(500);

 runservo.onRun(rotservo);
 runservo.setInterval(200);

}

void rotateDeg(float deg, float speed){ 
  int dir = (deg > 0)? HIGH:LOW;
  digitalWrite(dirPin,dir);

  int steps = abs(deg)*(1/0.225);
  float usDelay = (1/speed) * 70;

  for(int i=0; i < steps; i++){ 
    digitalWrite(stepperPin, HIGH); 
    delayMicroseconds(usDelay);

    digitalWrite(stepperPin, LOW); 
    delayMicroseconds(usDelay); 
  } 
}

bool rotright = false;
bool rotleft = false;
bool servoL = false;
bool servoR = false;

// Поток степпера:
void rotstep() { 
  while (rotright || rotleft)
  {
    if (rotright)
    {
      rotateDeg(-360, .1);
      delay(100);
      rotateDeg(-360, .1);
      rotright = false;
    }
    else
    {
      rotateDeg(360, .1);
      delay(100);
      rotateDeg(360, .1);
    }
  }
 
}
// поток сервопривода
void rotservo() { 
  if(servoL)
  {
    agle = agle - 2;
    servo.write(agle);
    servoL = false;
  }
  else if (servoR)
    {
      agle = agle + 2;
      servo.write(agle);
      servoL = false;
    } 
}

void step(boolean dir,int steps){
  digitalWrite(dirPin,dir);
  delay(50);
  for(int i=0;i<steps;i++){
    digitalWrite(stepperPin, HIGH);
    delayMicroseconds(100);
    digitalWrite(stepperPin, LOW);
    delayMicroseconds(100);
  }
}


 
void loop()
{
 char isKeyPress = key.getKey();

 if(isKeyPress == '#'){
 // # - поворот серво
 servoR = true;
      if (runservo.shouldRun())
        runservo.run(); // запускаем поток
 } 
 if(isKeyPress == '*'){
 // * - поворот серво
  servoL = true;
        if (runservo.shouldRun())
        runservo.run(); // запускаем поток
 } 

 if(isKeyPress == '0'){
 // * - поворот серво в первоначальное положение
  servo.write(agle=85);
 } 
 if(isKeyPress == '1'){
   // 1 - поворот двигателя право в первоначальное положение
    if (rotright)
    {
      delay(500);
      rotright = false;
    }
    else
    {
      rotright = true;      
    }
    if (runstep.shouldRun())
        runstep.run(); // запускаем поток
        
}
 if(isKeyPress == '3'){  
   // 1 - поворот двигателя лево в первоначальное положение
    if (rotleft)
    {
      delay(500);
      rotleft = false;
    }
    else
    {
      rotleft = true;
    }
    if (runstep.shouldRun())
        runstep.run(); // запускаем поток
    
 }
}

Второй код основной. Я плюнул на запуск двигателя с кнопки и включил его постоянно работать, а другими кнопками изменял положение сервопривода, но он с первого раза не реагирует на нажатие, видимо когда только нажатие попадает между этапами вращения.

#include <StaticThreadController.h>
#include <Thread.h>
#include <ThreadController.h>
#include <Servo.h>
#include <Keypad.h>
#include <plcLib.h>

int dirPin = 8;
int stepperPin = 9;
Servo servo;
Thread runstep = Thread();
Thread runservo = Thread();

char keyMap[4][4] = {
 {'1','2','3', 'A'},
 {'4','5','6', 'B'},
 {'7','8','9', 'C'},
 {'*','0','#', 'D'}
};
 
byte rowsPins[4] = { 50, 48, 46, 44 };
byte colsPins[4] = { 42, 40, 38, 36 };
 
Keypad key = Keypad( makeKeymap(keyMap), rowsPins, colsPins, 4, 4 );
 
int agle = 85;
String message = "";
void setup()
{
 pinMode(dirPin, OUTPUT);
 pinMode(stepperPin, OUTPUT);
 setupPLC();
 servo.attach(7);
 servo.write(85);

 runstep.onRun(rotstep);
 runstep.setInterval(500);

 runservo.onRun(rotservo);
 runservo.setInterval(200);

}

void rotateDeg(float deg, float speed){ 
  int dir = (deg > 0)? HIGH:LOW;
  digitalWrite(dirPin,dir);

  int steps = abs(deg)*(1/0.225);
  float usDelay = (1/speed) * 70;

  for(int i=0; i < steps; i++){ 
    digitalWrite(stepperPin, HIGH); 
    delayMicroseconds(usDelay);

    digitalWrite(stepperPin, LOW); 
    delayMicroseconds(usDelay); 
  } 
}

bool rotright = false;
bool rotleft = false;
bool servoL = false;
bool servoR = false;

// Поток степпера:
void rotstep() { 
  while (rotright || rotleft)
  {
    if (rotright)
    {
      rotateDeg(-360, .1);
      delay(100);
      rotateDeg(-360, .1);
      rotright = false;
    }
    else
    {
      rotateDeg(360, .1);
      delay(100);
      rotateDeg(360, .1);
    }
  }
 
}
// поток сервопривода
void rotservo() { 
  if(servoL)
  {
    agle = agle - 2;
    servo.write(agle);
    servoL = false;
  }
  else if (servoR)
    {
      agle = agle + 2;
      servo.write(agle);
      servoL = false;
    } 
}

void step(boolean dir,int steps){
  digitalWrite(dirPin,dir);
  delay(50);
  for(int i=0;i<steps;i++){
    digitalWrite(stepperPin, HIGH);
    delayMicroseconds(100);
    digitalWrite(stepperPin, LOW);
    delayMicroseconds(100);
  }
}


 
void loop()
{
 char isKeyPress = key.getKey();

rotateDeg(360, .71);
delay(1);
  
 if(isKeyPress == '#'){
 // # - поворот серво
 servoR = true;
      if (runservo.shouldRun())
        runservo.run(); // запускаем поток
 } 
 if(isKeyPress == '*'){
 // * - поворот серво
  servoL = true;
        if (runservo.shouldRun())
        runservo.run(); // запускаем поток
 } 

 if(isKeyPress == '0'){
 // * - поворот серво в первоначальное положение
  servo.write(agle=85);
 } 
 if(isKeyPress == '1'){
   // 1 - поворот двигателя право в первоначальное положение
    if (rotright)
    {
      delay(500);
      rotright = false;
    }
    else
    {
      rotright = true;      
    }
    if (runstep.shouldRun())
        runstep.run(); // запускаем поток
        
}
 if(isKeyPress == '3'){  
   // 1 - поворот двигателя лево в первоначальное положение
    if (rotleft)
    {
      delay(500);
      rotleft = false;
    }
    else
    {
      rotleft = true;
    }
    if (runstep.shouldRun())
        runstep.run(); // запускаем поток
    
 }
}

Как можно сделать, чтобы серво сразу реагировал на нажатие. И как сделать запуск и стоп степпера по кнопке, при этом чтобы серво жил своей жизнью и тоже реагировал на кнопки.

СПАСИБО!!

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

Robot_Chickn пишет:

Как можно сделать, чтобы серво сразу реагировал на нажатие. И как сделать запуск и стоп степпера по кнопке, при этом чтобы серво жил своей жизнью и тоже реагировал на кнопки.

убрать делеи... все. нафиг.

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

везде? просто до этого было без делэй, но тоже не работало, это уже код с экспериментами.

 

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

Сейчас убрал везде делэй и убрал постоянное вращение. Запустить вращение могу, остановить не могу. и серво не работает((

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

Robot_Chickn пишет:

Сейчас убрал везде делэй и убрал постоянное вращение. Запустить вращение могу, остановить не могу. и серво не работает((

теперь убери циклы

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

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

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

убрал цикл. в итоге двигатель останавливается когда выполнит команду и серво параллельно не работает

 

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

Robot_Chickn пишет:

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

постоянно вращаться - это находиться в вечном цикле?

067   while (rotright || rotleft)
068   {
069     if (rotright)
070     {
071       rotateDeg(-360, .1);
072       delay(100);
073       rotateDeg(-360, .1);
074       rotright = false;
075     }
076     else
077     {
078       rotateDeg(360, .1);
079       delay(100);
080       rotateDeg(360, .1);
081     }
082   }

без rotleft = false; ты отсюда не выйдешь никогда

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

пока контроллер занят вышеперечисленным, ты не сможешь делать что-то ещё - нажимать кнопки, снимать показания датчиков, реагировать на другие события.

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

Robot_Chickn пишет:

убрал цикл. в итоге двигатель останавливается когда выполнит команду и серво параллельно не работает

двигатель должен делать что-то без команды?

с чего бы серво не работать, что ему не даёт?

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

я этого не понимаю. Да, задумка была, что двигатель в вечном цикле, пока я не изменю лог.переменную на фолс, с помощью кнопки. 

у меня получилось параллельно управлять сервой, только когда в основном цикле луп я сделал постоянным вращение двигателя и тогда после его отработки, нажимая и держа кнопку я мог пробиваться сервой, чтобы поменять положение.

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

Robot_Chickn пишет:

я этого не понимаю. Да, задумка была, что двигатель в вечном цикле, пока я не изменю лог.переменную на фолс, с помощью кнопки. 

ок. ну, это типа логическая философия.
для того, что бы изменить переменную, нужно выйти из цикла... но это же у тебя вечный цикл? правда?
т.е. ты не можешь изменить переменную, код изменения которой исполняется вне цикла.
у тебя есть выход - поместить код, изменяющий переменную в этот цикл.
плюс у тебя есть что-то ещё, помимо цикла, которое должно исполняться параллельно.
у тебя есть выход - поместить весь код в этот цикл, фактически расширив цикл до размеров луп.
но, тогда ты точно не сможешь остановить двигатель.
у тебя есть выход - воспользоваться конструкцией if () {}
внезапно!
оказывается, тебе цикл был не нужен - о чём тебе и говорил выше...
Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

я уже второй день думаю, что ты имел в виду. но видимо не дошло до меня. Сделал так:

// Поток степпера:
void rotstep() { 

    if (rotright)
    {
      rotateDeg(-360, .1);
    }
    else
    {
      rotateDeg(360, .1);
    }
runstep.run();
 
}

в итоге все снова зациклилось и остановить двигатель не могу и серво не слушается.

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

можете написать подробнее?

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

Robot_Chickn пишет:

можете написать подробнее?

не нужно ничего писать - медитируй на свой код и думай, какая такая неведомая сила не даёт тебе исполнить код кнопок.

8321942.jpg

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

)))

в цикле луп сделал if проверку на перезапуск двигателя, т.е. если не отменен запуск, то снова в параллельный поток уходить. в итоге можно останавливать двигатель, но двигатель работает не постоянно, т.к. есть лаг во времени на обработку кода. И теперь его можно останавливать (двигать серво) и это можно сделать, только в тот момент, когда двигатель остновился((

Добавил это в луп:

 if (rotright || rotleft)
  {
    if (runstep.shouldRun())
    {
        runstep.run(); // запускаем поток
    }
  }

видимо я не доконца понимаю, как работает thread

nik182
Offline
Зарегистрирован: 04.05.2015

Не надо в loop делать какие либо проверки. В loop должна быть одна вещь - controll.run();. Все проверки нужно делать в подпрограммах thread. Там внутри thread подпрограмм ни чего не заLOOPливать. После инициализации thread сам будет вызывать подпрограмму с заданной вами периодичностью. Делайте несколько thread в каждом отдельная задача. Одна включать - выключать двигатель в зависимости от флага. Вторая менять флаг в зависимости от состояния кнопки. Третья - что ещё хочешь. Главное нигде ничего не ждать.      

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

nik182 пишет:

Не надо в loop делать какие либо проверки. В loop должна быть одна вещь - controll.run();. Все проверки нужно делать в подпрограммах thread. Там внутри thread подпрограмм ни чего не заLOOPливать. После инициализации thread сам будет вызывать подпрограмму с заданной вами периодичностью. Делайте несколько thread в каждом отдельная задача. Одна включать - выключать двигатель в зависимости от флага. Вторая менять флаг в зависимости от состояния кнопки. Третья - что ещё хочешь. Главное нигде ничего не ждать.      

Так у меня так и сделано сейчас. Но не работает. вот последний код. сейчас думаю, как еще извернуться. 

А двигатель делает фикисрованное кол-во оборотов и останавливается, его надо постоянно перезапускать.

#include <StaticThreadController.h>
#include <Thread.h>
#include <ThreadController.h>
#include <Servo.h>
#include <Keypad.h>
#include <plcLib.h>

int dirPin = 8;
int stepperPin = 9;
Servo servo;
Thread runstep = Thread();
Thread runservo = Thread();

char keyMap[4][4] = {
 {'1','2','3', 'A'},
 {'4','5','6', 'B'},
 {'7','8','9', 'C'},
 {'*','0','#', 'D'}
};

byte rowsPins[4] = { 50, 48, 46, 44 };
byte colsPins[4] = { 42, 40, 38, 36 };

Keypad key = Keypad( makeKeymap(keyMap), rowsPins, colsPins, 4, 4 );

int agle = 83;
void setup()
{
 pinMode(dirPin, OUTPUT);
 pinMode(stepperPin, OUTPUT);
 setupPLC();
 servo.attach(7);
 servo.write(87);

 runstep.onRun(rotstep);
 runstep.setInterval(500);

 runservo.onRun(rotservo);
 runservo.setInterval(200);

}

void rotateDeg(float deg, float speed){ 
  int dir = (deg > 0)? HIGH:LOW;
  digitalWrite(dirPin,dir);

  int steps = abs(deg)*(1/0.225);
  float usDelay = (1/speed) * 70;

  for(int i=0; i < steps; i++){ 
    digitalWrite(stepperPin, HIGH); 
    delayMicroseconds(usDelay);

    digitalWrite(stepperPin, LOW); 
    delayMicroseconds(usDelay); 
  } 
}

bool rotright = false;
bool rotleft = false;
bool servoL = false;
bool servoR = false;

// Поток степпера:
void rotstep() { 
    if (rotright)
    {
      rotateDeg(-360, .1);
    }
    else
    {
      rotateDeg(360, .1);
    }

}
// поток сервопривода
void rotservo() { 
  if(servoL)
  {
    agle = agle - 2;
    servo.write(agle);
    servoL = false;
  }
  else if (servoR)
    {
      agle = agle + 2;
      servo.write(agle);
      servoL = false;
    } 
}

void loop()
{
 char isKeyPress = key.getKey();

 if (rotright || rotleft)
  {
    if (runstep.shouldRun())
    {
        runstep.run(); // запускаем поток
    }
  }
  
 if(isKeyPress == '#'){
 // # - поворот серво
 servoR = true;
      if (runservo.shouldRun())
        runservo.run(); // запускаем поток
 } 
 if(isKeyPress == '*'){
 // * - поворот серво
  servoL = true;
        if (runservo.shouldRun())
        runservo.run(); // запускаем поток
 } 

 if(isKeyPress == '0'){
 // * - поворот серво в первоначальное положение
  servo.write(agle=83);
 } 

 if(isKeyPress == '1'){
   // 1 - поворот двигателя право в первоначальное положение
    if (rotright)
    {
      rotright = false;
    }
    else
    {
      rotright = true;      
    }
  }
 if(isKeyPress == '3'){  
   // 1 - поворот двигателя лево в первоначальное положение
    if (rotleft)
    {
      rotleft = false;
    }
    else
    {
      rotleft = true;
    }
  }
}

 

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

Robot_Chickn, ты бы начал с малого - запускать и останавливать двигатель одной тактовой кнопкой.

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

ок, начну с этого! но я так понял, что это надо обязательно сделать через параллельный процесс. иначе будущее не прикрутишь потом.

nik182
Offline
Зарегистрирован: 04.05.2015

Robot_Chickn пишет:

nik182 пишет:

Не надо в loop делать какие либо проверки. В loop должна быть одна вещь - controll.run();.    

Так у меня так и сделано сейчас. Но не работает.

#include <StaticThreadController.h>

#include <Thread.h>
#include <ThreadController.h>
#include <Servo.h>
#include <Keypad.h>
#include <plcLib.h>

int dirPin = 8;
int stepperPin = 9;
Servo servo;
Thread runstep = Thread();
Thread runservo = Thread();

char keyMap[4][4] = {
 {'1','2','3', 'A'},
 {'4','5','6', 'B'},
 {'7','8','9', 'C'},
 {'*','0','#', 'D'}
};

byte rowsPins[4] = { 50, 48, 46, 44 };
byte colsPins[4] = { 42, 40, 38, 36 };

Keypad key = Keypad( makeKeymap(keyMap), rowsPins, colsPins, 4, 4 );

int agle = 83;
void setup()
{
 pinMode(dirPin, OUTPUT);
 pinMode(stepperPin, OUTPUT);
 setupPLC();
 servo.attach(7);
 servo.write(87);

 runstep.onRun(rotstep);
 runstep.setInterval(500);

 runservo.onRun(rotservo);
 runservo.setInterval(200);

}

void rotateDeg(float deg, float speed){ 
  int dir = (deg > 0)? HIGH:LOW;
  digitalWrite(dirPin,dir);

  int steps = abs(deg)*(1/0.225);
  float usDelay = (1/speed) * 70;

  for(int i=0; i < steps; i++){ 
    digitalWrite(stepperPin, HIGH); 
    delayMicroseconds(usDelay);

    digitalWrite(stepperPin, LOW); 
    delayMicroseconds(usDelay); 
  } 
}

bool rotright = false;
bool rotleft = false;
bool servoL = false;
bool servoR = false;

// Поток степпера:
void rotstep() { 
    if (rotright)
    {
      rotateDeg(-360, .1);
    }
    else
    {
      rotateDeg(360, .1);
    }

}
// поток сервопривода
void rotservo() { 
  if(servoL)
  {
    agle = agle - 2;
    servo.write(agle);
    servoL = false;
  }
  else if (servoR)
    {
      agle = agle + 2;
      servo.write(agle);
      servoL = false;
    } 
}

void loop()
{
 char isKeyPress = key.getKey();

 if (rotright || rotleft)
  {
    if (runstep.shouldRun())
    {
        runstep.run(); // запускаем поток
    }
  }
  
 if(isKeyPress == '#'){
 // # - поворот серво
 servoR = true;
      if (runservo.shouldRun())
        runservo.run(); // запускаем поток
 } 
 if(isKeyPress == '*'){
 // * - поворот серво
  servoL = true;
        if (runservo.shouldRun())
        runservo.run(); // запускаем поток
 } 

 if(isKeyPress == '0'){
 // * - поворот серво в первоначальное положение
  servo.write(agle=83);
 } 

 if(isKeyPress == '1'){
   // 1 - поворот двигателя право в первоначальное положение
    if (rotright)
    {
      rotright = false;
    }
    else
    {
      rotright = true;      
    }
  }
 if(isKeyPress == '3'){  
   // 1 - поворот двигателя лево в первоначальное положение
    if (rotleft)
    {
      rotleft = false;
    }
    else
    {
      rotleft = true;
    }
  }
}

У тебя в loop() целая куча кода. Зачем? Ты ж thread используешь. Все RUN надо сделать в  setup(). 

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

Robot_Chickn пишет:

ок, начну с этого! но я так понял, что это надо обязательно сделать через параллельный процесс. иначе будущее не прикрутишь потом.

признавайся, кто тебе насрал в голову этими параллельными процессами?

забудь о параллельных, перпендикулярных и других процессах - просто пиши код, который не будет превращать контроллер в кирпич.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Мда. Ну кто так пишет параллельные процессы. 

Вариант может быть таким. 

/*
#1
#2
#3
*/
//#1
//#2
//#3
void setup() {
  //#1
  //#2
  //#3
}
void loop() {
  static uint32_t MILLIS ;
  MILLIS = millis() ;
  //#1 1000 миллисекунд вычислит. поток 1
  static uint32_t past_1 = 0 ;
  if (MILLIS - past_1 >= 1000) { // если прошло 1000 миллисек
    past_1 = MILLIS ;
    // сам код
    MILLIS = millis() ;
  }
  //#2  200 миллисекунд вычислит. поток 2
  static uint32_t past_2 = 0 ;
  if (MILLIS - past_2 >= 200) { // если прошло 200 миллисек
    past_2 = MILLIS ;
    // сам код
    MILLIS = millis() ;
  }
  //#3  100 миллисекунд вычислит. поток 3
  static uint32_t past_3 = 0 ;
  if (MILLIS - past_3 >= 100) { // если прошло 100 миллисек
    past_3 = MILLIS ;
    // сам код
  }
}

Но , даже в этом вариаете не все праллельные процессы  не переносят совместную работу. Точне не все умеют их писать.

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

я просто раньше в дипломе использовал параллельные процессы и все работало шикарно, но это совсем из другой сферы (не ардуино, а другая плата). А вот эти миллисекунды я не могу понять. Откуда мне знать сколько времени занимает у меня каждый процесс. Но видимо придется в них разобраться и сделать так. Но все равно всем СПАСИБО!

ветка не заканчивается, мне еще нужна будет помощь))

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Похоже вам диплом нашару зачли. Процесс  не измеряют длиной и сколько он длится. Процесс измеряют как часто он должен повторяется. Вот опрос кнопок он 0,2 секунды (200 микросекунд) должен повторятся. Ну не может чаще по кнопке стучать. У вас шаговый двигатель. У него есть скорость поворота. То есть период времени одного шага двигателя.   Конечно может где-то и есть системыы, где пользователю программисту не надо заморачиваться созданием  механизма организации процессов. Это делает среда. То в среде ардуино такого нет. 

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

qwone пишет:

Похоже вам диплом нашару зачли. Процесс  не измеряют длиной и сколько он длится. Процесс измеряют как часто он должен повторяется. Вот опрос кнопок он 0,2 секунды (200 микросекунд) должен повторятся. Ну не может чаще по кнопке стучать. У вас шаговый двигатель. У него есть скорость поворота. То есть период времени одного шага двигателя.   Конечно может где-то и есть системыы, где пользователю программисту не надо заморачиваться созданием  механизма организации процессов. Это делает среда. То в среде ардуино такого нет. 

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

#include <StaticThreadController.h>
#include <Thread.h>
#include <ThreadController.h>
#include <Servo.h>
#include <Keypad.h>
#include <plcLib.h>

int dirPin = 8;
int stepperPin = 9;
Servo servo;

char keyMap[4][4] = {
 {'1','2','3', 'A'},
 {'4','5','6', 'B'},
 {'7','8','9', 'C'},
 {'*','0','#', 'D'}
};
 
byte rowsPins[4] = { 50, 48, 46, 44 };
byte colsPins[4] = { 42, 40, 38, 36 };
 
Keypad key = Keypad( makeKeymap(keyMap), rowsPins, colsPins, 4, 4 );
 
int agle = 83;
String message = "";
float speedy = 0.1;


void setup()
{
 pinMode(dirPin, OUTPUT);
 pinMode(stepperPin, OUTPUT);
 setupPLC();
 servo.attach(7);
 servo.write(87);

}

void rotateDeg(float deg, float speed){ 
  int dir = (deg > 0)? HIGH:LOW;
  digitalWrite(dirPin,dir);

  int steps = abs(deg)*(1/0.225);
  float usDelay = (1/speed) * 70;

  for(int i=0; i < steps; i++){ 
    digitalWrite(stepperPin, HIGH); 
    delayMicroseconds(usDelay);

    digitalWrite(stepperPin, LOW); 
    delayMicroseconds(usDelay); 
  } 
}

bool rotright = false;
bool rotleft = false;
bool servoL = false;
bool servoR = false;
bool servoC = false;

void step(boolean dir,int steps){
  digitalWrite(dirPin,dir);
//  delay(50);
  for(int i=0;i<steps;i++){
    digitalWrite(stepperPin, HIGH);
    delayMicroseconds(100);
    digitalWrite(stepperPin, LOW);
    delayMicroseconds(100);
  }
}


 
void loop()
{
 char isKeyPress = key.getKey();
static uint32_t MILLIS ;
MILLIS = millis() ;

     if(isKeyPress == '#'){
     // # - поворот серво
     servoL = true;    
     } 

static uint32_t past_1 = 0 ;
  if (MILLIS - past_1 >= 200) { // если прошло 200 миллисек
    past_1 = MILLIS ; 
    if (servoL)
    {
      servoL = false;
     agle = agle + 2;
     servo.write(agle); 
    }
    MILLIS = millis() ;
  }

if(isKeyPress == '*'){
     // # - поворот серво
     servoR = true;
}
static uint32_t past_2 = 0 ;
  if (MILLIS - past_2 >= 200) { // если прошло 200 миллисек
    past_2 = MILLIS ;    
     if (servoR)
     {
      servoR = false;
     agle = agle - 2;
     servo.write(agle);     
     } 
    MILLIS = millis() ;
  }

if(isKeyPress == '0'){
  servoC = true;
}
static uint32_t past_3 = 0 ;
  if (MILLIS - past_3 >= 200) { // если прошло 200 миллисек
    past_3 = MILLIS ;    
     if (servoC)
     {
      servoC = false;
     // # - поворот серво
     agle = 83;
     servo.write(agle);     
     } 
    MILLIS = millis() ;
  }
///////////////////////////////////////
     if(isKeyPress == '1'){
     // # - поворот двигателя
       if (rotright)
       {  rotright = false;  }
       else
       {  rotright = true; }
     }
static uint32_t past_4 = 0 ;
if (MILLIS - past_4 >= (1/speedy) * 70) { // расчет времени на обработку вращения
    past_4 = MILLIS ;    

     if (rotright)
     {
        rotateDeg(360, speedy);
     }
    MILLIS = millis() ;
 }


if(isKeyPress == '3'){
     // # - поворот двигателя
       if (rotleft)
       {  rotleft = false;  }
       else
       {  rotleft = true; }
     }
static uint32_t past_5 = 0 ;
if (MILLIS - past_5 >= (1/speedy) * 70) { // расчет времени на обработку вращения
    past_5 = MILLIS ;    
     
     if (rotleft)
     {
        rotateDeg(-360, speedy);
     }
    MILLIS = millis() ;
 }

 if(isKeyPress == '2'){
     // # - уменьшение скорости двигателя
      speedy = speedy - 0.1;
     }

if(isKeyPress == 'A'){
     // # - увеличение скорости двигателя
      speedy = speedy + 0.1;
     }

}

 

nik182
Offline
Зарегистрирован: 04.05.2015

У тебя в пп void step(boolean dir,int steps),void rotateDeg(float deg, float speed)  зависает выполнение. Вот кнопки и не жмуться. Избавлятся надо от for циклов. У тебя же loop() крутится. Его и используй. Иначе никакие параллельные процессы нормально не заработают. И ещё хорощо бы избавится от float. Очень много едят памяти и времени на расчёты. delayMicroseconds() это тоже зло. Отработку моторов лучше загнать в прерывание таймера. С тем что у тебя делает код на весь круг это единицы милисекунд. Если правильно организовать все программа будет летать, задержки реакции на клавиши не будет.   

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016
 

все лишнее обрал, но цикл во вращение не знаю, как убрать. Когда сделал без него в лупе, то двигатель можно сказать не двигается, поэтому без понятия, как сделать. Переменные float заменил на double.

void rotateDeg(float deg, float speed){ 
  int dir = (deg > 0)? HIGH:LOW;
  digitalWrite(dirPin,dir);

  int steps = abs(deg)*(1/0.225);
  float usDelay = (1/speed) * 70;

  for(int i=0; i < steps; i++){ 
    digitalWrite(stepperPin, HIGH); 
    delayMicroseconds(usDelay);

    digitalWrite(stepperPin, LOW); 
    delayMicroseconds(usDelay); 
  } 
}

и на сколько в цикле delayMicroseconds нужны я тоже не знаю

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Robot_Chickn пишет:

все лишнее обрал, но цикл во вращение не знаю, как убрать. 

и на сколько в цикле delayMicroseconds нужны я тоже не знаю

Вы сами же захотели организовать программу в виде процессов.

1 процесс обработка кнопок, анализ команд с них и выработка решения

2 процесс  работа шагового двигателя. 

Так что надо делать свой процесс.

/*
#1 драйвер ШД direction -> 8 (dirPin)
              step      -> 9 (stepperPin)
*/
//#1 шаговый двигатель
const int usDelay = 20; // длительность шага ШД
const int dirPin = 8;
const int stepperPin = 9;
bool stepperPinStat;
bool dir; // направление вращения 1 по часовой / 0 против
int runStepMotor = 1; // 1 вращение / 0 стоит

void setup() {
  //#1
  pinMode(dirPin, OUTPUT);
  digitalWrite(dirPin, dir = 0); // установить вращение по чпсовой
  pinMode(stepperPin, OUTPUT);
  digitalWrite(stepperPin, stepperPinStat = 0); //
}

void loop() {
  //#1
  static uint32_t past_1 = 0 ;
  if (millis() - past_1 >= usDelay) { // если прошло 1000 миллисек
    past_1 = millis() ;
    if (runStepMotor) { // если надо врщать двигатель
      stepperPinStat = ! stepperPinStat;
      digitalWrite(stepperPin, stepperPinStat); // то надо его повернуть
    }
  }
}

А иначе зачем городить такой огород.

nik182
Offline
Зарегистрирован: 04.05.2015

Robot_Chickn пишет:

 Переменные float заменил на double.

Eсли ардуина не DUE то разницы нет никакой. По хорошему, формулы лучше преобразовать так, что бы в расчетах применялись только int типы. 

 

nik182
Offline
Зарегистрирован: 04.05.2015

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

#include <TimerOne.h>
#include <Keypad.h>

int dirPin = 8;
int stepperPin = 9;
volatile uint16_t steps=1;
uint8_t speedy=10; 
char keyMap[4][4] = {
 {'1','2','3', 'A'},
 {'4','5','6', 'B'},
 {'7','8','9', 'C'},
 {'*','0','#', 'D'}
};
byte rowsPins[4] = { 50, 48, 46, 44 };
byte colsPins[4] = { 42, 40, 38, 36 };
Keypad key = Keypad( makeKeymap(keyMap), rowsPins, colsPins, 4, 4 );

void timerIsr();

 
void setup() 
{
  Timer1.initialize(100); // set a timer of length 1000 microseconds 
  Timer1.attachInterrupt( timerIsr ); // attach the service routine here
  Timer1.stop();
}
 
void loop()
{
  char isKeyPress = key.getKey();
  if((isKeyPress == '1')&(steps==0))
  {  
    digitalWrite(dirPin,HIGH);
    noInterrupts();
    steps = (uint16_t) 2000UL*360/225;
    interrupts();
    Timer1.resume();
  }

  if((isKeyPress == '3')&(steps==0))
  {
    digitalWrite(dirPin,LOW);
    noInterrupts();
    steps = (uint16_t) 2000UL*360/225;
    interrupts();
    Timer1.resume();
  }

   if (isKeyPress == 'A'){
      speedy -= 1; if (speedy<1) speedy=1; 
      noInterrupts();
      Timer1.setPeriod(70UL*speedy);
      if (steps==0) steps=1;
      interrupts();   
   }

   if(isKeyPress == '2'){
      speedy += 1; if (speedy>10) speedy=10;     
      noInterrupts();
      Timer1.setPeriod(70UL*speedy);
      if (steps==0) steps=1;
      interrupts();
   }
}
 
/// --------------------------
/// Custom ISR Timer Routine
/// --------------------------
void timerIsr()
{
  if (steps % 2) digitalWrite(stepperPin, HIGH); else digitalWrite(stepperPin, LOW);
  steps-=1;
  if (steps==0)  Timer1.stop();
}

 

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

nik182. Код не работает. Вообще не реагирует степпер на кнопки. Если по умолчанию поставить step = 1, то при нажатие на запуск двигателя, он дергается на один степ (видимо) и больше не реагирует на кнопки.

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

Robot_Chickn пишет:

Код не работает. Вообще не реагирует степпер на кнопки. Если по умолчанию поставить step = 1, то при нажатие на запуск двигателя, он дергается на один степ (видимо) и больше не реагирует на кнопки.

да, что за фигня? у всего мира двигатели кнопкой управляются, а у одного уникала-тебя - нет.

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

Ребят, по сути задача решена, но криво с моей стороны. Моя следующая задача поставить тахометр, либо ик диод и фоторезистор, чтобы я мог измерять скорость вращений выходного вала. Относительно его показаний, я буду изменять работу сервака.

Что лучше использовать? и смогу ли я при грамотном коде обрабатывать показания оборотов, подавать изменяющееся значения скорости вращения на степпер и менять положения ардуино внутри одного ардуино мега без существенных тормозов? 

 

Клапауций 234
Offline
Зарегистрирован: 24.10.2016
qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Robot_Chickn пишет:

Что лучше использовать? и смогу ли я при грамотном коде обрабатывать показания оборотов, подавать изменяющееся значения скорости вращения на степпер и менять положения ардуино внутри одного ардуино мега без существенных тормозов? 

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

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

qwone пишет:

Вы сами же захотели организовать программу в виде процессов.

1 процесс обработка кнопок, анализ команд с них и выработка решения

2 процесс  работа шагового двигателя. 

Так что надо делать свой процесс.

А иначе зачем городить такой огород.

если честно, то я не понял, что вы имеете в виду. Мне нужно в одно условие миллис засунуть все нажатия кнопок с таймаутом 200, второе условие - это степпер, а третье - серво. Правильно? если usdelay сделать 20, то у нас будет всего 50 шагов в секунду, чтобы увеличить скорость, нам надо будет значение меньше 20, точно ардуино сможет это обрабатывать корректно? я правильно все понял или нет?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Robot_Chickn пишет:

если честно, то я не понял, что вы имеете в виду. Мне нужно в одно условие миллис засунуть все нажатия кнопок с таймаутом 200, второе условие - это степпер, а третье - серво. Правильно? если usdelay сделать 20, то у нас будет всего 50 шагов в секунду, чтобы увеличить скорость, нам надо будет значение меньше 20, точно ардуино сможет это обрабатывать корректно? я правильно все понял или нет?

Ну это я бы так делал. Другие может похоже, но с другими приемами. Но как вы сможете я не знаю.

Сервы как вариант так были бы.

/*
#1 Серва1 упр. выв -> 12    (servo1_pin)
               +5В -> +5В
               GND -> GND
   Серва2 упр. выв -> 11    (servo2_pin)
               +5В -> +5В
               GND -> GND
   Серва3 упр. выв -> 10    (servo3_pin)
               +5В -> +5В
               GND -> GND
   Серва4 упр. выв -> 9     (servo4_pin)
               +5В -> +5В
               GND -> GND
   Серва5 упр. выв -> 8     (servo5_pin)
               +5В -> +5В
               GND -> GND
               
#2 резистор  нижний выв   -> GND
             средний выв  -> A0    (R1_pin)
             верхний выв  -> +5
   резистор  нижний выв   -> GND
             средний выв  -> A1    (R2_pin)
             верхний выв  -> +5
   резистор  нижний выв   -> GND
             средний выв  -> A2    (R3_pin)
             верхний выв  -> +5
   резистор  нижний выв   -> GND
             средний выв  -> A3    (R4_pin)
             верхний выв  -> +5
   резистор  нижний выв   -> GND
             средний выв  -> A4    (R5_pin)
             верхний выв  -> +5
*/
//#1
const int servo1_pin = 12;
uint16_t servo1_value = 544 ; // величина на серве 544-2400 мкс.
uint8_t servo1;//

const int servo2_pin = 11;
uint16_t servo2_value = 544 ; // величина на серве 544-2400 мкс.
uint8_t servo2;//

const int servo3_pin = 10;
uint16_t servo3_value = 544 ; // величина на серве 544-2400 мкс.
uint8_t servo3;//

const int servo4_pin =  9;
uint16_t servo4_value = 544 ; // величина на серве 544-2400 мкс.
uint8_t servo4;//

const int servo5_pin =  8;
uint16_t servo5_value = 544 ; // величина на серве 544-2400 мкс.
uint8_t servo5;//
//#2
const int R1_pin = A0;// нога резистора
const int R2_pin = A1;// нога резистора
const int R3_pin = A2;// нога резистора
const int R4_pin = A3;// нога резистора
const int R5_pin = A4;// нога резистора

void setup() {
  //#1

  pinMode      (servo1_pin, OUTPUT);
  digitalWrite (servo1_pin, servo1 = 0);
  pinMode      (servo2_pin, OUTPUT);
  digitalWrite (servo2_pin, servo2 = 0);
  pinMode      (servo3_pin, OUTPUT);
  digitalWrite (servo3_pin, servo3 = 0);
  pinMode      (servo4_pin, OUTPUT);
  digitalWrite (servo4_pin, servo4 = 0);
  pinMode      (servo5_pin, OUTPUT);
  digitalWrite (servo5_pin, servo5 = 0);

  //#2
}
void loop() {
  //#1 20 миллисекунд обслуживание сервы 1 и 2
  static uint32_t past_1 = 0 ;

  if  (servo1 && (micros() - past_1 >= servo1_value))
    digitalWrite (servo1_pin, servo1 = 0);
  if  (servo2 && (micros() - past_1 >= servo2_value))
    digitalWrite (servo2_pin, servo2 = 0);
  if  (servo3 && (micros() - past_1 >= servo3_value))
    digitalWrite (servo3_pin, servo3 = 0);
  if  (servo4 && (micros() - past_1 >= servo4_value))
    digitalWrite (servo3_pin, servo3 = 0);
  if  (servo5 && (micros() - past_1 >= servo5_value))
    digitalWrite (servo5_pin, servo5 = 0);


  if (micros() - past_1 >= 20000) { // если прошло 20000 микросек
    past_1 = micros() ;

    digitalWrite (servo1_pin, servo1 = 1);
    digitalWrite (servo2_pin, servo2 = 1);
    digitalWrite (servo3_pin, servo3 = 1);
    digitalWrite (servo4_pin, servo4 = 1);
    digitalWrite (servo5_pin, servo5 = 1);

  }
  //#2
  static uint32_t past_2 = 0 ;
  if (millis() - past_2 >= 200) { // если прошло 200000 микросек
    past_2 = millis() ;

    servo1_value = map (analogRead(R1_pin), 0, 1023, 544, 2400);
    servo2_value = map (analogRead(R2_pin), 0, 1023, 544, 2400);
    servo3_value = map (analogRead(R3_pin), 0, 1023, 544, 2400);
    servo4_value = map (analogRead(R4_pin), 0, 1023, 544, 2400);
    servo5_value = map (analogRead(R5_pin), 0, 1023, 544, 2400);

  }
}

 

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

qwone, вы готовы за меня написать данную программу? мини тз я пришлю, готов заплатить за ваше потраченное время. какая примерно цена? и как с вами связаться напрямую? 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Не я не рискну. Для себя можно, а для других я не справлюсь. Поищите других и на месте где живете.

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

Кто нибудь другой готов мне в этом помочь? я так быстрее разберусь и смогу проверить свою модель(идею) 

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

Robot_Chickn пишет:

Кто нибудь другой готов мне в этом помочь? я так быстрее разберусь и смогу проверить свою модель(идею) 

в чём помочь? библиотека управления двигателем не обладает функционалом запуска/остановки двигателя?

эти функции сложно запускать кнопками?

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

написать адекватный код на кнопки, 1 серво привод, 1 степпер и 1 или 2 тахометра (еще не решил). Чтобы все это работало корректно. 

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

Robot_Chickn пишет:

написать адекватный код на кнопки, 1 серво привод, 1 степпер и 1 или 2 тахометра (еще не решил). Чтобы все это работало корректно. 

прошу тебя ответить на простой вопрос - обладает ли библиотека управления двигателем функционалом "старт/стоп"?

Robot_Chickn
Offline
Зарегистрирован: 09.11.2016

Клапауций 234 пишет:

Robot_Chickn пишет:

написать адекватный код на кнопки, 1 серво привод, 1 степпер и 1 или 2 тахометра (еще не решил). Чтобы все это работало корректно. 

прошу тебя ответить на простой вопрос - обладает ли библиотека управления двигателем функционалом "старт/стоп"?

наверно нет, я деталей библиотеки не знаю, только то, что написал в коде.

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

Robot_Chickn пишет:

наверно нет, я деталей библиотеки не знаю, только то, что написал в коде.

приехали... и, как ты собрался останавливать двигатель, если ты его и раскрутить не можешь?

nik182
Offline
Зарегистрирован: 04.05.2015

Добавте в setup() последней строкой steps=0; Или измените один раз скорость, потом сделайте шаг.

У меня нет keypad и мотора, поэтому отлаживал на нане, сериал порте и 13 ноге - светодиоде вот этим кодом:

#include <FlexiTimer2.h>
#include <Keypad.h>
#include <Servo.h>


int dirPin = 8;
int stepperPin = 13;
volatile uint16_t steps=0;
uint8_t speedy=10; 
uint8_t angle=2; 
word ang=50,val=50;

char keyMap[4][4] = {
 {'1','2','3', 'A'},
 {'4','5','6', 'B'},
 {'7','8','9', 'C'},
 {'*','0','#', 'D'}
};
byte rowsPins[4] = { 50, 48, 46, 44 };
byte colsPins[4] = { 42, 40, 38, 36 };
Keypad key = Keypad( makeKeymap(keyMap), rowsPins, colsPins, 4, 4 );
Servo servo1,servo2,servo3,servo4,servo5;

void timerIsr();

 
void setup() 
{
  Serial.begin(115200);
  pinMode(dirPin, OUTPUT);
  pinMode(stepperPin, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);

  FlexiTimer2::set(1000UL,0.00007,timerIsr);
  steps=0;
  servo1.attach(7);
  servo1.write(10);
  servo2.attach(8);
  servo2.write(10);
  servo3.attach(9);
  servo3.write(10);
  servo4.attach(10);
  servo4.write(10);
  servo5.attach(11);
  servo5.write(10);

}
 
void loop()
{
  char isKeyPress;
  if (Serial.available()){
    isKeyPress = (char)Serial.read();
  }

  if((isKeyPress == '1')&(steps==0))
  {  
    digitalWrite(dirPin,HIGH);
    noInterrupts();
    steps = (uint16_t) (2000UL*angle/225);
    interrupts();
      Serial.print("Left ");
      Serial.println(steps);
    FlexiTimer2::start();
  }

  if((isKeyPress == '2')&(steps==0))
  {
    digitalWrite(dirPin,HIGH);
    noInterrupts();
    steps = (uint16_t) (2000UL*angle/225);
    interrupts();
      Serial.print("Left ");
      Serial.println(steps);
     FlexiTimer2::start();
  }

   if (isKeyPress == '3'){
      speedy -= 1; if (speedy<1) speedy=1; 
      Serial.print("speed=");
      Serial.println(speedy);
      noInterrupts();
//      FlexiTimer2::set(1000UL*speedy,0.00007,timerIsr);
//      interrupts();

        FlexiTimer2::setPeriod(1000UL*speedy);
//      if (steps==0) steps=1;
      interrupts();
   }

   if(isKeyPress == '4'){
      speedy += 1; if (speedy>10) speedy=10;     
      Serial.print("speed=");
      Serial.println(speedy);
      noInterrupts();
//      FlexiTimer2::set(1000UL*speedy,0.00007,timerIsr);
      FlexiTimer2::setPeriod(1000UL*speedy);
//      if (steps==0) steps=1;
      interrupts();
   }
   if (isKeyPress == '5'){
      angle -= 1; if (angle<1) angle=1; 
      Serial.print("angle=");
      Serial.println(angle);
   }

   if(isKeyPress == '6'){
      angle += 1; if (angle>10) angle=10; 
      Serial.print("angle=");
      Serial.println(angle);
   }

   if(isKeyPress == '7'){
      ang += 10; if (ang>110) ang=110; 
      Serial.print("angleS1R=");
      Serial.println(ang);
       servo1.write(ang);
   }

   if(isKeyPress == '8'){
      ang -= 10; if (ang<10) ang=10; 
      Serial.print("angleS1L=");
      Serial.println(ang);
      servo1.write(ang);
   }

 static uint32_t past_2 = 0 ;

  if (millis() - past_2 >= 200) { // если прошло 200000 микросек
      past_2 = millis() ;
      val=(val*7+analogRead(A0))/8;
      servo2.write(map (val, 0, 1023, 10, 110));   
  };
}
 
/// --------------------------
/// Custom ISR Timer Routine
/// --------------------------
void timerIsr()
{
  if (steps % 2) digitalWrite(stepperPin, LOW); else digitalWrite(stepperPin, HIGH);
  steps-=1;
  if (steps==0)  { FlexiTimer2::stop(); Serial.println(" ");}
  else{
  Serial.print(" ");
  Serial.print(steps);
  };
}

 Всё моргает как задумано. На каждый градус угла около четырёх импульсов. Скорость терминала 115200. Изменять скорость можно в процессе вращения - ничего не тормозит обмен с клавишами. Во время отработки вращения крутятся сервы и с клавиатуры и резистором на А0.

В библиотеку добавил

void FlexiTimer2::setPeriod(unsigned long units) {
time_units = units;
}