• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.
  • PLEASE: Read the FORUM RULES BEFORE registering!

Galil Code Files


Active User
Active Member
Hope the OP don't mind the thread drift I'm doing, sorry.

If you have a nine button JOG panel that you can connect to inputs 1 through 9 use this Jog routine I wrote: it works perfectly

'****************** Jog Buttons Program ***************
'Karl Townsend, Dassel, MN, USA
'Nine button Keypad installed, inputs 1,2 for X; 3,4 for Y
'5,6 for Z; 7,8 for A; 9 for fast jog
'buttons are wired NC, reverse logic if doing NO

'set beginning parameters(CN 1,1 set elsewhere)
#JOG ; SH ; JG 0,0,0,0 ; slow=5000 ; fast=25000

'main program loop jumps to sub on input
JS#XJOGF,@IN[1]=0 ; JS#XJOGR,@IN[2]=0
JS#YJOGF,@IN[3]=0 ; JS#YJOGR,@IN[4]=0
JS#ZJOGF,@IN[5]=0 ; JS#ZJOGR,@IN[6]=0
JS#DJOGF,@IN[7]=0 ; JS#DJOGR,@IN[8]=0

'eight subroutines below, one for each axis and direction
'line1 checks that input is still made exits if it isn't
'line2 exits if on a limit switch, note this is for NC switches
'line3 sets slew speed based on input9
'line4 restarts an axis if a limit switch was hit;
'line4 waits then loops if button still made or exits
'line5 sets speed back to 0 and exits subroutine

#XJOGF ; WT50 ; JP#END1,@IN[1]=1
IF(@IN[9]=0) ; JGX=fast ; ELSE ; JGX=slow ; ENDIF
IF(_SCX>1) ; BGX ; ENDIF ; WT100 ; JP#LOOP1,@IN[1]=0
#END1 ; JGX=0 ; WT100 ; EN

#XJOGR ; WT50 ; JP#END2,@IN[2]=1
IF(@IN[9]=0) ; JGX=-fast ; ELSE ; JGX=-slow ; ENDIF
IF(_SCX>1) ; BGX ; ENDIF ; WT100 ; JP#LOOP2,@IN[2]=0
#END2 ; JGX=0 ; WT100 ; EN

#YJOGF ; WT50 ; JP#END3,@IN[3]=1
IF(@IN[9]=0) ; JGY=fast ; ELSE ; JGY=slow ; ENDIF
IF(_SCY>1) ; BGY ; ENDIF ; WT100 ; JP#LOOP3,@IN[3]=0
#END3 ; JGY=0 ; WT100 ; EN

#YJOGR ; WT50 ; JP#END4,@IN[4]=1
IF(@IN[9]=0) ; JGY=-fast ; ELSE ; JGY=-slow ; ENDIF
IF(_SCY>1) ; BGY ; ENDIF ; WT100 ; JP#LOOP4,@IN[4]=0
#END4 ; JGY=0 ; WT100 ; EN

#ZJOGF ; WT50 ; JP#END5,@IN[5]=1
IF(@IN[9]=0) ; JGZ=fast ; ELSE ; JGZ=slow ; ENDIF
IF(_SCZ>1) ; BGZ ; ENDIF ; WT100 ; JP#LOOP5,@IN[5]=0
#END5 ; JGZ=0 ; WT100 ; EN

#ZJOGR ; WT50 ; JP#END6,@IN[6]=1
IF(@IN[9]=0) ; JGZ=-fast ; ELSE ; JGZ=-slow ; ENDIF
IF(_SCZ>1) ; BGZ ; ENDIF ; WT100 ; JP#LOOP6,@IN[6]=0
#END6 ; JGZ=0 ; WT100 ; EN

#DJOGF ; WT50 ; JP#END7,@IN[7]=1
IF(@IN[9]=0) ; JGD=(fast/2) ; ELSE ; JGD=slow ; ENDIF
IF(_SCD>1) ; BGD ; ENDIF ; WT100 ; JP#LOOP7,@IN[7]=0
#END7 ; JGD=0 ; WT100 ; EN

#DJOGR ; WT50 ; JP#END8,@IN[8]=1
IF(@IN[9]=0) ; JGD=-(fast/2) ; ELSE ; JGD=-slow ; ENDIF
IF(_SCD>1) ; BGD ; ENDIF ; WT100 ; JP#LOOP8,@IN[8]=0
#END8 ; JGD=0 ; WT100 ; EN


Global Moderator
Staff member
I like what you did with the _SC, never tried that one.

What controller are you using? Since you have a Input 9, I assume you are using a 5 or more axis controller.


Active User
Active Member
I have several machines using this JOG routine. Had to build my own using the low level Galil commands because keyboard jog SUXS and the one supplied by the software vendor had a latency issue (push the button then wait a sec for the machine to move)

Yep, figuring to use _SC was the secret here, had to make the routine bullet proof. My first several trials would hang on a limit switch. This routine is for a four axis control on 1850 to 1880 boards. I have the same thing on a lathe with five buttons and on a plasma table with seven.



Global Moderator
Staff member
I'm using a 1846 on my mill. I wrote my own Windows based program. I generate the DMC command strings from standard G-code then just drip them to the controller as needed.

For instance:
G0 X-20.0287 Y-5.1713 translates to XPOS=-508729;YPOS=-131351;ZPOS=0;VSRAPID=42333;XQ#G0,3

Which then executes this code
LI L,M,N<-1>(_VVS/20);LE;BG S

This code executes the rapid Z move first, then the X-Y linear move. This insures that the Z is in a safe position for rapid moves. A G1 vector move does not have the safe Z code in it so that it will cut a proper 3D profile. At the end of any operation it fires an interrupt to say "Hey, I'm done, I need something else to do"

For the jog functions, I can use the keyboard, mouse, or a touch screen (Send_DMCCommand "JGX =" & JGSlowX & ";BGX"). I just fire a STn on key up. If a limit is hit, it drops out the outputs (#LIMSWI;OP 0,0,65535), so I have to hand crank it off of the LS.
Last edited:


Active User
Active Member
Neat stuff there. Not often you meet another Galil bit head. :) I see you know exactly what I was talking about, when a limit switch is hit, the current program is dropped and Galil executes #LIMSW

I'm told Mach 3 has a plugin for Galil boards. I've never played with it. have you?

You'd also be a great candidate for Camsoft. But its awful expensive if you don't consult for them.



Global Moderator
Staff member
I did a retrofit on a 4-axis (basically has 2 independent Z-axes) CNC router for a customer using Mach3 CNC software and stepper motors and a couple of cheap parallel interface boards (this was not my system of choice, it was dictated by the customers’ budget). It worked pretty well except it would tend to lose pulses on turns and on the Z-axis. I could never get it exactly right no matter what adjustments I made. I finally tried installing a Galil Motion Control DMC-1846, 4-axis motion controller, and tried to run it on Mach3 with the Galil third party plug-in. That was a complete disaster. Mach3 was trying to micro-manage the very intelligent Galil card and Galil didn't like it one bit.

It would work OK, at slower speeds, but when brought up to normal production speeds it failed miserably. By production speeds, I mean cutting at 150 IPM with 300 IPM rapids. This failure was what prompted me to write my own software. I also closed the loop on the control by installing magnetic scales on it and am running the steppers as servos in velocity mode with an analog CMD signal. From the Galil perspective, it thinks it's running servo motors. That machine will now run accurately all day at 150 IPM, and is capable of 600 IPM rapids, but I have it limited to 300 IPM on the rapids.

Here is a screen shot of my mill software.

DC_CNC ScreenShot.jpg


Active User
Active Member
WOW, I'm impressed Jim.

You even have a graphics viewport. that's a feature I can't live without - shows you most of your mistakes in the Gcode.

I'm an I/O hog and everything must be opto-isolated. Used 72 on the Excello. Both lathes I built with 32 additional to the Galil card (3 axis - 8in 8out plus limits and homes) and ran out of I/O. Toolchangers and quality operator panels are the big ticket items here. Are you using more I/O than comes with Galil? I see they sell compatible PLC software and hardware.



Global Moderator
Staff member
Thank you.

The right hand viewport is the toolpath, data taken directly from the DRO, it does an overlay of the part so you can compare on a dry run for testing and when running.

72 I/O? That's a lot of I/O.

I power the inputs (both limits and the general use inputs) directly from the 12V rail on the breakout board which comes directly from the computer power supply. All of outputs are opto-isolated. I have the DB-14064 board installed. That gives an additional 64 I/O configurable as in or out in banks of 8 points. The extended I/O is all opto-isolated. Right now I am only using 3 general inputs, and 4 general outputs. I have a total easily available, 16 in and 16 out. I could add more, but I would have to install a different extended I/O rack. I will be using all of the available I/O when I finish building the operator control panel. Right now I am running everything from the keyboard and screen. I can operate everything from just the screen if needed.

It is possible to use the RIO-47xxx devices as extended I/O and coordinate their action with the main motion controller. These are better used with the 40x0 series of controllers, running in a master/slave configuration. You really can't do that with the 18xx series, you need to have a supervisor computer in the loop because there is no Ethernet or serial I/O port available on the 18xx series devices, both are available on the 40x0 devices.


Active User
Active Member
Say, this might interest you...

This macro does rigid power tapping on the CNC mill. A lot of the macro is written in the control's language but the real work is done with Galil. Should be easy for you to pick out (\## is just a variable name, the comment will explain the variable)

' G84
'format is G84 X_ Y_ Z_ R_ Q_ C_ L_
'check that spindle is off
IF #34=1 THEN MESSAGE Spindle running:EXIT
IF #35=1 THEN MESSAGE Spindle running:EXIT

IF\775=84THENGOTO :SKIP84 'second or later point on modal command

READOUT3 \850 'current Z position
ISTHERE X;\50;\851 'X axis coordinate
IF\50=0THEN MESSAGE Need X value:\851=x 'get X from last commanded move
ISTHERE Y;\50;\852 'Y axis coordinate
IF\50=0THEN MESSAGE Need Y value:\852=y 'get Y from last commanded move
ISTHERE Z;\50;\853 'Z axis coordinate
z=\850 'this stops crashes if operator forgets G80
ISTHERE R;\50;\854 'R axis coordinate
IF\50=0THEN \854={\850}: MESSAGE No R value, start at current Z from READOUT3
r=0 'this stops crashes if operator forgets G80
ISTHERE C;\50;\855 'C feed is 1/thread
IF\50=0THEN \855={f/s} 'calculate C from current feed and speed
IF\50=0THEN QUESTION No C (lead) value, use current speed and feed \855 ? ;\55;N:IF\55<>Y THEN EXIT
c=0 'this stops crashes if operator forgets G80
ISTHERE Q;\50;\857 'Q is peck value
IF\50=0THEN \857=0 'no peck, just all the way down and out
q=0 'this stops crashes if operator forgets G80
ISTHERE L;\50;\858:IF\858>1THEN\858=1 'L is left hand thread, any value results in \858=1
IF\50=0THEN \858=-1 'if no L value, right hand thread
l=0 'this stops crashes if operator forgets G80

:SKIP84 'don't collect Z,R,C,Q,L on second or later point in modal command

\864=0 'flag for second pass if peck cycle

'Calculate electronic gearing
'assume machine is in backgear, gear ratio is 92/15
'Z encoder is 20,000 spindle encoder is 4000 from CNCsetup
'a negative value makes Z go down on CW rotation \858 variable
'Feed per rev is in \855
\860={\858*\855*(20000/((92/15)*4000))} '\860 is electronic gear ratio
\860={(INT(100000*\860))/100000} 'round to five decimal places

'Calculate number of spindle turns in encoder counts for this 4000 count spindle encoder, back gear ratio is 92/15
' R plane - Z depth is distance; divide by Feed to get toal revolutions
\861={INT(((\854-\853)/\855)*4000*(92/15))} '(R plane - Z value) / thread pitch * encoder counts per rev.
\862={INT((\857/\855)*4000*(92/15))} '(Q peck distance) / thread pitch * encoder counts per rev.

'Calculate depth of tap pass
IF \862=0 THEN \863=\861 'no peck
IF \862>0 THEN IF \862<\861 THEN \863=\862 'if there's a peck value, and peck is less than total depth; move peck amount
IF \862>0 THEN IF \862>=\861 THEN \863=\861 'if toal depth less than peck, no peck

RAPID x;y 'rapid to x y position
RAPID ;;\854 'rapid to R plane, or current Z if no R

IF\864=1 THEN IF \863>\861 THEN \863=\861 'check not too deep on 2nd+ pass
IF \858=-1 THEN [SPINCW] 'right hand tap going down
IF \858=1 THEN [SPINCCW] 'left hand tap going down
'if first time through;FindIndex mark,set spindle to slave Z,electronic gear ratio

'NOTE changed to DP,,,,0 on 04 05 09 program bugging on FI

:TAPLOOPDOWN 'run spindle till total encoder counts
SLEEP 0.0025 'sleep 25 msec.
COMMAND MG_TPE 'get spindle encoder count
RESPONSE \866:IF \858=1 THEN \866={-1*\866} 'current counts; *-1 if left hand
IF \866>\863 THEN [STOPSPINDLE]:GOTO :TAPBOTTOM 'run spindle till total encoder counts

:TAPBOTTOM 'back tap out
IF \858=1 THEN [SPINCW] 'right hand tap going up
IF \858=-1 THEN [SPINCCW] 'left hand tap going up

:UPTAPLOOP 'run spindle till total encoder counts
SLEEP 0.0025
RESPONSE \866:IF \858=1 THEN \866={-1*\866} 'current counts; *-1 if left hand
IF \866<O THEN [STOPSPINDLE]:GOTO :DONETAP 'tap is back to the top

IF \863<{\861-250} THEN \863={\863+\862}:\864=1:GOTO :pECKLOOP
'\864 flag for second pass
'made {861- 250} to not do another pass if very close to depth
'if not at full depth, add peck value to depth, set flag for second+pass, start again

COMMAND GR ,,0 'turn off electronic gearing
'MACHHOME3 \868 'current home readout
'MACHZERO ;;\868 'rezero to current home readout
'NOTE: Above 4 lines needed because registers get confused with electronic gearing


'bugs below if using tool offsets
READOUT3 \869 'current Z position
HOMEZ \869
'NOTE first four lines above bugging 04 10 09, second trial

RAPID ;;\850 'rapid to Z start plane