Showing posts with label EE. Show all posts
Showing posts with label EE. Show all posts

2014-06-09

Stepper motor control with EasyDriver and Python on Linux desktop

My Mechanical Engineering colleagues recently asked me to build them a software-controlled stepper motor system - they wanna apply high-power pulse laser on the surface of rotating objects. Of course, the software must have GUI.



Hardware

I decided to control the stepper motor using a Linux PC with parallel ports (yes, people are still building motherboards with parallel ports), because developing software for desktop Linux is much easier. Oh, for tablets and smart phone fans, how do your devices talk to physical world? 

In searching for a proper driver chip/board for the stepper motor, I came across the handy EasyDriver board designed by Brian Schmalzhaus. I just need to provide one rising edge to the STEP pin of it, the stepper motor will rotate one step. I can control the direction of rotation and step size by configuring certain pins. It saves me the hassle of computing waveforms for controlling stepper motors. Check the references below to see how EasyDriver can simply your life.

Lastly, very important, let the EasyDriver board and the PC share the common ground. Otherwise the control signal from parallel port may not work (e.g., a high from parallel port is not high to the ground level of EasyDriver), or the parallel port might get burned.

Oh, one more thing, the EasyDriver board only drives bipolar stepper motors.

My circuit is prototyped on a breadboard like below:

The circuit takes power from the power supply of the desktop computer on which the control software will run. I used Pin 2 and Pin 4 of the parallel port to control the STEP and DIR on Easy Driver. MS1 and MS2 are grounded because I only use full step mode. I used two LEDs to show the signals from parallel ports.

Here is circuit in reality. As you can see, the circuit takes power from the old floppy disk power jack.


I used Saleae's Logic as a USB logic analyzer to check the waveforms. As you can see, for every rising edge on channel 4, the state of the first 4 channels change.

Software

At first I planned to use parapin, a C-based library for parallel port I/O. I used it when I was in college. After googling, I found out a Python module called PyParallel and it greatly simplifies software development.

I wrote a small piece of Python code below to control it.
"""This software is free software licensed under GNU GPL 3.0
Copyleft 2014 Forrest Sheng Bao http://fsbao.net

Dependencies: 
1. pyparallel: Can be installed on Ubuntu via
            sudo apt-get install python-parallel

Notes for Linux: 
1. make sure you execute
      sudo rmmod lp
           and
      sudo modprobe ppdev
  on your Unix shell first. 
2. Add yourself into lp user group on your system if you don't wanna use sudo all the time. 

Help the people under Communism tyranny in China, North Korea, Viet Nam and Cuba. 

"""

def rotate(Step, Dir, Step_Pin=5, Dir_Pin=2, Delay=0.25):
    """Rotate the motor by _Step_ steps in _Dir_ direction

    Input
    =======
    Step: integer
    Dir: string, 0 for clockwise and 1 for counterclockwise
    Step_Pin: int, the pin used to control stepping signal
    Dir_Pin: int, the pin used to control rotation direction
    Delay: float, the delay between each step. Do not set it 
           too small to exceed your motor's speed limit. 

    Notes
    =======
    The data pins in parallel ports are from 2 to 8. 

    """

    import parallel
    import time
    p = parallel.Parallel()

    p.setData(0)

    for i in range(int(Step)):
        p.setData(2 ** (Dir_Pin - 2) * Dir) # set or keep direction
        time.sleep(Delay)
        p.setData(2 ** (Dir_Pin - 2) * Dir + 2 ** (Step_Pin - 2)) # keep direction and rotate
        time.sleep(Delay)
    
#    p.setData(0)
    
if __name__ == "__main__" :
    import sys
    Step = int(sys.argv[1])
    Dir  = int(sys.argv[2])
    Delay = float(sys.argv[3])
    rotate(Step, Dir, Delay=Delay)


Note

1. The chip on EasyDriver can get really hot - up to 136 Celsius! Do not use it with a motor that requires lots of current and/or rotate the motor too frequently. Mine got burned out pretty soon. So I am ordering a motor with less torque but smaller current.
2. Do not send pulse to STEP pin of EasyDriver faster than the maximum speed of your motor. It will cause damage.

Questions and comments are all welcome!

References:

1. Easy Driver Example by Brain Schmalzhaus himself, http://www.schmalzhaus.com/EasyDriver/Examples/EasyDriverExamples.html
2. Easy Driver Example by Sparkfun, https://www.sparkfun.com/tutorials/400








2008-03-18

Why Z-transform is related to digital filter design

by Forrest Sheng Bao http://fsbao.net

A friend of mine asked me an interesting question: Why do we learn Z-transform and then study designing digital filter? Well, this is interesting. But the clue is simple.

By default, lowercase function name are in time domain and uppercase function names are in Z-domain, a.k.a discrete complex domain. Y or y means the output where as X or x means the input. H or h means the filter.

Abbreviations and notations:
ZT: z-Transform
FIR: Finite Impulse Response
IIR: Infinite Impulse Response
Z(x): performing z-transform on signal x

The Digital Filter and Transfer Function



A digital filter works on sampled, discrete time signal, rather than continuous signal as analog filters. There are only few operations we can play on time series: summation, scalar multiplication and delay. The flow of data can be backward, the feedback in IIR filter. For example, a smooth filter that averages 3 consecutive points can be built by summarize current input, previous input and the second previous input.

A digital filter has an input and an output, which are the original series and the filtered series respectively. If you consider a digital filter as a blackbox, the relationship between its input and output can be represented by a transfer function H(z) in Z domain:

H(z)= \frac{N(z)}{D(z)} = \frac{ b_0 + b_1 z^{-1} + b_2 z^{-2} + \cdots + b_L z^{-L} }{ 1+ a_1 z^{-1} + a_2 z^{-2} + \cdots + a_M z^{-M} } (1)

such that
Y(z) = X(z) H(z).

The inverse z-transform (iZT) of the transform function is the impulse response, which characterize the system behavior in time domain. Depending on whether the transfer function H(z) has denominators, the impulse response of the system can be finite or infinite and thus lead to two types of filters, FIR filter and IIR filter. Before explaining those two types, I need to introduce a very important property of ZT.

The Time-shifting Property of z-Transform and the building of Digital Filters



ZT can be considered as a discrete-time version of Laplace transform by discretized the time. ZT has the property known as time-shifting property that
Z[x(n-k)]=z^{-k}Z[x(n)].
The power over z at Z-domain means a delay in time domain. You cannot have positive power over z since in reality the system is causal. You cannot have a signal before it happens. Time domain summation, scalar multiplication and delay can be represented by the summation, coefficients and powers of z on the transfer function. That is why people always relate digital filter design with ZT. For example, in time domain, the I/O equation of a smooth filter is

y(n)=\frac{x(n)+x(n-1)+x(n-2)}{3} (2)

Apply iZT on both side of the equation and the time-shifting property of ZT, we have

Y(z) = X(z) H(z) = X(z) \frac{1+ z^{-1} + z^{-2}}{3}

So, once you see the transfer function, you know how to build such a filter in time domain.

Did we miss something? Oh, the feedback. As you can see, Eq. 2 has no feedback. Why? And what if I want a filter that has back-propagation in time domain?

FIR and IIR: The Difference on the Denominator



Take a look at Eq. 1, if you multiply the denominator on both sides of the equation, you will notice that the left hand side, the output side, contains the negative power of z, thus, the delay of output. Hence, if one coefficient of the denominators (a_i's) is not zero, the output is not only contributed by the input or its delays but also previous output, the feedback.

A clearer picture can be seen by transforming Eq .1 back to time domain:

y(n) = -a_1 y(n-1) - \cdots - a_M y(n-M) + b_0 x(n) + \cdots + b_L x(n-L)

If one a_i is not zero, the response to any input signal can be infinite since previous output will always contribute current output. For example,

y(n) = 2 y(n-1) + x(n) = 2 (y(n-2)+x(n-1)) + x(n) = 4(y(n-3)+x(n-2)) + 2 x(n-1) + x(n) = \cdots

To any finite input, the output of such system is infinite. The impulse response is also infinite. So, a digital filter that has a transfer function with at least a_i \noteq 0 is called an IIR filter.

The output will continue increase its value. Hence, the system is divergent. If you study the relationship between the transfer function and system stability, the system is stable and causal if and only if all poles lie inside the unit circle of the z-plane. An IIR filter may not be stable if you choose the bad denominator coefficients for its transfer function.

So, let's talk about FIR filter. If all denominator coefficients of the transfer function are 0, the output will purely depend on the input without any feedback from previous output. The response of an FIR filter to a finite input is finite, as in the example in Eq. 2 and 3. You can consider FIR filter as a special case (denominator=1) of IIR filter.