Урок 29. StepMotor — библиотека управления шаговыми двигателями в системе Ардуино. Библиотека прерывания по таймеру 1 TimerOne.

Шаговый привод

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

Предыдущий урок     Список уроков     Следующий урок

Предыдущий урок был посвящен подключению униполярных шаговых двигателей к плате Ардуино и стандартной библиотеке Stepper.

 

На мой взгляд, библиотека Stepper может быть использована только для демонстрации и проверки работы двигателей. В практических приложениях применение этой библиотеки крайне ограничено из-за ряда недостатков:

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

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

 

StepMotor  - библиотека управления шаговыми двигателями в системе Ардуино.

От стандартной библиотеки Stepper мою библиотеку отличает:

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

Загрузить библиотеку StepMotor.h можно по этой ссылке:

Зарегистрируйтесь и оплатитеВсего 60 руб. в месяц за доступ ко всем ресурсам сайта!

Как установить написано в нескольких предыдущих уроках, например, в уроке 9.

Описание класса StepMotor.

Я привожу только public методы.

class StepMotor {

  public:
    StepMotor(byte pinA, byte pinB, byte pinC, byte pinD); // конструктор
    void  control();  // управление, метод должен вызываться регулярно с максимальной частотой коммутации фаз
    void  step(int steps);  // инициирует поворот двигателя на заданное число шагов
    void  setMode(byte stepMode, boolean fixStop);  // задает режимы коммутации фаз и остановки
    void  setDivider(int divider);  // установка делителя частоты для коммутации фаз
    int readSteps();  // чтение оставшихся шагов
}

Описание методов класса StepMotor.

void  control()

Метод должен вызываться регулярно в параллельном процессе. Частота вызова метода определяет частоту коммутации фаз двигателя. Делитель частоты, устанавливаемый функцией setDivider, делит именно частоту вызова control().

// обработчик прерывания
void  timerInterrupt() {
  myMotor.control(); // управление двигателем
}

void  step(int steps)

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

Запустив вращение двигателя функцией step(), например

myMotor.step(400);  // сделать 400 шагов против часовой стрелки

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

myMotor.step(0);  // остановить двигатель

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

myMotor.step(32000);  // постоянное вращение

О том, что двигатель остановился, программа может узнать с помощью функции  readSteps().

void  setMode(byte stepMode, boolean fixStop)

Метод задает режим коммутации фаз двигателя и состояние остановленного двигателя.

stepMode – режим управления двигателем.

Значение stepMode Режим
0 Шаговый
1 Полу шаговый
2 Между шаговый

О режимах коммутации  обмоток шаговых двигателей можно посмотреть по этой ссылке.

fixStop – определяет режим остановленного двигателя.

Значение fixStop Состояние двигателя в остановленном состоянии
false С обмоток снимается напряжение, двигатель разблокирован
true Через обмотки продолжает течь ток удержания, ротор находится в фиксированном положении

myMotor.setMode(0, false);  // шаговый режим, без фиксации при остановке

myMotor.setMode(1, true);  // полу  шаговый режим, с фиксацией ротора при остановке

void  setDivider(int divider)

Метод задает коэффициент деления частоты вызова функции control(), а значит, определяет скорость вращения двигателя. Для расчетов можно использовать следующую формулу:

Rpm = 60 000  /   ( divider  * Tcontrol * Nдвигателя  )

  • Rpm – скорость вращения в оборотах в минуту;
  • Tcontrol – период вызова метода control() в мс;
  • Nдвигателя – число шагов двигателя на полный оборот.

Для полу шагового режима формула несколько меняется.

Rpm = 30 000  /   ( divider  * Tcontrol * Nдвигателя  ).

Например,

myMotor.setDivider(21);     // делитель частоты 21 (при прерывании 1 мс период коммутации фаз 21 мс)

означает, что фазы будут коммутироваться через каждые 21 мс. Это соответствует скорости вращения:

Rpm = 60 000 / ( 21 * 1 * 48 ) = 59,5 об./мин или примерно один оборот в сек.

int readSteps()

Метод позволяет узнать количество шагов, оставшихся до остановки двигателя. Если он возвращает 0, то это означает, что двигатель остановился.

if (myMotor.readSteps() == 0)  {

// двигатель остановился

}

 

Примеры использования библиотеки StepMotor.

Библиотеку необходимо загрузить и установить (можно посмотреть в уроке 9).

Зарегистрируйтесь и оплатитеВсего 60 руб. в месяц за доступ ко всем ресурсам сайта!

Для проверки примеров я использовал драйвер и двигатель PM35S-048 из предыдущего урока. У двигателя 48 шагов на оборот.

Подключение двигателя к Ардуино

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

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

// программа управления шаговым двигателем с помощью библиотеки StepMotor
// двигатель вращается постоянно против часовой стрелке со скоростью 60 об. в мин
 
#include <MsTimer2.h>
#include <StepMotor.h>

StepMotor myMotor(10, 11, 12, 13);  // создаем объект типа StepMotor, задаем выводы для фаз

void setup() {
  MsTimer2::set(1, timerInterrupt); // задаем период прерывания по таймеру 1 мс
  MsTimer2::start();               // разрешаем прерывание по таймеру
  myMotor.setMode(0, false);  // шаговый режим, без фиксации при остановке
  myMotor.setDivider(21);     // делитель частоты 21 (при прерывании 1 мс период коммутации фаз 21 мс)
}

void loop() {
  myMotor.step(1000);
}

//-------------------------------------- обработчик прерывания 1 мс
void  timerInterrupt() {
  myMotor.control(); // управвление двигателем
}

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

Вот скетч аналога программы из предыдущего урока. Двигатель делает 5 оборотов против часовой стрелки, затем пауза 1 сек. Еще 5 оборотов по часовой стрелки, пауза 1 сек и так в бесконечном цикле.

// программа управления шаговым двигателем с помощью библиотеки StepMotor
// двигатель вращается против часовой срелки 5 оборотов, пауза 1 сек,
// 5 оборотов по часовой стрелке, пауза 1 сек, и так в бесконечном цикле
#include <MsTimer2.h>
#include <StepMotor.h>

StepMotor myMotor(10, 11, 12, 13);  // создаем объект типа StepMotor, задаем выводы для фаз

unsigned int timeCounter; // счетчик времени
byte md;  // режим: 0 - вращение против ч.с., 1 - пауза, 2 - вращение против ч.с., 3 - пауза

void setup() {
  MsTimer2::set(1, timerInterrupt); // задаем период прерывания по таймеру 1 мс
  MsTimer2::start();               // разрешаем прерывание по таймеру
  myMotor.setMode(0, false);  // шаговый режим, без фиксации при остановке
  myMotor.setDivider(21);     // делитель частоты 21 (при прерывании 1 мс период коммутации фаз 21 мс)
  md= 0;  // начальный режим
  myMotor.step(240);  // начальный запуск
}

void loop() {

  // управление вращением двигателя
  if (md == 0)  {
    // пять оборотов против часовой стрелки
    if (myMotor.readSteps() == 0) { md=1; timeCounter=0; }
  }
  else if (md == 1) {
    // пауза 1 сек
    if (timeCounter >= 1000)  { md=2; myMotor.step(-240); }
  }
  else if (md == 2) {
    // пять оборотов по часовой стрелке
    if (myMotor.readSteps() == 0) { md=3; timeCounter=0; }   
  }
  else {
    // пауза 1 сек
    if (timeCounter >= 1000)  { md=0; myMotor.step(240); }   
  }

}

//-------------------------------------- обработчик прерывания 1 мс
void  timerInterrupt() {
  myMotor.control(); // управление двигателем
  timeCounter++; // счетчик времени
}

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

Библиотека StepMotor отсчитывает время переключения фаз от периода вызова функции control(). Функция control() обычно вызывается прерыванием от таймера. Период прерывания определяет скорость вращения двигателя по формуле, описанной выше:

Rpm = 60 000  /   ( divider  * Tcontrol * Nдвигателя  ).

Видно, что зависимость скорости вращения от периода вызова метода control() нелинейная, с гиперболической зависимостью. Например, для двигателя из предыдущего урока (48 шагов на оборот) и периода вызова метода control() 1 мс получим следующие значения скоростей.

divider Скорость вращения, об. / мин
1 1250
2 625
3 417
4 312
5 250
6 208
7 179
8 156
. . . . . .

При малых значениях делителя divider скорость вращения задается со значительным шагом.  При увеличении коэффициента divider шаг уменьшается. Т.е. если необходима плавная регулировка скорости, следует уменьшить период вызова control() и увеличить значение делителя. А библиотека MsTimer2 позволяет формировать прерывание с минимальным периодом 1 мс. Для прерываний с меньшим периодом существует другая библиотека управления таймером.

 

Библиотека TimerOne.

Библиотека использует таймер 1 контроллера Ардуино и позволяет формировать прерывания с периодом от 1 мкс до 8,4 сек. Дискретность установки времени - 1 мкс.

Кроме того она управляет режимами ШИМ на выводах микроконтроллера, но сейчас мы будем использовать TimerOne только для формирования временных интервалов.

Работать с библиотекой достаточно просто. Загрузить ее можно по этой ссылке TimerOne-r11.zip. Как установить, написано в уроке 9.

Методы TimerOne.

void initialize(long microseconds)

Метод инициализирует таймер. Должен быть вызван прежде использования любого другого метода.

Аргумент microseconds задает период таймера в мкс. По умолчанию задана 1 сек.

Timer1.initialize(250);  // инициализация таймера 1, период 250 мкс

void setPeriod(long microseconds)

Метод устанавливает период таймера в диапазоне 1 мкс … 8,4 сек.

Timer1. setPeriod (250);  // период 250 мкс

void start()

Метод запускает таймер с нового периода. Следует использовать, если таймер был остановлен.

void stop()

Метод останавливает таймер.

void restart()

Перезапускает таймер с нового периода.

void attachInterrupt(void (*isr)(), long microseconds)

Метод вызывает функцию с заданным периодом прерывания.

Timer1.attachInterrupt(timerInterrupt, 250);  // задаем обработчик прерываний функции timerInterrupt

void detachInterrupt()

Метод запрещает прерывание.

Timer1. detachInterrupt();  // запретить прерывание от таймера 1

unsigned long read()

Метод позволяет считать текущее время таймера.

void pwm(char pin, int duty, long microseconds)

Генерирует сигнал ШИМ на выводе, заданном аргументом pin. На Ардуино могут использоваться выводы 9 и 10. Скважность задается аргументом duty в диапазоне 0 … 1023.

void setPwmDuty(char pin, int duty)

Задает значение ШИМ на выводе.

void disablePwm(char pin)

Выключает режим ШИМ для вывода.

С использованием библиотеки TimerOne программа постоянного вращения двигателя выглядит так.

// программа управления шаговым двигателем с помощью библиотеки StepMotor
// двигатель вращается постоянно против часовой стрелке со скоростью 60 об. в мин
 
#include <TimerOne.h>
#include <StepMotor.h>

StepMotor myMotor(10, 11, 12, 13);  // создаем объект типа StepMotor, задаем выводы для фаз

void setup() {
  Timer1.initialize(250);  // инициализация таймера 1, период 250 мкс
  Timer1.attachInterrupt(timerInterrupt, 250);  // задаем обработчик прерываний
  myMotor.setMode(0, false);  // шаговый режим, без фиксации при остановке
  myMotor.setDivider(83);     // делитель частоты 83
}

void loop() {
  myMotor.step(1000);
}

//-------------------------------------- обработчик прерывания 1 мс
void  timerInterrupt() {
  myMotor.control(); // управление двигателем
}

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

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

 

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

Предыдущий урок     Список уроков     Следующий урок

2

Автор публикации

не в сети 7 часов

Эдуард

285
Комментарии: 1945Публикации: 197Регистрация: 13-12-2015

75 комментариев на «Урок 29. StepMotor — библиотека управления шаговыми двигателями в системе Ардуино. Библиотека прерывания по таймеру 1 TimerOne.»

  1. У Вас на сайте отличные статьи, материал исчерпывающий и доходчиво преподнесен!

    0
    • Здравствуйте. Мне очень нужна помощь, у меня осталось всего три дня, помогите мне поставить паузу в алгоритм, который я скину. У меня не получается сделать паузу в шаговом двигателе при повороте.
      #include // Подключаем библиотеку управления шаговым двигателем. По умолчанию настроена на двигатель 28BYJ-48-5V
      CustomStepper stepper(8, 9, 10, 11); // Указываем пины, к которым подключен драйвер шагового двигателя

      int example = 1; // Переменная для демонстрации работы, отвечающая за смену режимов

      void setup()
      {
      stepper.setRPM(12); // Устанавливаем кол-во оборотов в минуту
      stepper.setSPR(4075.7728395); // Устанавливаем кол-во шагов на полный оборот. Максимальное значение 4075.7728395
      }

      void loop()
      {
      if (stepper.isDone() and example == 1) // Когда предыдущая команда выполнена (см. ниже), метод stepper.isDone() возвращает true
      {
      stepper.setDirection(CW); // Устанавливает направление вращения. Может принимать 3 значения: CW — по часовой, CCW — против часовой, STOP
      stepper.rotate(1); // Устанавливает вращение на заданное кол-во оборотов
      example = 2;
      }
      if (stepper.isDone() and example == 2)
      {
      stepper.setDirection(CCW);
      stepper.rotateDegrees(90); // Поворачивает вал на заданное кол-во градусов. Можно указывать десятичную точность (например 90.5), но не принимаются отрицательные значения
      example = 3;
      }
      if (stepper.isDone() and example == 3)
      {
      stepper.setDirection(CW);
      stepper.rotate(); // Будет вращать пока не получит команду о смене направления или пока не получит директиву STOP
      }
      stepper.run(); // Этот метод обязателен в блоке loop. Он инициирует работу двигателя, когда это необходимо
      }

      0
      • Там три действия. Вот мне необходимо, чтобы после поворота двигателя на 90 градусов он остановился на какое то время и потом продолжил крутиться на постоянной основе. Как прописать паузу? команда Delay не работает или я ее неправильно прописываю

        0
        • Здравствуйте!
          А как вы используете delay()? Попробуйте использовать эту функцию только после остановки двигателя в начале блоков if (в скобках {}) до вызова функций stepper.

          0
        • Ха, я как раз после танцев с бубном с библиотекой CustomStepper нашел данный ресурс. Она не работает с прерываниями, в этом ее основная ущербность. Пришел к этому выводу самостоятельно после двух потерянных вечеров. Команда delay у вас не работает, потому что код до нее не доходит, система ждет остановки мотора, метод stepper.isDone() почему то возвращает значение false при добавлении любого исполняемого кода в скетч.

          0
  2. Здравствуйте, а этой библиотекой можно управлять например 4-мя шаговыми двигателями через отдельные драйвера посредством сигналов step и dir?

    0
    • Здравствуйте. Этой библиотекой можно управлять несколькими двигателями, но с простыми драйверами-ключами. Для STEP/DIR драйверов есть другая библиотека уроки 34, 35. Ей также можно управлять несколькими двигателями.

      0
  3. Добрый день, уважаемый автор, Эдуард!
    Добрый день, уважаемый коллеги!

    Во-первых, хочу поздравить всех с праздником и пожелать успехов в творчестве, хорошего самочувствия, оптимизма и всего самого наилучшего! Пусть сбываются все Ваши мечты и планы. А теперь по теме данного урока №29. Спасибо автору Эдуарду за его старание, за его компетенцию и достаточно высокий уровень профессионализма. Но, к моему сожалению, не всё так сладко, Эдуард! Так, например, во-первых, Ваша основная программа, которой Вы посвятили урок №31 не проходит компиляцию. При выполнении компиляции Arduino IDE выдает целую серию ошибок. Отсюда вывод: программа сырая, не проверенная и не прошла отладку автором перед её демонстрацией. Это ни есть хорошо, уважаемый Эдуард! Во-вторых, после прохода по приведенной в уроке ссылке и скачивании основной Вашей программы русские буквы в комментариях — не читаются. Видимо, шрифт выбран какой-то специфический, который вместо руских букв прописывает какие-то иероглифы. В результате текст комментариев — не читаемый и автоматически превращается в муссор. Спасибо за понимание! Буду благодарен автору урока Эдуарду, если он услышит мои пожелания и внесет необходимые корректировки в текст программы и урока. Спасибо всем! С уважением, Валерий.

    0
    • Валерий! Спасибо за добрые слова.
      Что касается остального. Программы тщательно проверены, и не мной одним. Если выдает ошибки при компиляции, значит у вас в системе что-то не так. Может быть не установлена библиотека, может очень старая версия Arduino IDE, может файлы находятся в каталоге названным русскими буквами…
      Иероглифы вместо русских вам показывает браузер. Можете установить другую кодировку и все будет русскими буквами. Но Вы же не в браузере собираитесь программировать. Загрузите файл в Arduino IDE и все будет нормально. Скетчи программ созданы в Arduino IDE и сохраняют исходную кодировку кириллических символов.

      0
      • О, спасибо за такой быстрый ответ. Вот не могу понять, у меня гибридный двигатель 57HS7630A4 (nema 23), драйвер на микросхеме TB6600 и плата arduino Uno R3. Я использую интерфейсы контроллера DIR, Step и GND. Не подскажите, как мне программировать функцию StepMotor myMotor? Там же 4 переменных…

        0
          • STEP, DIR — это входы на драйвере, которые соединяются с цифровыми выводами на arduino. У Вас функция StepMotor(byte pinA, byte pinB, byte pinC, byte pinD) задействует 4 пина на ардуино.

            0
          • Анатолий. Посмотрите уроки 34 и 35. Урок 29 и библиотека StepMotor для простых драйверов-ключей. Для STEP/DIR драйверов есть другая библиотека.

            0
    • Извиняюсь, это из стандартной библиотеки. Нашел. Я новичок и не знаю, что стандартно, а что нет. Не плохо было бы упомянуть об этом.

      0
  4. STEP — Вход драйвера для шаговых импульсов (рабочим является передний фронт, длительность > 10мкс)
    DIR — Вход драйвера для управления направлением вращения вала шагового двигателя

    Задача пока запустить гибридный шаговый двигатель.

    0
  5. Здравствуйте Эдуард.
    для знакомства с библиотекой пробую использовать мотор 28BYJ-48-5V
    команда MT.step(10) — работает. но почему то эти 10 шагов двигатель делает со скоростью примерно 3-4 шага в секунду… хотя судя по его характеристикам он должен делать 2048 шагов (оборот) — за 4 секунды.
    не знаете, в чем причина такого его поведения?

    0
    • Здравствуйте! Скорость вращения двигателя зависит от: времени периода прерывания, значения делителя, числа шагов двигателя на оборот, режима переключения фаз. Проверяйте все составляющие.

      0
  6. Извините, а здесь нет ошибки?
    if ( _mode == 0 ) {

    switch (_stepPhase) {
    case 0:
    digitalWrite(_pinA, HIGH);
    digitalWrite(_pinB, LOW);
    digitalWrite(_pinC, LOW);
    digitalWrite(_pinD, LOW);
    break;
    case 1:
    digitalWrite(_pinA, LOW);
    digitalWrite(_pinB, HIGH);
    digitalWrite(_pinC, LOW);
    digitalWrite(_pinD, LOW);
    break;
    case 2:
    digitalWrite(_pinA, LOW);
    digitalWrite(_pinB, LOW);
    digitalWrite(_pinC, HIGH);
    digitalWrite(_pinD, LOW);
    break;
    case 3:
    digitalWrite(_pinA, LOW);
    digitalWrite(_pinB, LOW);
    digitalWrite(_pinC, LOW);
    digitalWrite(_pinD, HIGH);
    break;
    }
    }
    Просто биполярник у меня не заводится с таким кодом.
    Завелся с таким:
    if ( _mode == 0 ) {

    switch (_stepPhase) {
    case 0:
    digitalWrite(_pinA, HIGH);
    digitalWrite(_pinB, LOW);
    digitalWrite(_pinC, HIGH);
    digitalWrite(_pinD, LOW);
    break;
    case 1:
    digitalWrite(_pinA, LOW);
    digitalWrite(_pinB, HIGH);
    digitalWrite(_pinC, HIGH);
    digitalWrite(_pinD, LOW);
    break;
    case 2:
    digitalWrite(_pinA, LOW);
    digitalWrite(_pinB, HIGH);
    digitalWrite(_pinC, LOW);
    digitalWrite(_pinD, HIGH);
    break;
    case 3:
    digitalWrite(_pinA, HIGH);
    digitalWrite(_pinB, LOW);
    digitalWrite(_pinC, LOW);
    digitalWrite(_pinD, HIGH);
    break;
    }
    }
    в соответствии с: http://robocup.idi.ntnu.no/wiki/images/c/c6/PL15S020.pdf

    0
    • Я проверил. Все скетчи из уроков работают. Может у вас схема драйвера другая? Или обмотки двигателя подключены по другому?

      0
      • да вроде обычная схема подключения шагового биполярного двигателя от CD-Rom через L293D.

        0
        • Я не знаю этого драйвера. Значит у него другая логика, чем у L298. На L298 все работает. Посмотрите урок 33. В нем я подключаю биполярный двигатель.

          0
          • http://myrobot.ru/wiki/index.php?n=Projects.MyDRIVER

            Брал схему подключения с этого сайта.

            0
          • Посмотрите внимательно схему подключения в уроке 33. Входы драйвера IN1, IN2, IN3, IN4 подключены соответственно к выводам управления фазами A, C, B, D.

            0
  7. Здравствуйте! Проверьте меня. Все пересмотрел…
    Вот схема как подключено:
    https://cloud.mail.ru/public/5Z2t/hM9MeTETm
    Результат:
    https://cloud.mail.ru/public/KH2Y/E8rjBNaZL
    КОД:
    #include

    StepMotor myMotor(8, 9, 12, 13); // создаем объект типа
    ….
    void setup(){

    MsTimer2::set(1, timerInterrupt); // задаем период прерывания по таймеру 1 мс
    MsTimer2::start(); // разрешаем прерывание по таймеру

    myMotor.setMode(0, false); // шаговый режим, без фиксации при остановке
    myMotor.setDivider(50);
    ….
    }

    void loop(){

    if (myMotor.readSteps() == 0)
    {
    myMotor.setDivider(52-abs(xPosition));
    myMotor.step(-0.5*xPosition);
    }


    }

    void timerInterrupt() {
    myMotor.control(); // управление двигателем
    timeCounter++; // счетчик времени
    }

    0
    • Здравствуйте!
      Попробуйте сначала просто вращать двигатель. Потом движение до заданной точки без изменения скорости.

      0
  8. Эдуард, приветствую! Как правильно вставить в код строки, если нужна остановка двигателя по фотодатчику?

    StepMotor myMotor(10, 11, 12, 13); // создаем объект типа StepMotor, задаем выводы для фаз
    const int pinPhoto = 9; // Назначаем вывод 9 фотодатчику ID103
    const int ENA = 8; // Input ENA,ENB драйвера L298N подключены к выводу 8 Ардуино

    unsigned int timeCounter; // счетчик времени
    byte md; // режим: 0 — вращение против ч.с., 1 — пауза, 2 — вращение по ч.с., 3 — пауза

    void setup() {
    pinMode(pinPhoto, INPUT); // Объявляем назначение PIN-ам

    MsTimer2::set(1, timerInterrupt); // задаем период прерывания по таймеру 1 мс
    MsTimer2::start(); // разрешаем прерывание по таймеру
    myMotor.setMode(2, false); // между шаговый режим, без фиксации при остановке
    myMotor.setDivider(21); // делитель частоты 21 (при прерывании 1 мс период коммутации фаз 21 мс)
    md= 0; // начальный режим
    myMotor.step(576); // начальный запуск

    0
    • Здравствуйте!
      Вы не написали какой активный уровень у датчика. Если 1, то

      void loop() {
      if( digitalRead(pinPhoto) == HIGH) myMotor.step(0);
      else myMotor.step(100);
      }

      Двигатель вращается, если состояние вывода pinPhoto имеет низкий уровень и останавливается, если вывод находится в высоком уровне.

      0
  9. Добрый день, Эдуард! Да, я немного не правильно сформулировал вопрос. Задача простая: открывать и закрывать жалюзи по уровню освещенности ФД. Не суть важно, что на ФД, 0 или 1. Допустим, при «0» мотор крутится по часовой стрелке на 576 оборотов, при «1» — против.

    0
    • Здравствуйте!
      Надо выделить 2 события переход состояния датчика из 0 в 1 и из 1 в 0. И на эти события вызывать myMotor.step(576) и myMotor.step(-576). Если хотите, откройте тему на форуме сайта, я помогу с программой. В комментариях тяжело общаться на объемные темы.

      0
  10. Строку
    const int ENA = 8; // Input ENA,ENB драйвера L298N подключены к выводу 8 Ардуино
    можно закомментировать, она в этом случае не нужна

    0
  11. Существует проблема с подключением шагового двигателя
    VID60 является усовершенствованной версией на основе VID69 двигателя часов. Имеется оптико-механическая система обнаружения физического расположения стрелок часов. Алгоритм для синхронизации времени аналоговый дисплей в режиме реального времени.

    Нулевая функция обнаружения (построен в OSRAM LPT80A ИК-приемника)
    Широкий диапазон рабочих напряжений: 5 ~ 10В.
    Низкое потребление тока: 18mA, 5V, 2X90mW
    Пиковый ток 18 мА при 5 В
    С непосредственным приводом от μ-контроллера.
    Большой статическое усилие.
    Пригодны для применения в автомобильной промышленности.
    Рабочий диапазон температур -40 ° С ~ 105oC

    Вариант с установкой на плату:
    VID60-02 (усиленная шахта, вал высотой 12,1мм)
    из описания есть понимание, что опто-датчик на стрелку не завязан. Так ли это. И есть ли схема подключения шагового двигателя с оптодатчиком? Спасибо

    0
  12. Добрый день! у меня движок FL57STH76-2804A драйвер l298n

    Не получается запустить чтоб просто вращался.

    Какой должен быть параметр setDivider. пробовал разные не крутит. только дребезжит или свистит.

    0
    • Здравствуйте!
      Программа из урока должна работать. Там myMotor.setDivider(21).
      Скорее всего, вы фазы попутали, или какая-то из фаз не работает.

      0
      • С ардуиновской библиотекой он работает. Но по одному движку. Двигатели новые и драйвера тоже. Фазы перепроверил. Но реакция та же

        0
          • Сравните в уроке 28
            Stepper motor(48, 10, 12, 11, 13); // объект motor, 48 шагов на оборот
            и уроке 29
            StepMotor myMotor(10, 11, 12, 13); // создаем объект типа StepMotor, задаем выводы для фаз

            0
          • Все заработала. Но есть одна проблемка.
            У меня работаю два двигателя. один вращается без остановки и с ним все хорошо. А второй делает N шагов потом меняет направления и Опять N шагов. И так 10 раз. и где- то на 5 раз он начинает делать остановки секунду -две и дальше идет. С чем это связанно.?

            Вот код while (start) {
            if (10> I) {
            if (md == 0) {
            if (myMotor1.readSteps() == 0) { md=1; myMotor1.step((N*200/5)); I= I + 1;}
            }
            else if (md == 1) {
            if (myMotor1.readSteps() == 0) { md=0; myMotor1.step(-(N*200/5)); I= I + 1;}
            }
            }
            else {
            if (myMotor1.readSteps() == 0) {
            start = false;
            myMotor1.step(0);
            myMotor2.step(0);
            }
            }

            0
          • I становится больше 10 и все прекращается. Выведите I в последовательный порт и посмотрите, что делается.

            0
          • Вы меня видимо не правильно поняли. он должен 10 раз проработать туда сюда. но на 2-3 ходке. двигатель останавливается на 2 секунды и дальше идет и опять остановка она не связана с переменой I что-то другое

            0
      • вот код
        #include
        #include

        StepMotor myMotor(10, 11, 12, 13); // создаем объект типа StepMotor, задаем выводы для фаз

        void setup() {
        Timer1.initialize(25); // инициализация таймера 1, период 250 мкс
        Timer1.attachInterrupt(timerInterrupt, 25); // задаем обработчик прерываний
        myMotor.setMode(1, false); // шаговый режим, без фиксации при остановке
        myMotor.setDivider(21); // делитель частоты 83
        myMotor.step(200);
        }

        void loop() {

        }

        //————————————— обработчик прерывания 1 мс
        void timerInterrupt() {
        myMotor.control(); // управление двигателем
        }

        0
  13. Эдуард, подскажите а сервопривод типа SG90 — это один из вариантов шагового двигателя или это отделений девайс? И можно ли им управлять при помощи тех же библиотек что и для шагового двигателя? Нет ли у вас урока про сервоприводы?

    0
    • Здравствуйте!
      Это не шаговый двигатель. Это коллекторный двигатель с датчиком угла и схемой управления. Устройству задается угол положения ротора, а он его отрабатывает.

      0
  14. Спасибо за библиотеку.
    Поигрался — работает отлично.
    Возможность одновременной работы с несколькими моторами плюсик.
    К сожалению, не получается плавной регулировки скорости с помощью потенциометра — рывки, дёрганья.
    Делитель частоты меняю от 5 до 100.
    Что то подсказать можете или проблема не решаема.

    0
    • Здравствуйте!
      Способ один — уменьшение периода прерывания. Почитайте в уроке о скорости вращения. Там эта проблема затронута.

      1
  15. День добрый , подскажите , а как мне сделать так что бы количество шагов менять например не в программе а в отладочном режиме с экрана ?

    0
  16. Добрый день. Подскажите я правильно понимаю, для регулировки скорости потенциометром, myMotor.setDivider(21); выносим из setup в loop и подставляем значения с потенциометра.

    0
  17. Здравствуйте, Эдуард.
    Мне надо управлять, как минимум, пятью nema32 и силовым реле, значит контроллер KFB-3.0 мне не подойдет или два понадобится? И если да, то как их синхронизировать?

    0
  18. Здравствуйте,Эдуард. Подскажите что эти строки делают и зачем они нужны? void timerInterrupt() {
    myMotor.control(); // управвление двигателем

    0
    • Здравствуйте!
      В этом месте происходит управление двигателем. С периодом, заданным временем таймера, вызывается функция control. В ней отсчитывается нужное время и переключаются фазы двигателя. Это происходит параллельной задачей. Другие функции задают режимы, запускают шаги двигателя…

      0
  19. Эдуард, добрый день! Ругается на
    Timer1.attachInterrupt(timerInterrupt, 250); // задаем обработчик прерываний
    Что не так?
    Это полное описание ошибки.

    C:\Step_davy\Step_davy.ino: In function ‘void setup()’:

    Step_davy:21:26: error: ‘timerInterrupt’ was not declared in this scope

    Timer1.attachInterrupt(timerInterrupt, 250); // обработчик прерываний

    ^

    exit status 1
    ‘timerInterrupt’ was not declared in this scope

    1
  20. Здравствуйте!
    Я написал скетч по вашему принципу, и мне он выдает ошибку. В этом предложении.

    Timer1.attachInterrupt(timerInterrupt, 250);

    Этот код, который сделал я на 4 мотора.

    #include
    #include

    //StepDirDriver myMotor1 (10, 11, 12);
    StepDirDriver myMotor2 (A0, A1, 38);
    StepDirDriver myMotor3 (A6, A7, A2);
    StepDirDriver myMotor4 (26, 28, 24);
    StepDirDriver myMotor5 (36, 34, 30);

    unsigned int timeCounter;
    byte md;

    void setup() {
    Timer1.initialize(250);
    Timer1.attachInterrupt(timerInterrupt, 250);
    myMotor1.setMode(0, false);
    myMotor1.setDivider(5);
    myMotor2.setMode(0, false);
    myMotor2.setDivider(5);
    myMotor3.setMode(0, false);
    myMotor3.setDivider(5);
    myMotor4.setMode(0, false);
    myMotor4.setDivider(5);
    md= 0;
    myMotor1.step(0);
    myMotor2.step(0);
    myMotor3.step(0);
    myMotor4.step(0);
    }

    void loop() {

    if (md == 0) {

    if (myMotor1.readSteps() == 0)
    { md=1; timeCounter=0; }
    }
    else if (md == 1) {

    if (timeCounter >= 1000) {
    md=2;
    myMotor1.step(800);
    myMotor2.step(800);
    myMotor3.step(800);
    myMotor4.step(800); }
    }
    else if (md == 2) {

    if (myMotor1.readSteps() == 0) {
    md=3; timeCounter=0; }
    }
    else if {

    if (timeCounter >= 1000) {
    md=3;
    myMotor1.step(-800);
    myMotor2.step(-800);
    myMotor3.step(-800);
    myMotor4.step(-800); }

    else if (md == 3) {

    if (myMotor1.readSteps() == 0) {
    md=4; timeCounter=0; }
    }
    else if {

    if (timeCounter >= 1000) {
    md=4;
    myMotor1.step(-800);
    myMotor2.step(800);
    myMotor3.step(800);
    myMotor4.step(-800); }

    }

    else if (md == 4) {

    if (myMotor1.readSteps() == 0) {
    md=4; timeCounter=0; }
    }
    else if {

    if (timeCounter >= 1000) {
    md=4;
    myMotor1.step(800);
    myMotor2.step(-800);
    myMotor3.step(-800);
    myMotor4.step(800); }

    }
    }

    void timerInterrupt() {
    myMotor1.control();
    myMotor2.control();
    myMotor3.control();
    myMotor4.control();
    timeCounter++; //
    }

    0
  21. а можно зделат так чтобы по нажатии кнопки двигател делал один шаг нажатием ешо раз ешо один шаг а нажтием другой кнопки работал реверс по 1 шагам

    0
    • void loop() {
      if (digitalRead(KN1) == 0) // нажатие кнопки 1
      {
      motor.step(1); // вперед
      }

      else
      {
      motor.step(0); // стоп
      }

      if (digitalRead(KN2) == 0) // нажатие кнопки 2

      {
      motor.step(-1); // реверс
      }
      else
      {
      motor.step(0); // стоп
      }

      0
  22. Приветствую. А можно ли наоборот сделать — скетч будет следить за состоянием шагового двигателя и в случае поворота/шага вперёд и назад будет считать и увеличивать показания на дисплее/индикаторе?
    Заранее спасибо и всем Бобра!

    0
    • Здравствуйте!
      Шаговый двигатель вместо датчика положения использовать? Для этого есть инкрементальные энкодеры.

      0
  23. Здравствуйте! Как всегда, толково и по делу! Только мне не дает покоя один вопрос. Когда-то в 86-ом году наше КБ очень плотно работало с шаговыми двигателями. Использовали типовые платы минского КБТМ. Плату нужно было настроить под конкретный привод. Очень много внимания уделялось Разгону — Торможению. Без правильной настройки этого параметра двигатель или визжал на месте и не мог двинуться, или терял шаги, или работал на очень малой скорости. Настройку производили, в основном, по звуку. Правильно настроенный привод издавал тихий приятный звук без визжания. Почему то в Ваших статьях этот вопрос опускается.

    0
    • Еще вспомнил. Пробовали для оптимизации разгона ставить своеобразный оптический датчик угла поворота. Разгон получался довольно вялым, но двигатель работал мягко и выходил на большие скорости. Но этот датчик искажал моментно массовые характеристики привода, и когда датчик снимали после проведения настройки, то привод начинал явно грустить. Т.е. эта идей не проканала… Оставить датчик на серийной установке не было возможности.

      0
      • https://kolotushkin.com/article.php?id=44
        Долго ковырял инет по вопросу разгона-торможения, много чего наковырял, но особо впечатлила статейка: «Плавный пуск и остановка биполярного шагового двигателя. Спец драйвер на Digispark Attiny85».
        https://kolotushkin.com/article.php?id=44
        Идея, как по мне крайне интересная… Digispark Attiny85 вешается на I2C и полностью управляет шаговиком учетом с разгона-торможения. Ресурсы основного проца при этом остаются свободными!!!

        0

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

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

Нажимая кнопку "Отправить" Вы даёте свое согласие на обработку введенной персональной информации в соответствии с Федеральным Законом №152-ФЗ от 27.07.2006 "О персональных данных".