Public feed #890610

Mine

public text v1 · immutable
Raw Edit
·published 2008-02-03 21:56 UTC
rendered paste body
#!/usr/local/bin/python

"""
    Counterbore G-Code Generator
    BETA Version
    Copyright (C) <2008>  <John Thornton>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    e-mail me any suggestions to "jet1024 at semo dot net"
    If you make money using this software
    you must donate $20 USD to a local food bank
    or the food police will get you! Think of others from time to time...
    
    To make it a menu item in Ubuntu use the Alacarte Menu Editor and add 
    the command python YourPathToThisFile/face.py
    make sure you have made the file execuatble by right
    clicking and selecting properties then Permissions and Execute
    
    To use with EMC2 see the instructions at: 
    http://wiki.linuxcnc.org/cgi-bin/emcinfo.pl?Simple_EMC_G-Code_Generators

"""
from Tkinter import *
from math import *
import tkMessageBox
import os

IN_AXIS = os.environ.has_key("AXIS_PROGRESS_BAR")

class Application(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.grid()
        self.createWidgets()

    def createWidgets(self):
        self.title = Label(self, text='Socket Head Cap Screw Counterbore G-Code Generator')
        self.title.grid(row=0, column=0, columnspan=10)

        self.cl1 = Label(self, text=' Number SHCS ')
        self.cl1.grid(row=1, column=0)
        self.SHCS1=[(' 0',1),(' 1',2),(' 2',3),(' 3',4),(' 4',5),
        (' 5',6),(' 6',7),(' 8',8),('10',9),('12',10)]
        self.var1 = IntVar()
        for text, value in self.SHCS1:
            self.rb1 = Radiobutton(self, text=text, value=value, variable=self.var1,
            font="monospace 10")
            self.rb1.grid(column=0,row=value+1)
            self.rb1.bind("<ButtonRelease-1>", self.rb1event)
        self.var1.set(0)
        
        self.cl2 = Label(self, text=' Fraction SHCS ')
        self.cl2.grid(row=1, column=1)
        self.SHCS2=[('  1/4',1),(' 5/16',2),('  3/8',3),(' 7/16',4),('  1/2',5),
        (' 9/16',6),('  5/8',7),('  3/4',8),('  7/8',9),('1    ',10),
        ('1-1/8',11),('1-1/4',12),('1-1/2',13),('1-3/4',14),('2    ',15)]
        self.var2 = IntVar()
        for text, value in self.SHCS2:
            self.rb2=Radiobutton(self, text=text, value=value, variable=self.var2,
            font="monospace 10")
            self.rb2.grid(column=1,row=value+1)
            self.rb2.bind("<ButtonRelease-1>", self.rb2event)

        self.cl3 = Label(self, text=' Metric SHCS ')
        self.cl3.grid(row=1, column=2)
        self.SHCS3=[('M1.6',1),('M2  ',2),('M2.5',3),('M3  ',4),('M4  ',5),
        ('M5  ',6),('M6  ',7),('M8  ',8),('M10 ',9),('M12 ',10),
        ('M14 ',11),('M16 ',12),('M18 ',13),('M20 ',14),('M24 ',15),
        ('M30 ',16),('M36 ',17),('M42 ',18),('M48 ',19)]
        self.var3 = IntVar()
        for text, value in self.SHCS3:
            self.rb3=Radiobutton(self, text=text, value=value, variable=self.var3,
            font="monospace 10")
            self.rb3.grid(column=2,row=value+1)
            self.rb3.bind("<ButtonRelease-1>", self.rb3event)

        self.st1 = Label(self, text='Clearance Height Z  ')
        self.st1.grid(row=1, column=3)
        self.ClearanceHeightVar = StringVar()
        self.ClearanceHeightE = Entry(self, width=10, textvariable=self.ClearanceHeightVar)
        self.ClearanceHeightE.grid(row=2, column=3)
        self.ClearanceHeightVar.set('0.2500')

        self.st2 = Label(self, text='Material Top Z')
        self.st2.grid(row=3, column=3)
        self.MaterialTopVar = StringVar()
        self.MaterialTopE = Entry(self, width=10, textvariable=self.MaterialTopVar)
        self.MaterialTopE.grid(row=4, column=3)
        self.MaterialTopVar.set('0.000')

        self.st3 = Label(self, text='Start Height Z')
        self.st3.grid(row=5, column=3)
        self.StartHeightVar = StringVar()
        self.StartHeightE = Entry(self, width=10, textvariable=self.StartHeightVar)
        self.StartHeightE.grid(row=6, column=3)
        self.StartHeightVar.set('0.1000')
        
        self.st4 = Label(self, text='Tool Diameter')
        self.st4.grid(row=7, column=3)
        self.ToolDiameterVar = StringVar()
        self.ToolDiameterE = Entry(self, width=10, textvariable=self.ToolDiameterVar)
        self.ToolDiameterE.grid(row=8, column=3)
        self.ToolDiameterE.focus_set()
        
        self.st5 = Label(self, text='Spindle RPM')
        self.st5.grid(row=9, column=3)
        self.SpindleRPMVar = StringVar()
        self.SpindleRPME = Entry(self, width=10, textvariable=self.SpindleRPMVar)
        self.SpindleRPME.grid(row=10, column=3)

        self.st6 = Label(self, text='Feed Rate')
        self.st6.grid(row=11, column=3)
        self.FeedRateVar = StringVar()
        self.FeedRateE = Entry(self, width=10, textvariable=self.FeedRateVar)
        self.FeedRateE.grid(row=12, column=3)
        self.FeedRateVar.set('10.0')

        self.st7 = Label(self, text='Depth of Cut')
        self.st7.grid(row=13, column=3)
        self.DepthOfCutVar = StringVar()
        self.DepthOfCutE = Entry(self, width=10, textvariable=self.DepthOfCutVar)
        self.DepthOfCutE.grid(row=14, column=3)

        self.st8 = Label(self, text='Stepover')
        self.st8.grid(row=15, column=3)
        self.StepOverVar = StringVar()
        self.StepOverE = Entry(self, width=10, textvariable=self.StepOverVar)
        self.StepOverE.grid(row=16, column=3)

        self.st9 = Label(self, text='Spiral Depth')
        self.st9.grid(row=17, column=3)
        self.SpiralDepthVar = StringVar()
        self.SpiralDepthE = Entry(self, width=10, textvariable=self.SpiralDepthVar)
        self.SpiralDepthE.grid(row=18, column=3)

        self.InsertEOFVar = IntVar()
        self.InsertEOF = Checkbutton(self, text='Insert EOF', 
            variable=self.InsertEOFVar, indicatoron=0, 
            selectcolor='green', width=10)
        self.InsertEOF.grid(row=19, column=3, rowspan=2)

        self.st10 = Label(self, text='X Location')
        self.st10.grid(row=1, column=4, sticky=W)
        self.XCenterVar = StringVar()
        self.XCenterE = Entry(self, width=10, textvariable=self.XCenterVar)
        self.XCenterE.grid(row=2, column=4, sticky=W)
        self.XCenterE.bind("<Return>", self.MoveToY)
        self.XCenterE.bind("<KP_Enter>", self.MoveToY)

        self.st11 = Label(self, text='Y Location')
        self.st11.grid(row=1, column=4, sticky=E)
        self.YCenterVar = StringVar()
        self.YCenterE = Entry(self, width=10, textvariable=self.YCenterVar)
        self.YCenterE.grid(row=2, column=4, sticky=E)
        self.YCenterE.bind("<Return>", self.AddToList)
        self.YCenterE.bind("<KP_Enter>", self.AddToList)

        self.st12 = Label(self, text='Hole Diameter')
        self.st12.grid(row=13, column=0)
        self.HoleDiameterVar = StringVar()
        self.HoleDiameterE = Entry(self, width=10, textvariable=self.HoleDiameterVar)
        self.HoleDiameterE.grid(row=14, column=0)

        self.st13 = Label(self, text='Hole Depth')
        self.st13.grid(row=15, column=0)
        self.HoleDepthVar = StringVar()
        self.HoleDepthE = Entry(self, width=10, textvariable=self.HoleDepthVar)
        self.HoleDepthE.grid(row=16, column=0)

        self.st14 = Label(self, text='Cut Direction')
        self.st14.grid(row=18, column=0)
        self.CutDirection=[('Climb',1),('Conventional', 2)]
        self.CutDirectionVar = IntVar()
        for text, value in self.CutDirection:
            self.rb4=Radiobutton(self, text=text, value=value, variable=self.CutDirectionVar)
            self.rb4.grid(column=0,row=value+18, sticky=W)
        self.CutDirectionVar.set(1)
        
        self.st15 = Label(self, text='X & Y List')
        self.st15.grid(row=3, column=4)
        self.CordList = Listbox(self, height=20)
        self.CordList.grid(row=4, column=4, rowspan=17, sticky=E+W+N+S)
        self.CordList.bind("<Double-Button-1>", self.EditListItem)
        self.CordList.bind("<ButtonRelease-1>", self.MouseSelect)
        self.CordList.bind("<Delete>", self.RemoveFromList)
        self.ListIndex = ''
        self.CLScroll = Scrollbar(self,command = self.CordList.yview)
        self.CLScroll.grid(row=4, column=5, rowspan=17, sticky=N+S+W)
        self.CordList.configure(yscrollcommand = self.CLScroll.set) 

        self.st16 = Label(self, text='G-Code')
        self.st16.grid(row=1, column=6)
        self.g_code = Text(self,width=50,height=25,bd=2)
        self.g_code.grid(row=2, column=6, rowspan=20, sticky=E+W+N+S)
        self.Gscroll = Scrollbar(self,command = self.g_code.yview)
        self.Gscroll.grid(row=2, column=7, rowspan=20, sticky=N+S+W)
        self.g_code.configure(yscrollcommand = self.Gscroll.set) 

        self.GenerateBtn = Button(self, text="Generate", command=self.GeneratePath, width=7)
        self.GenerateBtn.grid(row=22, column=3)

        if IN_AXIS:
            self.WriteButton = Button(self, text='To AXIS',\
                command=self.WriteToAxis)
        else:
            self.WriteButton = Button(self, text='To Clipboard',
                command=self.CopyClipboard, width=7)
        self.WriteButton.grid(row=22, column=4)

        self.quitButton = Button(self, text="Quit", command=self.quit, width=7)
        self.quitButton.grid(row=22, column=6)

        self.nSHCS = {1:'No.0,0.125,0.060',
                      2:'No.1,0.15625,0.073',
                      3:'No.2,0.1875,0.086',
                      4:'No.3,0.21875,0.099',
                      5:'No.4,0.21875,0.112',
                      6:'No.5,0.250,0.125',
                      7:'No.6,0.28125,0.138',
                      8:'No.8,0.3125,0.164',
                      9:'No.10,0.375,0.190',
                     10:'No.12,0.40625,0.216'}
        self.fSHCS = {1:'1/4",0.4375,0.250',
                      2:'5/16",0.53125,0.313',
                      3:'3/8",0.625,0.375',
                      4:'7/16",0.7185,0.438',
                      5:'1/2",0.8125,0.500',
                      6:'9/16",0.90625,0.563',
                      7:'5/8",1.0,0.625',
                      8:'3/4",1.1875,0.750',
                      9:'7/8",1.375,0.875',
                     10:'1",1.625,1.000',
                     11:'1-1/8",1.8125,1.125',
                     12:'1-1/4",2.000,1.250',
                     13:'1-1/2",2.375,1.500',
                     14:'1-3/4",2.750,1.750',
                     15:'2",3.125,2.000'}
        self.mSHCS = {1:'M1.6,3.50,1.6',
                      2:'M2,4.40,2.0',
                      3:'M2.5,5.40,2.5',
                      4:'M3,6.00,3.0',
                      5:'M4,8.25,4.0',
                      6:'M5,9.75,5.0',
                      7:'M6,11.20,6.0',
                      8:'M8,14.50,8.0',
                      9:'M10,17.50,10.0',
                     10:'M12,19.50,12.0',
                     11:'M14,22.50,14.0',
                     12:'M16,25.50,16.0',
                     13:'M18,28.50,18.0',
                     14:'M20,31.50,20.0',
                     15:'M24,37.50,24.0',
                     16:'M30,47.50,30.0',
                     17:'M36,56.50,36.0',
                     18:'M42,66.00,42.0',
                     19:'M48,75.00,48.0',}

    def GeneratePath(self):
        self.ClearanceHeight = float(self.ClearanceHeightVar.get())
        self.StartHeight = float(self.StartHeightVar.get())
        self.MaterialTop = float(self.MaterialTopVar.get())
        self.FeedRate = float(self.FeedRateVar.get())
        if len(self.SpindleRPMVar.get()) > 0:
            self.SpindleRPM = int(self.SpindleRPMVar.get())
        self.ToolDiameter = float(self.ToolDiameterVar.get())
        self.HoleDiameter = float(self.HoleDiameterVar.get())
        self.HoleRadius = self.HoleDiameter/2
        self.HoleDepth = float(self.HoleDepthVar.get())
        self.FinishPathDiameter = self.HoleDiameter - self.ToolDiameter

        # Max Depth of Cut
        if len(self.DepthOfCutVar.get()) == 0:
            self.MaxCutDepth = self.ToolDiameter/4
        else:
            self.MaxCutDepth = float(self.DepthOfCutVar.get())

        # Depth of each cut
        if self.HoleDepth > self.MaxCutDepth:
            self.NumberOfCuts = int(ceil(self.HoleDepth/self.MaxCutDepth))
            self.CutDepth = self.HoleDepth / self.NumberOfCuts
        else:
            self.CutDepth = self.HoleDepth

        # Spiral Depth of Cut
        if len(self.SpiralDepthVar.get()) == 0:
            self.SpiralDepth = self.CutDepth / 4
            self.NumberOfSpirals = 4
        else:
            self.NumberOfSpirals = int(ceil(self.CutDepth/float(self.SpiralDepthE.get())))
            self.SpiralDepth = self.CutDepth / self.NumberOfSpirals
        # Stepover
        if len(self.StepOverVar.get()) == 0:
            self.StepOver = self.ToolDiameter * .75
        else:
            self.StepOver = float(self.StepOverVar.get())
        self.StepOver = self.FinishPathDiameter / \
            int(ceil(self.FinishPathDiameter / self.StepOver))
        self.FinishPathRadius = self.FinishPathDiameter / 2
        self.ArcCenterOffset = self.StepOver / 8

        # Number of Circles
        self.NumberOfCircles = int(self.FinishPathDiameter/self.StepOver)
        
        if self.ToolDiameter < self.HoleDiameter:
            # generate tool paths
            self.g_code.insert(END, '(SHCS Counterbore, Diameter = %.4f, Depth = %.4f )\n'\
                %(self.HoleDiameter, self.HoleDepth))
            self.g_code.insert(END, '(Number of Cuts %d, Depth of Cut %.4f)\n' \
                %(self.NumberOfCuts, self.CutDepth))
            self.g_code.insert(END, '(Tool Diameter = %.4f)\n' %self.ToolDiameter)
            if len(self.SpindleRPMVar.get()) > 0:
                self.g_code.insert(END, 'F%.1f S%d\n' %(self.FeedRate, self.SpindleRPM))
            else:
                self.g_code.insert(END, 'F%.1f\n' %(self.FeedRate))
            for n in range(0,int(self.CordList.size())):
                self.Items = self.CordList.get(0,END)
                self.SplitUp = self.Items[n].split()
                self.XCenter = float(self.SplitUp[0].lstrip('XY'))
                self.YCenter = float(self.SplitUp[1].lstrip('XY'))
                self.g_code.insert(END, '(Hole Center X%.4f Y%.4f)\n' \
                   %(self.XCenter, self.YCenter))
                           
                # raise to clearance height
                self.g_code.insert(END, 'G0 Z%.4f\n' %(self.ClearanceHeight))

                if self.ToolDiameter <= self.HoleRadius:
                    
                    # go to start position at 12 o'clock
                    self.g_code.insert(END, 'G0 X%.4f Y%.4f\n'\
                         %(self.XCenter, self.YCenter+self.StepOver))
                    # go to start height
                    self.g_code.insert(END, 'G1 Z%.4f\n' %(self.StartHeight))

                    # spiral down to material top
                    self.g_code.insert(END, 'G3 X%.4f Y%.4f Z%.4f J%.4f\n' \
                            %(self.XCenter, self.YCenter+self.StepOver,\
                            self.MaterialTop, -self.StepOver))
                    self.CurrentZ = self.MaterialTop
                            
                    for n in range(0,self.NumberOfCuts):
                        # spiral down to cut depth
                        self.g_code.insert(END, '(spiral down)\n')
                        for n in range(0,self.NumberOfSpirals):
                            self.g_code.insert(END, 'G3 X%.4f Y%.4f Z%.4f J%.4f\n' \
                                %(self.XCenter, self.YCenter+self.StepOver,\
                                self.CurrentZ-self.SpiralDepth, -self.StepOver))
                            self.CurrentZ = self.CurrentZ - self.SpiralDepth

                        # spiral out to max cut diameter
                        self.g_code.insert(END, '(spiral out)\n')
                        # cypher destination of each arc end point
                        self.XMinus = self.XCenter - (self.StepOver + (self.ArcCenterOffset*2))
                        self.YMinus = self.YCenter - (self.StepOver + (self.ArcCenterOffset*4))
                        self.XPlus = self.XCenter + (self.StepOver + (self.ArcCenterOffset*6))
                        self.YPlus = self.YCenter + (self.StepOver*2)
                        for n in range(1,self.NumberOfCircles):
                            # 1st arc
                            #print 'arc center offset %f' %self.ArcCenterOffset
                            #print n
                            self.g_code.insert(END, 'G3 X%.4f Y%.4f I%.4f J%.4f\n' \
                                %(self.XMinus, (self.YCenter),
                                -self.ArcCenterOffset, \
                                -(self.ArcCenterOffset+(self.StepOver*n))))
                            self.XMinus = self.XMinus - self.StepOver
                            # 2nd arc
                            self.g_code.insert(END, 'G3 X%.4f Y%.4f I%.4f J%.4f\n' \
                                %(self.XCenter, (self.YMinus),
                                (self.ArcCenterOffset*3)+(self.StepOver*n), \
                                -self.ArcCenterOffset))
                            self.YMinus = self.YMinus - self.StepOver
                            # 3rd arc
                            self.g_code.insert(END, 'G3 X%.4f Y%.4f I%.4f J%.4f\n' \
                                %(self.XPlus, (self.YCenter),
                                self.ArcCenterOffset, \
                                (self.ArcCenterOffset*5)+(self.StepOver*n)))
                            self.XPlus = self.XPlus + self.StepOver
                            # 4th arc
                            self.g_code.insert(END, 'G3 X%.4f Y%.4f I%.4f J%.4f\n' \
                                %(self.XCenter, (self.YPlus),
                                -((self.ArcCenterOffset*7)+(self.StepOver*n)),\
                                 self.ArcCenterOffset))
                            self.YPlus = self.YPlus + self.StepOver

                        # clean up circle
                        self.g_code.insert(END, 'G3 X%.4f Y%.4f J%.4f\n' \
                            %(self.XCenter, (self.YPlus-self.StepOver), \
                                -(self.StepOver+(self.StepOver*n))))
                        if n < self.NumberOfCuts:
                            # go back to start positions
                            self.g_code.insert(END, 'G1 X%.4f Y%.4f\n' \
                                %(self.XCenter, self.YCenter+self.StepOver))
                elif self.ToolDiameter > self.HoleRadius:
                    # start at 12 o'clock and spiral down to final depth
                    self.Offset = self.HoleDiameter - self.ToolDiameter
                    self.ArcRadius = self.Offset/2
                    self.StartPositionY = self.YCenter - (self.Offset/2)
                    self.ArcRadius = self.Offset/2
                    # go to start position
                    self.g_code.insert(END, 'G0 X%.4f Y%.4f\n' \
                    %(self.XCenter,self.StartPositionY))
                    # go to start height
                    self.g_code.insert(END, 'G1 Z%.4f\n' %(self.StartHeight))
                    # spiral down
                    self.NextZPosition = self.CutDepth
                    for n in range(0,self.NumberOfCuts):
                        self.g_code.insert(END, 'G3 X%.4f Y%.4f Z%.4f J%.4f\n' \
                            %(self.XCenter,self.StartPositionY \
                            ,-(self.NextZPosition), self.ArcRadius))
                        self.NextZPosition = self.NextZPosition + self.CutDepth

                    # clean up circle
                    self.g_code.insert(END, 'G3 X%.4f Y%.4f J%.4f\n' \
                        %(self.XCenter, self.StartPositionY, \
                        self.FinishPathRadius))
        
                # return to center
                self.g_code.insert(END, 'G1 X%.4f Y%.4f\n' %(self.XCenter, self.YCenter))
                # return to safe Z height
                self.g_code.insert(END, 'G0 Z%.4f\n' %(self.ClearanceHeight))
                self.g_code.insert(END, '(end of SHCS Counterbore)\n')
            if self.InsertEOFVar.get() == 1:
                self.g_code.insert(END, 'M2\n')
        else:
            tkMessageBox.showwarning('Entry Error', 'Tool Diameter Larger than Hole!')
            self.ToolDiameterE.focus_set()
            self.ToolDiameterE.select_range(0, END)

    def WriteToAxis(self):
        sys.stdout.write(self.g_code.get(0.0, END))
        self.quit()

    def CopyClipboard(self):
        self.g_code.clipboard_clear()
        self.g_code.clipboard_append(self.g_code.get(0.0, END))
        
    def rb1event(self,var):
        self.ns = self.nSHCS[self.var1.get()]
        self.nssp = self.ns.split(',')
        self.HoleDiameterVar.set(self.nssp[1])
        self.HoleDepthVar.set(self.nssp[2])
        self.var2.set(0)
        self.var3.set(0)

    def rb2event(self,var):
        self.fs = self.fSHCS[self.var2.get()]
        self.fssp = self.fs.split(',')
        self.HoleDiameterVar.set(self.fssp[1])
        self.HoleDepthVar.set(self.fssp[2])     
        self.var1.set(0)
        self.var3.set(0)
 
    def rb3event(self,var):
        self.ms = self.mSHCS[self.var3.get()]
        self.mssp = self.ms.split(',')
        self.InchHoleDia = str(.03937*float(self.mssp[1]))
        self.InchHoleDepth = str(.03937*float(self.mssp[2]))
        self.HoleDiameterVar.set(self.InchHoleDia)
        self.HoleDepthVar.set(self.InchHoleDepth)
        self.var1.set(0)
        self.var2.set(0)

    def MoveToY(self,var):
        self.YCenterE.focus_set()

    def AddToList(self,var):
        self.InsertString = 'X%.4f Y%.4f' %(float(self.XCenterE.get()), 
            float(self.YCenterE.get()))
        if len(self.ListIndex) > 0:
            self.CordList.delete(int(self.ListIndex))
            self.CordList.insert(int(self.ListIndex), self.InsertString)
            self.ListIndex = ''
        else:
            self.CordList.insert(END, self.InsertString)
        self.XCenterVar.set('')
        self.YCenterVar.set('')
        self.XCenterE.focus_set()

    def EditListItem(self,var):
        self.ListIndex = self.CordList.curselection()[0]
        self.seltext = []
        self.seltext = self.CordList.get(self.ListIndex).split()
        self.Xtext = self.seltext[0]
        self.Ytext = self.seltext[1]
        self.XCenterVar.set(self.Xtext[1:])
        self.YCenterVar.set(self.Ytext[1:])
        self.XCenter.focus_set()         

    def RemoveFromList(self,var):
        self.ListIndex = self.CordList.curselection()[0]
        self.CordList.delete(int(self.ListIndex))
        self.ListIndex = ''

    def MouseSelect(self, var):
        self.CordList.focus_set()

app = Application()
app.master.title("Counterbore")
app.mainloop()