Arduino, шаговый двигатель 28-BYJ48 и драйвер ULN2003

Шаговый двигатель - это мотор, который управляется несколькими электромагнитными катушками.

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

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

В данной статье мы рассмотрим работу униполярного шагового двигателя 28-BYJ48 с драйвером ULN2003.

Шаговый двигатель 28-BYJ48
Шаговый двигатель 28-BYJ48 и драйвер ULN2003

Униполярные шаговые двигатели имеют пять или шесть контактов для подключения и четыре электромагнитные катушки в корпусе (если быть более точными, то две катушки, разделенные на четыре). Центральные контакты катушек соединены вместе и используются для подачи питания на двигатель. Эти шаговые моторы называются униполярными, потому-что питание всегда подается на один из этих полюсов.

Спецификация и драйвер шагового двигателя

Существуют разные модели драйверов (контроллеров) шаговых двигателей. Среди них можно выделить самые популярные в DIY разработках на базе Arduino: L293, ULN2003, A3967SLB.

Как правило, шаговый двигатель 28-BYJ48 используют в паре с драйвером ULN2003.

Спецификацию шагового двигателя 28-BYJ48 на английском языке вы можете скачать здесь. Краткие выдержки основных технических характеристик приведены ниже:

  • Напряжение питания: 5 В (постоянный ток);
  • Количество фаз: 4;
  • Количество шагов: 64;
  • Угол поврота на один шаг: 5.625 градуса
  • Частота: 100 Герц;
  • Частота холостого хода по часовой стрелке: > 600 Герц;
  • Частота холостого хода против часовой стрелки: > 1000 Герц;
  • Крутящий момент > 34.3 миллиньютон на метр;
  • Сопротивление вращению: 600-1200 грамм на сантиметр;
  • Класс элетробезопасности: A;

Внешний вид и схемы подключения ULN2003 приведены на изображениях ниже

Драйвер шагового двигателя ULN2003 Схема подключения ULN2003 к шаговому двигателю Схема подключения ULN2003 к Arduino и шаговому двигателю

Таблица переключения фаз на ULN2003

Примечание. Если вы захотите использовать плату L293 вместо ULN2003, красный контакт подключать не надо.

Arduino, ULN2003 и 28-BYJ48

Необходимые компоненты

Вам понадобятся:

  1. Микроконтроллер Arduino.
  2. Шаговый двигатель BYJ48 5В.
  3. Драйвер шагового двигателя ULN2003.
  4. Коннекторы.
  5. Источник питания 5v - необязательно.

Скетч для Arduino

В Arduino IDE есть встроенная библиотека для управления шаговыми двигателями. После подключения шагового двигателя, ULN2003 и Arduino, вы можете загрузить скетч из категории Examples и ...

На этом этапе возникают определенные нюансы:

У этого двигателя передаточное отношение 1:64, а угол поворота 5.625, то есть у него 4096 шагов.

Шаг = Количество шагов на один поворот * передаточное отношение.

Шаги= (360/5.625)*64"Передаточное отношение" = 64 * 64 =4096. Это значение надо учесть в скетче Arduino.

А вот угол поворота для шаговых двигателей от adafruit равен 7.5 градусов, а передаточное отношение 1:16, так что количество шагов за 1 полный оборот вала равно:

Шаги за один оборот = 360 / 7.5 = 48.

Шаги = 48 * 16 = 768

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

Модуль драйвера шагового двигателя ULN2003 подключается к Arduino контактами IN1 - IN4 к D8 - D11 соответственно.

Для подачи питания на ваш мотор, рекомендуется использовать внешний источник питания 5V с силой тока 500mA минимум. Не питайте двигатель непосредственно от контакта 5V на плате Arduino.

Проблема направления вращения в библиотеке и как ее исправить

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

step(steps);

То есть, вам надо указать в параметрах количество шагов для поворота ротора вала.

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

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

Измененный код для Arduino

Окончательная версия скетча для шагового двигателя:

/* Скетч для шагового двигателя BYJ48

Схема подключения: IN1 >> D8 IN2 >> D9 IN3 >> D10 IN4 >> D11 VCC ... 5V.

Лучше использовать внешний источник питания Gnd

Автор кода: Mohannad Rawashdeh

Детали на русском языке: /arduino-shagovii-motor-28-BYJ48-draiver-ULN2003

Англоязычный вариант: http://www.instructables.com/member/Mohannad+Rawashdeh/ 28/9/2013 */

#define IN1 8

#define IN2 9

#define IN3 10

#define IN4 11

int Steps = 0;

boolean Direction = true;

unsigned long last_time;

unsigned long currentMillis ;

int steps_left=4095;

long time;

void setup()

{

Serial.begin(115200);

pinMode(IN1, OUTPUT);

pinMode(IN2, OUTPUT);

pinMode(IN3, OUTPUT);

pinMode(IN4, OUTPUT);

// delay(1000);

}

void loop()

{

while(steps_left>0){

currentMillis = micros();

if(currentMillis-last_time>=1000){

stepper(1);

time=time+micros()-last_time;

last_time=micros();

steps_left--;

}

}

Serial.println(time);

Serial.println("Wait...!");

delay(2000);

Direction=!Direction;

steps_left=4095;

}

void stepper(int xw){

for (int x=0;x<xw;x++){

switch(Steps){

case 0:

digitalWrite(IN1, LOW);

digitalWrite(IN2, LOW);

digitalWrite(IN3, LOW);

digitalWrite(IN4, HIGH);

break;

case 1:

digitalWrite(IN1, LOW);

digitalWrite(IN2, LOW);

digitalWrite(IN3, HIGH);

digitalWrite(IN4, HIGH);

break;

case 2:

digitalWrite(IN1, LOW);

digitalWrite(IN2, LOW);

digitalWrite(IN3, HIGH);

digitalWrite(IN4, LOW);

break;

case 3:

digitalWrite(IN1, LOW);

digitalWrite(IN2, HIGH);

digitalWrite(IN3, HIGH);

digitalWrite(IN4, LOW);

break;

case 4:

digitalWrite(IN1, LOW);

digitalWrite(IN2, HIGH);

digitalWrite(IN3, LOW);

digitalWrite(IN4, LOW);

break;

case 5:

digitalWrite(IN1, HIGH);

digitalWrite(IN2, HIGH);

digitalWrite(IN3, LOW);

digitalWrite(IN4, LOW);

break;

case 6:

digitalWrite(IN1, HIGH);

digitalWrite(IN2, LOW);

digitalWrite(IN3, LOW);

digitalWrite(IN4, LOW);

break;

case 7:

digitalWrite(IN1, HIGH);

digitalWrite(IN2, LOW);

digitalWrite(IN3, LOW);

digitalWrite(IN4, HIGH);

break;

default:

digitalWrite(IN1, LOW);

digitalWrite(IN2, LOW);

digitalWrite(IN3, LOW);

digitalWrite(IN4, LOW);

break;

}

SetDirection();

}

}

void SetDirection(){

if(Direction==1){ Steps++;}

if(Direction==0){ Steps--; }

if(Steps>7){Steps=0;}

if(Steps<0){Steps=7; }

}

Видео работающего мотора приведено ниже:

Но есть и более интересный вариант - написать собственную библиотеку для шагового двигателя

Собственная библиотека для корректной работы 28BYJ-48 с ULN2003

Как уже было указано выше, стандартная библиотека Arduino для работы с шаговыми двигателями отрабатывает некорректно в связке с мотором 28BYJ-48 и драйвером ULN2003. При этом, эта модель двигателя и драйвер ULN2003 - качественная бюджетная связка для ваших проектов на Arduino.

Пример кода, рассмотренный выше, неплохой, но было бы хорошо организовать собственную отдельную библиотеку для работы с шаговым двигателем 28BYJ-48 и Arduino. Решение, представленное ниже, предполагает базовое понимание C++ и понимания принципов работы шаговых двигателей.

Шаг 1. Создаем файл StepperMotor.h

Начнем с написания класса StepperMotor.

Создайте файл с названием StepperMotor.h и скопируйте следующий код:

#ifndef Stepper_h

#define Stepper_h

class StepperMotor {

public:

StepperMotor(int In1, int In2, int In3, int In4); // конструктор, который устанавливает inputs

void setStepDuration(int duration); // Функция для установки длительности шага

void step(int noOfSteps); // Делаем указанное количество шагов. + для одного направления и - для другого

int duration; // длительность шага в мс

int inputPins[4]; // номера input пинов

};

#endif

Даже если вы не сильны в C++, объявление класса говорит само за себя.

Шаг2. Создаем файл StepperMotor.cpp

Теперь давайте напишем интерфейс класса.

Создайте файл с названием StepperMotor.cpp вставьте в него код, представленный ниже.

#include <Arduino.h>

#include <StepperMotor.h>

StepperMotor::StepperMotor(int In1, int In2, int In3, int In4){

// Записываем номера пинов в массив inputPins

this->inputPins[0] = In1;

this->inputPins[1] = In2;

this->inputPins[2] = In3;

this->inputPins[3] = In4;

// Проходим в цикле по массиву inputPins, устанавливая каждый из них в режим Output

for (int inputCount = 0; inputCount < 4; inputCount++){

pinMode(this->inputPins[inputCount], OUTPUT);

}

duration = 50;

}

void StepperMotor::setStepDuration(int duration){

this->duration = duration;

}

void StepperMotor::step(int noOfSteps){

/*

* в данном 2D массиве хранится последовательность, которая

* используется для поворота. В строках хранится шаг,

* а в столбцах - текущий input пин

*/

bool sequence[][4] = {{LOW, LOW, LOW, HIGH},

{LOW, LOW, HIGH, HIGH},

{LOW, LOW, HIGH, LOW},

{LOW, HIGH, HIGH, LOW},

{LOW, HIGH, LOW, LOW},

{HIGH, HIGH, LOW, LOW},

{HIGH, LOW, LOW, LOW},

{HIGH, LOW, LOW, HIGH}};

int factor = abs(noOfSteps) / noOfSteps; // Если noOfSteps со знаком +, factor = 1. Если noOfSteps со знаком -, factor = -1

noOfSteps = abs(noOfSteps); // Если noOfSteps был отрицательным, делаем его позитивным для дальнейших операций

/*

* В цикле ниже обрабатываем массив sequence

* указанное количество раз

*/

for(int sequenceNum = 0; sequenceNum <= noOfSteps/8; sequenceNum++){

for(int position = 0; (position < 8) && (position < (noOfSteps - sequenceNum*8)); position++){

delay(duration);

for(int inputCount = 0; inputCount < 4; inputCount++){

digitalWrite(this->inputPins[inputCount], sequence[(int)(3.5-(3.5*factor)+(factor*position))][inputCount]);

}

}

}

}

Давайте посмотрим на конструктор на строчке 4. Мы начинаем с того, что добавляем выбранные пользователем пины в массив inputinputPins в строчках 6-9. В результате мы получаем простой и интуитивно понятный доступ к номерам пинов в дальнейшем коде.

В 12 строке мы пробегаемся по массиву inputinputPins и устанавливаем для каждого режим OUTPUT.

В 15 строке мы устанавливаем длительность шага по-умолчанию равной 15 мс.

В 18 строчке у нас функция-сеттер для установки длительности шага.

Теперь давайте рассмотрим метод step. Этот метод дает возможность шаговому двигателю делать переданное методу количество шагов.

В 28 строчке мы объявляем частоту вращения с использованием 2-х мерного массива. Строки представляют шаг, столбцы - выходящие пины.

В 37 строчке рассчитывается значение переменной factor, которое равно +1 или -1 в зависимости от знака, который мы передали при указании шагов. Это значение используется для определения направления перебора массива, то есть, в результате, для изменения направления вращения.

В 38 строчке мы присваем noOfSteps переменной позитивное значение.

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

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

В 46 строчке мы устанавливаем задержку в соответствии со спецификацией.

В 47 строке мы пробегаемся по номерам пинов.

В 48 строке мы передаем цифровой сигнал на текущий номер пина.

Если переменная factor отрицательная, в 48-й строчке кода строки массива обрабатываются в противоположном порядке, то есть с низу вверх.

Доступ к библиотеке для шагового двигателя из Arduino IDE

Нам осталось добавить созданные файлы в папку библиотек Arduino IDE и мы сможем импортировать ее в любой наш проект.

Перейдите в папку:

C:\Program Files (x86)\Arduino\libraries

И создайте папку под названием StepperMotor.

Переместите созданные файлы .h и .cpp в созданную папку.

Теперь вы можете импортировать библиотеку в IDE (sketch > import library... > StepperMotor) с помощью директивы

#include <StepperMotor.h'>