' Reads in a nc-file and creates toolpathedit features ' ' Author: Amji Ramanujam -- Edited by Mayank Maheshwary to add support for Heidenhain ' Organization: Engineering Geometry Systems ' Date: 09/18/07 ' Copyright (c) 2006, Engineering Geometry Systems ' ' General Description: ' This macro reads in a nc-file and tries to backplot the moves described in the cnc file ' Add this script to the list of add-ins ' Run this basic macro from the view menu ' A file open dialog will be presented. Use it to locate and open the nc-file ' The dialog will parse the nc-file and create a number of toolpath edit features. ' Assign a tool to each of the feature ' It is ready to be simulated Option Explicit ' True if file is G-code, else it is false Dim GFile As Boolean ' Tool_path is a new data type that defines the fields which stores the info regarding the tool path Type Tool_path movement As Integer '0 - Rapid, 1 - Linear, 2 - CW curve, 3 - CCW curve x As Double y As Double z As Double centerX As Double centerY As Double centerZ As Double feed As Double cutter_comp As tagFMUDOCutterCompType coolant As tagFMCoolantType speed As Double plane As String normX As Double normY As Double normZ As Double End Type 'Sub Main ' Dim inp_file_full As String, out_file_full As String, abs_cntr As Boolean, prof_ext As Boolean ' inp_file_full = "C:\Documents and Settings\Mayank.EGS\My Documents\test_hh.txt" 'inp_file_full = "C:\Documents and Settings\Mayank.EGS\Desktop\tmp_turn.txt" ' out_file_full = "C:\Documents and Settings\Mayank.EGS\My Documents\test_hh_result.txt" ' abs_cntr = True ' prof_ext = True ' Backplotter(0,inp_file_full,out_file_full,abs_cntr,prof_ext) 'End Sub Public Sub RunBackplotter Dim mode As Integer mode = 1 ' 1=interactive 0=test_mode (no_questions asked) Backplotter(mode) End Sub Public Function Backplotter(ByVal mode As Integer, Optional ByVal nc_fname As String, Optional ByVal output_fname As String, Optional ByVal is_abs_center As Boolean, Optional ByVal extract_profile As Boolean) Dim tmp_record As Tool_path ' This stores the current record's information Dim prev_record As Tool_path ' This stores the current record's information tmp_record.movement = 0 tmp_record.X = 0 ' These co-ordinates need to be initialized thru the api that reads the post options tmp_record.Y = 0 tmp_record.Z = 0 tmp_record.Feed = 0 tmp_record.cutter_comp=eCCT_NotSetOnToolpathObj tmp_record.coolant =eCT_CoolantOff tmp_record.Speed = 0 tmp_record.centerX = 0 tmp_record.centerY = 0 tmp_record.centerZ = 0 tmp_record.plane = "xy" tmp_record.normX = 0 tmp_record.normY = 0 tmp_record.normZ = 1 Dim inp_filename As String Dim out_filename As String Dim f_content As String Dim pos As Integer Dim i As Integer Dim num_code As String Dim n_w As Integer ' This will store the number of keywords that we are looking for. Eg: M, G, F, S will make 4 keywords Dim write_to_file As Boolean 'This variable is set when one of the fields is changed, so we know when to write to the file and when it is wasteful to do so (avoids duplicates) Dim create_new_tpf As Boolean 'This is a flag to notify that a new toolpath feature should be created.This is set when we encounter a M6(toolchange) Dim ignore_xy As Boolean ' This flag will be set when we encounter a G53, because we want to ignore those X,Y,Z changes, because G53 is machine coordinates Dim is_turning As Boolean ' This flag will be set if the document is a turning doc Dim ignore_line As Boolean ' Specifically here for the G76 (threading canned cycle) Dim abs_center As Boolean '1 absolute centers (very uncommon in nc-codes) 0 (default) - centers are relative to the start point of the arc Dim profile_extract As Boolean '0 - Don't extract profiles from canned cycels 1 (default) - extract profiles Dim first_tp_created As Boolean ' Sometimes the nc code doesnot start with a M6. So no toolpath feature is created. This flag is a remedy for that. If a toolpathfeatrue is not yet created when a write to file part is executed this flag will be used to create a toolpath feature at that point Dim lowLine As Integer Dim highLine As Integer profile_extract = True write_to_file = False create_new_tpf = False prev_record = tmp_record 'Stuff needed For Toolpath addition 'abs_center = dlgConfig.optGroup1 Dim doc As FMDocument Dim setup As FMSetup Dim features_fm As FMFeatures Dim tp_feature As FMToolpathFeature Dim tp_oper As FMToolpathOperation Dim tp_pts As FMToolpathPts Dim err_str As String Dim tool_list(100) As String Dim current_tool As String Dim key_wrd() 'Array declaration Dim key_wrd_hh() 'Array declaration for Heidenhain Dim numKwrdHH As Integer Dim foundKwrd As Boolean Dim num As String key_wrd() = Array("G","T","M","X","Y","Z","F","S","U","V","W","I","J","K","R","P","Q") 'key_wrd_hh() = Array("BEGIN", "CYCL", "CC", "C", "R","TOOL", "L", "G","T","M","X","Y","Z","F") 'key_wrd_hh() = Array("M25", "TOOL CALL", "TOOL DEF", "CYCL", "CC", "C", "L") key_wrd_hh() = Array("TOOL CALL", "TOOL DEF", "CYCL", "CC", "C", "L") n_w =UBound(key_wrd) numKwrdHH = UBound(key_wrd_hh) ' Get the current document info Set doc = Application.ActiveDocument Set setup = doc.ActiveSetup Set features_fm = setup.Features If setup.Type = eST_Turning Then tmp_record.plane="xz" tmp_record.normX = 0 tmp_record.normY = 1 tmp_record.normZ = 0 is_turning = True End If If mode = 1 Then inp_filename = GetFilePath$(,"nc;txt",,"Open NC file",0) If inp_filename="" Then Exit All End If out_filename = "C:\test_out.txt" ElseIf mode =0 Then inp_filename = nc_fname out_filename = output_fname End If get_tools(inp_filename, tool_list) Open inp_filename For Input As #100 Open out_filename For Output As #200 ' Creating the toolpath feature For adding points to it If mode = 1 Then If is_turning = True Then Begin Dialog UserDialog 360,196,"Configuration" ' %GRID:10,7,1,1 OptionGroup .OptGroup1 OptionButton 50,42,90,14,"Relative",.OptionButton1 OptionButton 210,42,90,14,"Absolute",.OptionButton2 Text 20,14,80,14,"Center",.Text1,2 PushButton 130,154,100,21,"Done",.PushButton1 Text 30,84,90,14,"Canned Cycle",.Text2 CheckBox 60,112,200,14,"Extract profile",.CheckBox1 End Dialog Dim dlgTurningConfig As UserDialog dlgTurningConfig.OptGroup1 = 0 dlgTurningConfig.CheckBox1 = 1 Dialog dlgTurningConfig abs_center = dlgTurningConfig.optGroup1 profile_extract = dlgTurningConfig.CheckBox1 Else Begin Dialog UserDialog 290,112,"Configuration" ' %GRID:10,7,1,1 OptionGroup .OptGroup1 OptionButton 50,42,90,14,"Relative",.OptionButton1 OptionButton 170,42,90,14,"Absolute",.OptionButton2 Text 110,21,80,14,"Center",.Text1,2 PushButton 100,77,100,21,"Done",.PushButton1 End Dialog Dim dlgMillingConfig As UserDialog dlgMillingConfig.OptGroup1 = 0 Dialog dlgMillingConfig abs_center = dlgMillingConfig.optGroup1 End If ElseIf mode = 0 Then abs_center = is_abs_center profile_extract = extract_profile End If ' Set tp_oper = tp_feature.Operations(1) ' Set tp_pts = tp_oper.GetPointList 'Check if the file is G-code Line Input #100,f_content pos = InStr(UCase(f_content), "BEGIN PGM") If pos <> 0 Then GFile = False Else GFile = True End If ReadFile: While Not EOF(100) Line Input #100,f_content ignore_xy = False ' G53 is non-modal, so we are resetting this flag to false at the begining of every line read If GFile Then pre_process(f_content) ' The string is passed to this function to take care of filenames and comments End If If GFile Then If profile_extract = False Then pos = InStr(UCase(f_content), "N") If pos <> 0 Then num_code = get_num(f_content,pos) If Val(num_code) >= lowLine And Val(num_code) <= highLine Then GoTo ReadFile End If End If End If End If ' Loop for G-code file If GFile Then For i = 0 To (n_w) While 1 ' This while loop makes sure that the same G-code is checked over and over again in the same line pos = InStr(UCase(f_content),key_wrd(i)) If pos <> 0 Then num_code = get_num(f_content,pos) If num_code <> "Error" Then ' Check for false-positive populate_record(num_code,key_wrd(i), tmp_record, prev_record, create_new_tpf, ignore_xy, is_turning, ignore_line, lowLine, highLine, abs_center, profile_extract, tool_list, current_tool) End If If ignore_line = True Then ignore_line = False Exit For End If If create_new_tpf = True Then If is_turning = True Then Set tp_feature = features_fm.AddToolpath(eST_Turning,eTG_EndMill, 0,0,0,err_str, True) Else Set tp_feature = features_fm.AddToolpath(eST_Milling,eTG_All, 0,0,0,err_str, True) End If Set tp_oper = tp_feature.Operations(1) Set tp_pts = tp_oper.GetPointList If current_tool <> "" Then tp_oper.OverrideTool(current_tool,True) End If create_new_tpf = False first_tp_created = True End If Else Exit While ' The while loop will exit when there are no more occurances of the code in that line End If Wend Next i ' Loop for Heidenhain file Else foundKwrd = False For i = 0 To (numKwrdHH) pos = InStr(UCase(f_content),key_wrd_hh(i)) If pos <> 0 Then foundKwrd = True If key_wrd_hh(i) = "CC" Then pos = InStr(UCase(f_content), "X") If pos <> 0 Then num = get_num_hh(f_content, pos) tmp_record.centerX = Val(num) End If pos = InStr(UCase(f_content), "Y") If pos <> 0 Then num = get_num_hh(f_content, pos) tmp_record.centerY = Val(num) End If GoTo ReadFile End If 'num_code = get_num(f_content,pos) 'If num_code <> "Error" Then ' Check for false-positive populate_record_hh(key_wrd_hh(i), f_content, tmp_record, prev_record, create_new_tpf, ignore_xy, is_turning, ignore_line, lowLine, highLine, abs_center, profile_extract, tool_list, current_tool) 'End If If ignore_line = True Then ignore_line = False Exit For End If If create_new_tpf = True Then If is_turning = True Then Set tp_feature = features_fm.AddToolpath(eST_Turning,eTG_EndMill, 0,0,0,err_str, True) Else Set tp_feature = features_fm.AddToolpath(eST_Milling,eTG_All, 0,0,0,err_str, True) End If Set tp_oper = tp_feature.Operations(1) Set tp_pts = tp_oper.GetPointList If current_tool <> "" Then tp_oper.OverrideTool(current_tool,True) End If create_new_tpf = False first_tp_created = True End If 'Else ' Exit While ' The while loop will exit when there are no more occurances of the code in that line Exit For End If Next i End If write_to_file = True If prev_record.X = tmp_record.X And prev_record.Y = tmp_record.Y And prev_record.Z = tmp_record.Z And prev_record.movement=tmp_record.movement Then write_to_file = False End If If write_to_file = False Then If tmp_record.movement = 2 Or tmp_record.movement = 3 Then If prev_record.centerX <> tmp_record.centerX Or prev_record.centerY <> tmp_record.centerY Or prev_record.centerZ<>tmp_record.centerZ Then write_to_file = True End If End If End If If write_to_file=True Then 'this flag is set if any of the parameters is changed If first_tp_created = False Then If is_turning = True Then Set tp_feature = features_fm.AddToolpath(eST_Turning,eTG_EndMill, 0,0,0,err_str, True) Else Set tp_feature = features_fm.AddToolpath(eST_Milling,eTG_All, 0,0,0,err_str, True) End If Set tp_oper = tp_feature.Operations(1) Set tp_pts = tp_oper.GetPointList If current_tool <> "" Then tp_oper.OverrideTool(current_tool,True) End If first_tp_created = True End If Print #200, tmp_record.movement;","; tmp_record.X; ","; tmp_record.Y;","; tmp_record.Z; ",";tmp_record.Feed;",";tmp_record.cutter_comp;",";tmp_record.coolant ;",";tmp_record.centerX;",";tmp_record.centerY;",";tmp_record.centerZ prev_record = tmp_record Select Case tmp_record.movement Case 0 tp_pts.AddToolpathPt(tmp_record.X,tmp_record.Y, tmp_record.Z, -1, tmp_record.cutter_comp,tmp_record.coolant) Case 1 tp_pts.AddToolpathPt(tmp_record.X,tmp_record.Y, tmp_record.Z, -2, tmp_record.cutter_comp,tmp_record.coolant) Case 2 tp_pts.AddToolpathArc(tmp_record.X,tmp_record.Y, tmp_record.Z, tmp_record.centerX, tmp_record.centerY, tmp_record.centerZ, True, -2, tmp_record.coolant, tmp_record.normX, tmp_record.normY, tmp_record.normZ) Case 3 tp_pts.AddToolpathArc(tmp_record.X,tmp_record.Y, tmp_record.Z, tmp_record.centerX, tmp_record.centerY, tmp_record.centerZ, False, -2, tmp_record.coolant, tmp_record.normX, tmp_record.normY, tmp_record.normZ) End Select tmp_record.centerX = prev_record.X tmp_record.centerY = prev_record.Y tmp_record.centerZ = prev_record.Z tp_pts.Update() End If Wend If mode = 1 Then MsgBox "Done" End If Close #100 Close #200 End Function ' Automatic tool assignment using user-defined header Function get_tools(ByVal file_name As String, ByRef tool_list) Dim string_array Dim f_content, tool_num, tool_name As String Dim pos, index_val As Integer Open file_name For Input As #100 While Not EOF(100) Line Input #100,f_content Trim(f_content) pos = InStr(UCase(f_content), "(LOAD") If pos <> 0 Then pos = InStr(UCase(f_content), "T") tool_num = get_num(f_content, pos) If tool_num = "Error" Then MsgBox "Error in tool specification, quitting now" Close #100 Exit Function Else index_val = Val(tool_num) End If string_array = Split(f_content, "=") pos = InStr(string_array(UBound(string_array)),")") Mid(string_array(UBound(string_array)), pos, 1) = Space(1) ' removing the last closing bracket tool_name = Trim(string_array(UBound(string_array))) ' This get the tool name only without the spaces in front or back If (0=check_tool(tool_name)) Then MsgBox tool_name & " : Tool doesnot exist in the current crib, check the tool name or the list of tools in the crib" Else tool_list(index_val) = tool_name End If End If Wend Close #100 End Function Function check_tool(ByVal tool_name As String) Dim doc As FMDocument Dim cur_crib As FMToolCrib Dim tools_list As FMTools Dim tmp, tul As FMTool Set doc = Application.ActiveDocument Set cur_crib = doc.ActiveToolCrib() Set tools_list = cur_crib.Tools(eTG_EndMill) For Each tul In tools_list If tool_name = tul.Name Then check_tool = 1 Exit Function End If Next tul check_tool = 0 End Function Function get_num(ByRef inp_str As String, ByVal pos As Integer) Dim code As String Dim next_char As String code =" " Mid(inp_str,pos,1)=" " ' This overwrites the currently read code to avoid re-detecting the same code over and over again pos = pos+1 next_char=Mid(inp_str,pos,1) While is_number(next_char) code = code & next_char pos = pos + 1 next_char=Mid(inp_str,pos,1) Wend If code <> " " Then ' This is to make sure that there is an actual number in there instead of some false-positive like : %GM4 which might flag a false-positve for G get_num = Str(Val(code)) Else get_num = "Error" End If End Function Function populate_record(ByVal num As String, ByVal alpha As String, ByRef tmp_record As Tool_path, ByRef prev_record As Tool_path, ByRef create_new_tpf As Boolean, ByRef ignore_xy As Boolean, ByVal is_turning As Boolean, ByRef ignore_line As Boolean, ByRef lowLine As Integer, ByRef highLine As Integer, ByVal abs_center As Boolean, ByVal profile_extract As Boolean, ByRef tools_list, ByRef current_tool As String) Static is_rel As Boolean '= False ' This variable will determine wheter the co-ordinates in the nc code mean absolute XYZ or relative XYZ Static is_curve As Boolean '= False ' This flag is used for determing the context of the R-word whether the R is for a radius of a curve or a hole Static is_canned_cycle As Boolean 'write_to_file = True Select Case alpha Case "G" Select Case Val(num) Case 0 'rapid move tmp_record.movement = 0 is_curve = False Case 1 'linear move tmp_record.movement = 1 is_curve = False Case 2 'CW curve tmp_record.movement = 2 is_curve = True Case 3 'CCW curve tmp_record.movement = 3 is_curve = True Case 40 'Cutter Comp off tmp_record.cutter_comp = eCCT_Off Case 41 'Cutter comp left tmp_record.cutter_comp = eCCT_Left Case 42 'Cutter comp right tmp_record.cutter_comp = eCCT_Right Case 17 'The plane for tool movement tmp_record.plane = "xy" tmp_record.normX = 0 tmp_record.normY = 0 tmp_record.normZ = 1 Case 18 'The plane for tool movement tmp_record.plane = "xz" tmp_record.normX = 0 tmp_record.normY = 1 tmp_record.normZ = 0 Case 19 'The plane for tool movement tmp_record.plane = "yz" tmp_record.normX = 1 tmp_record.normY = 0 tmp_record.normZ = 0 Case 53 ' This specifies to use the machine co-ordinate system instead of the work-piece co-ordinate system ' So this command and the X and Y co-ords will be ignored ignore_xy = True ' Case 54 ' 'First block on the table (later) ' ' Case 55 ' 'Second block on the table (later) ' If canned cycles are supported, then we have to restore the previous G-code for the move command (this will be saved in a static variable by one of the G81-G89 cases) Case 71 ignore_xy = Not profile_extract Case 72 ignore_xy = Not profile_extract Case 73 ignore_xy = Not profile_extract Case 76 ' This is the threading canned cycle ignore_line =True Case 80 ' This is canned cycle off is_canned_cycle = False ' If in the future we handle canned cycles, then we need to store the previous G-code state, (which is often times G00) Case 81 'This is the code for one of the canned drill cycle is_canned_cycle = True Case 82 'This is the code for one of the canned drill cycle is_canned_cycle = True Case 83 'This is the code for one of the canned drill cycle is_canned_cycle = True Case 84 'This is the code for one of the canned drill cycle is_canned_cycle = True Case 85 'This is the code for one of the canned drill cycle is_canned_cycle = True Case 86 'This is the code for one of the canned drill cycle is_canned_cycle = True Case 87 'This is the code for one of the canned drill cycle is_canned_cycle = True Case 88 'This is the code for one of the canned drill cycle is_canned_cycle = True Case 89 'This is the code for one of the canned drill cycle is_canned_cycle = True Case 90 'Absolute Co-ordinate system is_rel = False Case 91 'Relative Co-ordinate system is_rel = True Case Else ' This does nothing End Select Case "X" If ignore_xy = False Then If is_turning = True Then 'For turning the X needs to be divided by 2 (the radius, diameter conflict) num = Str(Val(num)/2) End If If is_rel Then tmp_record.X = tmp_record.X+Val(num) Else tmp_record.X = Val(num) End If End If Case "Y" If ignore_xy = False Then If is_rel Then tmp_record.Y = tmp_record.Y+Val(num) Else tmp_record.Y = Val(num) End If End If Case "Z" If ignore_xy = False Then If is_rel Then tmp_record.Z = tmp_record.Z+Val(num) Else tmp_record.Z = Val(num) End If End If Case "U" If ignore_xy = False Then tmp_record.X =tmp_record.X + Val(num) End If Case "V" If ignore_xy = False Then tmp_record.Y =tmp_record.Y + Val(num) End If Case "W" If ignore_xy = False Then tmp_record.Z =tmp_record.Z + Val(num) End If Case "M" Select Case Val(num) Case 6 'This is the toolchange code, so create a new tool-path-feature here create_new_tpf = True Case 8 tmp_record.coolant = eCT_Flood Case 9 tmp_record.coolant = eCT_CoolantOff Case 7 tmp_record.coolant = eCT_Mist Case Else 'Do nothing End Select Case "F" tmp_record.Feed = Val(num) Case "S" tmp_record.Speed = Val(num) Case "I" If abs_center = False Then tmp_record.centerX = prev_record.X + Val(num) Else tmp_record.centerX = Val(num) End If Case "J" If abs_center = False Then tmp_record.centerY = prev_record.Y + Val(num) Else tmp_record.centerY = Val(num) End If Case "K" If abs_center = False Then tmp_record.centerZ = prev_record.Z + Val(num) Else tmp_record.centerZ = Val(num) End If Case "R" If (is_curve= True And is_canned_cycle = False) Then Dim x1,y1,z1,x2,y2,z2,x3,y3,z3 As Double Dim r, q As Double Dim center1, center2 As Double r = Val(num) Select Case tmp_record.plane Case "xy" x1 = prev_record.X y1 = prev_record.Y x2 = tmp_record.X y2 = tmp_record.Y Case "xz" x1 = prev_record.X y1 = prev_record.Z x2 = tmp_record.X y2 = tmp_record.Z Case "yz" x1 = prev_record.Y y1 = prev_record.Z x2 = tmp_record.Y y2 = tmp_record.Z End Select x3 = (x1+x2)/2 y3 = (y1+y2)/2 q = Sqr((x2-x1)^2 + (y2-y1)^2) If q =0 Then MsgBox "Encountered a circle with Radius, insufficient data" End End If If ((q/2) >= r) Then MsgBox "Radius too small. Cannot proceed" End End If If r<0 Then center1 = x3 + Sqr(r^2-(q/2)^2)*(y1-y2)/q center2 = y3 + Sqr(r^2-(q/2)^2)*(x2-x1)/q Else center1 = x3 - Sqr(r^2-(q/2)^2)*(y1-y2)/q center2 = y3 - Sqr(r^2-(q/2)^2)*(x2-x1)/q End If Select Case tmp_record.plane Case "xy" tmp_record.centerX = center1 tmp_record.centerY = center2 Case "xz" tmp_record.centerX = center1 tmp_record.centerZ = center2 Case "yz" tmp_record.centerY = center1 tmp_record.centerZ = center2 End Select End If Case "P" lowLine = Val(num) Case "Q" highLine = Val(num) Case "T" If(is_turning = True) Then create_new_tpf = True ' For a turning nc-file the tool change is at the T-word not at M6 Mid(num,Len(num)-1,2)= Space(2) End If 'Tool number is extrated to assign tool in the next tool change current_tool =tools_list(Val(num)) Case Else 'Do nothing End Select End Function Function get_num_hh(ByRef inp_str As String, ByVal pos As Integer) Dim code As String Dim next_char As String If Mid(inp_str,pos,1) = "F" And Mid(inp_str,pos+1,3) = "MAX" Then get_num_hh = "MAX" Else code =" " 'Mid(inp_str,pos,1)=" " ' This overwrites the currently read code to avoid re-detecting the same code over and over again pos = pos+1 next_char=Mid(inp_str,pos,1) While is_number(next_char) code = code & next_char pos = pos + 1 next_char=Mid(inp_str,pos,1) Wend If code <> " " Then ' This is to make sure that there is an actual number in there instead of some false-positive like : %GM4 which might flag a false-positve for G get_num_hh = Str(Val(code)) Else get_num_hh = "Error" End If End If End Function ' Fix the feed value for Heidenhain code Function FixFeedVal(ByRef num) Dim n As Integer Dim lastNum As String 'n = Val(num) 'n = n/10 'num = Str(n) n = Len(num) lastNum = Right(num, 1) Mid(num, n, 1) = "." num = num & lastNum End Function ' Get the X, Y, Z, R values Function getXYZR_hh(ByVal f_content As String, ByRef tmp_record As Tool_path, ByVal ignore_xy As Boolean, ByVal is_turning As Boolean, ByRef is_rel As Boolean) Dim pos As Integer, num As String pos = InStr(UCase(f_content), "X") If pos <> 0 Then num = get_num_hh(f_content, pos) If num <> "Error" Then If ignore_xy = False Then If is_turning = True Then 'For turning the X needs to be divided by 2 (the radius, diameter conflict) num = Str(Val(num)/2) End If 'Check for relative coordinates 'If is_rel Then If Mid(UCase(f_content),pos-1,1) = "I" Then tmp_record.X = tmp_record.X+Val(num) Else tmp_record.X = Val(num) End If End If End If End If pos = InStr(UCase(f_content), "Y") If pos <> 0 Then num = get_num_hh(f_content, pos) If num <> "Error" Then If ignore_xy = False Then 'Check for relative coordinates 'If is_rel Then If Mid(UCase(f_content),pos-1,1) = "I" Then tmp_record.Y = tmp_record.Y+Val(num) Else tmp_record.Y = Val(num) End If End If End If End If pos = InStr(UCase(f_content), "Z") If pos <> 0 Then num = get_num_hh(f_content, pos) If num <> "Error" Then If ignore_xy = False Then 'Check for relative coordinates 'If is_rel Then If Mid(UCase(f_content),pos-1,1) = "I" Then tmp_record.Z = tmp_record.Z+Val(num) Else tmp_record.Z = Val(num) End If End If End If End If ' What about R? pos = InStr(UCase(f_content), "R") If pos <> 0 Then 'num = get_num_hh(f_content, pos) 'if num <> "Error" num = Mid(UCase(f_content),pos+1,1) If num = "0" Then 'Cutter Comp off tmp_record.cutter_comp = eCCT_Off ElseIf num = "L" Then 'Cutter comp left tmp_record.cutter_comp = eCCT_Left ElseIf num = "R" Then 'Cutter comp right tmp_record.cutter_comp = eCCT_Right End If End If End Function Function processM(ByVal f_content As String, ByRef tmp_record As Tool_path) Dim pos As Integer, num As String pos = InStr(UCase(f_content), "M") If pos <> 0 Then num = get_num_hh(f_content, pos) Select Case Val(num) 'Case 6 'This is the toolchange code, so create a new tool-path-feature here ' create_new_tpf = True Case 8 tmp_record.coolant = eCT_Flood Case 9 tmp_record.coolant = eCT_CoolantOff Case 7 tmp_record.coolant = eCT_Mist Case 25 tmp_record.movement = 0 Case Else 'Do nothing End Select End If End Function ' Populate_record function for Heidenhain Function populate_record_hh(ByVal alpha As String, ByVal f_content As String, ByRef tmp_record As Tool_path, ByRef prev_record As Tool_path, ByRef create_new_tpf As Boolean, ByRef ignore_xy As Boolean, ByVal is_turning As Boolean, ByRef ignore_line As Boolean, ByRef lowLine As Integer, ByRef highLine As Integer, ByVal abs_center As Boolean, ByVal profile_extract As Boolean, ByRef tools_list, ByRef current_tool As String) Static is_rel As Boolean ' This variable will determine wheter the co-ordinates in the nc code mean absolute XYZ or relative XYZ Static is_curve As Boolean ' This flag is used for determing the context of the R-word whether the R is for a radius of a curve or a hole Static is_canned_cycle As Boolean Dim pos As Integer, num As String is_rel = False 'write_to_file = True Select Case alpha Case "L" ' Find whether it is linear or rapid move pos = InStr(UCase(f_content), "F") If pos <> 0 Then num = get_num_hh(f_content, pos) If num = "MAX" Then 'rapid move tmp_record.movement = 0 is_curve = False ElseIf num <> "Error" Then 'linear move tmp_record.movement = 1 is_curve = False ' Need to add the decimal FixFeedVal(num) tmp_record.Feed = Val(num) ' What about when F doesn't have a value? End If End If getXYZR_hh(f_content, tmp_record, ignore_xy, is_turning, is_rel) processM(f_content, tmp_record) ' Define circle center 'Case "CC" ' pos = InStr(UCase(f_content), "X") ' If pos <> 0 Then ' num = get_num_hh(f_content, pos) ' tmp_record.centerX = Val(num) ' End If ' pos = InStr(UCase(f_content), "Y") ' If pos <> 0 Then ' num = get_num_hh(f_content, pos) ' tmp_record.centerY = Val(num) ' End If ' Circular arc Case "C" pos = InStr(UCase(f_content), "F") If pos <> 0 Then num = get_num_hh(f_content, pos) Rem if num = "MAX" then Rem 'rapid move Rem tmp_record.movement = 0 Rem is_curve = False Rem Else If num <> "Error" Then 'linear move 'tmp_record.movement = 1 'is_curve = False ' Need to add the decimal FixFeedVal(num) tmp_record.Feed = Val(num) ' What about when F doesn't have a value? End If End If 'pos = InStr(UCase(f_content), "DR+") pos = InStr(UCase(f_content), "DR-") If pos <> 0 Then 'CW curve tmp_record.movement = 2 is_curve = True End If 'pos = InStr(UCase(f_content), "DR-") pos = InStr(UCase(f_content), "DR+") If pos <> 0 Then 'CCW curve tmp_record.movement = 3 is_curve = True End If getXYZR_hh(f_content, tmp_record, ignore_xy, is_turning, is_rel) Case "TOOL CALL" create_new_tpf = True Case "TOOL DEF" Case "CYCL" Rem Case 53 Rem ' This specifies to use the machine co-ordinate system instead of the work-piece co-ordinate system Rem ' So this command and the X and Y co-ords will be ignored Rem ignore_xy = True ' Case 54 ' 'First block on the table (later) ' ' Case 55 ' 'Second block on the table (later) ' If canned cycles are supported, then we have to restore the previous G-code for the move command (this will be saved in a static variable by one of the G81-G89 cases) Rem Case 71 Rem ignore_xy = Not profile_extract Rem Case 72 Rem ignore_xy = Not profile_extract Rem Case 73 Rem ignore_xy = Not profile_extract Rem Case 76 Rem ' This is the threading canned cycle Rem ignore_line =True Rem Case 80 Rem ' This is canned cycle off Rem is_canned_cycle = False Rem ' If in the future we handle canned cycles, then we need to store the previous G-code state, (which is often times G00) Rem Case 81 Rem 'This is the code for one of the canned drill cycle Rem is_canned_cycle = True Rem Case 82 Rem 'This is the code for one of the canned drill cycle Rem is_canned_cycle = True Rem Case 83 Rem 'This is the code for one of the canned drill cycle Rem is_canned_cycle = True Rem Case 84 Rem 'This is the code for one of the canned drill cycle Rem is_canned_cycle = True Rem Case 85 Rem 'This is the code for one of the canned drill cycle Rem is_canned_cycle = True Rem Case 86 Rem 'This is the code for one of the canned drill cycle Rem is_canned_cycle = True Rem Case 87 Rem 'This is the code for one of the canned drill cycle Rem is_canned_cycle = True Rem Case 88 Rem 'This is the code for one of the canned drill cycle Rem is_canned_cycle = True Rem Case 89 Rem 'This is the code for one of the canned drill cycle Rem is_canned_cycle = True Rem Case 90 Rem 'Absolute Co-ordinate system Rem is_rel = False Rem Case 91 Rem 'Relative Co-ordinate system Rem is_rel = True Case Else 'Do nothing End Select End Function ' This function will find out if the current character is a number or not; ' The reason to write this is to include "." "-" "+" in the list of characters that needs to be recognized as numbers Function is_number(ByVal t_str As String) If IsNumeric(t_str) Or t_str="." Or t_str="-" Or t_str="+" Then is_number=True Else is_number=False End If End Function 'Removes comments & filename at the begining of the file Function pre_process(ByRef t_str As String) Dim char_pos As Integer Dim r_len As Integer ' to store the length of the comment Dim comment_chars Dim filename_chars Dim comment_pos As Integer ' to store the position where the comment char is found Dim i As Integer comment_chars=Array("*","'","%") filename_chars = Array("O",":") t_str=Trim(t_str) 'Finding Filenames For i = 0 To UBound(filename_chars) If 1=InStr(t_str,filename_chars(i)) Then ' Check if the first char is one of the filename indicators, if so then replace the whole line with spaces Mid(t_str,1,Len(t_str))=Space(Len(t_str)) Exit For End If Next i 'Finding comments For i = 0 To UBound(comment_chars) comment_pos = InStr(t_str,comment_chars(i)) If 0<>comment_pos Then r_len = Len(t_str)-comment_pos+1 Mid(t_str, comment_pos, r_len)= Space(r_len) Exit For End If Next i ' Special case for paranthesis While 0 <>InStr(t_str,"(") comment_pos = InStr(t_str, "(") r_len = InStr(t_str, ")") - comment_pos +1 ' The + 1 part is to make sure the closing paranthesis is removed too Mid(t_str, comment_pos,r_len)=Space(r_len) Wend End Function