// Пины подключения:
#define STEP_PIN 9 // Подключен к STEP драйвера
#define DIR_PIN 8 // Подключен к DIR драйвера
#define ENABLE_PIN 7 // Подключен к ENABLE (опционально)
#define ENDSTOP_PIN 2
int delayTime = 5000; // Начальная задержка (медленно)
int minDelay = 200; // Минимальная задержка (макс. скорость)
int acceleration = 20;
long CurPos = 0;
long targetPosition = 0;
long CurSpeed = 0;
long currentDelay = 0;
const long decelerationDistanceKoef = 1; // Коэффициент торможения
const long minDecelerationDistance = 50; // Минимальное расстояние торможения
long decelerationDistance = 0;
bool isCalibrated = false;
bool isMoving = false;
// Переменные для отслеживания времени
unsigned long prevTime = 0;
const long reportInterval = 100; // Интервал отчетов в мс
void setup() {
Serial.begin(9600);
pinMode(STEP_PIN, OUTPUT);
pinMode(DIR_PIN, OUTPUT);
pinMode(DIR_PIN, INPUT);
calibrate();
}
void loop() {
// Здесь можно добавить управление через Serial
if (Serial.available()) {
long target = Serial.parseInt();
if (target != 0) {
moveToPosition(target);
}
}
if (isMoving) {
moveMant();
}
// Периодический вывод статуса в режиме ожидания
printStatus();
delay(1);
}
// функция делает шаг двигателя с заданым делеем
void makeStep(int d) {
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(d);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(d);
CurPos += (digitalRead(DIR_PIN) ? 1 : -1);
}
//калибровка
void calibrate() {
Serial.println("Калибровка... Движение к концевику");
digitalWrite(DIR_PIN, LOW); // Движение в сторону концевика
while (!digitalRead(ENDSTOP_PIN)) { // Пока концевик не сработал
makeStep(1000);
printStatus(); // Вывод статуса во время калибровки
}
CurPos = 0;
isCalibrated = true;
Serial.println("Калибровка завершена! Текущая позиция: 0");
}
// вывод статуса
void printStatus() {
unsigned long currentTime = millis();
if (currentTime - prevTime >= reportInterval) {
prevTime = currentTime;
Serial.print("Позиция: ");
Serial.print(CurPos);
Serial.print(" шагов | ускорение ");
Serial.print(currentDelay);
Serial.print(" мкс | Время: ");
Serial.print(currentTime / 1000.0, 2);
Serial.print(" сек ");
Serial.println(decelerationDistance);
}
}
//выбо стороны движения
void moveToPosition(long position) {
if (!isCalibrated) {
Serial.println("Ошибка: сначала выполните калибровку!");
return;
}
targetPosition = position;
long distance = targetPosition - CurPos;
if (distance == 0) return;
// Устанавливаем направление
digitalWrite(DIR_PIN, (distance > 0) ? HIGH : LOW);
// Начинаем движение
isMoving = true;
currentDelay = delayTime; // Начинаем с минимальной скорости
Serial.print("Движение к позиции: ");
Serial.println(targetPosition);
}
void moveMant(){
// Рассчитываем направление и расстояние
long distanceToTarget = targetPosition - CurPos;
long absDistance = abs(distanceToTarget);
// Если достигли цели - останавливаемся
if (absDistance == 0) {
isMoving = false;
return;
}
digitalWrite(DIR_PIN, distanceToTarget > 0 ? HIGH : LOW);
// Вычисляем расстояние, необходимое для торможения
decelerationDistance = calculateDecelerationDistance(currentDelay,absDistance);
// Управление ускорением/замедлением
if (absDistance <= decelerationDistance) {
// Фаза торможения
currentDelay += acceleration;
if (currentDelay > delayTime) currentDelay = delayTime;
}
else if (currentDelay > minDelay) {
// Фаза ускорения
currentDelay -= acceleration;
if (currentDelay < minDelay) currentDelay = minDelay;
}
makeStep(currentDelay);
}
long calculateDecelerationDistance(int currentDelay, long remainingDistance) {
// Рассчитываем базовое расстояние торможения на основе текущей скорости
float speedFactor = (float)(currentDelay - minDelay) / (delayTime - minDelay);
long baseDeceleration = decelerationDistanceKoef * (currentDelay - minDelay);
// Корректируем с учетом оставшейся дистанции
long dynamicDeceleration = min(baseDeceleration, remainingDistance);
// Гарантируем минимальное расстояние торможения
return max(dynamicDeceleration, minDecelerationDistance);
}