Управляем шаговым двигателем с помощью Arduino

Когда-то совсем давно в мои руки попался ДШ MDrive17 со встроенным контроллером, который позволял управлять им по средствам интерфейса RS-422 с компьютера, например, и, даже, предварительно программировать «мозги» двигателя. Но двигатель «казенный», поэтому не годится для применения в личных проектах.( Поэтому еще в начале постройки ЧПУ станка, я приобрел маломощный ДШ 200-0,08, что бы немного поупражняться в этой теме. И вот, пока основные двигатели и электроника еще в пути, а с механикой практически все закончено, есть время для экспериментов.

Итак, ДШ 200-0,08 — биполярный двигатель, имеет 4 провода для подключения.  Поэтому можно ограничится драйвером L298. В принципе, это минимальный набор для подключения шаговика.  Главный минус такого подхода — это необходимость задействования 4-х выходов микроконтроллера с ШИМ’ом. То есть к моей нано больше одного не привязать… Но для экспериментов можно использовать, а можно и сделать, в последствии, интегрированный контроллер для каждого двигателя.) ДШ питается от 12В, и потребляет 2А, при этом разогревая L298  до 50°С.

Все элементы я смонтировал на макетной плате и занялся программированием. Для начала открыл пример stepper_oneRevolution из набора примеров Arduino IDE. Прошил его и убедился. что подключено все правильно и ДШ работает. Следующая задача — научится управлять двигателем простыми командами с терминала. В упрощенном виде, все управление сводится к установке скорости и направления движения, а так же количества шагов, которые должен сделать ДШ в заданном направлении. В IDE уже имеется библиотека <Stepper.h>, которая применяется в sample,  предлагаю ей воспользоваться и в своем скетче. Да это не «тру», но позволит сэкономить существенное время, тем более искусство управления двигателем 4-мя выводами МК само по себе вряд ли стоит того.

Установка скорости будет выглядеть так: сперва посылаем в терминал символ «S» — устанавливается флаг команды установки скорости, далее МК ждет последовательность из трех символов, если она «верна», то есть может быть преобразована в число отличное от нуля, например «200», то устанавливается новая скорость ДШ, с помощью библиотечной функции myStepper.setSpeed(200). Иначе выводится информация об ошибке.

Для начала вращения следует послать в терминал последовательность: символ «C» — сообщение о начале команды движения, после которой МК ожидает пять символов. Первый показывает направления движения «F» — нормальное, «B» — обратное. Последующие 4-е символа представляют собой количество шагов. Если первый символ в последовательности будет отличный от указанных, то команда не будет выполнена, и выведется сообщение об ошибке. Иначе ДШ повернет вал на указанное число шагов. Скриншот терминала при работе представлен ниже:

А теперь предлагаю посмотреть сам скетч:

#include <Stepper.h> // подключаем библиотеку управления ДШ 
 
const int stepsPerRevolution = 200;  // только для инициализации
 
// инициализируем пины подключения ДШ библиотечной функцией
Stepper myStepper(stepsPerRevolution, 8,9,10,11);   
 
// массивы перемен
char stepMas[4]; // массив разрядов шага
char speedMas[3]; // массив разрядов скорости
char CurChar; // текущий символ
char Com_strt = 0; // флаг начала команды движения
char Com_Speed = 0; // флаг начала команды установки скорости
const int Speed_default = 100; // скорость по умолчанию
int Speed_rev = 0; // установленная скорость
int NSteps = 0; // количество шагов
char Dir; //направление 
 
void setup() {
  // установка скорости по умолчанию
  myStepper.setSpeed(Speed_default);
  // инициализация UART
  Serial.begin(9600);
}
 
// бесконечный цикл
void loop() {
  /* если есть символ в UART и установлен флаг
  начала команды движения или установки скорости*/
  if ((Serial.available() > 0)&&(Com_strt == 0)&&
      (Com_Speed == 0)) {
    //читаем байт из порта
    CurChar = Serial.read();
    //если это символ С то устанавливаем флаг начала команды движения
    if (CurChar == 'C') {
      Com_strt = 1;
      Serial.println("Comand start / Ok!");
    } else {
      //если это символ S то устанавливаем флаг начала команды установки скорости
      if (CurChar == 'S') {
        Com_Speed = 1;
        Serial.println("Set speed / Ok!");
      }
    }
  }  
 
  /*если в порту больше 2-х символов и установлен
  флаг начала команды установки скорости*/
  if ((Serial.available() > 2)&&(Com_Speed == 1)) {
    // сбрасываем флаг
    Com_Speed = 0;
    Serial.print("Speed: ");
    //читаем последовательность из 3-х символов в массив
    for (int i=0; i<3; i++) {
      speedMas[i] = Serial.read();
    }
    //конвертируем массив байт в целое
    Speed_rev = atoi(speedMas);
    //если целое больше нули, то устанавливаем новую скорость
    if (Speed_rev > 0) {
      myStepper.setSpeed(Speed_rev);
      Serial.println(Speed_rev);
      Serial.println("New speed / Ok!");
    } else {
      // если нет, то выводим сообщение об ошибке
      Serial.println("Set speed ERROR! ");
    }
    Serial.println("/--------------------------------------/");
  }
 
  /*если в порту больше 4-х символов и установлен
  флаг начала команды движения*/
  if ((Serial.available() > 4)&&(Com_strt == 1)) {
    // сбрасываем флаг команды движения
    Com_strt = 0;
    Serial.println("Motion");
    //чтьаем байт направления
    Dir = Serial.read();
 
    //читаем байты в массив
    for (int i=0; i<4; i++) {
      stepMas[i] = Serial.read();
    }
    Serial.print("Steps: "
    );
    // переводим массив байт в число шагов
    NSteps = ((int)stepMas[0]-48)*1000+((int)stepMas[1]-48)*100+
    ((int)stepMas[2]-48)*10+((int)stepMas[3]-48);
    Serial.println(NSteps);
    //если символ F то направление нормальное
    if (Dir == 'F') {
      Serial.println("Dir: front");
      //делаем Nsteps шагов в нормальном направлении
      myStepper.step(NSteps);
      Serial.println("Comand end / Ok!");
    } else {
      //если символ B то вращаем назад
      if (Dir == 'B') {
        Serial.println("Dir: back");
        //делаем Nsteps шагов в обратном направлении
        myStepper.step(-NSteps);
        Serial.println("Comand end / Ok!");
      } else {
        //если Dir - другой символ, то ошибка команды
        Serial.println("Comand ERROR!");
      }
 
    }
    Dir = 0;
    Serial.println("/--------------------------------------/");
  }
}
#include <Stepper.h> // подключаем библиотеку управления ДШ 

const int stepsPerRevolution = 200;  // только для инициализации

// инициализируем пины подключения ДШ библиотечной функцией
Stepper myStepper(stepsPerRevolution, 8,9,10,11);   

// массивы перемен
char stepMas[4]; // массив разрядов шага
char speedMas[3]; // массив разрядов скорости
char CurChar; // текущий символ
char Com_strt = 0; // флаг начала команды движения
char Com_Speed = 0; // флаг начала команды установки скорости
const int Speed_default = 100; // скорость по умолчанию
int Speed_rev = 0; // установленная скорость
int NSteps = 0; // количество шагов
char Dir; //направление 

void setup() {
  // установка скорости по умолчанию
  myStepper.setSpeed(Speed_default);
  // инициализация UART
  Serial.begin(9600);
}

// бесконечный цикл
void loop() {
  /* если есть символ в UART и установлен флаг
  начала команды движения или установки скорости*/
  if ((Serial.available() > 0)&&(Com_strt == 0)&&
      (Com_Speed == 0)) {
    //читаем байт из порта
    CurChar = Serial.read();
    //если это символ С то устанавливаем флаг начала команды движения
    if (CurChar == 'C') {
      Com_strt = 1;
      Serial.println("Comand start / Ok!");
    } else {
      //если это символ S то устанавливаем флаг начала команды установки скорости
      if (CurChar == 'S') {
        Com_Speed = 1;
        Serial.println("Set speed / Ok!");
      }
    }
  }  

  /*если в порту больше 2-х символов и установлен
  флаг начала команды установки скорости*/
  if ((Serial.available() > 2)&&(Com_Speed == 1)) {
    // сбрасываем флаг
    Com_Speed = 0;
    Serial.print("Speed: ");
    //читаем последовательность из 3-х символов в массив
    for (int i=0; i<3; i++) {
      speedMas[i] = Serial.read();
    }
    //конвертируем массив байт в целое
    Speed_rev = atoi(speedMas);
    //если целое больше нули, то устанавливаем новую скорость
    if (Speed_rev > 0) {
      myStepper.setSpeed(Speed_rev);
      Serial.println(Speed_rev);
      Serial.println("New speed / Ok!");
    } else {
      // если нет, то выводим сообщение об ошибке
      Serial.println("Set speed ERROR! ");
    }
    Serial.println("/--------------------------------------/");
  }

  /*если в порту больше 4-х символов и установлен
  флаг начала команды движения*/
  if ((Serial.available() > 4)&&(Com_strt == 1)) {
    // сбрасываем флаг команды движения
    Com_strt = 0;
    Serial.println("Motion");
    //чтьаем байт направления
    Dir = Serial.read();

    //читаем байты в массив
    for (int i=0; i<4; i++) {
      stepMas[i] = Serial.read();
    }
    Serial.print("Steps: "
    );
    // переводим массив байт в число шагов
    NSteps = ((int)stepMas[0]-48)*1000+((int)stepMas[1]-48)*100+
    ((int)stepMas[2]-48)*10+((int)stepMas[3]-48);
    Serial.println(NSteps);
    //если символ F то направление нормальное
    if (Dir == 'F') {
      Serial.println("Dir: front");
      //делаем Nsteps шагов в нормальном направлении
      myStepper.step(NSteps);
      Serial.println("Comand end / Ok!");
    } else {
      //если символ B то вращаем назад
      if (Dir == 'B') {
        Serial.println("Dir: back");
        //делаем Nsteps шагов в обратном направлении
        myStepper.step(-NSteps);
        Serial.println("Comand end / Ok!");
      } else {
        //если Dir - другой символ, то ошибка команды
        Serial.println("Comand ERROR!");
      }

    }
    Dir = 0;
    Serial.println("/--------------------------------------/");
  }
}

Считаю, что комментариев к коду достаточно.) По сути, получилось весьма урезанная версия MDrive. Чуть позднее посмотрю, что еще можно выжать из данного двигателя и arduino.

Запись опубликована в рубрике AVR, ЧПУ. Добавьте в закладки постоянную ссылку.

         
Подписаться на новые статьи блога:

9 комментариев: Управляем шаговым двигателем с помощью Arduino

  1. Данила говорит:

    В функции ввода скорости «Speed_rev = atoi(speedMas);» что за функция atoi? В руководстве не нашел.

    • Delirium говорит:

      atoi() конвертирует строку ASCII (или массив байт, как написано в комментарии) в целое число.

      • Данила говорит:

        А почему тогда для направления и дальности используется конструкция:
        NSteps = ((int)stepMas[0]-48)*1000+((int)stepMas[1]-48)*100+
        ((int)stepMas[2]-48)*10+((int)stepMas[3]-48);

        • Delirium говорит:

          Еще один способ перевода. ANCII коды цифр начинаются с 48 (для 0) и идут подряд до 57 (для 9), что и позволяет составить такое выражение и воспользоваться им. Почему я этот способ применил тут, а на atoi(), я уже не помню.)

  2. Михаил говорит:

    не могу запустить двигатель, постоянно пишет ошибку в кол-ве шагов.
    Ввожу: S-> 100-> C->F0500 и постоянно вылезает вот такое сообщение:
    Comand start / Ok!
    Motion
    Steps: 22123
    Comand ERROR!

    В коде черным по-русски написано что 5 умножается на 100 и плюсуется с нулями.
    Вопрос: от куда он берет такие большие числа?

  3. Артем говорит:

    а на какие выводы подключать к ардуино, их как-то инициализировать надо?

    • Delirium говорит:

      Собстно, в коде приведенном есть ответ:
      // инициализируем пины подключения ДШ библиотечной функцией
      Stepper myStepper(stepsPerRevolution, 8,9,10,11);
      Номера выводов конечно можно менять.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Лимит времени истёк. Пожалуйста, перезагрузите CAPTCHA.