Отрицательное ускорение или проблема с AccelStepper
- Войдите на сайт для отправки комментариев
Как можно реализовать равнозамедленное движение шаговика? То есть мгновенный старт с равномерным замедлением до полной остановки.
Сейчас использую для этого AccelStepper, который не понимает отрицательного значения ускорения. Приходится делать через runSpeed() и цикл с setSpeed(). Всё бы хорошо, но из-за цикла runSpeed() вызывается недостаточно часто и скорость получается ниже, чем нужно. Значительно ниже, особенно при большой скорости.
Хотя это странно, т.к. описанная выше проблема наблюдается даже когда время между шагами больше времени, потраченного на цикл. Например цикл проходит за 200 мкс, но при скорости один шаг в 400 мкс мотор крутится примерно в два раза медленнее нужного.
Вот мой текущий код для DRV8834. Но его лучше не смотреть, там черт ногу сломит.
#include <AccelStepper.h> #define STEP 5 #define DIR 6 #define M0 7 #define M1 8 #define BATTERY 3 #define MOTOR_MAX 1200 #define DRIVER_MAX 10000 AccelStepper stepper(AccelStepper::DRIVER, STEP, DIR); float path, vRatio, motorSpeed = 0, elapsed = 0; int accelType = 0, dir = 0, micRes[2] = {0, 1}; unsigned long time = 0, start = 0; void setup() { path = 920 / 2.5 / 16 * 200; //path (steps) = path (mm) / timing belt pitch (mm) / teeths on pulley * steps per turnover; vRatio = 0.9821; Serial.begin(9600); stepper.setMaxSpeed(MOTOR_MAX); stepper.setSpeed(0); } void loop() { stepper.runSpeed(); if (start) work(); else tuning(); } void tuning() { if(Serial.available() > 0) { char val = Serial.read(); switch(val) { case '*': report(); break; case '+': delay(100); char buffer[20]; int i = 0; while(Serial.available() && i < 19) buffer[i++] = Serial.read(); buffer[i++] = '\0'; sscanf(buffer, "%d %d %d", &dir, &accelType, &time); if((dir == 0 || dir == 1) && ((accelType == 0 && ceil(path / time) <= MOTOR_MAX) || (accelType >= 1 && accelType <= 4 && ceil(path / time * 2) <= MOTOR_MAX))) { digitalWrite(13, HIGH); work(); } break; } } } void work() { if(Serial.available() > 0) { char val = Serial.read(); if(val == '-') { stop(); return; } if(val == '*') report(); } if(start == 0) { start = millis(); } elapsed = (millis() - start) / 1000.0; if(elapsed < time) { switch(accelType) { case 0: motorSpeed = path / time; break; case 1: motorSpeed = 2.0 * path * elapsed / time / time; break; case 2: motorSpeed = 2.0 * path * (time - elapsed) / time / time; break; case 3: if(elapsed * 2.0 < time) motorSpeed = 4.0 * path * elapsed / time / time; else motorSpeed = 4.0 * path * (time - elapsed) / time / time; break; case 4: if(elapsed * 2.0 < time) motorSpeed = 4.0 * path * (time / 2.0 - elapsed) / time / time; else motorSpeed = 4.0 * path * (elapsed - time / 2.0) / time / time; break; default: stop(); return; } while(motorSpeed * micRes[1] * 2 <= DRIVER_MAX && micRes[1] < 32) micRes[1] *= 2; while(motorSpeed * micRes[1] > DRIVER_MAX && micRes[1] > 1) micRes[1] *= 0.5; if(micRes[0] != micRes[1]) microstep(); if(dir) stepper.setSpeed(-motorSpeed * micRes[1]); else stepper.setSpeed(motorSpeed * micRes[1]); } else stop(); } void microstep() { switch(micRes[1]) { case 1: pinMode(M0, OUTPUT); digitalWrite(M0, LOW); digitalWrite(M1, LOW); break; case 2: pinMode(M0, OUTPUT); digitalWrite(M0, HIGH); digitalWrite(M1, LOW); break; case 4: pinMode(M0, INPUT); digitalWrite(M1, LOW); break; case 8: pinMode(M0, OUTPUT); digitalWrite(M0, LOW); digitalWrite(M1, HIGH); break; case 16: pinMode(M0, OUTPUT); digitalWrite(M0, HIGH); digitalWrite(M1, HIGH); break; case 32: pinMode(M0, INPUT); digitalWrite(M1, HIGH); break; } micRes[0] = micRes[1]; } void stop() { digitalWrite(13, LOW); stepper.setSpeed(0); start = 0; time = 0; elapsed = 0; while(Serial.available() > 0) Serial.read(); } void report() { int i, voltage = 0; for(i = 0; i < 10; i++) voltage += analogRead(BATTERY); Serial.print(dir); Serial.print(' '); Serial.print(accelType); Serial.print(' '); Serial.print(time); Serial.print(' '); Serial.print(time - elapsed, 0); Serial.print(' '); Serial.println(voltage * vRatio / i, 0); }
а как вы собираетесь мгновенно разогнать мотор до больших скоростей
шаговики мгновенно не разгоняются
а как вы собираетесь мгновенно разогнать мотор до больших скоростей
шаговики мгновенно не разгоняются
Да, слово «большая» тут неуместно. Я имел ввиду, что погрешность зависит от скорости. Причем от скорости в шагах-в-секунду, а не от скорости в оборотах-в-минуту. А т.к. я использую микрошаг, то даже на низких оборотах сталкиваюсь с этой проблемой.
P.S. Максимальная скорость моего мотора 360 RPM, и он без проблем может разогнаться до неё с места, мгновенно. Но такая скорость использоваться, конечно же, не будет. Речь ведь про всё тот же timelapse-слайдер, с которым я мучаю местных форумчан уже полгода.
Частично решил проблему созданием некоего подобия многозадачности библиотекой TimerOne.
Сейчас использую для этого AccelStepper, который не понимает отрицательного значения ускорения.
Зачем ей понимать? Ускорение ускорению рознь. Как таковое ускорение не может быть отрицательным, так же как и скорость, но за то имеет напрвление. Но это все теория.
А проблема ваша решается просто, когда стартуете устанавливаете одно ускорение, набрали максимальную скорость (или достигли середины хода) установили другое ускорение. Вот и будет вам быстрое ускорение и медленное замедление.
Зачем ей понимать? Ускорение ускорению рознь. Как таковое ускорение не может быть отрицательным, так же как и скорость, но за то имеет напрвление. Но это все теория.
А проблема ваша решается просто, когда стартуете устанавливаете одно ускорение, набрали максимальную скорость (или достигли середины хода) установили другое ускорение. Вот и будет вам быстрое ускорение и медленное замедление.
Хмм... Менять на ходу ускорение как-то не додумался. Спасибо, попробую.
P.S. Максимальная скорость моего мотора 360 RPM, и он без проблем может разогнаться до неё с места, мгновенно.
а что это за такой шустрый шаговик?
да ещё на максимум мгновенно выходящий...
а что это за такой шустрый шаговик?
да ещё на максимум мгновенно выходящий...
Вот такой. Разве это много? Шесть оборотов в секунду же всего и 1200 PPS. Если верить интернету, то «Немы» до 10000 PPS рабочих бывают.