0

Stepper Motor Shield/Wing Driver
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Stepper Motor Shield/Wing Driver

by cartere on Thu Jan 19, 2017 10:53 am

Wonderful to have a place to ask questions :)
Trying to add release to the stepper library would it be something as simple as setting ain1, bin1, ain2, bin2 to 0?

The python scoping has me confused, would it look like:
Code: Select all | TOGGLE FULL SIZE
def release(self):
       self.ain1 = 0
       self.bin1 = 0
       self.ain2 = 0
       self.biin2 = 0



Looking a little deeper this makes more sense:
Code: Select all | TOGGLE FULL SIZE
def release(self):
    self._pin(self.ain1, False)
    self._pin(self.ain2, False)
    self._pin(self.bin1, False)
    self._pin(self.bin2, False)
Last edited by cartere on Thu Jan 19, 2017 11:13 am, edited 1 time in total.

cartere
 
Posts: 19
Joined: Thu Jan 19, 2017 10:35 am

Re: Stepper Motor Shield/Wing Driver

by adafruit_support_bill on Thu Jan 19, 2017 11:11 am

Yes. That should work.

adafruit_support_bill
 
Posts: 81590
Joined: Sat Feb 07, 2009 10:11 am

Re: Stepper Motor Shield/Wing Driver

by cartere on Thu Jan 19, 2017 12:27 pm

Success!

Code: Select all | TOGGLE FULL SIZE
# Stepper Motor Shield/Wing Driver
# Based on Adafruit Motorshield library:
# https://github.com/adafruit/Adafruit_Motor_Shield_V2_Library
# Author: Tony DiCola
import pca9685


# Constants that specify the direction and style of steps.
FORWARD = const(1)
BACKWARD = const(2)
SINGLE = const(1)
DOUBLE = const(2)
INTERLEAVE = const(3)
MICROSTEP = const(4)

# Not a const so users can change this global to 8 or 16 to change step size
MICROSTEPS = 16

# Microstepping curves (these are constants but need to be tuples/indexable):
_MICROSTEPCURVE8 = (0, 50, 98, 142, 180, 212, 236, 250, 255)
_MICROSTEPCURVE16 = (0, 25, 50, 74, 98, 120, 141, 162, 180, 197, 212, 225, 236, 244, 250, 253, 255)

# Define PWM outputs for each of two available steppers.
# Each tuple defines for a stepper: pwma, ain2, ain1, pwmb, bin2, bin1
_STEPPERS = ((8, 9, 10, 13, 12, 11), (2, 3, 4, 7, 6, 5))


class StepperMotor:
    def __init__(self, pca, pwma, ain2, ain1, pwmb, bin2, bin1):
        self.pca9685 = pca
        self.pwma = pwma
        self.ain2 = ain2
        self.ain1 = ain1
        self.pwmb = pwmb
        self.bin2 = bin2
        self.bin1 = bin1
        self.currentstep = 0

    def _pwm(self, pin, value):
        if value > 4095:
            self.pca9685.pwm(pin, 4096, 0)
        else:
            self.pca9685.pwm(pin, 0, value)

    def _pin(self, pin, value):
        if value:
            self.pca9685.pwm(pin, 4096, 0)
        else:
            self.pca9685.pwm(pin, 0, 0)

    def onestep(self, direction, style):
        ocra = 255
        ocrb = 255
        # Adjust current steps based on the direction and type of step.
        if style == SINGLE:
            if (self.currentstep//(MICROSTEPS//2)) % 2:
                if direction == FORWARD:
                    self.currentstep += MICROSTEPS//2
                else:
                    self.currentstep -= MICROSTEPS//2
            else:
                if direction == FORWARD:
                    self.currentstep += MICROSTEPS
                else:
                    self.currentstep -= MICROSTEPS
        elif style == DOUBLE:
            if not (self.currentstep//(MICROSTEPS//2)) % 2:
                if direction == FORWARD:
                    self.currentstep += MICROSTEPS//2
                else:
                    self.currentstep -= MICROSTEPS//2
            else:
                if direction == FORWARD:
                    self.currentstep += MICROSTEPS
                else:
                    self.currentstep -= MICROSTEPS
        elif style == INTERLEAVE:
            if direction == FORWARD:
                self.currentstep += MICROSTEPS//2
            else:
                self.currentstep -= MICROSTEPS//2
        elif style == MICROSTEP:
            if direction == FORWARD:
                self.currentstep += 1
            else:
                self.currentstep -= 1
            self.currentstep += MICROSTEPS*4
            self.currentstep %= MICROSTEPS*4
            ocra = 0
            ocrb = 0
            if MICROSTEPS == 8:
                curve = _MICROSTEPCURVE8
            elif MICROSTEPS == 16:
                curve = _MICROSTEPCURVE16
            else:
                raise RuntimeError('MICROSTEPS must be 8 or 16!')
            if 0 <= self.currentstep < MICROSTEPS:
                ocra = curve[MICROSTEPS - self.currentstep]
                ocrb = curve[self.currentstep]
            elif MICROSTEPS <= self.currentstep < MICROSTEPS*2:
                ocra = curve[self.currentstep - MICROSTEPS]
                ocrb = curve[MICROSTEPS*2 - self.currentstep]
            elif MICROSTEPS*2 <= self.currentstep < MICROSTEPS*3:
                ocra = curve[MICROSTEPS*3 - self.currentstep]
                ocrb = curve[self.currentstep - MICROSTEPS*2]
            elif MICROSTEPS*3 <= self.currentstep < MICROSTEPS*4:
                ocra = curve[self.currentstep - MICROSTEPS*3]
                ocrb = curve[MICROSTEPS*4 - self.currentstep]
        self.currentstep += MICROSTEPS*4
        self.currentstep %= MICROSTEPS*4
        # Set PWM outputs.
        self._pwm(self.pwma, ocra*16)
        self._pwm(self.pwmb, ocrb*16)
        latch_state = 0
        # Determine which coils to energize:
        if style == MICROSTEP:
            if 0 <= self.currentstep < MICROSTEPS:
                latch_state |= 0x3
            elif MICROSTEPS <= self.currentstep < MICROSTEPS*2:
                latch_state |= 0x6
            elif MICROSTEPS*2 <= self.currentstep < MICROSTEPS*3:
                latch_state |= 0xC
            elif MICROSTEPS*3 <= self.currentstep < MICROSTEPS*4:
                latch_state |= 0x9
        else:
            latch_step = self.currentstep//(MICROSTEPS//2)
            if latch_step == 0:
                latch_state |= 0x1  # energize coil 1 only
            elif latch_step == 1:
                latch_state |= 0x3  # energize coil 1+2
            elif latch_step == 2:
                latch_state |= 0x2  # energize coil 2 only
            elif latch_step == 3:
                latch_state |= 0x6  # energize coil 2+3
            elif latch_step == 4:
                latch_state |= 0x4  # energize coil 3 only
            elif latch_step == 5:
                latch_state |= 0xC  # energize coil 3+4
            elif latch_step == 6:
                latch_state |= 0x8  # energize coil 4 only
            elif latch_step == 7:
                latch_state |= 0x9  # energize coil 1+4
        # Energize coils as appropriate:
        if latch_state & 0x1:
            self._pin(self.ain2, True)
        else:
            self._pin(self.ain2, False)
        if latch_state & 0x2:
            self._pin(self.bin1, True)
        else:
            self._pin(self.bin1, False)
        if latch_state & 0x4:
            self._pin(self.ain1, True)
        else:
            self._pin(self.ain1, False)
        if latch_state & 0x8:
            self._pin(self.bin2, True)
        else:
            self._pin(self.bin2, False)
        return self.currentstep

    def release(self):
        self._pin(self.ain1, False)
        self._pin(self.ain2, False)
        self._pin(self.bin1, False)
        self._pin(self.bin2, False)
        self._pwm(self.pwma, 0)
        self._pwm(self.pwmb, 0)   

class Steppers:
    def __init__(self, i2c, address=0x60, freq=1600):
        self.pca9685 = pca9685.PCA9685(i2c, address)
        self.pca9685.freq(freq)

    def get_stepper(self, num):
        pwma, ain2, ain1, pwmb, bin2, bin1 = _STEPPERS[num]
        return StepperMotor(self.pca9685, pwma, ain2, ain1, pwmb, bin2, bin1)

cartere
 
Posts: 19
Joined: Thu Jan 19, 2017 10:35 am

Re: Stepper Motor Shield/Wing Driver

by adafruit_support_bill on Thu Jan 19, 2017 12:45 pm

Great! Thanks for posting your results.

adafruit_support_bill
 
Posts: 81590
Joined: Sat Feb 07, 2009 10:11 am

Please be positive and constructive with your questions and comments.