Управление шаговым двигателем 28BYJ-48 с драйвером ULN2003 и Arduino

Управление шаговым двигателем 28BYJ-48 с драйвером ULN2003 и Arduino

Шаговые двигатели окружают нас гораздо чаще, чем мы думаем. Они незаметно работают за кулисами во всевозможных повседневных устройствах — жалюзи, 3D-принтерах, камерах видеонаблюдения, станках с ЧПУ и многом другом.

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

Если вы только начинаете работу с шаговыми двигателями, 28BYJ-48 — отличный выбор. Он недорогой, широко доступный и простой в использовании с Arduino. В этом руководстве мы покажем вам, как его подключить, и рассмотрим два способа управления: один с использованием встроенной библиотеки Stepper для Arduino, а другой — с помощью более продвинутой библиотеки AccelStepper.

Давайте начнём и добавим движение в ваш следующий проект!

Знаете ли вы, как работают шаговые двигатели?

Шаговый двигатель — это тип бесщёточного двигателя постоянного тока, который перемещается точными, маленькими шагами вместо непрерывного вращения. Принцип работы шагового двигателя основан на магнитных полях. Он состоит из двух основных компонентов: ротора (подвижная часть) с магнитными зубцами и статора (неподвижная часть) с электромагнитными катушками.

Когда электричество протекает через эти катушки в определённом порядке, каждая катушка создаёт магнитное поле. Это магнитное поле притягивает ближайшие зубцы ротора, заставляя двигатель продвигаться на один точный, фиксированный угловой шаг, называемый шагом.

Управление шаговым двигателем 28BYJ-48 с драйвером ULN2003 и Arduino

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

  • Последовательность импульсов определяет, в каком направлении вращается двигатель

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

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

Последовательно возбуждая катушки, шаг за шагом, одну за другой в определённом порядке, мы можем заставить двигатель повернуться ровно настолько, насколько нужно, с нужной скоростью и в нужном направлении. Этот точный контроль делает шаговые двигатели идеальными для таких устройств, как 3D-принтеры, станки с ЧПУ или роботизированные руки, где важно точное позиционирование.

Шаговый двигатель 28BYJ-48

28BYJ-48 — это маленький 5-проводной униполярный шаговый двигатель, работающий от 5 вольт. Он идеально подходит для проектов, требующих точного, управляемого перемещения, например, для движения роботизированной руки в заданные позиции.

Этот двигатель имеет компактный, круглый корпус диаметром около 28 мм. Он оснащён двумя небольшими фланцами для крепления к поверхностям. Вал имеет форму «Double-D», то есть частично плоский с двух сторон. Такая форма облегчает крепление колёс или других деталей с помощью установочного винта.

Управление шаговым двигателем 28BYJ-48 с драйвером ULN2003 и Arduino

Несмотря на небольшие размеры, двигатель обеспечивает солидный крутящий момент — около 34,3 мН·м, при скорости вращения приблизительно 15 об/мин.

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

Распиновка

28BYJ-48 имеет пять проводов. Распиновка следующая:

Управление шаговым двигателем 28BYJ-48 с драйвером ULN2003 и Arduino

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

Каждый конец катушки вместе с его центральным отводом образует так называемую фазу. Поскольку есть две катушки и у каждой есть центральный отвод, двигатель имеет в общей сложности четыре фазы.

Управление шаговым двигателем 28BYJ-48 с драйвером ULN2003 и Arduino

Красный провод всегда должен быть подключён к положительному напряжению (HIGH). Когда вы подключаете любой из оставшихся четырёх проводов к отрицательному напряжению (LOW), соответствующая фаза возбуждается и помогает вращать двигатель.

Чтобы двигатель вращался, вы возбуждаете эти четыре фазы в определённой последовательности. Эта последовательность называется последовательностью шагов.

Передаточное число редуктора

Согласно техническому описанию, без редуктора каждый шаг перемещает вал на 11,25°. Это означает, что для одного полного оборота потребуется 32 шага (поскольку 360° ÷ 11,25° = 32 шага).

Однако этот двигатель имеет встроенный редуктор с передаточным отношением 64:1. Это означает, что внутренний ротор должен совершить 64 оборота, прежде чем выходной вал совершит один полный оборот. С этим редуктором для одного полного оборота выходного вала теперь требуется 32 × 64 = 2048 шагов.

Управление шаговым двигателем 28BYJ-48 с драйвером ULN2003 и Arduino

Встроенный редуктор служит важной цели: он замедляет скорость вращения двигателя, одновременно увеличивая его крутящий момент. Этот компромисс объясняет, почему двигатель вращается со скоростью всего 15 об/мин, но при этом может генерировать относительно большой крутящий момент около 34,3 мН·м.

Не все двигатели 28BYJ-48 имеют одинаковое передаточное число. Некоторые версии (в зависимости от производителя) могут использовать соотношение 1:16, что даёт 512 шагов на оборот вместо 2048.

Потребляемая мощность

Шаговый двигатель 28BYJ-48 работает от 5 вольт, но потребляет значительное количество тока — около 240 миллиампер (мА) на фазу.

Также важно отметить, что шаговые двигатели, включая 28BYJ-48, потребляют энергию даже когда не вращаются. Это потому, что им необходимо удерживать свою позицию и создавать крутящий момент для сопротивления внешним силам. Для этого двигатель поддерживает небольшой электрический ток, протекающий через его катушки. Этот ток создаёт магнитное поле, которое фиксирует вал двигателя на месте. Величина тока, необходимого для удержания позиции, называется током удержания. Это нужно учитывать при создании проектов.

Технические характеристики

Вот технические характеристики:

Рабочее напряжение

5VDC

Рабочий ток

240mA (типичный)

Количество фаз

4

Передаточное число редуктора

64:1

Угол шага

5.625°/64

Частота

100Hz

Тяговый крутящий момент

>34.3mN.m(120Hz)

Крутящий момент самопозиционирования

>34.3mN.m

Момент трения

600-1200 gf.cm

Момент втягивания

300 gf.cm

Для получения дополнительной информации обратитесь к техническому описанию ниже.

Плата драйвера ULN2003

Микроконтроллеры, такие как Arduino, отлично подходят для управления электроникой, но у них есть ограничение — они могут выдавать лишь небольшой ток, обычно около 20–40 мА на вывод GPIO. Однако шаговому двигателю 28BYJ-48 требуется значительно больше мощности — около 240 мА на фазу. Это в шесть раз больше, чем Arduino может безопасно обеспечить!

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

Микросхема ULN2003 содержит семь пар транзисторов Дарлингтона. Каждая пара может выдерживать ток до 500 мА и напряжение до 50 вольт, чего более чем достаточно для этого двигателя! Плата использует четыре из этих пар для управления четырьмя фазами шагового двигателя.

Есть ещё одна важная причина использовать ULN2003: шаговые двигатели являются индуктивной нагрузкой, что означает, что они могут генерировать высоковольтные выбросы, известные как обратная ЭДС (электродвижущая сила), особенно при переключении. Эти выбросы могут повредить ваш микроконтроллер или другие компоненты. К счастью, микросхема ULN2003 имеет встроенные обратные диоды (также называемые диодами свободного хода), которые безопасно поглощают эти скачки напряжения и помогают защитить вашу схему.

Управление шаговым двигателем 28BYJ-48 с драйвером ULN2003 и Arduino

Плата драйвера ULN2003 имеет четыре управляющих входа (IN1–IN4), которые принимают сигналы от Arduino, и подключение источника питания.

Она также оснащена разъёмом JST, совместимым с 5-проводным разъёмом двигателя 28BYJ-48. Это позволяет легко подключить двигатель к плате без необходимости дополнительной проводки.

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

Также на плате есть перемычка ВКЛ/ВЫКЛ, которая позволяет отключить двигатель без необходимости отсоединять провода.

Распиновка платы драйвера шагового двигателя ULN2003

Плата драйвера шагового двигателя ULN2003 имеет следующую распиновку:

Управление шаговым двигателем 28BYJ-48 с драйвером ULN2003 и Arduino

IN1 — IN4 — управляющие входы, используемые для отправки последовательности шагов на двигатель. Их подключают к цифровым выводам Arduino.

GND — это вывод заземления.

VCC обеспечивает питание двигателя. Имейте в виду, что двигатель потребляет много тока, поэтому лучше использовать отдельный источник питания 5В, а не запитывать его от самого Arduino.

Motor Connector — разъём для подключения двигателя к плате. Этот разъём имеет ключ, то есть его можно вставить только одним способом, что помогает избежать ошибок подключения.

Схема подключения шагового двигателя 28BYJ-48 и драйвера ULN2003 к Arduino

Теперь давайте подключим двигатель к Arduino. Подключение простое и понятное.

Сначала подключите выводы IN1, IN2, IN3 и IN4 платы драйвера к цифровым выводам 8, 9, 10 и 11 Arduino. Затем вставьте двигатель 28BYJ-48 в разъём для двигателя на плате драйвера ULN2003.

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

Наконец, убедитесь, что схема и Arduino имеют общую землю.

Вот краткая справочная таблица подключений выводов:

ULN2003 DriverArduino
IN18
IN29
IN310
IN411
GNDGND

На этой схеме показано, как именно всё подключить:

Управление шаговым двигателем 28BYJ-48 с драйвером ULN2003 и Arduino

Пример кода Arduino 1 — использование встроенной библиотеки Stepper

В этом первом примере мы будем использовать библиотеку Stepper, которая поставляется вместе с Arduino IDE. Эта библиотека выполняет всю сложную работу по формированию последовательностей шагов за вас, значительно упрощая управление как униполярными, так и биполярными шаговыми двигателями.

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

//Includes the Arduino Stepper Library
#include <Stepper.h>

// Defines the number of steps per rotation
const int stepsPerRevolution = 2048;

// Creates an instance of stepper class
// Pins entered in sequence IN1-IN3-IN2-IN4 for proper step sequence
Stepper myStepper = Stepper(stepsPerRevolution, 8, 10, 9, 11);

void setup() {
  // Nothing to do (Stepper Library sets pins as outputs)
}

void loop() {
  // Rotate CW slowly at 5 RPM
  myStepper.setSpeed(5);
  myStepper.step(stepsPerRevolution);
  delay(1000);

  // Rotate CCW quickly at 10 RPM
  myStepper.setSpeed(10);
  myStepper.step(-stepsPerRevolution);
  delay(1000);
}

Объяснение кода

Давайте разберём, как работает эта программа.

Скетч начинается с подключения библиотеки Stepper. Эта библиотека предоставляет нам доступ к функциям, помогающим управлять шаговыми двигателями.

#include <Stepper.h>

Далее мы сообщаем Arduino, сколько шагов необходимо нашему двигателю для одного полного оборота, что в данном случае составляет 2048 шагов.

const int stepsPerRevolution = 2048;

После этого мы создаём объект класса Stepper. Мы передаём этому объекту две части информации: количество шагов на оборот и номера выводов Arduino, подключённых к плате драйвера двигателя.

Вы можете заметить необычный порядок выводов — IN1, IN3, IN2, IN4 — вместо ожидаемого (IN1, IN2, IN3, IN4). Это потому, что двигатель 28BYJ-48 следует специальной последовательности шагов: IN1-IN3-IN2-IN4. Если выводы указаны в неправильном порядке, двигатель может работать некорректно или вообще не работать.

Stepper myStepper = Stepper(stepsPerRevolution, 8, 10, 9, 11);

Функция setup() в нашей программе пуста. Обычно в этой функции мы настраиваем выводы для использования, но библиотека Stepper автоматически настраивает выводы за нас, поэтому нам не нужно ничего сюда добавлять.

void setup() {
}

В функции loop() мы сначала устанавливаем скорость двигателя с помощью setSpeed(). Затем используем функцию step(), чтобы указать двигателю, сколько шагов нужно сделать. Если число, переданное в step(), положительное, двигатель вращается по часовой стрелке. Если отрицательное — против часовой стрелки.

Таким образом, в нашей программе двигатель сначала медленно вращается по часовой стрелке со скоростью 5 об/мин в течение 2048 шагов (один полный оборот). Затем он ждёт одну секунду. После этого он вращается быстрее в противоположном направлении со скоростью 10 об/мин ещё 2048 шагов. Весь процесс повторяется бесконечно.

void loop() {
  // Rotate CW slowly at 5 RPM
  myStepper.setSpeed(5);
  myStepper.step(stepsPerRevolution);
  delay(1000);

  // Rotate CCW quickly at 10 RPM
  myStepper.setSpeed(10);
  myStepper.step(-stepsPerRevolution);
  delay(1000);
}

Важно понимать, что функция step() является блокирующей. Это означает, что когда вы приказываете двигателю сделать определённое количество шагов, Arduino останавливается и ждёт, пока все шаги не будут выполнены, прежде чем перейти к следующей инструкции. Например, если вы установите скорость 1 об/мин и прикажете двигателю сделать один полный оборот (2048 шагов), Arduino будет стоять целую минуту, прежде чем перейти к следующей строке кода.

Пример кода Arduino 2 — использование библиотеки AccelStepper

Встроенная библиотека Stepper для Arduino отлично подходит для простых проектов с одним двигателем. Однако если вам нужно управлять несколькими шаговыми двигателями одновременно или вы хотите более плавное движение с ускорением и замедлением, вам понадобится что-то более продвинутое.

Вот тут на помощь приходит библиотека AccelStepper! Эта мощная библиотека специально разработана для более сложного управления шаговыми двигателями. В отличие от базовой библиотеки Stepper, AccelStepper может:

  • Управлять несколькими шаговыми двигателями одновременно, с независимым пошаговым движением каждого.

  • Поддерживать ускорение и замедление.

  • Поддерживать полушаговый режим для более плавного и точного перемещения.

Поскольку эта библиотека не входит в стандартную поставку Arduino IDE, вам нужно установить её перед использованием.

Установка библиотеки

Для установки библиотеки:

  1. Сначала откройте Arduino IDE. Затем нажмите на значок Менеджер библиотек на левой боковой панели.

  2. Введите «accelstepper» в поле поиска для фильтрации результатов.

  3. Найдите библиотеку AccelStepper от Mike McCauley.

  4. Нажмите кнопку Install, чтобы добавить её в Arduino IDE.

Управление шаговым двигателем 28BYJ-48 с драйвером ULN2003 и Arduino

Код Arduino

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

// Include the AccelStepper Library
#include <AccelStepper.h>

// Define step constant
#define MotorInterfaceType 4

// Creates an instance
// Pins entered in sequence IN1-IN3-IN2-IN4 for proper step sequence
AccelStepper myStepper(MotorInterfaceType, 8, 10, 9, 11);

void setup() {
  // set the maximum speed, acceleration factor,
  // initial speed and the target position
  myStepper.setMaxSpeed(1000.0);
  myStepper.setAcceleration(50.0);
  myStepper.setSpeed(200);
  myStepper.moveTo(2048);
}

void loop() {
  // Change direction once the motor reaches target position
  if (myStepper.distanceToGo() == 0)
    myStepper.moveTo(-myStepper.currentPosition());

  // Move the motor one step
  myStepper.run();
}

Объяснение кода

Скетч начинается с подключения только что установленной библиотеки AccelStepper.

#include <AccelStepper.h>

Затем мы определяем тип интерфейса двигателя. Поскольку мы используем 4-проводной шаговый двигатель в режиме полного шага, мы устанавливаем эту константу равной 4. Если вам нужно более плавное движение, вы можете использовать полушаговый режим, изменив это значение на 8.

#define MotorInterfaceType 4

Далее мы создаём объект класса AccelStepper. При его настройке мы предоставляем две части информации: тип интерфейса двигателя, который мы только что определили, и выводы Arduino, подключённые к плате драйвера двигателя.

Как и в первом примере, мы используем специальную последовательность выводов IN1-IN3-IN2-IN4 (подключённых к выводам Arduino 8, 10, 9 и 11). Помните, этот необычный порядок необходим, потому что двигатель 28BYJ-48 требует именно такую последовательность для правильной работы. Если выводы расположены неправильно, двигатель может работать некорректно или вообще не работать.

AccelStepper myStepper(MotorInterfaceType, 8, 10, 9, 11);

В функции setup() мы настраиваем несколько важных параметров:

  • setMaxSpeed() устанавливает максимальную скорость, которую двигатель может достичь

  • setAcceleration() управляет тем, как быстро двигатель ускоряется или замедляется — это помогает создать плавное движение вместо резких рывков

  • setSpeed() устанавливает начальную скорость

  • moveTo() указывает двигателю первую целевую позицию, которая в данном случае составляет 2048 шагов (один полный оборот для 28BYJ-48)

void setup() {
  myStepper.setMaxSpeed(1000.0);
  myStepper.setAcceleration(50.0);
  myStepper.setSpeed(200);
  myStepper.moveTo(2048);
}

Теперь в функции loop() мы проверяем, достиг ли двигатель целевой позиции, используя distanceToGo(). Когда это значение становится равным нулю, это означает, что двигатель достиг пункта назначения. В этот момент мы меняем направление двигателя, устанавливая новую цель, противоположную текущей позиции. Это заставляет двигатель двигаться вперёд и назад бесконечно, меняя направление после каждого полного оборота.

В конце цикла мы вызываем функцию run(). Это крайне важно! В отличие от базовой библиотеки Stepper, где двигатель начинает двигаться сразу при вызове step(), библиотека AccelStepper работает по-другому. Вы должны вызывать run() многократно, чтобы двигатель действительно двигался. Если вы забудете этот шаг, ваш двигатель не сделает ничего, даже если вы установили скорость и цель.

void loop() {
  // Change direction once the motor reaches target position
  if (myStepper.distanceToGo() == 0)
    myStepper.moveTo(-myStepper.currentPosition());

  // Move the motor one step
  myStepper.run();
}

Пример кода Arduino 3 — одновременное управление двумя шаговыми двигателями 28BYJ-48

В этом третьем примере мы будем одновременно управлять двумя шаговыми двигателями 28BYJ-48. Это сложно сделать с базовой библиотекой Stepper, но становится гораздо проще при использовании более мощной библиотеки AccelStepper.

Схема подключения

Для начала нам нужно добавить второй шаговый двигатель 28BYJ-48 к нашей установке. Каждый двигатель требует своей платы драйвера ULN2003. Для второго драйвера подключите VCC к выводу 5V и GND к выводу заземления на отдельном источнике питания. Затем подключите четыре управляющих входа IN1–IN4 к выводам Arduino 4, 5, 6 и 7. Теперь оба двигателя подключены и готовы к работе.

В следующей таблице перечислены подключения выводов:

ULN2003 Driver 1Arduino
IN18
IN29
IN310
IN411
GNDGND
ULN2003 Driver 2Arduino
IN14
IN25
IN36
IN47
GNDGND

На изображении ниже показано, как собрать схему.

Управление шаговым двигателем 28BYJ-48 с драйвером ULN2003 и Arduino

Код Arduino

Вот скетч, который запускает один двигатель в полушаговом режиме, а другой — в режиме полного шага. Оба двигателя сначала ускоряются, затем замедляются. После завершения полного оборота каждый двигатель изменит направление и повторит процесс.

// Include the AccelStepper Library
#include <AccelStepper.h>

// Define step constants
#define FULLSTEP 4
#define HALFSTEP 8

// Creates two instances
// Pins entered in sequence IN1-IN3-IN2-IN4 for proper step sequence
AccelStepper stepper1(HALFSTEP, 8, 10, 9, 11);
AccelStepper stepper2(FULLSTEP, 4, 6, 5, 7);

void setup() {
  // set the maximum speed, acceleration factor,
  // initial speed and the target position for motor 1
  stepper1.setMaxSpeed(1000.0);
  stepper1.setAcceleration(50.0);
  stepper1.setSpeed(200);
  stepper1.moveTo(2048);

  // set the same for motor 2
  stepper2.setMaxSpeed(1000.0);
  stepper2.setAcceleration(50.0);
  stepper2.setSpeed(200);
  stepper2.moveTo(-2048);
}

void loop() {
  // Change direction once the motor reaches target position
  if (stepper1.distanceToGo() == 0)
    stepper1.moveTo(-stepper1.currentPosition());
  if (stepper2.distanceToGo() == 0)
    stepper2.moveTo(-stepper2.currentPosition());

  // Move the motor one step
  stepper1.run();
  stepper2.run();
}

Объяснение кода

Сначала мы подключаем библиотеку AccelStepper, как и в предыдущем примере.

#include <AccelStepper.h>

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

#define FULLSTEP 4
#define HALFSTEP 8

Далее мы создаём два отдельных объекта AccelStepper, по одному для каждого двигателя. При настройке первого двигателя мы указываем полушаговый режим и подключаем его к выводам Arduino 8, 10, 9 и 11, используя правильную последовательность для двигателя 28BYJ-48 (IN1-IN3-IN2-IN4). Для второго двигателя мы используем режим полного шага и подключаем его к выводам 4, 6, 5 и 7, также в правильной последовательности.

AccelStepper stepper1(HALFSTEP, 8, 10, 9, 11);
AccelStepper stepper2(FULLSTEP, 4, 6, 5, 7);

В функции setup() мы настраиваем несколько важных параметров для обоих двигателей:

  • Устанавливаем максимальную скорость 1000 шагов в секунду для обоих двигателей

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

  • Устанавливаем начальную скорость для каждого двигателя с помощью setSpeed()

  • Задаём каждому двигателю свою целевую позицию с помощью moveTo()

Поскольку двигатель 28BYJ-48 требует 2048 шагов для одного полного оборота, мы используем это число как целевое значение. Чтобы второй двигатель вращался в противоположном направлении от первого, мы просто используем -2048 в качестве его цели.

void setup() {
  // settings for motor 1
  stepper1.setMaxSpeed(1000.0);
  stepper1.setAcceleration(50.0);
  stepper1.setSpeed(200);
  stepper1.moveTo(2048);

  // settings for motor 2
  stepper2.setMaxSpeed(1000.0);
  stepper2.setAcceleration(50.0);
  stepper2.setSpeed(200);
  stepper2.moveTo(-2048);
}

В функции loop() мы используем два отдельных оператора if — по одному для каждого двигателя — чтобы проверить, достиг ли каждый двигатель своего пункта назначения. Мы делаем это, проверяя, равно ли distanceToGo() нулю, что означает, что двигатель достиг целевой позиции. Когда это происходит, мы меняем направление двигателя, устанавливая новую цель, противоположную текущей позиции. Таким образом, двигатель продолжает двигаться вперёд и назад, совершая один полный оборот в каждом направлении снова и снова.

В конце цикла мы вызываем функцию run() для обоих двигателей. Этот шаг абсолютно необходим — без него ни один двигатель не будет двигаться, даже если вы установили скорости и цели. Вы должны продолжать вызывать run() внутри цикла, чтобы двигатели действительно вращались.

void loop() {
  // Change direction once the motor reaches target position
  if (stepper1.distanceToGo() == 0)
    stepper1.moveTo(-stepper1.currentPosition());
  if (stepper2.distanceToGo() == 0)
    stepper2.moveTo(-stepper2.currentPosition());

  // Move the motor one step
  stepper1.run();
  stepper2.run();
}