|
To remind myself what I did, and to share with anyone who may be interested, I decided to record the details on a web page. The machine was designed to be cheaply made in a home workshop equipped with a lathe, drilling machine and a selection of hand tools.
M.D.F chipboard was chosen for the base board, this floor grade material is sufficiently stable for the job, and looks nice when its varnished! For the slides to create the 'x' and 'y' axis, I used 1 inch (25.4mm) diameter seamless mild steel tubing.
Two parallel tubes form the 'y' axis, and two more tubes forming a travelling bridge run on the 'y' axis tubes. A trolley running along the travelling bridge forms the 'x' axis, this in turn carries the vertical 'z' axis. Drive is by stepper motors, each motor turns a 12mm diameter threaded bar, with corresponding M12 threaded nuts attached to the moving elements , except for the 'z' axis, which is raised and lowered manually. The problem of ensuring the 'x' axis bridge stayed square to the 'y' axis bars was solved by each 'y' axis guide bar having it's own motor and threaded bar. The two motors are only synchronised electrically, there is no mechanical connection between the two. Connection to the computer is made via the parallel printer port.
The port connects to a circuit board that displays the status of the port's outputs on 8 led's. These outputs are also taken from the board's switching transistors to a 9-way 'D' socket, and this in turn taken to extra output transistors that are capable of carrying the current required to power the stepper motors. The 'y' axis and 'x' axis motors use 4 of the 8 available outputs each. At the bottom of the page I've included a link if you want to know more about parallel port connections and stepper motors. Control software was written in Qbasic for dos. The full program can be seen in the column to the right of this page. To create the analemma profiles for the sundial, the profile 'x' and 'y' values are calculated by another program that is not described here,
and the profile is read into the machine control program.
The program sends motor step instruction as a series 'LPRINT' commands that are received by the motor electronics from the parallel port. Links and future project. The reason I wanted to re-visit this 1995 project is because for future
projects (as yet undecided),I want to learn computer machine control using Linux and programming in 'C', and I don't know much about either subject, so re-writing the basic program in 'C' would be a good introduction.
Please feel free to email me, Peter Daykin if you want to know any more, or perhaps have a better way of doing things to share with me. The finished sundial can be seen on the Derbyshire Sundials site. http://www.pandy.me.uk/sundials/pdsdials.htm Lots of useful stuff can be found on Ian Harries pages, starting with stepper motors at http://www.doc.ic.ac.uk/~ih/doc/stepper/ He also covers interfacing to the computer parallel printer port. Update 27 January 2006 Re-writing the program in C
is moving ahead slowly, I have the 'x' and 'y' axis motors working from my Linux box with linear interpolation of the 'x' and 'y'
axis plus I've managed to find out how to ramp the motor speed up and down, that's something that defeated me in the dos
version. A new link to give inspiration to anyone looking for a stepper motor machine tool project.
This version 30 November 2008 |
DECLARE SUB Ring () DECLARE SUB Readme () DECLARE SUB control () DECLARE SUB Fileplot () DECLARE SUB Keydrive () DECLARE SUB Menudisp () DECLARE SUB Stepdrive () DECLARE SUB Filein () DECLARE SUB Delay () '*********************** 'Title "STEPOUT" 'Version 1.4 7-1-95....Circle added 'Description - input motor steps and output to stepper driver 'Written P.L.Daykin Nov 93 'QBASIC '*********************** DECLARE SUB Xmax270 () DECLARE SUB Xmax360 () DECLARE SUB Ymax270 () DECLARE SUB Ymax360 () DECLARE SUB Xmax180 () DECLARE SUB Ymax180 () DECLARE SUB Testquad () DECLARE SUB Quadout180y () DECLARE SUB Quadout270y () DECLARE SUB Quadout360y () DECLARE SUB Ymax90 () DECLARE SUB Quadout90y () DECLARE SUB Xmax90 () DECLARE SUB Quadout90xy () DECLARE SUB Quadout90x () DECLARE SUB Quadout180xy () DECLARE SUB Quadout180x () DECLARE SUB Quadout270xy () DECLARE SUB Quadout270x () DECLARE SUB Quadout360xy () DECLARE SUB Quadout360x () DEFSNG A-Z DIM SHARED xinc DIM SHARED yinc DIM SHARED xprev DIM SHARED yprev DIM SHARED c DIM SHARED a(367, 3) DO 'LPRINT CHR$(0) CALL Menudisp LOCATE 19, 35: INPUT "Item "; item IF item = 1 THEN CALL Keydrive ELSEIF item = 2 THEN CALL Stepdrive ELSEIF item = 3 THEN CALL Filein ELSEIF item = 4 THEN CALL Fileplot ELSEIF item = 5 THEN LPRINT CHR$(0) ELSEIF item = 6 THEN CALL Ring ELSEIF item = 7 THEN CALL Readme END IF LOOP END SUB control DIM p AS STRING IF c = 99 THEN EXIT SUB ELSEIF c = 71 THEN EXIT SUB ELSEIF c = 73 THEN PRINT "*** PEN UP ***" ELSEIF c = 81 THEN PRINT "*** PEN DOWN ***" END IF LPRINT CHR$(0) PRINT "Press enter" p = INPUT$(1) END SUB SUB Delay DIM n AS INTEGER speed = 250 FOR n = 1 TO speed NEXT n END SUB SUB Filein DIM F AS STRING DIM n AS INTEGER DIM filenum AS INTEGER CLS INPUT "Filename..in inverted commas "; F OPEN "I", #1, F DO n = n + 1 INPUT #1, a(n, 1)'----xabs INPUT #1, a(n, 2)'----yabs INPUT #1, a(n, 3)'----control number 73 pen up 81 pen down LOOP UNTIL a(n, 3) = 71 CLOSE 'SLEEP 0 END SUB SUB Fileplot DIM p AS STRING CLS scale = 2 xdatumshift = 0 ydatumshift = 0 n = 1 xinc = INT((a(1, 1) + xdatumshift) * scale)'--first move from yinc = INT((a(1, 2) + ydatumshift) * scale)'-- x y zero c = a(1, 3) xinctot = xinc yinctot = yinc CALL Testquad CALL control'------------pen control DO n = n + 1 ink$ = INKEY$ IF ink$ <> "" THEN PRINT "** PEN UP ** back to x y zero" p = INPUT$(1) xinc = 0 - xinctot yinc = 0 - yinctot CALL Testquad EXIT DO END IF xabs = (a(n, 1) + xdatumshift) * scale yabs = (a(n, 2) + ydatumshift) * scale c = a(n, 3) IF c = 71 THEN PRINT "*** HOME / PEN UP *** press enter" p = INPUT$(1) END IF xinc = INT(xabs) - xinctot yinc = INT(yabs) - yinctot xinctot = xinc + xinctot yinctot = yinc + yinctot CALL Testquad CALL control PRINT , " n "; n, "xinc "; xinc, "yinc "; yinc, "control "; c LOOP UNTIL c = 71 PRINT : LPRINT CHR$(0) PRINT "Press enter.... run complete" p = INPUT$(1) END SUB SUB Keydrive DIM k AS STRING DIM scancode AS INTEGER CLS PRINT "Press escape to exit" DO DO k = INKEY$ LOOP UNTIL k <> "" IF LEN(k) = 1 THEN IF k <> CHR$(27) THEN PRINT "You entered "; k END IF ELSE scancode = ASC(MID$(k, 2, 1)) SELECT CASE scancode CASE 72 CALL Quadout90y'---------------------Up arrow yprev = yprev + 1 CASE 80 CALL Quadout270y'--------------------Down arrow yprev = yprev - 1 CASE 75 CALL Quadout180x'--------------------Left arrow xprev = xprev - 1 CASE 77 CALL Quadout90x'---------------------Right arrow xprev = xprev + 1 END SELECT END IF LOOP UNTIL k = CHR$(27) END SUB SUB Menudisp '********************************************* SCREEN 9: COLOR 14, 1: CLS LINE (5, 7)-(635, 335), , B LOCATE 1, 28: PRINT "** X Y Drive control **" COLOR 11, 1 LOCATE 5, 32: PRINT "1) Keydrive" LOCATE 7, 32: PRINT "2) Stepdrive" LOCATE 9, 32: PRINT "3) Input file" LOCATE 11, 32: PRINT "4) Plot file" LOCATE 13, 32: PRINT "5) Power off" LOCATE 15, 32: PRINT "6) Circle" LOCATE 17, 32: PRINT "7) Info'" END SUB SUB Quadout180x LPRINT CHR$(6) CALL Delay LPRINT CHR$(10) CALL Delay LPRINT CHR$(9) CALL Delay LPRINT CHR$(5) PRINT "Quadout180x" END SUB SUB Quadout180xy LPRINT CHR$(102) CALL Delay LPRINT CHR$(170) CALL Delay LPRINT CHR$(153) CALL Delay LPRINT CHR$(85) PRINT "Quadout180xy" END SUB SUB Quadout270xy LPRINT CHR$(150) CALL Delay LPRINT CHR$(170) CALL Delay LPRINT CHR$(105) CALL Delay LPRINT CHR$(85) PRINT "Quadout270xy" END SUB SUB Quadout270y LPRINT CHR$(144) CALL Delay LPRINT CHR$(160) CALL Delay LPRINT CHR$(96) CALL Delay LPRINT CHR$(80) PRINT "Quadout270y" END SUB SUB Quadout360xy LPRINT CHR$(153) CALL Delay LPRINT CHR$(170) CALL Delay LPRINT CHR$(102) CALL Delay LPRINT CHR$(85) PRINT "Quadout360xy" END SUB SUB Quadout90x LPRINT CHR$(9) CALL Delay LPRINT CHR$(10) CALL Delay LPRINT CHR$(6) CALL Delay LPRINT CHR$(5) PRINT "Quadout90x" END SUB SUB Quadout90xy LPRINT CHR$(105) CALL Delay LPRINT CHR$(170) CALL Delay LPRINT CHR$(150) CALL Delay LPRINT CHR$(85) PRINT "Quadout90xy" END SUB SUB Quadout90y LPRINT CHR$(96) CALL Delay LPRINT CHR$(160) CALL Delay LPRINT CHR$(144) CALL Delay LPRINT CHR$(80) PRINT "Quadout90y" END SUB SUB Readme CLS PRINT "Keydrive will move x and y axis by using the keyboard arrow keys." PRINT "Stepdrive uses input in motor steps, 1*4 steps = 1.75mm/12 = 0.1458mm" PRINT "or 0.00574 inch. Note that Stepdrive works in absolute, the x y zero " PRINT "position for both Stepdrive and Keydrive is set from Stepdrive after" PRINT "moving to the required position." PRINT "Filein reads in from the disc drive included in the file spec'." PRINT "Fileplot moves x and y axis to the data in Filein, including onscreen" PRINT "instructions for pen up/down. If escape is pressed in cycle, the axis" PRINT "move back to x y zero. X y zero is taken from the position of the axis" PRINT "at cycle start, and is independant of Stepdrive x y zero." PRINT "Move the axis round before inputting the file to settle the motors." PRINT "Circle draws with centre at x y zero, and pen down is at 3 o'clock." PRINT TAB(25); "***Press esc' to exit***" DO k$ = INKEY$ LOOP UNTIL k$ = CHR$(27) END SUB SUB Ring CLS DIM p AS STRING ppi = 8 * ATN(1) s = ppi / 1440 rad = 174 PRINT "Rad is set at "; rad; " this gives a rad of 1 inch" INPUT "Alter rad ? Y \ N "; a$ IF a$ = "y" THEN INPUT "New rad "; rad ELSEIF a$ = "Y" THEN INPUT "New rad "; rad END IF PRINT "x , y zero is at circle centre." PRINT "Press escape to return" PRINT "***PEN UP*** press enter" p = INPUT$(1) xinc = rad yinc = 0 xinctot = xinc yinctot = yinc CALL Testquad PRINT "***PEN DOWN*** press enter" p = INPUT$(1) FOR n = 0 TO ppi STEP s ink$ = INKEY$ IF ink$ <> "" THEN PRINT "***PEN UP*** press enter" p = INPUT$(1) xinc = 0 - xinctot yinc = 0 - yinctot CALL Testquad EXIT SUB END IF xabs = COS(n) * rad yabs = SIN(n) * rad xinc = INT(xabs) - xinctot yinc = INT(yabs) - yinctot xinctot = xinc + xinctot yinctot = yinc + yinctot CALL Testquad NEXT n PRINT "***PEN UP*** press enter" p = INPUT$(1) xinc = 0 - xinctot yinc = 0 - yinctot CALL Testquad LPRINT CHR$(0) PRINT "Press enter.... run complete" p = INPUT$(1) END SUB SUB Stepdrive DIM k AS STRING CLS DO LPRINT CHR$(0) PRINT "***************" INPUT " Q to quit or Z to zero x and y "; k IF k = LCASE$("q") THEN EXIT SUB ELSEIF k = LCASE$("z") THEN xabs = 0: yabs = 0: xprev = 0: yprev = 0 PRINT "x and y now at zero for Keydrive and Stepdrive" END IF INPUT "xabsolute "; xabs INPUT "yabsolute "; yabs xinc = xabs - xprev yinc = yabs - yprev xprev = xabs yprev = yabs CALL Testquad LOOP END SUB SUB Testquad IF xinc >= 0 AND yinc >= 0 THEN '--------test for quadrant quad = 90 ELSEIF xinc < 0 AND yinc >= 0 THEN quad = 180 ELSEIF xinc <= 0 AND yinc < 0 THEN quad = 270 ELSEIF xinc > 0 AND yinc < 0 THEN quad = 360 ELSE PRINT "Test for quadrant fault" END IF xinc = ABS(xinc)'----------remove minus sign if present yinc = ABS(yinc) IF xinc >= yinc AND quad = 90 THEN '-----test for Xmax90 etc CALL Xmax90 ELSEIF yinc >= xinc AND quad = 90 THEN CALL Ymax90 EXIT SUB END IF IF xinc >= yinc AND quad = 180 THEN '-----test for Xmax180 CALL Xmax180 ELSEIF yinc >= xinc AND quad = 180 THEN CALL Ymax180 EXIT SUB END IF IF xinc >= yinc AND quad = 270 THEN '-----test for Xmax270 CALL Xmax270 ELSEIF yinc >= xinc AND quad = 270 THEN CALL Ymax270 EXIT SUB END IF IF xinc >= yinc AND quad = 360 THEN '-----test for Ymax360 CALL Xmax360 ELSEIF yinc >= xinc AND quad = 360 THEN CALL Ymax360 END IF END SUB SUB Xmax180 'Stepper x y linear interpolation IF yinc = 0 THEN mult = xinc GOTO X180 END IF mult = xinc / yinc - .001 X180: ystep = 1 FOR xstep = 1 TO xinc IF (ystep * mult) < xstep THEN ystep = ystep + 1 CALL Quadout180xy ELSE CALL Quadout180x END IF NEXT END SUB SUB Xmax270 'Stepper x y linear interpolation mult = xinc / yinc - .001 ystep = 1 FOR xstep = 1 TO xinc IF (ystep * mult) < xstep THEN ystep = ystep + 1 CALL Quadout270xy ELSE CALL Quadout180x END IF NEXT END SUB SUB Xmax360 'Stepper x y linear interpolation mult = xinc / yinc - .001 ystep = 1 FOR xstep = 1 TO xinc IF (ystep * mult) < xstep THEN ystep = ystep + 1 CALL Quadout360xy ELSE CALL Quadout90x END IF NEXT END SUB SUB Xmax90 'Stepper x y linear interpolation IF yinc = 0 THEN mult = xinc GOTO X90 END IF mult = xinc / yinc - .001 X90: ystep = 1 FOR xstep = 1 TO xinc IF (ystep * mult) < xstep THEN ystep = ystep + 1 CALL Quadout90xy ELSE CALL Quadout90x END IF NEXT END SUB SUB Ymax180 'Stepper x y linear interpolation mult = yinc / xinc - .001 xstep = 1 FOR ystep = 1 TO yinc IF (xstep * mult) < ystep THEN xstep = xstep + 1 CALL Quadout180xy ELSE CALL Quadout90y END IF NEXT END SUB SUB Ymax270 'Stepper x y linear interpolation IF xinc = 0 THEN mult = yinc GOTO Y270 END IF mult = yinc / xinc - .001 Y270: xstep = 1 FOR ystep = 1 TO yinc IF (xstep * mult) < ystep THEN xstep = xstep + 1 CALL Quadout270xy ELSE CALL Quadout270y END IF NEXT END SUB SUB Ymax360 'Stepper x y linear interpolation mult = yinc / xinc - .001 xstep = 1 FOR ystep = 1 TO yinc IF (xstep * mult) < ystep THEN xstep = xstep + 1 CALL Quadout360xy ELSE CALL Quadout270y END IF NEXT END SUB SUB Ymax90 'Stepper x y linear interpolation IF xinc = 0 THEN mult = yinc GOTO Y90 END IF mult = yinc / xinc - .001 Y90: xstep = 1 FOR ystep = 1 TO yinc IF (xstep * mult) < ystep THEN xstep = xstep + 1 CALL Quadout90xy ELSE CALL Quadout90y END IF NEXT END SUB |