Управление биполярным шаговым двигателем при помощи инкрементального (инкрементного) энкодера EC11, Arduino Nano и DRW8825
Для проекта используется:
Плата Arduino Nano, инкрементальный (инкрементный) энкодер EC11, драйвер для шагового двигателя DRV8825, макетная плата, соединительные провода, и биполярный шаговый двигатель Mitsumi.
//Начало скетча для теста контактов энкодера
void setup()
{
Serial.begin(9600);
pinMode( 2, OUTPUT); digitalWrite( 2, HIGH);
pinMode( 3, INPUT);
pinMode( 4, INPUT);
pinMode( 5, INPUT);
}
void loop()
{
int sw = digitalRead(3);
int clk = digitalRead(5);
int dt = digitalRead(4);
Serial.print("SW="); Serial.print(sw);
delay(10);
Serial.print(" CLK="); Serial.print(clk);
delay(10);
Serial.print(" DT="); Serial.println(dt);
delay(100);
}
//Конец скетча для теста контактов энкодера
После загрузки скетча для теста контактов энкодера, можно подключать энкодер к плате Arduino Nano, как показано на этой схеме.
Этот вариант кода, не отключает драйвер шагового двигателя, то есть после завершения вращения продолжается подача питания на шаговый двигатель, таким образом происходит потребление энергии, но зато таким образом, вал шагового двигателя жестко удерживается.
Внимание! Если при удержании вала шаговый двигатель нагревается более чем на 50 градусов, то следует уменьшить подачу тока, немного повернув регулятор на драйвере шагового двигателя, по часовой стрелке (для DRW8825)!
При использовании драйвера шагового двигателя A4988, уменьшение тока происходит при вращении регулятора против часовой стрелки!
//Начало первого варианта кода
const int stepPin = 11;
const int enablePin = 12;
const int dirPin = 13;
const int plus = 2;
const int sw = 3;
const int dt = 4;
const int clk = 5;
int state_SW = 0;
int state_DT = 0;
int state_CLK = 0;
int i = 0, j = 0, steps = 0;
int limit, limit_1 = 1, limit_2 = 5;
void setup()
{
Serial.begin(9600);
pinMode( plus, OUTPUT); digitalWrite( 2, HIGH);
pinMode( sw, INPUT);
pinMode( dt, INPUT);
pinMode( clk, INPUT);
pinMode( stepPin, OUTPUT); digitalWrite( stepPin, LOW);
pinMode( enablePin, OUTPUT); digitalWrite( enablePin, LOW);
pinMode( dirPin, OUTPUT); digitalWrite( dirPin, LOW);
}
void loop()
{
state_SW = digitalRead(sw);
state_DT = digitalRead(dt);
state_CLK = digitalRead(clk);
if (state_SW == LOW) {
limit = limit_2;
} else {
limit = limit_1;
}
if ((state_DT == HIGH) && (state_CLK == LOW) && (i == 0) && (j == 0)) {
i = 1;
}
if ((state_DT == LOW) && (state_CLK == LOW) && (i == 1) && (j == 0)) {
i = 2;
}
if ((state_DT == LOW) && (state_CLK == HIGH) && (i == 2) && (j == 0)) {
i = 3;
}
if ((state_DT == HIGH) && (state_CLK == HIGH) && (i == 3) && (j == 0)) {
i = 0;
Serial.println("Step +");
steps = limit; digitalWrite( dirPin, HIGH);
}
if ((state_DT == LOW) && (state_CLK == HIGH) && (j == 0) && (i == 0)) {
j = 1;
}
if ((state_DT == LOW) && (state_CLK == LOW) && (j == 1) && (i == 0)) {
j = 2;
}
if ((state_DT == HIGH) && (state_CLK == LOW) && (j == 2) && (i == 0)) {
j = 3;
}
if ((state_DT == HIGH) && (state_CLK == HIGH) && (j == 3) && (i == 0)) {
j = 0;
Serial.println("Step -");
steps = limit; digitalWrite( dirPin, LOW);
}
if (steps > 0) {
steps--;
digitalWrite( stepPin, HIGH); delay(5);
digitalWrite( stepPin, LOW);
}
}
//Конец первого варианта кода
Этот вариант кода более оптимизированный, но драйвер шагового двигателя отключается через пол секунды после завершения вращения вала. Таким образом отключается подача питания на шаговый двигатель, это снизит расход энергии, но и отключит момент удержания вала.
//Начало второго варианта кода
const int stepPin = 11; //Контакт для подключения к Step
const int enablePin = 12; //Контакт для подключения к Enable
const int dirPin = 13; //Контакт для подключения к Dir
const int plus = 2; //Контакт для подачи питания на энкодер
const int sw = 3; //Контакт для подключения кнопки энкодера
const int dt = 4; //Контакт для подключения линии энкодера DT
const int clk = 5; //Контакт для подключения линии энкодера CLK
int state_SW = 0; //Переменная для хранения состояния кнопки энкодера
int state_DT = 0; //Переменная для хранения состояния линии энкодера DT
int state_CLK = 0; //Переменная для хранения состояния линии энкодера CLK
int steps = 0; //Переменная для хранения количества шагов, которые надо выполнить
int limit, limit_1 = 1, limit_2 = 5; //Переменные задающие количество шагов
unsigned long saveMillis = 0; //Переменная для хранения значения времени
void setup()
{
//Подключение к шине UART (Может пригодиться для отладки кода)
//Serial.begin(9600);
pinMode( plus, OUTPUT); //Назначить контакт plus как выход
digitalWrite( plus, HIGH); //Задать высокий уровень контакту plus
pinMode( sw, INPUT); //Назначить контакт sw как вход
pinMode( dt, INPUT); //Назначить контакт dt как вход
pinMode( clk, INPUT); //Назначить контакт clk как вход
pinMode( stepPin, OUTPUT); //Назначить контакт stepPin как выход
digitalWrite( stepPin, LOW); //Задать низкий уровень контакту stepPin
pinMode( enablePin, OUTPUT); //Назначить контакт enablePin как выход
pinMode( dirPin, OUTPUT); //Назначить контакт dirPin как выход
digitalWrite( dirPin, LOW); //Задать низкий уровень контакту dirPin
state_CLK = digitalRead(clk); //Считывает начальное состояние входа clk
}
void loop()
{
state_SW = digitalRead(sw); //Считывает текущее состояние выхода sw
state_DT = digitalRead(dt); //Считывает текущее состояние выхода dt
if (state_SW == LOW) {
limit = limit_2; //Если кнопка энкодера нажата, то добавлять по 5 шагов
} else {
limit = limit_1; //Если кнопка энкодера не нажата, то прибавлять по 1 шагу
}
//Если прошло более чем пол секунды после того как вращался шаговый двигатель
//то задать высокий уровень контакту enablePin, то есть выключить драйвер шагового двигателя
if (millis() - saveMillis > 500) { digitalWrite( enablePin, HIGH);}
// Если предыдущее и текущее состояние входа dt различаются, это означает, что произошел импульс
if (state_DT != state_CLK){
// Если состояние входа clk отличается от состояния выхода dt, это означает, что энкодер вращается по часовой
if (digitalRead(clk) != state_DT) {
//Serial.println("Step +"); //Сообшить в порт UART о свершившемся событии
steps = limit; //К переменной steps прибавить количество шагов
digitalWrite( dirPin, HIGH); //Задать высокий уровень контакту dirPin
digitalWrite( enablePin, LOW);//Задать низкий уровень контакту enablePin (включить драйвер ШД)
saveMillis = millis(); //Запомнить текущее время
} else {
//Serial.println("Step -"); //Сообшить в порт UART о свершившемся событии
steps = limit; //К переменной steps прибавить количество шагов
digitalWrite( dirPin, LOW); //Задать низкий уровень контакту dirPin
digitalWrite( enablePin, LOW);//Задать низкий уровень контакту enablePin (включить драйвер ШД)
saveMillis = millis(); //Запомнить текущее время
}
}
state_CLK = state_DT; // Обновляет предыдущее состояние входа clk текущим состоянием
if (steps > 0) { //Если имеются шаги, то выполнить 1 шаг
steps--; //Отнять 1 шаг их общего количества
digitalWrite( stepPin, HIGH); //Задать высокий уровень контакту stepPin
delay(5); //Выполнить паузу 5 миллисекунд
digitalWrite( stepPin, LOW); //Задать низкий уровень контакту stepPin
}
}
//Конец второго варианта кода
После загрузки скетча можно собрать все, как показано на этой схеме.