Hello all,
This may be a far fetched request but just trying to make my life easier here. I am programming thermoforming production molds in aluminum and therefore must drill a lot of .025 holes to allow vacuum to pass through without deforming the part. What I have been doing is manually splitting the toolpath every 10 holes or so and inserting a line of code in the program to go and do a tool length breakage test on a renishaw probe because when drilling 400+ holes it takes a long time to try and find where it broke at in a drill that small. My question is, is there a way to write a macro to have powermill sort the toolpath along the x direction two way in y, but then split the toolpath based on a specified number of holes and then create different toolpaths for the specified number?
Solved! Go to Solution.
Solved by barr.jarryd. Go to Solution.
Hey there,
As for the ordering of the toolpath, in the toolpath dialog menu under or, you can have the drill move in whatever direction you would like.
For the macro to split, give me a few hours to figure this one out. This one will be a bit tough lol.
Thank you
So this macro is not 100% what you are looking for but I'm sure it will help speed up the process.
This will take your feature set, reorder it, then split it into segments of 10 features per set. You can change that amount yourself via the code.
Hopefully this helps you out a bit.
//-----------------------------------------------------------------// // this macro was written by @barr.jarryd. Original macro // // included references to three additional macros. This way the // // code does not repeat itself, and there // // is only one file and one bit of code to edit should there ever // // be a change to the macro. // //-----------------------------------------------------------------// // UPDATES // // detailed updates go here. include 'who, when, what' // //-----------------------------------------------------------------// //Sort active featureset in the x direction 2 ways EDIT FEATURESET "1" SORT "xz" ACTIVATE FEATURESET "1" // Create an empty list STRING LIST featList = {} // Fill list with feature names from featureset 1 FOREACH f in components(entity('featureset','1')) { INT Number = add_last(featList, f.name) } //Start Selecting Features INT Count = 0 WHILE size(featList) > 10 { WHILE $Count < 10 { // Pull features from list to select STRING select = remove_first(featList) EDIT FEATURESET "1" SELECT $select $Count = $Count + 1 } //Once you hit 10 selected copy into new Featureset and delete the one in the existing. Change this value if you want to increase the amount of features to split by. IF $Count == 10 { COPY FEATURESET "1" SELECTED DELETE FEATURESET "1" SELECTED $Count = 0 } } //Once the sets ahve been sorted, rename the sets for use STRING newName = "" INT i = 1 FOREACH fs in FOLDER('FeatureSet') { $newName = $fs.name + "-" RENAME FEATURESET $fs.name $newName } FOREACH fs in FOLDER('FeatureSet') { $newName = $i RENAME FEATURESET $fs.name $newName $i = $i + 1 } MESSAGE INFO "Begin Programming"
Thanks! I've went through and changed a few things to make it work more customized to what I have setup but you definitely gave me a huge jump towards what I was looking for. Still trying to get into macro programming some more, I appreciate the work you put in for me
Well @barr.jarryd kind of beat me to it but I stayed up late last night taking a stab at this. I'll post my version because it does a few things differently. Maybe you can merge the too. Mine will take an existing monolithic drill path and create individual toolpaths with only the specified number of hole features. This code doesn't assume a featureset, it grabs it directly from the toolpath. It also doesn't assume all of the features in that featureset were used for the toolpath. You could probably add a STRING argument to the main function to pass in the toolpath name so you didn't have to manually change each time.
FUNCTION Main() { // Change this to the toolpath name STRING $toolpathName = "MyDrillPathName" // Change this to be the number of holes to split that path at INT $holeSplitValue = 10 // Setup the variables BOOL $entityExists = FALSE STRING $featureSetName = "" INT $featureCount = 0 // Check to see if the toolpath exists CALL DoesEntityNameExist('Toolpath', $toolpathName, $entityExists) IF $entityExists == FALSE { // Not an existing toolpath. Abort! MACRO ABORT } // Check to see if it's a drilling strategy IF entity('Toolpath', 'MyDrillPathName').Strategy == 'drill' { // Activate the path so it'll activate featuresset and // also sellect the features used for calculating the path ACTIVATE TOOLPATH $toolpathName // Get the featureset name $featureSetName = entity('Toolpath', $toolpathName).FeatureSet.Name // Create a STRING LIST to store the new generated featureset names STRING LIST $tempFeaturesetNameList = {} // Get the next safe name for a generates featureset STRING $nextAvailableName = "" CALL GetSafeEntityName('FeatureSet', $featureSetName, $nextAvailableName) // We make a copy of the orignal featureset so we omly get the features // that were used during the calculation of the path COPY FEATURESET $featureSetName SELECTED ACTIVATE FEATURESET $nextAvailableName // Loop through and split the featuresets up by the specified // number of features. This part was writen at 3am so it's pretty // bad and the logic could probably be cleaned up a lot INT $holeCount = 0 FOREACH $name IN extract(components(entity('featureset', $nextAvailableName)),'name') { // Check to see if we've reached or split value yet. If so // we'll break out those features into a new featureset IF $holeCount == $holeSplitValue { $holeCount = 0 STRING $tempName = "" CALL GetSafeEntityName('FeatureSet', $nextAvailableName, $tempName) COPY FEATURESET $nextAvailableName SELECTED //$nextAvailableName = $tempName ACTIVATE FEATURESET $nextAvailableName EDIT FEATURESET $nextAvailableName DESELECT ALL INT $i = add_last($tempFeaturesetNameList, $tempName) } // Continue sellecting the features EDIT FEATURESET $nextAvailableName SELECT $name $holeCount = $holeCount + 1 } // This is nasty but, because of the bad logic above, we'll // still have the remaining selected holes that didn't reached // our split value so we'll do one final split STRING $tempName = "" CALL GetSafeEntityName('FeatureSet', $nextAvailableName, $tempName) COPY FEATURESET $nextAvailableName SELECTED INT $i = add_last($tempFeaturesetNameList, $tempName) // Get the next safe name for a toolpath STRING $newPathName = "" $newPathName = $toolpathName //CALL GetSafeEntityName('Toolpath', $toolpathName, $newPathName) //Loop through the copied featureset names and generate a drill //path, based on your existing one FOREACH $copiedFeatureset IN $tempFeaturesetNameList { ACTIVATE TOOLPATH $newPathName FORM TOOLPATH STRING $tempName = "" CALL GetSafeEntityName('Toolpath', $newPathName, $tempName) EDIT TOOLPATH $newPathName CLONE $newPathName = $tempName ACTIVATE TOOLPATH $newPathName FORM TOOLPATH ACTIVATE Featureset $copiedFeatureset EDIT TOOLPATH $newPathName CALCULATE $newPathName = $tempName } } } // Checks to see if an entity's name exists FUNCTION DoesEntityNameExist(STRING entityType, STRING entityName, OUTPUT BOOL exists) { $exists = entity_exists($entityType, $entityName) } // Returns the next available safe name for an entity FUNCTION GetSafeEntityName(STRING entityType, STRING baseName, OUTPUT STRING safeName) { $safeName = new_entity_name($entityType, $baseName) }
Your next problem is going to be injecting your probe code in between each path. In the old Ductpost there was a feature where you could create a test block between the paths (in the NCProgram) and have a certain function do something with it in the written NC. It was years ago and I never got it to work. If you've already got that part covered, cool.
I reread what I wrote and it could've been worded better! It kind of sounded like a jab at @barr.jarryd 's code, with all of that "doesn't assume" crap. That was not at all how I meant it! So I just want to say I'm sorry if that's how it was received.
Its all good man lol.
I understood what you meant. No offense taken.
Yours is for sure more indepth than mine.
No offense is good, thanks!
The Ductpost function I mentioned earlier is named ppfun (a less mature person would snicker at that). It looks like it exists in PMPost, as well.
https://forums.autodesk.com/t5/powermill-forum/nc-text-blocks/td-p/6999740
That thread has a screenshot of a ppfun set up in the PMPost software. I don't have the Ductpost documentation here at home but I looked at it at work today and it gives a short description on its usage. I forgot to bring it home, unfortunately. I'll bring it home tomorrow and post a screen cap of the section that talks about it.
Not going to lie, I got a good chuckle at the name haha.
I'll take a deeper look into that when I get home after work today. Thanks for the info!
There's are several bugs in my code! The first is I have the starting path name hardcoded in one spot, instead of using the variable that's at the top of the macro.
// Check to see if it's a drilling strategy IF entity('Toolpath', 'MyDrillPathName').Strategy == 'drill' { // Should be // Check to see if it's a drilling strategy IF entity('Toolpath', $toolpathName).Strategy == 'drill' {
And then the most embarrassing one is that Activating the toolpath will not select the features if every hole was used to calculate the drill path. It only selects them if a subset of the hole features were used, which is the only way I tested it!
I don't have the time right now but I'll go back and fix those things, in case some future person tries to use it.
I was going to go to bed but it didn't take long to fix. No more hardcoded name and I check to see if the copied featureset is empty and, if it is, I delete it and use the original featureset.
FUNCTION Main() { // Change this to the toolpath name STRING $toolpathName = "MyDrillPathName" // Change this to be the number of holes to split that path at INT $holeSplitValue = 10 // Setup the variables BOOL $entityExists = FALSE STRING $featureSetName = "" INT $featureCount = 0 // Check to see if the toolpath exists CALL DoesEntityNameExist('Toolpath', $toolpathName, $entityExists) IF $entityExists == FALSE { // Not an existing toolpath. Abort! MACRO ABORT } // Check to see if it's a drilling strategy IF entity('Toolpath', $toolpathName).Strategy == 'drill' { // Activate the path so it'll activate featuresset and // also sellect the features used for calculating the path ACTIVATE TOOLPATH $toolpathName // Get the featureset name $featureSetName = entity('Toolpath', $toolpathName).FeatureSet.Name // Create a STRING LIST to store the new generated featureset names STRING LIST $tempFeaturesetNameList = {} // Get the next safe name for a generates featureset STRING $nextAvailableName = "" CALL GetSafeEntityName('FeatureSet', $featureSetName, $nextAvailableName) // We make a copy of the orignal featureset so we omly get the features // that were used during the calculation of the path COPY FEATURESET $featureSetName SELECTED // Check to see if the copied featureset has any items // If it doesn't, we know every featureset was used to // calculate the drill path REAL $featureCount = entity('FeatureSet', $nextAvailableName).num_items IF $featureCount == 0 { // It's empty and we need to deal with that fact DELETE FEATURESET $nextAvailableName $nextAvailableName = $featureSetName } ACTIVATE FEATURESET $nextAvailableName // Loop through and split the featuresets up by the specified // number of features. This part was writen at 3am so it's pretty // bad and the logic could probably be cleaned up a lot INT $holeCount = 0 FOREACH $name IN extract(components(entity('featureset', $nextAvailableName)),'name') { // Check to see if we've reached or split value yet. If so // we'll break out those features into a new featureset IF $holeCount == $holeSplitValue { $holeCount = 0 STRING $tempName = "" CALL GetSafeEntityName('FeatureSet', $nextAvailableName, $tempName) COPY FEATURESET $nextAvailableName SELECTED //$nextAvailableName = $tempName ACTIVATE FEATURESET $nextAvailableName EDIT FEATURESET $nextAvailableName DESELECT ALL INT $i = add_last($tempFeaturesetNameList, $tempName) } // Continue sellecting the features EDIT FEATURESET $nextAvailableName SELECT $name $holeCount = $holeCount + 1 } // This is nasty but, because of the bad logic above, we'll // still have the remaining selected holes that didn't reached // our split value so we'll do one final split STRING $tempName = "" CALL GetSafeEntityName('FeatureSet', $nextAvailableName, $tempName) COPY FEATURESET $nextAvailableName SELECTED INT $i = add_last($tempFeaturesetNameList, $tempName) // Get the next safe name for a toolpath STRING $newPathName = "" $newPathName = $toolpathName //CALL GetSafeEntityName('Toolpath', $toolpathName, $newPathName) //Loop through the copied featureset names and generate a drill //path, based on your existing one FOREACH $copiedFeatureset IN $tempFeaturesetNameList { ACTIVATE TOOLPATH $newPathName FORM TOOLPATH STRING $tempName = "" CALL GetSafeEntityName('Toolpath', $newPathName, $tempName) EDIT TOOLPATH $newPathName CLONE $newPathName = $tempName ACTIVATE TOOLPATH $newPathName FORM TOOLPATH ACTIVATE Featureset $copiedFeatureset EDIT TOOLPATH $newPathName CALCULATE $newPathName = $tempName } } } // Checks to see if an entity's name exists FUNCTION DoesEntityNameExist(STRING entityType, STRING entityName, OUTPUT BOOL exists) { $exists = entity_exists($entityType, $entityName) } // Returns the next available safe name for an entity FUNCTION GetSafeEntityName(STRING entityType, STRING baseName, OUTPUT STRING safeName) { $safeName = new_entity_name($entityType, $baseName) }
Can't find what you're looking for? Ask the community or share your knowledge.