Stappenmotor & Raspberry Pi Pico

Natuurlijk wilde ik ook een motortje aan de Pico hangen. Een stappenmotortje; de hier al veel vaker gebruikte 28BYJ-48 dus.

Net als voor het OLED-scherm aansturing ik ook voor deze stappenmotor niet een “pakket” voor MicroPython beschikbaar. Maar het duo Rui & Sara Santos heeft op hun site wel iets beschikbaar.

# 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],
    ]

Bovenstaande script als “Stepper.py” naar de Pico gestuurd en onderstaand script uitgevoerd doet de motor prima heen er weer gaan.

# 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(90)
        sleep(0.5) # stop for a while
        
        stepper_motor.step_until_angle(45)
        sleep(0.5) # stop for a while
        
        stepper_motor.step_until_angle(135)
        sleep(0.5) # stop for a while
        
        stepper_motor.step_until_angle(180)
        sleep(0.5) # stop for a while
    
except KeyboardInterrupt:
    print('Keyboard interrupt')

Stepper_heen_en_weer.py

# 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 1 pins
IN1 = 28
IN2 = 27
IN3 = 26
IN4 = 22

# Define the stepper motor 2 pins
IN5 = 10
IN6 = 11
IN7 = 12
IN8 = 13

# Initialize the stepper motor
stepper_motor_1 = stepper.HalfStepMotor.frompins(IN1, IN2, IN3, IN4)
stepper_motor_2 = stepper.HalfStepMotor.frompins(IN5, IN6, IN7, IN8)

# Set the current position as position 0
stepper_motor_1.reset()
stepper_motor_2.reset()

try:
    while True:
        #Move 500 steps in clockwise direction
        stepper_motor_1.step(500)
        stepper_motor_2.step(500)
        sleep(0.5) # stop for a while
        
        # Move 500 steps in counterclockwise direction
        stepper_motor_1.step(-500)
        sleep(0.5) # stop for a while
        
        # Go to a specific position (in steps)
        stepper_motor_2.step_until(2000)
        sleep(0.5) # stop for a while
        
        # Force a direction using the dir paramter
        stepper_motor_2.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_1.step_until_angle(90)
        sleep(0.5) # stop for a while
        
        stepper_motor_1.step_until_angle(45)
        sleep(0.5) # stop for a while
        
        stepper_motor_2.step_until_angle(135)
        sleep(0.5) # stop for a while
        
        stepper_motor_2.step_until_angle(180)
        sleep(0.5) # stop for a while
    
except KeyboardInterrupt:
    print('Keyboard interrupt')

Een tweede motor eraan is eenvoudig. De eerste motor zit op de pinnen: IN1 = GPIO28, IN2 = GPIO27, IN3 = GPIO26 en IN4 = GPIO22. De tweede motor: IN5 = GPIO10, IN6 = GPIO11, IN7 = GPIO12 en IN8 = GPIO13.

Geef een reactie

Je e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *

Deze site gebruikt Akismet om spam te verminderen. Bekijk hoe je reactie gegevens worden verwerkt.