Jump to content

Welcome to eMastercam

Register now to participate in the forums, access the download area, buy Mastercam training materials, post processors and more. This message will be removed once you have signed in.

Use your display name or email address to sign in:

Zaffin_D

Verified Members
  • Posts

    374
  • Joined

  • Days Won

    1

Posts posted by Zaffin_D

  1. 8 hours ago, xx4g said:

    check out the source code for the propertyManager-AddIn chook featured  on github

    I'm not sure displaying the view ID number (v_idn) is helpful.  I think the work offset (woff_n) is what you're after.

    Aside from that, you're doing more work than you need to.  If you use an unordered_set as the container you won't need to check for duplicates.  You could also sort and uniquify your vector after adding the data to it.

    Examples of both techniques on repl.it  

  2. 1 hour ago, mustardcam said:

    Are you using a 5 axis drilling toolpath?

    My tool axis control is set to 5-axis.  I tipped the part 25 degrees and still got numbers I would except. 

     image.png.fc54da153a95d8193da10e8e9d64f52d.png

    Ref. Z position (Abs.)             : 54.378467
    Selected Z position (Abs.)         : 45.315389
    TOS Z position (Abs.)              : 45.315389
    Depth Z position (Abs.)            : 18.126156
    
    Ref. Z position (Inc.)             : 10.
    
    Sum of drl_ref_z$ and drl_sel_ref$ : 64.378467

    I don't remember this changing, but what version of Mastercam are you using?  Could you share a part file?  I'm curious why this is working for you. 

  3. 2 hours ago, mustardcam said:

    The predefined variables are not mapped correctly. Some are absolute and some are incremental adding the incremental values to known absolute reference values make them absolute as well. turns out this was a mapping issue and my calculations are working. 

    I'm glad you got this working, but you've lost me.  Adding the values as you show shouldn't generate a useful position.

    Consider the below hole; Yellow is the ref point, green is the selected point and top of stock, and red is the depth 

     image.png.29aad014e649345ac74d17267a36438b.png   

    I setup a drilling postblock to mimic your math

    pdrill$
    	"Ref. Z position (Abs.)             : ", *drl_ref_z$, e$
    	"Selected Z position (Abs.)         : ", *drl_zdrl_z$, e$ 
    	"TOS Z position (Abs.)              : ", *drl_tos_z$, e$
    	"Depth Z position (Abs.)            : ", *drl_depth_z$, e$ 
    	*e$
    	"Ref. Z position (Inc.)             : ", *drl_sel_ref$, e$
    	
    	zrefhgt = drl_ref_z$ + drl_sel_ref$
    	*e$
    	"Sum of drl_ref_z$ and drl_sel_ref$ : ", *zrefhgt, e$

    And that resulted in the following output.

    Ref. Z position (Abs.)             : 60.
    Selected Z position (Abs.)         : 50.
    TOS Z position (Abs.)              : 50.
    Depth Z position (Abs.)            : 20.
    
    Ref. Z position (Inc.)             : 10.
    
    Sum of drl_ref_z$ and drl_sel_ref$ : 70.

     

    I don't understand how a value of 70mm is useful.   

  4. 16 hours ago, mustardcam said:
    
     drl_init_z$   (clearance height)                          Mapped value
     drl_sel_ref$  (retract height)                            not mapped
     drl_sel_tos$  (top of stock)                              not mapped
     drl_ref_z$    (referance point in space for top of hole)  Mapped value  
     drl_depth_z$  (hole depth)                                Mapped value
    
    drl_sel_ref$ & drl_sel_tos$ get output from mastercam as inc values.
    I am using the calc's below to calculate these variables based on a mapped value
     
    zrefhgt = drl_ref_z$ + drl_sel_ref$
    ztoshgt = drl_ref_z$ + drl_sel_tos$
    
    FYI I'm new to post writing and open to advises if I'm doing it wrong. 
     

    Do you have the post documentation?  The docs the cover drl_ series of variables very well, though in my experience none of them are mapped automatically.

    Also the formulas don't make much sense to me; seeing as... 

    • drl_sel_ref$ is the distance from the selected point to the ref point
    • drl_sel_tos$ is the distance from the selected point to the top of stock
    • drl_ref_z$ is the absolute Z position of the ref point

    I'm not sure what you are trying to accomplish by adding them together. 

    Also, as this is a 3+2/5-axis application you'll likely have to rotate/map the values depending on how your machine handles tilted work planes.     

    You should contact your reseller or post developer; they will be able to get you sorted out.     

    • Like 1
  5. As far as I’m aware there isn’t one.  If you think about it how could there be.  A user can select any combination of arcs or solid holes with varying diameters(points could also be used, so no diameter); they can also select as many entities as they want.

    If you are looking to determine the diameter of a circle mill or helix bore, this can be done mathematically in the post; but if you’re using a drill op you’re out of luck.

    I suppose you could also use an add-in to get this information at posting time; it just depends how badly you want the information.

  6. 4 hours ago, jwvt88 said:

    For that post, we just have the normal "Tap" cycle, which we have already edited above to have the I and J. We also have a "Rigid Tapping Cycle" which has this:

    
    pmisc2$          #Canned Rigid Tapping Cycle
          pdrlcommonb
          #RH/LH based on spindle direction
          pbld, n$, sg95, e$
          pbld, n$, sm29, *speed, e$
          if met_tool$, pitch = n_tap_thds$  #Tap pitch (mm  per thread)
          else, pitch = 1/n_tap_thds$        #Tap pitch (inches per thread)
          pcan1, pbld, n$, *sgdrlref, *sgdrill, pxout, pyout, pfzout, pcout,
            prdrlout, *pitch, !feed, strcantext, e$
          pcom_movea

    So we always use the "Tap" cycle, and just fill in the pitch after I or J and delete the other. What we want it to do is just post out J=13 for 1/2-13 or I=1 for M6x1.... I would guess part of the problem is using a Fanuc post for a Brother control.. but everything else seems to work fine minus the tapping. But if we just aren't filling in a parameter correctly, that is definitely a possibility.

    My coworker has been working to fix all of our posts so he knows more than I do, but neither of us are experts. All of our other posts are now configured properly but we haven't been able to figure this one out. 

    Are you using Mastercam 2018 or later?  If so you cannot output a metric pitch in an inch file or vice versa.  The only workaround I'm aware of involves using the API to query the tool to determine if it's inch or metric.

    From the docs...

    Quote

    The meaning of this parameter changed in Mastercam 2018. Before Mastercam 2018, it indicated the units in which the tool was dimensioned. Beginning with Mastercam 2018, it indicates the system units as determined by the .config file. Tool dimensions are output in the units in which the part was programmed. For example, if you have a 12mm endmill and you are posting out an inch part, the value that is output to the NCI file (for example, parameter 20004.5) will be 0.4724.

    Many pre-2018 posts use a statement of the following form to determine if a tool is dimensioned in inch or metric units:

    
    if prmcode$ = 20007, is_my_tool_metric = rparsngl(sparameter$, 11)

    This logic no longer works in Mastercam 2018 and later versions.

     

    • Like 1
  7. 3 hours ago, crazy^millman said:

    @Zaffin_D Excellent work. I am interested to see how you would do it with the enhanced tool table if you don't mind sharing it. 

    Not much would change in this example; this...

    pwrtt$
        if (t$ > 0) & (gcode$ <> 1003),
            [
            p_add_to_tool_stack
            ]

    ...would change to this...

    ptooltable$ 
        if tt_count$ = 1,
            [
            p_add_to_tool_stack
            ]

     

    • Like 1
  8. So I could be way off in the weeds here, but it sounds like you want to use the index position of the tool in the buffer as the diameter offset.  Assuming that your buffer / tool list is non-repeating the below should work.

    First, I set up pwrtt$ so that a tool will only be added to the stack once no matter how many times it appears in the program.  I much prefer then enhanced tool table for this, but since you mentioned pwrtt$...  

    pwrtt$
    	if (t$ > 0) & (gcode$ <> 1003),
    		[
    		p_add_to_tool_stack
    		]

    Next, I defined the stack and associated variables.

    stack_101_size        : 0
    stack_101_index       : 0
    stack_101_result      : 0
    
    stack_101_tool_number : 0
    
    fstack 101 1

    Then I created a utility postblock to add the tool to the stack 

    p_add_to_tool_stack
    	t$ = push(101, stack_101_result, 1)

    The below postblock will iterate through the stack looking for a matching tool number to the one passed in.  If a match is found, it's index is set to diameter_offset and passed back by reference.  If no match is found -99999 is passed back  

    tool_number : 0
    diameter_offset : 0
    
    p_get_diameter_offset(tool_number, !diameter_offset)	
    	stack_101_index = 1
    
    	stack_101_size = pop(101, stack_101_result, 0)
    	while stack_101_index <= stack_101_size,
    		[
    		stack_101_tool_number = pop(101, stack_101_index, 5)
    		if tool_number = stack_101_tool_number,
    			[
    			diameter_offset = stack_101_index
    			stack_101_size = -99999
    			]
    		else, diameter_offset = -99999
    
    		stack_101_index = stack_101_index + 1
    		]

    To use this, at tool change (be it start-of-file, real, or null) do something like this

    psof$
    ptlchg$
    ptlchg0$
          p_get_diameter_offset(t$, !result)

    That's it.  If t$ exists in the list, it's index will be returned to result in this case.

    I hope that helps, but if not I'm sure someone more knowledgeable than I will step in.

      

    • Like 2
  9. Implement a modulo post block in your post, something like this should get you started...

    modulo_result : 0
    int_a         : 0
    int_n         : 0
    remainder     : 0
    
    p_modulo(int_a, int_n, !remainder)
    	modulo_result = int_a / int_n
    	modulo_result = int(modulo_result)
    	modulo_result = modulo_result * int_n
    	remainder = int_a - modulo_result

    Then call it passing in your spindle speed as int_a, 10 as int_n, and use any numeric value for the returning value (the remainder)

    p_modulo(ss$, 10, !result)

    If the remainder returns 0, your spindle speed is evenly divisible by ten, so it ends in zero. 

    Here are a few test cases

    	  p_modulo(20000, 10, !result)
    	  "->", ~result, e$
    	  //Output 
              // -> result 0.
    	  
    	  p_modulo(123456, 10, !result)
    	  "->", ~result, e$
    	  //Output 
              // -> result 6.
    	  
    	  p_modulo(45000, 10, !result)
    	  "->", ~result, e$
    	  //Output 
              // -> result 0.
    	  
    	  p_modulo(1776, 10, !result)
    	  "->", ~result, e$
    	  //Output 
              // -> result 6.
    	  
    	  p_modulo(1852, 10, !result)
    	  "->", ~result, e$
    	  //Output 
              // -> result 2.
    	  
    	  p_modulo(105, 10, !result)
    	  "->", ~result, e$
    	  //Output 
              // -> result 5.

     

    • Thanks 1
    • Like 1
  10. 13 hours ago, Dhananjay @Mastercam India said:

     Thank You sir, 😀 

    Issue resolved 

    Reason- Because of one space that sync. is not working .

    Do you have any document on this how to define other sync. code.

    which factor decide range of sync. code? 

     

    I recommend looking online for some resources about regular expressions.  It’s a vast topic, and it’s not one I’m qualified to cover; but I’ll do my best to break down the key parts of the regex.

    Starting off we have a word boundary \b.

    Next we match ‘M’ literally.

    The open and closing parentheses define a match group.

    The numbers between the braces define a range of values to match. So [1-9] will match 1, 2, 3, 4, 5, 6, 7, 8, or 9.

    The pipe ‘|’ means or, and with the two other patterns we can range check from 101-999.

    Again, I really recommend Googling regular expressions; you’ll find tons of resources.

    • Like 1
  11. 2 hours ago, Peter - NCS Ltd. said:

    No, stack is a standalone stuff and you can define as many as you wish.

    Correct(ish)  you can have as many stacks as you'd like, but they exist in memory.  If you want to write them to disk you must use the pop function with mode -1

    Quote

    –1 = Write the data record to a buffer that has been previously defined with the fbuf statement. 
    In this case, option indicates the number of the buffer where the data will be stored. 
    The success/fail code will be stored in value.

    Or you could use a different file stream to write the data to disk, but it's not as automatic.

     

    2 hours ago, Peter - NCS Ltd. said:

    AFAIK stack is limited to numbers only (no strings), but still they very useful.

    You should contact CNC's post department.

     

    30 minutes ago, pullo said:

    I was thinking more among lines  of :  can I use a buffer , close it  , redefine it  and use it again... I have not had the need to use buffers before ...

    Sort of, here is a Knowledgebase article that shows how to reuse a buffer, but as far as I'm aware you can't redefine it at runtime.  Something can be done for sure, but without more detail it's hard to know what options to present.

     

     

  12. 50 minutes ago, jlw™ said:

    Thanks for bringing that up Zack.  I've used opinfo a lot but to get nose radius I have that method memorized.  Can you show either of the other two methods?

     

    The docs cover this pretty well, but here is an example of both methods being used.

    insert_cr_pnci20000 : 0
    
    pnci20000$
        if prmcode$ = 20104,
            [
            insert_cr_pnci20000 = rparsngl(sparameter$, 4)
            ]
            
    insert_cr_opinfo    : 0
    
    lsof$
        sparameter$ = opinfo(20104, 0)
        insert_cr_opinfo = rparsngl(sparameter$, 4)
    
        ~insert_cr_opinfo, e$
        ~insert_cr_pnci20000, e$
    
        #// Output ->
        #// insert_cr_opinfo .03125
        #// insert_cr_pnci20000 .03125

     

    On thing to note; pnci20000$ will not run if the pparameter$ postblock is present in the post.  

    • Like 3
  13. 15 minutes ago, jlw™ said:

    TBH, there may be a way in the tool table or pwrtt section that is easier considering all the new stuff in there but I haven't dug into that.  Maybe Dale or some one will chime in.

    pnci20000$ is the preferred way to access the 20xxx and 30xxx range of parameters with the enhanced tool table.

    You can also use opinfo and parse the returned string, but that method isn’t quite as efficient.

     

     

    • Like 1
  14. 10 minutes ago, byte me said:

    I didn't see a change when I ran the code, I don't even use coolant so I am unfamiliar.

    I am pretty lost on this one..

    SlaveCam got it.

    You need to reset the main tool to the cloned assembly for the changes to stick.

    void OperationService::SetToolCoolant(int opID)
    {
    	auto op = TpMainOpMgr.GetMainOpList().OpByID(opID);
    	if (op != nullptr)
    	{
    		auto toolSystem = Cnc::Tool::GetToolSystem();
    		auto toolAssembly = Cnc::Tool::TlAssemblyCPtr();
    		if (toolSystem->Find(op->tl.slot, toolAssembly))
    		{
    			auto toolAssemblyClone = toolAssembly->Clone();
    
    			if (toolAssemblyClone->HasMainTool())
    			{
    				auto millTool = toolAssemblyClone->GetMillTool();
    
    				Cnc::Tool::TlCoolant tlCool;
    				tlCool.SetFloodState(0);
    				tlCool.SetFloodTime(1);
    				tlCool.SetMistState(0);
    				tlCool.SetMistTime(1);
    				tlCool.SetToolState(0);
    				tlCool.SetToolTime(1);
    
    				millTool->SetCannedTxtCoolant(tlCool);
    
    				toolAssemblyClone->SetMainTool(millTool);
    
    				toolSystem->Update(toolAssemblyClone);
    			}
    		}
    	}
    }

    The TlCoolant class is much more friendly than a vector.  Sadly I knew about it less than a year ago; my memory isn't what it used to be. 

    Makes me think that there has to be a friendlier way to update the operation coolant.

    • Like 1
  15. 12 minutes ago, byte me said:

    In that case you could also try this member function of the tool class :

     

    Have you tested this?

    I had the below function for setting a tool's coolant, but no matter what I do the coolant won't stick.

    void OperationService::SetToolCoolant(int opID)
    {
    	auto op = TpMainOpMgr.GetMainOpList().OpByID(opID);
    	if (op != nullptr)
    	{
    		auto toolSystem = Cnc::Tool::GetToolSystem();
    		auto toolAssembly = Cnc::Tool::TlAssemblyCPtr();
    		if (toolSystem->Find(op->tl.slot, toolAssembly))
    		{
    			if (toolAssembly->HasMainTool())
    			{
    				auto millTool = toolAssembly->GetMillTool();
    
    				std::vector<short> cannedTextCoolant(20);
    
    				cannedTextCoolant[0] = -3101;
    				cannedTextCoolant[1] = -4103;
    				cannedTextCoolant[2] = -5105;
    
    				millTool->SetCannedTxtCoolant(cannedTextCoolant);
    
    				toolSystem->Update(toolAssembly->Clone());
    			}
    		}
    	}
    }

     

    I'm also totally wrong about the right most digits.  They do have something to do with on and off; new theory below.

    • 01 and 02 sets ON and OFF for Coolant 1 
    • 03 and 04 sets ON and OFF for Coolant 2 
    • ...skip a few...
    • 19 and 20 sets ON and OFF for Coolant 10 

    So to set Coolant 5 to ON and Before, use -3109. 

    • Thanks 1
  16. Are you trying to modify the operation's coolant?  If so, new style coolant is handled by canned text...

    void OperationService::SetOperationCoolant(int opID)
    {
    	auto op = TpMainOpMgr.GetMainOpList().OpByID(opID);
    	if (op != nullptr)
    	{
    		op->cantxt.cantxt[0] = -3101;
    		op->cantxt.cantxt[1] = -4103;
    		op->cantxt.cantxt[2] = -5105;
    
    		DB_LIST_ENT_PTR dbPointer = nullptr;
    
    		auto isSuccess = false;
    
    		operation_manager(
    			op,
    			OPMGR_REWRITE,
    			&dbPointer,
    			&isSuccess);
    	}
    }

    The values are a bit of a mystery to me but as far as I can tell...

    • The left most digit will be a 3,4, or 5 corresponding to before, with, after
    • The two right most digits are the coolant; 00 is coolant 1 off, 01 is coolant 1 on, 02 is coolant 2 off,  03 is coolant 2 on etc.

    For example, -5105 would mean coolant 3 on, after.

  17. 19 minutes ago, baby byte said:

    I was trying to take the struct as a parameter,

    not sure if that is the reason i was having

    trouble. Nice example.. :thumbsup::turned:

    Yes, you can pass a struct, see below

    File: OperationService.h

    #pragma once
    
    namespace OperationServiceNative
    {
    	public value struct OperationData
    	{
    		System::String^ Comment;
    		int ID;
    		int Type;
    		int ToolNumber;
    	};
    
    	public ref class OperationService
    	{
    	public:
    		OperationService();
    
    		OperationData^ GetOperationData(int opID);
    
    		bool CreateOperation(OperationData% opData);
    
    		~OperationService();
    
    	};
    }

    File: OperationService.cpp

    #include "pch.h"
    
    #include "OperationService.h"
    
    OperationServiceNative::OperationService::OperationService()
    {
    }
    
    OperationServiceNative::OperationData^ OperationServiceNative::OperationService::GetOperationData(int opID)
    {
    	OperationData^ opData = nullptr;
    
    	auto operation = TpMainOpMgr.GetMainOpList().OpByID(opID);
    
    	if (operation != nullptr)
    	{
    		opData = gcnew OperationData();
    
    		System::String^ commentString = gcnew System::String(operation->comment);
    
    		opData->Comment = commentString;
    		opData->ID = operation->op_idn;
    		opData->Type = operation->opcode;
    		opData->ToolNumber = operation->tl.tlno;
    	}
    
    	return opData;
    }
    
    bool OperationServiceNative::OperationService::CreateOperation(OperationData% opData)
    {
    	//Code to create an operation with the OperationData struct
    
    	return false;
    }
    
    OperationServiceNative::OperationService::~OperationService()
    {
    }

    File: Main.cs

    namespace MyNetHook
    {
        using Mastercam.App;
        using Mastercam.App.Types;
    
        using OperationServiceNative;
    
     
        public class Main : NetHook3App
        {
    
            public override MCamReturn Run(int param)
            {
                var opService = new OperationService();
    
                var opData = (OperationData)opService.GetOperationData(1);
    
                var newOpData = new OperationData()
                {
                    Comment = "A new op",
                    ID = 2,
                    Type = 1,
                    ToolNumber = 1
                };
    
                var isSuccess = opService.CreateOperation(ref opData);
           
                return MCamReturn.NoErrors;
            }
    
        }
    }

     

    • Like 1

Join us!

eMastercam - your online source for all things Mastercam.

Together, we are the strongest Mastercam community on the web with over 56,000 members, and our online store offers a wide selection of training materials for all applications and skill levels.

Follow us

×
×
  • Create New...