Как контролировать скорость шагового двигателя 28BYJ-48 без использования библиотеки?

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

, 👍3

Обсуждение

начните с изучения примера скетча blinkWithoutDelay , который входит в комплект поставки Arduino IDE ... он научит вас, как выполнять события через определенные промежутки времени, не блокируя остальную часть кода, @jsotola


1 ответ


3

Шаговому двигателю всегда нужен драйвер. Поскольку драйвер ULN2003 (или аналогичный) обычно поставляется вместе с двигателем 28byj-48, я предполагаю, что у вас есть этот драйвер.

ULN2003 имеет 6 контактов:

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

  • Остальные 4 контакта (которые помечены как IN1 - IN4 на моей плате драйвера ULN2003) предназначены для управления фазами. Вам нужно подключить эти 4 контакта к 4 отдельным цифровым выходам на вашем Arduino. Поскольку это фазы шагового двигателя, вам нужно активировать их в правильном порядке. У вас есть этот паттерн

      1000
      0100
      0010
      0001
    

    для полных шагов, и этот шаблон

      1000
      1100
      0100
      0110
      0010
      0011
      0001
      1001
    

    на полшага. Каждая цифра каждого числа представляет состояние соответствующей фазы; 1 означает активированный / ВЫСОКИЙ, 0 означает деактивированный / НИЗКИЙ. Чтобы переместить шаговый двигатель вперед, вы перемещаетесь в списке фаз вниз. Чтобы двигаться назад, вы двигаетесь вверх по списку.

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

void loop(){
    step();
    delay(10);
}

Этот код будет делать шаг, а затем задерживаться на 10 мс. Таким образом, у нас есть примерно 1 шаг каждые 10 мс. При 64*64=4096 шагах на оборот (сам двигатель, кажется, имеет 64 шага; кроме того, на нем установлена шестерня с передаточным числом 64; для вас это может быть по-другому) мы получаем полный оборот каждые 4,096 с. Когда вы используете половину delay(), скорость будет двойной: с задержкой 5 мс мы получаем полный оборот каждые 2,048 с. Таким образом, вы можете использовать delay() для установки скорости двигателя.

Теперь нам нужна функция step (), которую я использовал выше. Существует несколько способов написать это в коде. Я бы предложил поместить контакты и фазы в массивы и перебирать их со статической переменной, которая удерживает текущую позицию в нашем фазовом паттерне. Что-то вроде этого:

//в глобальной области видимости определение выводов для фаз
int stepper_pins[4] = {2, 3, 4, 5};

void step(bool forward){
    const uint8_t phase_pattern[][4] = {
        {1,0,0,0},
        {0,1,0,0},
        ...
    };
    static uint8_t current_step = 0;
    if(forward){
        current_step = (current_step + 1) % 4;
    } else {
        current_step = (current_step - 1) % 4;
    }
    for(uint8_t i=0;i<4;i++){
        digitalWrite(stepper_pins[i], phase_pattern[current_step][i]);
    }
}

Мы удерживаем фазовую картину в 2-мерном массиве. Переменная current_step объявлена статической, поэтому она будет сохранять свое значение между выполнением функции. Затем - в зависимости от параметра forward - мы увеличиваем или уменьшаем текущий шаг и принимаем это значение по модулю 4 (количество фазовых паттернов). Это гарантирует, что current_step останется в диапазоне индексов нашего массива фазовых паттернов и будет перемещаться от конца паттерна к началу и наоборот. После этого мы перебираем 4 шаговых вывода и устанавливаем их в соответствии с текущим элементом в массиве phase_pattern. Вы можете легко освоить этот код за полшага.

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

Теперь: Почему бы не использовать delay()? Эта функция заблокирует выполнение другого кода. В это время Arduino просто играет большими пальцами. В общем, это считается плохой практикой. Это хорошо, когда вам нужна только одна функциональность и никакой отзывчивости. Но давайте предположим, что вы хотите добавить кнопку, чтобы двигатель реагировал на ваши нажатия кнопок. Вызовы Long delay() повлияют на отзывчивость вашего кода. Поэтому вместо этого вы можете использовать неблокирующий стиль кодирования. В мире Arduino это легко сделать с помощью функции millis (), которая возвращает количество миллисекунд с момента запуска и, таким образом, действует как часы. Обратитесь к примеру BlinkWithoutDelay, который поставляется с Arduino IDE, и ко многим учебникам в Интернете, которые вы можете найти с помощью поисковых запросов, таких как "Arduino millis tutorial" или что-то в этом роде.


ПРАВКА:

как ваш код управляет скоростью двигателя?

Вызов delay() определяет скорость двигателя. Если вы хотите изменить скорость, вам нужно изменить значение задержки. Вы не упомянули ни о каком устройстве ввода, поэтому я просто оставляю скорость постоянной. Но, конечно, вы можете определить переменную для задержки и изменить эту задержку на основе какого-либо устройства ввода. Как именно это делается, зависит от ваших требований, главным образом от того, какой тип ввода вы хотите использовать.

если бы мы не указывали никаких задержек между шагами, будет ли он вращаться на максимальных оборотах?

Если вы не используете никакой задержки, то, скорее всего, ваш код будет работать слишком быстро для двигателя. Водитель будет устанавливать фазы двигателя очень и очень быстро. Так быстро, что двигатель не может следовать за этим (потому что у него есть определенная инерция). (Точно так же, как колеса вашего автомобиля могут ослабить сцепление на улице и вращаться, не двигая автомобиль, статор двигателя может ослабить магнитное сцепление с ротором, что приводит к дальнейшему вращению фаз, но ротор, который стоит на месте), Так что вы достигнете максимальной скорости до этого и это зависит от двигателя, водителя, от того, сколько нагрузки на двигатели и сколько тока может дать вам ваш источник питания (однажды я попытался снабдить 3 из этих двигателей блоком питания 1A, но они двигались очень слабо, пока я не перешел на больший источник питания, который может обеспечьте около 5А, я думаю). Вам нужно проверить себя, насколько быстро вы можете управлять своими моторами. Поэтому старайтесь снижать задержки шаг за шагом, пока двигатель больше не перестанет двигаться в вашей установке. Тогда у вас есть минимальная задержка и максимальная скорость.

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

,

Ваше объяснение замечательно, но как ваш код управляет скоростью двигателя, @Akashbabutammali

И еще один вопрос: если бы мы не указывали никаких задержек между шагами, будет ли он вращаться на максимальных оборотах?, @Akashbabutammali

@Akashbabutammali Я добавил пояснения к обоим вопросам в своем ответе., @chrisl