Pi Pico controlling makerverse 2ch driver & 24BYJ 48 stepper

Hi All I am trying to build a rotating platform which will acomodate either a point and shoot style camera or a dslr for timelapse photography.

My tests are using a 24byj 48 stepper and the makerverse 2ch motor driver( PART NO ce08038) but will eventually be upgraded to a Nema 17 style stepper.

At the moment the code below is set to do 2000 steps in one direction and then 2000 in the other.

At the moment the motor will not move , even though I can hear it and feel it vibrate when the Pico and the seperate power supply are turned on.

Once I have this operating I will change the code to move only 10 steps (approx) and to pause between each 10 steps and flash a Led which will also become an output trigger pulse to a camera.
I am obviously missing something in this code as the motor is not turning .

The connections are correct because I can run other simpler code ( which Brenton supplied in one of the Core guides) without a problem.

PLEASE NOTE : The code compiles and gives me these 2 messages but nothing happens

print(“Rotating 2000 steps in one direction…”)
print(“Rotating 2000 steps in the other direction…”)

Any suggestions greatly appreciated
Nick

from machine import Pin, PWM
import time
from Makerverse_Motor_2ch import bipolarStepper
stepper = bipolarStepper(pwmPinA = 0, dirPinA = 1, pwmPinB = 2, dirPinB = 3, RPM = 100, stepsPerRotation = 2048)

# Define pins for your stepper motor driver
DIR_PINA = 1  # Example GPIO pin for direction
PWM_PINA = 0 # Example GPIO pin for step (PWM)  STEP

DIR_PINB = 3  # Example GPIO pin for direction
PWM_PINB = 2 # Example GPIO pin for step (PWM)   STEP

# Configure the direction pin
dir_pinA = Pin(DIR_PINA, Pin.OUT)
dir_pinB = Pin(DIR_PINB, Pin.OUT)


# Configure the PWM for the step pin
# Frequency determines the speed of stepping (higher freq = faster)
# Duty cycle controls the pulse width (e.g., 512 for 50% duty cycle)
pwm_PinA = PWM(Pin(PWM_PINA))
pwm_PinA.freq(1000)  # Set a base frequency for stepping (e.g., 1kHz)

pwm_PinB = PWM(Pin(PWM_PINB))
pwm_PinB.freq(1000)  # Set a base frequency for stepping (e.g., 1kHz)

def rotate_stepper(steps, direction, delay_ms=1):
    """
    Rotates the stepper motor for a given number of steps in a specified direction.

    Args:
        steps (int): The number of steps to rotate.
        direction (int): 0 for one direction, 1 for the other.
        delay_ms (int): Delay between step pulses in milliseconds.
    """
    dir_pinA.value(1) # Set the direction
    time.sleep_ms(10) # Small delay after changing direction (driver specific)
    dir_pinB.value(1) # Set the direction
    time.sleep_ms(10) # Small delay after changing direction (driver specific)
    
    dir_pinA.value(0) # Set the direction
    time.sleep_ms(10) # Small delay after changing direction (driver specific)
    dir_pinB.value(0) # Set the direction
    time.sleep_ms(10) # Small delay after changing direction (driver specific)
    
    

    for _ in range(steps):
        pwm_PinA.duty_u16(32768) # Set duty cycle to 50% (half of 65535 for 16-bit)
        time.sleep_ms(delay_ms)
        pwm_PinB.duty_u16(32768) # Set duty cycle to 50% (half of 65535 for 16-bit)
        time.sleep_ms(delay_ms)
        pwm_PinA.duty_u16(0)    # Turn off the pulse
        time.sleep_ms(delay_ms)
        pwm_PinB.duty_u16(0)    # Turn off the pulse
        time.sleep_ms(delay_ms)

# Example usage:
print("Rotating 2000 steps in one direction...")
rotate_stepper(2000, 0, delay_ms=2) # Rotate 2000 steps, direction 0, 2ms delay

time.sleep(1) # Wait for a second

print("Rotating 2000 steps in the other direction...")
rotate_stepper(2000, 1, delay_ms=2) # Rotate 2000 steps, direction 1, 2ms delay

# Optionally, stop the PWM if not needed continuously
# pwm_step.deinit()

The original code only had one direction pin and one step pin and I changed step pin for 2 dir pins and the 2 pwm pins as I thought that would give me usable code Here is the original code from the internet

from machine import Pin, PWM
import time

# Define pins for your stepper motor driver
DIR_PIN = 16  # Example GPIO pin for direction
STEP_PIN = 17 # Example GPIO pin for step (PWM)

# Configure the direction pin
dir_pin = Pin(DIR_PIN, Pin.OUT)

# Configure the PWM for the step pin
# Frequency determines the speed of stepping (higher freq = faster)
# Duty cycle controls the pulse width (e.g., 512 for 50% duty cycle)
pwm_step = PWM(Pin(STEP_PIN))
pwm_step.freq(1000)  # Set a base frequency for stepping (e.g., 1kHz)

def rotate_stepper(steps, direction, delay_ms=1):
    """
    Rotates the stepper motor for a given number of steps in a specified direction.

    Args:
        steps (int): The number of steps to rotate.
        direction (int): 0 for one direction, 1 for the other.
        delay_ms (int): Delay between step pulses in milliseconds.
    """
    dir_pin.value(direction) # Set the direction
    time.sleep_ms(10) # Small delay after changing direction (driver specific)

    for _ in range(steps):
        pwm_step.duty_u16(32768) # Set duty cycle to 50% (half of 65535 for 16-bit)
        time.sleep_ms(delay_ms)
        pwm_step.duty_u16(0)    # Turn off the pulse
        time.sleep_ms(delay_ms)

# Example usage:
print("Rotating 2000 steps in one direction...")
rotate_stepper(2000, 0, delay_ms=2) # Rotate 2000 steps, direction 0, 2ms delay

time.sleep(1) # Wait for a second

print("Rotating 2000 steps in the other direction...")
rotate_stepper(2000, 1, delay_ms=2) # Rotate 2000 steps, direction 1, 2ms delay

# Optionally, stop the PWM if not needed continuously
# pwm_step.deinit()

Hi @Nicholas193967,

I’ll be the first to admit that I’m not the best when it comes to working with motors, but I am noticing that you have initialise the stepper motor class on line 4:

stepper = bipolarStepper(pwmPinA = 0, dirPinA = 1, pwmPinB = 2, dirPinB = 3, RPM = 100, stepsPerRotation = 2048)

But then you don’t do anything with it.

According to the Github page, the below example would move the stepper 100 steps forward, 45 degrees backward, then returns to home.

from Makerverse_Motor_2ch import bipolarStepper

stepper = bipolarStepper(pwmPinA = 0, dirPinA = 1, pwmPinB = 2, dirPinB = 3)

stepper.rotate(50)
stepper.rotate(angle=-180)
stepper.returnHome()
1 Like

Hi Jane
Thanks for your reply.
The page you are referring to is this one

However this github page from Brenton

refers to a different way of doing the coding which appears to me to be more compact and his second video refers to code I cannot find in the guide, when you look at what he shows on the screen

# MicroPython classes for driving single motors, two motor robots, and stepper motors with 
# the Core Electronics Makerverse 2ch Motor Driver.
# 
# Written by Brenton Schulz
# Initial release: FEB-14-22

from machine import PWM, Pin
import time

_FORWARD = 1
_REVERSE = 0

class bipolarStepper():
    def __init__(self, pwmPinA = 0, dirPinA = 1, pwmPinB = 2, dirPinB = 3, RPM = 10, stepsPerRotation = 200):
        if isinstance(pwmPinA, int):
            pwmPinA = Pin(pwmPinA, Pin.OUT)
        elif isinstance(pwmPinA, Pin):
            pwmPinA = pwmPinA.init(mode=Pin.OUT)
        else:
            raise TypeError("Argument 'pwmA' must be an integer or Pin object")
        
        if isinstance(pwmPinB, int):
            pwmPinB = Pin(pwmPinB, Pin.OUT)
        elif isinstance(pwmPinB, Pin):
            pwmPinB = pwmPinB.init(mode=Pin.OUT)
        else:
            raise TypeError("Argument 'pwmA' must be an integer or Pin object")
        
        if isinstance(dirPinA, int):
            dirPinA = Pin(dirPinA, Pin.OUT)
        elif isinstance(dirPinA, Pin):
            dirPinA = dirPinA.init(mode=Pin.OUT)
        else:
            raise TypeError("Argument 'pwmA' must be an integer or Pin object")
        
        if isinstance(dirPinB, int):
            dirPinB = Pin(dirPinB, Pin.OUT)
        elif isinstance(dirPinB, Pin):
            dirPinB = dirPinB.init(mode=Pin.OUT)
        else:
            raise TypeError("Argument 'pwmA' must be an integer or Pin object")
        
        self.pwmA = pwmPinA
        self.pwmB = pwmPinB
        self.dirA = dirPinA
        self.dirB = dirPinB
        
        self.pwmA.on()
        self.pwmB.on()
        self.dirA.on()
        self.dirB.on()
        
        self.next = "A"
        
        self.steps = 0
        
        self.stepDelay_ms = int(60000/(RPM*stepsPerRotation))
        
        self.RPM = RPM
        self.stepsPerRotation = stepsPerRotation

    def setRPM(self, RPM):
        self.stepDelay_ms = int(60000/(RPM*self.stepsPerRotation))

    def setHome(self):
        self.steps = 0

    def returnHome(self):
        while self.steps > 0:
            self.backwardStep()
            time.sleep_ms(self.stepDelay_ms)
        while self.steps < 0:
            self.forwardStep()
            time.sleep_ms(self.stepDelay_ms)

    def getSteps(self):
        return self.steps
    
    def getAngle(self):
        return self.steps%self.stepsPerRotation / self.stepsPerRotation * 360

    def forwardStep(self):
        if self.next == "A":
            if self.dirA.value() == 1:
                self.dirA.off()
            else:
                self.dirA.on()
            self.next = "B"
        else:
            if self.dirB.value() == 1:
                self.dirB.off()
            else:
                self.dirB.on()
            self.next = "A"
        self.steps += 1
        
    def backwardStep(self):
        if self.next == "A":
            if self.dirB.value() == 1:
                self.dirB.off()
            else:
                self.dirB.on()
            self.next = "B"
        else:
            if self.dirA.value() == 1:
                self.dirA.off()
            else:
                self.dirA.on()
            self.next = "A"
        self.steps -= 1
        
    def rotate(self, steps = 0, angle = None):
        if angle is not None:
            steps = round(angle/360.0*self.stepsPerRotation)
        
        if steps < 0:
            while steps < 0:
                self.backwardStep()
                steps += 1
                time.sleep_ms(self.stepDelay_ms)
        else:
            while steps > 0:
                self.forwardStep()
                steps -= 1
                time.sleep_ms(self.stepDelay_ms)

However I cannot make this work !!!
For this reason I accessed the different code from the internet and modified it, which is the very first piece of code I supplied in my first post (above). My second post is the code I modified from the internet

The code in your email and the github link in your email are both different places.
The code in your post above I previously used but it becomes very long and is only repeating the same code over & over again ( at least 50 times,most likley it will be more than that(100 or 200 steps, with smaller steps) and I was hoping to make the code more compact. It follows as a zip file below

stepper zip.zip (567 Bytes)

Thankyou

1 Like

Don’t try and modify the libraries, they are designed to work with the electronics and unless you know what you are doing, that will lead to problems. Even if you want to make changes you should make new classes that inherit from them. You want to be calling the libraries from your main.py and then defining how you want them to move.

Let’s go back to your original code.

The code that you sent through in the stepper zip is definitely repeated far too many times for something identical. It would be worthwhile putting it into a loop.

from Makerverse_Motor_2ch import bipolarStepper
import time
from machine import Pin
stepper = bipolarStepper(pwmPinA = 0, dirPinA = 1, pwmPinB = 2, dirPinB = 3, RPM = 10, stepsPerRotation = 2048)
    
# For Pico W, use the 'LED' string. For a regular Pico, use `machine.Pin(25, machine.Pin.OUT)`
led = machine.Pin("LED", machine.Pin.OUT)
#Turns the LED, waits one second, turns it off

def flickerLED():
    led.value(True)  # Turn the LED on
    time.sleep(1)    # Wait for one second
    led.value(False) # Turn the LED off


for steps in range(10): #Change this to however many times you need it to loop.
    flickerLight()
    stepper.rotate(10)
    time.sleep_ms(500)

flickerLight()
#stepper.rotate(angle=-180)
stepper.returnHome()

That code should do what your original zip code did in a few lines.

I understand that it’s not what you’re ultimately trying to do, but let’s get on the same basis regarding code and go from there.

2 Likes

Thank you for sorting me out on this part of this project.
I have changed from the 24BYJ 48 to the Nema 17 but its a great feeling to be finally heading in the right direction

1 Like

No worries, Nicholas, glad I was able to help in some way :slight_smile: