#include "AccelStepper.h"
// Пины
#define STEP_PIN 9
#define DIR_PIN 8
#define ENDSTOP_PIN 2 // Концевик (подтянут к GND)
// Настройки двигателя
#define MOTOR_STEPS 200 // Количество шагов на оборот без микрошагов
#define MICROSTEPS 2 // Настройка микрошагов на драйвере (1, 2, 4, 8, 16...)
#define STEPS_PER_REV (MOTOR_STEPS * MICROSTEPS) // Полных шагов на оборот
#define MAX_SPEED 300 // Макс. скорость (оборотов/мин)
#define ACCELERATION 200 // Ускорение (оборотов/мин²)
#define CALIBRATION_SPEED 100 // Скорость калибровки (оборотов/мин)
AccelStepper stepper(AccelStepper::DRIVER, STEP_PIN, DIR_PIN);
// Флаг завершения калибровки
bool isCalibrated = false;
// Переменные для отслеживания времени
unsigned long prevTime = 0;
const long reportInterval = 100; // Интервал отчетов в мс
// ============================================
// Конвертация единиц
// ============================================
float rpmToStepsPerSec(float rpm) {
return rpm * STEPS_PER_REV / 60.0;
}
long revolutionsToSteps(float revolutions) {
return revolutions * STEPS_PER_REV;
}
float stepsToRevolutions(long steps) {
return steps / (float)STEPS_PER_REV;
}
// ============================================
// Калибровка (едет к концевику и сбрасывает в 0)
// ============================================
void calibrate() {
Serial.println("Калибровка... Движение к концевику");
// Устанавливаем скорость в шагах/сек
stepper.setSpeed(-rpmToStepsPerSec(CALIBRATION_SPEED));
while (digitalRead(ENDSTOP_PIN) != 1) { // Пока концевик не сработал
stepper.runSpeed();
Serial.print("Концевик: ");
Serial.print(digitalRead(ENDSTOP_PIN));
Serial.print(" | ");
printStatus(); // Вывод статуса во время калибровки
}
stepper.stop(); // Остановка
stepper.setCurrentPosition(0); // Сброс позиции в 0
isCalibrated = true;
Serial.println("Калибровка завершена! Текущая позиция: 0");
}
// ============================================
// Вывод текущего статуса (позиция, скорость, время)
// ============================================
void printStatus() {
unsigned long currentTime = millis();
if (currentTime - prevTime >= reportInterval) {
prevTime = currentTime;
Serial.print("Позиция: ");
Serial.print(stepper.currentPosition());
Serial.print(" шагов (");
Serial.print(stepsToRevolutions(stepper.currentPosition()), 3);
Serial.print(" об) | Скорость: ");
Serial.print(stepper.speed() * 60.0 / STEPS_PER_REV, 1);
Serial.print(" об/мин | Время: ");
Serial.print(currentTime / 1000.0, 2);
Serial.println(" сек");
}
}
// ============================================
// Движение к указанной позиции в шагах
// ============================================
void moveToPosition(long targetSteps) {
if (!isCalibrated) {
Serial.println("Ошибка: сначала выполните калибровку!");
return;
}
stepper.moveTo(targetSteps);
while (stepper.distanceToGo() != 0) {
stepper.run();
printStatus();
}
Serial.print("Приехали на позицию: ");
Serial.print(targetSteps);
Serial.print(" шагов (");
Serial.print(stepsToRevolutions(targetSteps), 3);
Serial.println(" об)");
}
// ============================================
// Движение на указанное число оборотов
// ============================================
void moveRevolutions(float revolutions) {
moveToPosition(revolutionsToSteps(revolutions));
}
// ============================================
// Настройка
// ============================================
void setup() {
Serial.begin(9600);
pinMode(ENDSTOP_PIN, INPUT); // Подтяжка к +5V
// Установка параметров скорости в шагах/сек
stepper.setMaxSpeed(rpmToStepsPerSec(MAX_SPEED));
stepper.setAcceleration(rpmToStepsPerSec(ACCELERATION));
Serial.println("Настройки двигателя:");
Serial.print("Шагов на оборот: ");
Serial.println(STEPS_PER_REV);
Serial.print("Микрошагов: ");
Serial.println(MICROSTEPS);
Serial.print("Макс. скорость: ");
Serial.print(MAX_SPEED);
Serial.println(" об/мин");
// Запуск калибровки при старте
calibrate();
}
// ============================================
// Основной цикл
// ============================================
void loop() {
// Управление через Serial
if (Serial.available()) {
float targetRevolutions = Serial.parseFloat();
if (targetRevolutions != 0) {
moveRevolutions(targetRevolutions);
}
}
// Периодический вывод статуса в режиме ожидания
printStatus();
delay(100);
}