Помогите разобраться с библиотекой AccelStepper

VladM
Offline
Зарегистрирован: 27.10.2016

Здравствуйте!

Никак не могу понять логику работы с этой библиотекой. А именно, как работает .run() В документации сказано, что для продолжения работы двигателя run() должна выполняться непрерывно. С примерами всё ясно и они работают. В них run() находится в loop, кроме него там ничего нет, поэтому условие непрерывного выполнения удовлетворяется.

Но в реальной задаче ситуация другая. Скетч парсит g-code с com-порта:

#include <AccelStepper.h>

#define MAX_BUF        (64)
char buffer[MAX_BUF];  // where we store the message until we get a newline
int sofar;  // how much is in the buffer

AccelStepper Zaxis(1, 4, 7);

float parsenumber(char code,float val) {
  char *ptr=buffer;
  while(ptr && *ptr && ptr<buffer+sofar) {
    if(*ptr==code) {
      return atof(ptr+1);
    }
    ptr=strchr(ptr,' ')+1;
  }
  return val;
} 

void processCommand() {
  int cmd = parsenumber('G',-1);
  switch(cmd) {
    case  1:
    Zaxis.setSpeed(1600*parsenumber('F',0)/60);
    Zaxis.move(1600*parsenumber('Z',0));
    Zaxis.runSpeed();
    //Serial.print(parsenumber('F',0));
    //Serial.print(parsenumber('Z',0));
    break;
    default:  break;
    }
 } 

void setup() {
  Serial.begin(115200);
  sofar=0;
  Zaxis.setMaxSpeed(12000);
  Zaxis.setAcceleration(16000);
}

void loop() {
  // listen for serial commands
  while(Serial.available() > 0) {  // if something is available
    char c=Serial.read();  // get it
    //Serial.print(c);  // repeat it back so I know you got the message
    if(sofar<MAX_BUF-1) buffer[sofar++]=c;  // store it
    if((c=='\n') || (c == '\r')) {
      // entire message received
      buffer[sofar]=0;  // end the buffer so string functions work right
      //Serial.print(F("\r\n"));  // echo a return character for humans
      processCommand();
      Serial.print("ok\n");
      sofar=0;
     
    }
  }
}

В loop мы слушаем порт, если что-то появилось, вызываем функцию processCommand(), которая парсит полученное с помощью parsenumber() и должна выполнить полученную команду g-code. 

Например, G1 Z10 F200. Переместиться на 10 мм по +Z со скоростью 200 мм/мин. 

Парсится всё правильно, setSpeed() и move() получают нужные значения. Одна проблема: как теперь выполнять комаду run() непрерывно? Получается, что она выполняется однократно. И действительно, рукой можно почувствовать, что на один шаг двигатель всё же срабатывает при получении g-code. Как сделать, чтобы двигатель отработал всё перемещение?

Спасибо!

GarryC
Offline
Зарегистрирован: 08.08.2016

Я не знаком с данной конкретной бибилиотекой, но общий подход в аналогичных случаях таков :

43 if (Serial.available() >0) { ...
56 };
57 Zaxis.runSpeed(); // добавляем это строчку внутрь основного цикла, но вне условия
 

VladM
Offline
Зарегистрирован: 27.10.2016

Спасибо! 

Увы, но теперь появилась новая проблема. При отрицательных значениях перемещения двигатель делает несколько оборотов в противоположную сторону, затем уже отрабатывает перемещение в нужную сторону. При положительных значениях всё работает правильно.

Проблема присутствует даже на простейшем тестовом скече:

#include <AccelStepper.h>

AccelStepper Zaxis(1, 4, 7);

void setup() {
  Serial.begin(115200);
  Zaxis.setMaxSpeed(12000);
  Zaxis.setAcceleration(16000);
  Zaxis.setSpeed(6000);
  Zaxis.move(-8000);
}

void loop() {
  Zaxis.run();
}

Железо Arduino UNO + CNC shild + A4988 + NEMA 17 0.9. Делитель выставлен на 1/16. Связка прекрасно работает с прошивкой grbl.

В чем может быть проблема?

vvadim
Offline
Зарегистрирован: 23.05.2012

внимательно посмотрите примеры

у вас совсем по другому написано

 

void loop() 
{ 
  stepper.setSpeed(1000);
  stepper.setAcceleration(500);
  stepper.moveTo(64000L);
  stepper.run(); 

}

 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Переменная или константа используемая как шаговая координата в этой библиотеке должна быть типа long.

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

VladM
Offline
Зарегистрирован: 27.10.2016

brokly пишет:

Переменная или константа используемая как шаговая координата в этой библиотеке должна быть типа long.

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

Ясно, буду разбираться. А есть какая-нибудь достойная альтернатива этой библиотеке? Для моей задачи Accel избыточна. Мне нужно управлять только одним шаговым двигателем, но максимально точно и плавно.

Поиск ничего не дал.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

"Плавно" - это с ускорениями ?

Я брал эту библиотеку, и вешал на прерывание. Из самой библиотеки выьрасывал контроль таймингов.

Вот тут посмотрите : http://arduino.ru/forum/programmirovanie/opyat-shagovik#comment-227068

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

VladM
Offline
Зарегистрирован: 27.10.2016

brokly пишет:

"Плавно" - это с ускорениями ?

Да

VladM
Offline
Зарегистрирован: 27.10.2016

Глюк проявляется, когда setSpeed() находится в loop. Если перенести его в setup, тогда нормально. Как только пользоваться этой библиотекой, если скорость необходимо переопределять? Очень бы хотелось от нее отказаться.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Что значит переопределять скорость? 

VladM
Offline
Зарегистрирован: 27.10.2016

Скорость очередного перемещения берется из g-code с com-порта. Её нельзя раз и навсегда забить в setup.

gagatli2007
Offline
Зарегистрирован: 29.10.2016

Здравствуйте. Я запустил библиотеку AccelStepper все работает все хорошо. Но когда я вставил библиотеку OneWire для измерения температуры у меня моторчик стал некорректно работать. Кто знает как решить эту проблему? Помогите пожалуйста очень нужно. Спасибо заранее!

vvadim
Offline
Зарегистрирован: 23.05.2012

gagatli2007 пишет:

Здравствуйте. Я запустил библиотеку AccelStepper все работает все хорошо. Но когда я вставил библиотеку OneWire для измерения температуры у меня моторчик стал некорректно работать. Кто знает как решить эту проблему? Помогите пожалуйста очень нужно. Спасибо заранее!

наверно у вас применяются задержки при измерении температуры, вот и тормоза

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

.run() выполняет перемещение строго на один импульс ( = поворот вала на угол 1,8 градуса, при соотношении в драйвере 1:1). Следовательно, если надо переместить (повернуть) на 180 градусов, надо сделать 100 шагов, т.е. 100 раз запустить этот .run() 

Для равномерности движения надо это делать без времязатратных операций, т.е. если во время выполнения этого цикла запустится что-то иное (отрисовка цифры, измерение чего-то), то ШД на это мгновение будет замирать. Выход есть - использовать прерывания, но вначале научитесь использовать основное - выполнение операции перемещения до конца, даже если будут замирания.

VladM
Offline
Зарегистрирован: 27.10.2016

Отказался от AccelStepper в пользу форка https://github.com/achest/stepperQ

Работает по прерываниям. Свою задачу уже реализовал. Рекомендую.