 |  | |
My Senior Project: Computer Guided LaserDirectron Scholarship 2008 Essay No. 45
by Nicholaus Antony Lacock
Current School: Senior at Pequea Valley High school
Intended School: Massachusetts Institute of Technology, Stanford University, Yale University, Cornell University, Carnegie Mellon University, Princeton University, Penn State (main campus) University, and University of Delaware
Although I have always been interested in science and technology, but until this summer I remained relatively ignorant to the field of computers and electronics. For this reason, I chose a senior project that would give me a reason to investigate: a computer guided carbon-dioxide laser. I started from scratch at the end of last school year, and spent most of my summer vacation researching and reading up on Python programming language and the field of electronics. After hours of reading and practicing code, I have acquired a decent handle on the language. In this paper I will explain how the computer will aim the laser and the code that I have written so far.
The laser will remain stationary and pointing at a stationary mirror at 45 degrees. That mirror then reflects the beam onto a second, moving mirror. The second mirror is controlled by two separate bipolar stepper motors; one that controls vertical movement and another that controls horizontal movement. They are both interfaced through the parallel port, through a micro-controller that I built myself.
Stepper motors are unique in that rather than free spinning, they rotate by precise amounts every time a current is applied to opposite poles. The advantage of this type of motor is that it operates on a binary truth table, plus it allows for exact positioning. A bipolar step motor has four inputs that are connected to four electromagnetic coils. In the center, there is a polarized magnet that is attached to the rotating shaft. By rotating the positive charge around the four motors, the center magnet is magnetically attracted to each coil in succession. Below is a diagram that illustrates the movement of the motor.
In Phase 1, the opposite coils 2 and 4 are energized. In Phase 2, the negative charged is rotated to the left, and coils 1 and 3 are energized. Phase 3 is the opposite of Phase 1, and Phase 4 is the opposite of Phase 2. Essentially, the south side of the inner magnet is attracted to the negatively charged coil, and the north side is attracted to the positively charged coil. In the table, 1 means a charge, and 0 no charge, and shows a full rotation of the stepper motor.
| | Coil 1 | Coil 2 | Coil 3 | Coil 4 |
| Phase 1 | 0 | 1(-) | 0 | 1(+) |
| Phase 2 | 1(-) | 0 | 1(+) | 0 |
| Phase 3 | 0 | 1(+) | 0 | 1(-) |
| Phase 4 | 1(+) | 0 | 1(-) | 0 |

The analog controller used to drive the stepper motor is called an H-bridge. It takes four signal inputs, and sends currents across a coil. Depending on which two of the four inputs is set high or low, the bridge is capable of sending current across a coil in either direction. Below is a schematic diagram of an H-bridge.

http://www.piclist.com/techref/piclist/jal/DrivingBipolarStepperMotors.htm 2000 G.Shearer
Therefore, by setting Q1 and Q3 to high, current would flow across the coil in the opposite direction it would by setting Q2 and Q4 high. In my situation, the motor coil is representative of two opposite coils of the step motors. This means that one step motor would require two H-bridges and eight inputs.
However, since phases 1 and 3 are opposite, as are phases 2 and 4 (see diagram above), by oscillating polarity externally we can narrow the number of inputs needed per H-bridge to two. I am using an integrated circuit that has four H-bridges, and an internal oscillator: perfect for controlling two stepper motors with only eight inputs!
Here is where the programming comes in. With this setup, we need four inputs per motor, two for each side of each motor. A 10 output will generate a forward step, and a 01 generates a backward step. So a full forward rotation for one motor would be made of the following nibbles sent in sequence: 1000 0010 1000 0010. Since there are two motors (one for vertical motion and one for horizontal motion), each output is sent in a sequence of a single byte. A full forward rotation for both motors is then predictable: 10001000 00100010 10001000 00100010.
For the first phase of my project, I have written software that uses a simple graphic interface where the user supplies a number of steps in each direction (as an integer) and a duration (of the laser pulse). It is based upon the x-y plane, horizontal being x and vertical being y. Therefore, positive values generate movement to the right (in the x direction) and up (in the y direction) and visa versa with negative values.
The most basic part of the control software takes three arguments: a number of steps in the x and y direction, and a duration. The duration is simply passed through the functions of the program with a default value of three seconds. The steps are a little harder to deal with. First, an empty list is constructed called output, with the default value of nothing (an empty list).
def oc(self,numStepx,numStepy,Duration=3,output=[]):
The "self" is a value necessary for placing the function in a class. The two "numStep" arguments refer to the number of steps supplied by the user. Once the function "oc" receives its values, it performs a series of tests, checking to see if any of the values are zero. If they are, it sends values to a function called "zeroPad" that handles values of zero, among other things.
if numStepx==0:
if numStepy==0:
Output().zeroPad(0,None,Duration)
else:
Output().zeroPad(numStepy,'y',Duration)
elif numStepy==0:
Output().zeroPad(numStepx,'x',Duration)
The above logic is to determine which, if any, value is zero and then sends arguments to "zeroPad" accordingly. The next set of tests determines which values are positive, which are negative, and then selects a two-bit binary string to match the direction it represents. As I explained above, 10 is right/up and 01 is left/down.
else:
if numStepx>0:
self.directionx='10'
if numStepx<0:
self.directionx='01'
if numStepy>0:
self.directiony='10'
if numStepy<0:
self.directiony='01'
In order to achieve maximum efficiency, the program needs to be able to send instructions to both motors at the same time. This means that if there are more steps in one axis than the other, there will be a series of binary instructions containing information for both axes, followed by a series of instructions for just one axis. To do so, the program uses a built-in function called "min()" which returns the smallest of two numbers in the form of an integer, and a function called "abs()" which returns the absolute value of each number. This number is stored in the variable "minnum" and is the number of steps that will contain instructions for both axes.
minnum=min(abs(numStepx),abs(numStepy))?
The next part then builds a list of binary strings and stores them in the list "output". It uses the two Unicode operators "!=" and "%", the first meaning "does not equal" and "the remainder of" respectfully. "Range(n)" is a function that returns a tuple (a set of values, separated by commas and enclosed by parentheses that is immutable) of the values from 0 to n-1. The "for" iterator takes each value from 0 to minnum-1 and checks to see if they have a remainder when divided by two (are even numbers). The logic following then puts even numbers in the first half of each nibble and odd numbers in the second half. This provides the higher-level oscillation necessary to drive the stepper motors.
for i in range(minnum):
if i%2!=0:
output.append('%s00%s00' %(self.directionx,self.directiony))
else:
output.append('00%s00%s' %(self.directionx, self.directiony))
It is also worth explaining the "%s" signs above. This is a concept called string formatting, and it allows a sub-string to be placed in the middle of a larger string. The values that are to be placed in the "%s" spot are enclosed in parentheses and preceded by a % sign. Once the binary list has been constructed, the function passes all the values to the function "numStepFinder".
Output().numStepFinder(numStepx,numStepy, minnum, Duration, output)
The function "numStepFinder" is an intermediate function that determines the number of steps remaining that will contain instructions for only one axis motor. It performs a series of tests, and depending whether the values are positive, negative, or equal, it performs the necessary addition or subtraction, and then passes the number of remaining steps and the axis that still needs instructions along to the function "zeroPad". It also uses another built-in function called "max()" that is similar to the function "min()", only it finds the maximum rather than the minimum.
def numStepFinder(self, numStepx, numStepy, minnum, Duration, output):
self.rmin=min(numStepx,numStepy)
self.rmax=max(numStepx,numStepy)
if self.rmin==self.rmax:
numStep=0
elif self.rmin>0 and self.rmax>0:
if self.rmin==numStepx:
numStep=numStepy-numStepx
else:
numStep=numStepx-numStepy
elif self.rmin<0:
if self.rmax<0:
numStep = self.rmin-self.rmax
else:
numStep = self.rmin+self.rmax
elif self.rmax<0:
if self.rmax<0:
numStep = self.rmax-self.rmin
else:
numStep = self.rmin+self.rmax
if minnum==abs(numStepx):
Output().zeroPad(numStep, 'y', Duration, output)
elif minnum==abs(numStepy):
Output().zeroPad(numStep, 'x', Duration, output)
Now, on to the function "zeroPad". As I have alluded to before, the main task of this function is to add blank instructions to one axis and correct instructions to the other while still maintaining the oscillation as mentioned before. This function takes 5 arguments: the normal "self" argument, an integer for the remaining number of steps, the axis that needs that number of steps, and the two that are passed through the whole program "Duration" and "output".
def zeroPad(self,numStep,yOrX,Duration,output=[]):
First, it checks to see if the number of steps is positive, negative, or zero and then chooses the corresponding binary string. If the number of steps is zero, then there is no further modification needed and the function skips the next part.
if numStep==0:
pass
if numStep>0:
self.direction='10'
elif numStep<0:
self.direction='01'
Next, it checks to see which axis needs further instructions. The x-axis motors are controlled by the first nibble and the y-axis by the second. It oscillates in the same manner as the function "oc".
if yOrX=='x':
for i in range(abs(numStep)):
if i%2!=0:
output.append('%s000000' %self.direction)
else:
output.append('00%s0000' %self.direction)
elif yOrX=='y':
for i in range(abs(numStep)):
if i%2!=0:
output.append('0000%s00' %self.direction)
else:
output.append('000000%s' %self.direction)
This function uses another built-in function that you may have noticed before: "append()". This built-in simply adds values onto the end of a list, so output.append(n) just adds the value "n" onto the end of the list "output". The final task of this function is to send the completed list of binary strings to the function "wrapUp".
Output().wrapUp(Duration,output)
The final two functions "wrapUp" and "send" are quite simple. Wrap-up simply converts the list of strings into a list of real binary integers and stores them in a list "numStepOut". It uses another built-in called "int()", which takes two arguments. The first is a string of numbers, and the second is an integer that selects the type of integer. By providing "2" as the second argument, the function constructs a binary integer. It then passes the list onto the function "send".
def wrapUp(self, Duration, output):
numOut=[]
for string in output:
numOut.append(int(string,2))
Output().send(Duration,numOut)
"Send" is the final function in the program. It calls the module "Parallel" and writes the list of binary numbers ("numOut") to the parallel port. It then sets pin 16 (or initOut) to high and waits for the supplied duration before setting it low again. Pin 16 controls the laser. The AutoFeed pin is hooked up to a certain pin of the integrated circuit that turns it on or off. By setting that pin to 1, it turns the IC off and it draws less power.
def send(self,Duration,numOut):
import parallel, time
par = parallel.Parallel()
for num in numOut:
par.setData(num)
par.setInitOut(1)
time.sleep(Duration)
par.setInitOut(0)
par.setAutoFeed(1)
I have interfaced this program using a graphic user interface module called wxPython. It is based upon the C++ GUI toolkit wxWidgets. The code for it is not very interesting, and using the code is largely derived from knowledge of the functions rather than logic. For this reason, I am not going to include the code for the GUI. I will give credit to the book "wxPython in Action", however. It has served as my reference for code and all the functions and subtleties of wxPython. Below is a screenshot of the GUI in action.

So, as you can see, I have spent a lot of time and thought into this project thus far, and I am excited to see the results. In the coming months, I plan on finishing construction on the aiming device and interfacing it with a more intuitive control system. By incorporating a camera, I hope to be able to aim the laser by simply clicking on a live image. I have already begun code to handle images and provide a more comprehensive GUI, but I plan on using the code explained here to construct and send binary instructions. I apologize for the length of the essay, but I felt it was necessary to fully explain it. Thanks for your time; I hope you have enjoyed reading my essay.
Sources (in MLA format):
Hetland, Magnus Lie. Beginning Python. New York, NY: Apress, 2005.
Rappin, Noel, and Robin Dunn. wxPython in Action. Greenwich, CT: Manning Publications Co., 2006
Shearer, G. "Driving Bipolar Stepper Motors." PicList. 2000. 4 Feb 2009
.
|
|
Shipping Policy |
|
Customer Services |
|
Payment Policy |
|
|
Est. Shipping
Cost
Time-in-Transit Map
FAQ - Shipping
Top Reasons for
Delays
UPS,
FedEx,
Postal
Office
Walk-in Sales
APO/FPO Shipping
International
Tracking Orders |
Return Rates
Store Statistics
Customer Satisfaction
Account Applications
Frequent Errors
FAQ-Services
FAQ-Tech Support
Newsletter
Order Status |
Credit Card via Phone
Purchase Order
Prepay, PayPal
Resellers
Corporate
Schools,
Government
Terms & Conditions
Price & Tax
FAQ-Payment
|
|
Top Brands |
|
Abit,
Acer,
AMD, Antec,
AOpen,
Asus,
ATI,
Biostar,
Buffalo,
Cooler Master, Corsair, Creative, Dell, D-Link,
Enermax,
FSP,
Gigabyte,
Hauppauge,
HP,
Intel,
InWin,
Kingston,
Lenovo,
Lian-Li,
Linksys,
Lite-On,
Logisys,
Logitech,
Maxtor,
Microsoft,
MSI,
Mushkin,
Netgear,
OCZ,
Seagate,
Shuttle,
Sony,
SuperMicro,
ThermalTake,
Vantec,
ViewSonic,
Western Digital,
XFX,
Zalman.
|
Have a question about our products, services or technical issues? Find the answer instantly! Type your question or key words in English:
95% email/ phone questions already have answers on our web site.
|
Copyright (c) 1997-2009 Directron.com, Inc., Houston, Texas
Buy -
Sell -
Trade -
Build -
Repair -
Upgrade -
Help -
Troubleshoot -
Shopping
Computers -
Laptops -
Servers -
Hardware -
Parts -
Software -
Peripherals -
Services
High Quality -
Low Prices -
Discount Shop -
Large Selection -
Free Products -
Fast Shipping
Affiliates: Dallas Computer Store - San Antonio Computer Store - K12 Education Computer Systems |
|  |