2

(Warning! I am not educated on this topic)

Hey folks. I'm posting here because I have a friend who desperately needs help with her project. I'm familiar with scripting, but not too much with programming. I do work in IT, so I'll do my best to provide the necessary information. She's trying to program a Raspberry Pi Zero to control a stepper motor using Python 3. Simple as that.

She followed these tutorials. Looks like she used the parts and wiring from #1 and the code from #2:

  1. https://tutorials-raspberrypi.com/how-to-control-a-stepper-motor-with-raspberry-pi-and-l293d-uln2003a/

  2. https://www.raspberrypi.org/forums/viewtopic.php?f=49&t=55580

Helpful pictures here. This is her actual setup: https://photos.app.goo.gl/WJbCo4UU3wAdo8913

Helpful notes: She mentioned she is not using a resistor between the power source and the L293D Driver IC.

Parts Used:

-Raspberry Pi Zero (Pi 2 or 3 was recommended, but the Zero has the same pin-out as the 2 & 3. She just had to solder on her own double-header)

-12V DC Power Bank

-Nema 17 Stepper Motor (https://www.amazon.com/STEPPERONLINE-17HS13-0404S1-Stepper-Motor-Printer/dp/B00PNEQ9T4)

-L293D Motor Driver IC (https://www.amazon.com/NDRTJM-SHOMPFL1045-L293D-Stepper-Driver/dp/B008XCGLNM)

-Breadboard w/ jumper cables (Duh!)

The code that she's using is below. When she attempts to run it, the motor just vibrates. Seems like it's repeatedly taking a step forward and a step back. No error codes are received. She also tried using another Nema 17 Stepper Motor that drawed 2A, but dropped down to the Nema 17 that draws .4A and gets the same result.

import RPi.GPIO as GPIO
import time

#variables

delay = 0.05
steps = 500

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

#Enable GPIO pins for ENA and ENB for stepper

enable_a = 18
enable_b = 22

#Enable pins for IN1-3 to control step sequence
 coil_A_1_pin = 17 #black
coil_A_2_pin = 4 #green
coil_B_1_pin = 24 #red
coil_B_2_pin = 23 #blue

#Set pin states

GPIO.setup(enable_a, GPIO.OUT)
GPIO.setup(enable_b, GPIO.OUT)
GPIO.setup(coil_A_1_pin, GPIO.OUT)
GPIO.setup(coil_A_2_pin, GPIO.OUT)
GPIO.setup(coil_B_1_pin, GPIO.OUT)
GPIO.setup(coil_B_2_pin, GPIO.OUT)

#set ENA and ENB to high to enable stepper

GPIO.output(enable_a, True)
GPIO.output(enable_b, True)

#function for step sequence

def setStep(w1, w2, w3, w4):
     GPIO.output(coil_A_1_pin, w1)
     GPIO.output(coil_A_2_pin, w2)
     GPIO.output(coil_B_1_pin, w3)   
     GPIO.output(coil_B_2_pin, w4) 

#loop through step sequence based on number of steps

for i in range(0, steps):
     setStep(1,1,0,0)
     time.sleep(delay)
     setStep(0,1,1,0)
     time.sleep(delay)
     setStep(0,0,1,1)
     time.sleep(delay)
     setStep(1,0,0,1)
     time.sleep(delay)

#reverse previous step sequence to reverse motor direction

for i in range(0, steps):
     setStep(1,0,0,1)
     time.sleep(delay)
     setStep(0,0,1,1)
     time.sleep(delay)
     setStep(0,1,1,0)
     time.sleep(delay)
     setStep(1,1,0,0)
     time.sleep(delay)

If there is ANYTHING I missed or more information that you require, please let me know and I will respond quickly! Any help is greatly appreciated! Thanks in advance!

JakeWesker
  • 33
  • 1
  • 5

4 Answers4

1

It looks like you're most of the way there... but the particular sequence isn't making the stepper step. With the L293D, the IO pin values are essentially what we drive the coil with, and I guess here coil_A and coil_B are the two coils with 1 and 2 being the ends of them (two coils is typical in a bipolar stepper motor). So the states you've applied are:

1100  == ==   No power
0110  << >>   both coils energised
0011  == ==   No power
1001  >> <<   both coils energised the opposite way

That doesn't provide a directional guide for the motor, and will most likely just lead to vibration. Try a full step pattern, where you flip the direction of one coil at a time:

fullsteps = ((0,1,0,1), (0,1,1,0), (1,0,1,0), (1,0,0,1))

for i in range(0, steps):
    for pattern in fullsteps:
        setStep(*pattern)
        time.sleep(delay)

The next variant one might try is half stepping, where we let the coils take two steps to transition from one direction to another:

halfsteps = ((0,1,0,1), (0,1,0,0), (0,1,1,0), (0,0,1,0), 
             (1,0,1,0), (1,0,0,0), (1,0,0,1), (0,0,0,1))

Upon second glance, that is in fact the pattern used in your first link (just below the comment "adjust if different" - just reversed and two half-steps out of phase with the version here).

At all times at least one coil is powered, keeping the motor from falling into an unknown position.

If we compare the tables shown in http://www.nmbtc.com/step-motors/engineering/full-half-and-microstepping/ their tables use the order A B ~A ~B, while your code used A ~A B ~B. So another way to make the code work should be just swapping B and ~A:

def setStep(w1, w3, w2, w4):
    GPIO.output(coil_A_1_pin, w1)
    GPIO.output(coil_A_2_pin, w2)
    GPIO.output(coil_B_1_pin, w3)   
    GPIO.output(coil_B_2_pin, w4) 
Yann Vernier
  • 15,414
  • 2
  • 28
  • 26
  • Sir, you are a gentleman and a scholar. I greatly appreciate your feedback. I'll be sure to use this information and come back to post a full solution or additional issues. Thanks so much again, Yann! – JakeWesker May 15 '18 at 21:08
  • She's getting it ready. I won't ditch this post. As soon as we try, I'll be back! – JakeWesker May 15 '18 at 21:44
  • That worked! I'll post the working code and post the configuration again for anyone who happens to view this post and needs a TL:DR. Yann, we greatly appreciate your expertise! Can't thank you enough. Your post also helped me understand how the coils in these motors work. Very simple once explained in the way you did. – JakeWesker May 16 '18 at 00:32
1

The code that worked is displayed below. You can use a Raspberry Pi Zero, 2, or 3. Other parts used were a 12V DC Power Bank, Breadboard, L293D Motor Driver IC, and a Nema 17 Stepper Motor (0.4A draw). This was all done using Python 3. Review the links above if you need pics or tutorials. Shout out to Yann for supplying the fix! He's the real MVP.

import RPi.GPIO as GPIO
import time

#variables

delay = 0.005
steps = 500

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

#Enable GPIO pins for ENA and ENB for stepper

enable_a = 18
enable_b = 22

#Enable pins for IN1-3 to control step sequence
 coil_A_1_pin = 17 #black
coil_A_2_pin = 4 #green
coil_B_1_pin = 24 #red
coil_B_2_pin = 23 #blue

#Set pin states

GPIO.setup(enable_a, GPIO.OUT)
GPIO.setup(enable_b, GPIO.OUT)
GPIO.setup(coil_A_1_pin, GPIO.OUT)
GPIO.setup(coil_A_2_pin, GPIO.OUT)
GPIO.setup(coil_B_1_pin, GPIO.OUT)
GPIO.setup(coil_B_2_pin, GPIO.OUT)

#set ENA and ENB to high to enable stepper

GPIO.output(enable_a, True)
GPIO.output(enable_b, True)

#function for step sequence

def setStep(w1, w2, w3, w4):
     GPIO.output(coil_A_1_pin, w1)
     GPIO.output(coil_A_2_pin, w2)
     GPIO.output(coil_B_1_pin, w3)   
     GPIO.output(coil_B_2_pin, w4) 

#loop through step sequence based on number of steps

for i in range(0, steps):
     setStep(0,1,0,1)
     time.sleep(delay)
     setStep(0,1,1,0)
     time.sleep(delay)
     setStep(1,0,1,0)
     time.sleep(delay)
     setStep(1,0,0,1)
     time.sleep(delay)

#reverse previous step sequence to reverse motor direction

for i in range(0, steps):
     setStep(1,0,0,1)
     time.sleep(delay)
     setStep(1,0,1,0)
     time.sleep(delay)
     setStep(0,1,1,0)
     time.sleep(delay)
     setStep(0,1,0,1)
     time.sleep(delay)
JakeWesker
  • 33
  • 1
  • 5
0

I'm using a similar setup using a raspberry pi zero W and a SDComponents MotorShield to control two stepper motors.

I'm using the code that they supplied on github: https://github.com/sbcshop/motor-shield

which looks pretty similar to how you have your code set up (take a look at the PiMotor.py file)

I noticed that using their default setup of sequencing, the stepper motors do a weird pattern of steps that seemed to bring it back to its original position. I've tried other sequences like the ones mentioned above, but they all resulted in the massively annoying vibrations that you (or your colleague) tried to describe.

I ultimately found a video that used another sequence and that seemed to work. Now, when I say that it "seemed to work" I mean that the motor is now successfully rotating forward instead of doing a tick forward and coming back to its original position. I changed the zeroes and ones on the PiMotor.py and ran the test code as below:

    def forward(self, delay, steps):
       for i in range(0, steps):
          setStep(1,0,1,1)
          time.sleep(delay)
          setStep(0,0,1,0)
          time.sleep(delay)
          setStep(0,1,0,0)
          time.sleep(delay)
          setStep(1,1,0,1)
          time.sleep(delay)

    def backward(self, delay, steps):
       for i in range(0, steps):
          setStep(1,1,0,1)
          time.sleep(delay)
          setStep(0,1,0,0)
          time.sleep(delay)
          setStep(0,0,1,0)
          time.sleep(delay)
          setStep(1,0,1,1)
          time.sleep(delay)

I found that sequencing on this youtube video --> https://youtu.be/ca8VP_zuMw8

the guy explains how he has it set up, which is similar to yours with the breadboard and all (I'm not using a breadboard), and I simply plugged in the numbers he show in 5:22 of that video for 'forward' and then flipped the table upside down to read from 3 to 0 to get the values for 'backward'.

I am now stuck trying to find out how to accelerate the stepper motor, but I'm not too experienced with python and I feel that this process will involve adding a speed variable that is dependent on the delay time between each step. There are also half stepping and micro stepping sequences that I'm trying to explore, but haven't been able to find any relevant resources.

I can provide pictures of what my setup looks like, and we can compare / help each other in our little projects. Let me know if that sequencing for the 'forward' and 'backward' works for you. Good luck!

Bo Kim
  • 1
0

Well, if there is vibration only, then you might have a problem with the delay. Just mentioning, in case you hadn't thought of it. Try a bigger delay.

ttarchala
  • 4,277
  • 2
  • 26
  • 36