Raspberry Pi Pico: управление шаговым двигателем с MicroPython

В этом руководстве вы узнаете, как управлять шаговым двигателем с помощью Raspberry Pi Pico. Мы будем использовать униполярный шаговый двигатель 28BYJ-48 с драйвером ULN2003. Вы узнаете, как подключить его к Raspberry Pi Pico и как управлять им с помощью модуля MicroPython.

Raspberry Pi Pico управление шаговым двигателем MicroPython 28BYJ-48 униполярный ULN2003 драйвер

Впервые работаете с Raspberry Pi Pico? Прочитайте следующее руководство: Начало работы с Raspberry Pi Pico (и Pico W).

В этом руководстве мы рассмотрим следующие темы:

Предварительные требования

Перед тем как продолжить, убедитесь, что вы выполнили следующие предварительные требования.

Прошивка MicroPython

Для выполнения этого руководства вам необходимо установить прошивку MicroPython на вашу плату Raspberry Pi Pico. Вам также понадобится IDE для написания и загрузки кода на плату.

Логотип MicroPython

Рекомендуемая IDE для Raspberry Pi Pico с MicroPython — это Thonny IDE. Следуйте следующему руководству, чтобы узнать, как установить Thonny IDE, прошить MicroPython и загрузить код на плату.

Альтернативно, если вам нравится программировать в VS Code, вы можете начать со следующего руководства:

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

Вам также понадобятся следующие компоненты:

Raspberry Pi Pico шаговый двигатель ULN2003
  • Raspberry Pi Pico

  • Шаговый двигатель 28BYJ-48 + драйвер ULN2003

  • Соединительные провода

  • Батарейный отсек 4xAA или любой другой источник питания (от 5 В до 12 В)

Знакомство с шаговыми двигателями

Шаговый двигатель — это бесщеточный электродвигатель постоянного тока, который делит полный оборот на определенное количество шагов. Он перемещается по одному шагу за раз, и каждый шаг имеет одинаковый размер. Это позволяет нам поворачивать двигатель на точный угол в точное положение. Шаговый двигатель может вращаться по часовой стрелке или против часовой стрелки.

На следующей фотографии показаны два шаговых двигателя 28BYJ-48.

Шаговые двигатели 28BYJ-48

Шаговые двигатели состоят из внутренних катушек, которые заставляют вал двигателя перемещаться по шагам в одном или другом направлении, когда ток подается на катушки определенным образом. Существует два типа шаговых двигателей: униполярные и биполярные. Мы не будем подробно рассматривать, как устроены шаговые двигатели и как они работают внутри.

Чтобы узнать более подробно, как они работают и в чем различия между каждым типом шагового двигателя, мы рекомендуем прочитать эту статью в блоге DroneBotWorkshop.

Шаговый двигатель 28BYJ-48

Существует множество шаговых двигателей с различными характеристиками. Мы будем использовать униполярный шаговый двигатель 28BYJ-48 с драйвером ULN2003 — эта комбинация широко используется любителями электроники и DIY-энтузиастами.

28BYJ-48 подключен к модулю драйвера ULN2003

Характеристики шагового двигателя 28BYJ-48

Характеристики шагового двигателя (для получения дополнительной информации обратитесь к даташиту):

  • Номинальное напряжение: 5 В постоянного тока

  • Количество фаз: 4

  • Передаточное число: 1/64

  • Угол шага: 5.625°/64

  • Частота: 100 Гц

Шаговый двигатель 28BYJ-48 имеет в общей сложности четыре катушки. Один конец катушек подключен к 5 В, что соответствует красному проводу двигателя. Другой конец катушек соответствует проводам синего, розового, желтого и оранжевого цветов. Подача тока на катушки в определенной логической последовательности заставляет двигатель совершать один шаг в одном или другом направлении.

Катушки шагового двигателя 28BYJ-48

Шаговый двигатель 28BYJ-48 имеет угол шага 5.625°/64 в полушаговом режиме. Это означает, что двигатель имеет угол шага 5.625° — поэтому ему нужно 360°/5.625° = 64 шага в полушаговом режиме. В полношаговом режиме: 64/2 = 32 шага для выполнения одного оборота.

Однако выходной вал приводится через передаточное число 64:1. Это означает, что вал (видимый снаружи двигателя) совершит один оборот, если двигатель внутри повернется 64 раза. Это означает, что двигатель должен совершить 32 x 64 = 2048 шагов, чтобы вал совершил один полный оборот. Это означает, что вы получите точность 360°/2048 шагов = 0.18°/шаг.

Итак, подведем итог:

  • Общее количество шагов на один оборот = 2048 шагов

  • Угол шага = 0.18°/шаг

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

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

Драйвер двигателя ULN2003

Для подключения шагового двигателя к Raspberry Pi Pico мы будем использовать драйвер ULN2003, как показано на рисунке ниже. Шаговый двигатель 28BYJ-48 часто продается вместе с драйвером ULN2003 в комплекте.

Модуль платы драйвера ULN2003

Модуль поставляется с разъемом, который позволяет легко и просто подключить двигатель к модулю. Он имеет четыре входных контакта для управления катушками, которые приводят в движение шаговый двигатель. Четыре светодиода обеспечивают визуальную индикацию состояния катушек.

Обозначения драйвера ULN2003

Распиновка драйвера ULN2003

В следующей таблице показана распиновка модуля:

Вывод

Описание

IN1

Управление двигателем: подключите к цифровому выводу Pico

IN2

Управление двигателем: подключите к цифровому выводу Pico

IN3

Управление двигателем: подключите к цифровому выводу Pico

IN4

Управление двигателем: подключите к цифровому выводу Pico

VCC

Питание двигателя

GND

Общая земля

Разъем двигателя

Подключите разъем провода двигателя

Подключение шагового двигателя к Raspberry Pi Pico

Давайте подключим шаговый двигатель к Raspberry Pi Pico через драйвер ULN2003. Мы подключим IN1, IN2, IN3 и IN4 к GPIO 28, 27, 26 и 22 соответственно. Вы можете использовать любые другие цифровые выводы, если укажете используемые выводы в коде.

Вы можете следовать приведенной ниже схеме подключения. Или используйте таблицу ниже в качестве справки.

Подключение шагового двигателя к Raspberry Pi Pico

Примечание

Вы должны питать драйвер двигателя от внешнего источника питания напряжением от 5 до 12 В. Мы используем 6.5 В от батарейного отсека.

Примечание

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

Драйвер ULN2003

Raspberry Pi Pico

IN1

GPIO 28

IN2

GPIO 27

IN3

GPIO 26

IN4

GPIO 22

Библиотека MicroPython для шагового двигателя

Существует несколько способов управления шаговым двигателем с помощью библиотеки. Мы будем использовать библиотеку, которая была создана специально для шагового двигателя 28BYJ-48, управляемого драйвером ULN2003.

Выполните следующие шаги, чтобы загрузить библиотеку на Raspberry Pi Pico.

  1. Создайте новый файл в Thonny IDE и скопируйте код библиотеки. Код библиотеки можно найти ниже (или вы можете скачать его по этой ссылке).

  2. Перейдите в File > Save as и выберите Raspberry Pi Pico.

  3. Назовите файл stepper.py и нажмите OK, чтобы сохранить файл на Raspberry Pi Pico.

# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-stepper-motor-micropython/
# Forked from: https://github.com/larsks/micropython-stepper-motor/blob/master/motor.py

import machine
import time

class Motor:
    stepms = 10

    # Do be defined by subclasses
    maxpos = 0
    states = []

    def __init__(self, p1, p2, p3, p4, stepms=None):
        self.pins = [p1, p2, p3, p4]

        if stepms is not None:
            self.stepms = stepms

        self._state = 0
        self._pos = 0

    def __repr__(self):
        return '<{} @ {}>'.format(
            self.__class__.__name__,
            self.pos,
        )

    @property
    def pos(self):
        return self._pos

    @classmethod
    def frompins(cls, *pins, **kwargs):
        return cls(*[machine.Pin(pin, machine.Pin.OUT) for pin in pins],
                   **kwargs)

    def reset(self):
        self._pos = 0

    def _step(self, dir):
        state = self.states[self._state]

        for i, val in enumerate(state):
            self.pins[i].value(val)

        self._state = (self._state + dir) % len(self.states)
        self._pos = (self._pos + dir) % self.maxpos

    def step(self, steps):
        dir = 1 if steps >= 0 else -1
        steps = abs(steps)

        for _ in range(steps):
            t_start = time.ticks_ms()

            self._step(dir)

            t_end = time.ticks_ms()
            t_delta = time.ticks_diff(t_end, t_start)
            time.sleep_ms(self.stepms - t_delta)

    def step_until(self, target, dir=None):
        if target < 0 or target > self.maxpos:
            raise ValueError(target)

        if dir is None:
            dir = 1 if target > self._pos else -1
            if abs(target - self._pos) > self.maxpos/2:
                dir = -dir

        while True:
            if self._pos == target:
                break
            self.step(dir)

    def step_until_angle(self, angle, dir=None):
        if angle < 0 or angle > 360:
            raise ValueError(angle)

        target = int(angle / 360 * self.maxpos)
        self.step_until(target, dir=dir)

    def step_degrees(self, degrees):
        if degrees < 0 or degrees > 360:
            raise ValueError("Degrees should be between 0 and 360")

        steps_to_take = int(degrees / 360 * self.maxpos)

        self.zero()  # Ignore the current position, start from zero
        self.step(steps_to_take)

class FullStepMotor(Motor):
    stepms = 5
    maxpos = 2048
    states = [\
        [1, 1, 0, 0],\
        [0, 1, 1, 0],\
        [0, 0, 1, 1],\
        [1, 0, 0, 1],\
    ]

class HalfStepMotor(Motor):
    stepms = 3
    maxpos = 4096
    states = [\
        [1, 0, 0, 0],\
        [1, 1, 0, 0],\
        [0, 1, 0, 0],\
        [0, 1, 1, 0],\
        [0, 0, 1, 0],\
        [0, 0, 1, 1],\
        [0, 0, 0, 1],\
        [1, 0, 0, 1],\
    ]

Вот и всё. Библиотека загружена на вашу плату. Теперь вы можете использовать функции библиотеки в своем коде, импортировав библиотеку.

Управление шаговым двигателем – код MicroPython

Библиотека, которую мы используем, очень интуитивно понятна в использовании. Следующий код демонстрирует различные доступные методы.

# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-stepper-motor-micropython/

import stepper
from time import sleep

# Define the stepper motor pins
IN1 = 28
IN2 = 27
IN3 = 26
IN4 = 22

# Initialize the stepper motor
stepper_motor = stepper.HalfStepMotor.frompins(IN1, IN2, IN3, IN4)

# Set the current position as position 0
stepper_motor.reset()

try:
    while True:
        #Move 500 steps in clockwise direction
        stepper_motor.step(500)
        sleep(0.5) # stop for a while

        # Move 500 steps in counterclockwise direction
        stepper_motor.step(-500)
        sleep(0.5) # stop for a while

        # Go to a specific position (in steps)
        stepper_motor.step_until(2000)
        sleep(0.5) # stop for a while

        # Force a direction using the dir paramter
        stepper_motor.step_until(2000, dir=-1)
        sleep(0.5) # stop for a while

        # Go to a specific position (angle, maximum is 359, otherwise it will spin indefinetely)
        stepper_motor.step_until_angle(359)
        sleep(0.5) # stop for a while

except KeyboardInterrupt:
    print('Keyboard interrupt')

Как работает код

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

Сначала вам нужна библиотека stepper, которую вы только что загрузили на Raspberry Pi Pico.

import stepper

Затем определите выводы, которые вы используете для управления шаговым двигателем через драйвер ULN2003. Если вы используете другие выводы, измените следующие строки:

# Define the stepper motor pins
IN1 = 28
IN2 = 27
IN3 = 26
IN4 = 22

Затем инициализируйте шаговый двигатель следующим образом (мы используем полушаговый режим, как объяснялось ранее).

# Initialize the stepper motor
stepper_motor = stepper.HalfStepMotor.frompins(IN1, IN2, IN3, IN4)

Перед тем как начать перемещение двигателя, мы используем метод reset(), чтобы сообщить коду, что текущая позиция шагового двигателя — это позиция 0.

# Set the current position as position 0
stepper_motor.reset()

Затем у нас есть цикл while, в котором мы перемещаем двигатель с помощью различных методов.

try:
    while True:

Метод step() перемещает двигатель на заданное количество шагов по часовой стрелке. Передайте в качестве аргумента количество шагов, которое вы хотите совершить.

#Move 500 steps in clockwise direction
stepper_motor.step(500)

Вы также можете передать отрицательное число для движения против часовой стрелки.

# Move 500 steps in counterclockwise direction
stepper_motor.step(-500)

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

# Go to a specific position (in steps)
stepper_motor.step_until(2000)

В любой момент в вашем коде вы можете вызвать метод reset(), чтобы определить новую точку отсчета (позиция 0).

Вы можете передать дополнительный параметр в метод step_until() — параметр dir. Он может быть равен 1, чтобы заставить двигатель вращаться по часовой стрелке, или -1, чтобы заставить двигатель вращаться против часовой стрелки.

# Force a direction using the dir parameter
stepper_motor.step_until(2000, dir=-1)
sleep(0.5) # stop for a while

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

stepper_motor.step_until_angle(359)

Тестирование кода

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

Raspberry Pi Pico управление шаговым двигателем Raspberry Pi Pico управление шаговым двигателем - результат

Заключение

В этом руководстве вы узнали, как управлять шаговым двигателем с помощью Raspberry Pi Pico, запрограммированного на MicroPython. Один из самых популярных двигателей для использования в проектах DIY-любителей — это униполярный шаговый двигатель 28BYJ-48 с драйвером ULN2003.

Если вы хотите подключить другие двигатели к Raspberry Pi Pico, ознакомьтесь с руководствами ниже: