Mach3 Plugin - Rigid Tapping
To perform Rigid Tapping from Mach3 the tapping parameters are set into GCode Variables, then a Macro (M84) is called which downloads the parameters to KFLOP/Kogna, notifies KFLOP/Kogna to perform the Tap Cycle, then waits until KFLOP/Kogna sets a variable indicating the operation has completed.
A requirement for Rigid Tapping is that the Spindle has encoder feedback and is possible to move in a fairly controlled manner. The Z axis motion is "geared" to the measured Spindle Encoder Position throughout the cycle.
There are three parts to the process: The GCode, the M84 Macro, and the KFlop User Program. Examples can be found here.
Example Rigid Tap Call From GCode
We use a Macro M84 as Mach3 uses the normal G84 Tap cycle for a floating tapholder technique and doesn't currently support a rigid tap GCode.
Note that the forward cutting rate (RPM) and the retraction rate (RPM) can be defined separately. A cyclic forward/retract motion can be specified to cut the thread to the total depth. If a simple single motion is desired, set the Z depth forward motion to the Z depth Total.
G0X0Y0Z5 (Call a Rigid Tap Sequence) #10=20 (TPI - Threads per inch) #11=700 (Forward Cutting RPM) #12=1000 (Retract RPM) #13=0.75 (Z depth Total inches) #14=0.2 (Z depth Forward per Motion) #15=0.05 (Z depth Retract per Motion) M84 G0X4Y0Z5 (Call a Rigid Tap Sequence) #10=20 (TPI - Threads per inch) #11=700 (Forward Cutting RPM) #12=1000 (Retract RPM) #13=0.75 (Z depth Total inches) #14=0.2 (Z depth Forward per Motion) #15=0.05 (Z depth Retract per Motion) M84 M2
Mach3 M84 Macro
This macro moves the GCode Tapping Variables to Mach3 User DROs, downloads then to KFLOP/Kogna UserData variables, Triggers KFLOP/Kogna to perform the Tap Cycle, then waits until KFLOP/Kogna sets a User Data Variable indicating the cycle is complete.
' Macro for Rigid Tappin with Dynomotion KFLOP ' ' pass variables to KFLOP ' ' Var DRO KFLOP UserVar Description ' #10 1010 18 19 TPI - Threads per inch ' #11 1011 20 21 Forward Cutting RPM ' #12 1012 22 23 Retract RPM ' #13 1013 24 25 Z depth Total inches ' #14 1014 26 27 Z depth Forward per Motion ' #15 1015 28 29 Z depth Retract per Motion ' 1016 30 31 Set by KFLOP when complete 'Move the GCode Vars into DROS and send them to KFLOP User Vars For i=0 To 5 Call SetUserDRO(1010+i, GetVar(10+i)) NotifyPlugins(19010+i) Next i Call SetUserDRO(1016, 0)'clear the complete flag NotifyPlugins(19010+6) NotifyPlugins(10084) 'do the TAP!! While GetUserDRO(1016)=0 Sleep(50) NotifyPlugins(18016) 'upload the complete flag Wend
KFLOP/Kogna Notify User C Program that performs the Rigid Tap Cycle
The C Program that performs the Rigid Tap Cycle. This assumes that the Spindle axis can be controlled like a Servo Axis within KFLOP/Kogna (although it is not defined as an axis within Mach3). The defines must be set per your specific system. A low pass filter is used to smooth the commanded Z motion for the case where the Spindle Motion might be too Jerky for the Z Axis to follow without possibly stalling, it also smoothes the response that would be otherwise stepped because user programs only execute every other servo sample. A Tau of 0.001 performs as a low pass filter with a time constant of 1ms.
#include "KMotionDef.h"
//Plugin calls for Mach3 NotifyPlugins Commands
void Tap(void);
main()
{
int msg = persist.UserData[6]; // Mach3 notify Message 10000-10999
printf("Mach3 Notify Call, Message = %d\n",msg);
if (msg==10084)
{
Tap();
}
}
// R I G I D T A P P I N G
#define ZAXIS 7
#define SPINDLE_AXIS 6
#define Z_CNTS_PER_INCH -20000.0
#define CNTS_PER_REV (8192*14/16)
#define TAU 0.001
double SlaveGain,ToCut,TotalCut,Z0,S0;
void DoSlave(void);
void DoTap(double Dist, double Rate, double TPI);
void Tap();
{
// #10 1010 18 19 TPI
// #11 1011 20 21 Forward Cutting RPM
// #12 1012 22 23 Retract RPM
// #13 1013 24 25 Z depth Total inches
// #14 1014 26 27 Z depth Forward per Motion
// #15 1015 28 29 Z depth Retract per Motion
// #16 1015 30 31 Complete Flag
double TPI = *(double *)&persist.UserData[18];
double CutRPM = *(double *)&persist.UserData[20];
double RetractRPM = *(double *)&persist.UserData[22];
double ZDist = *(double *)&persist.UserData[24];
double ZForward = *(double *)&persist.UserData[26];
double ZReverse = *(double *)&persist.UserData[28];
double FeedRate = CutRPM/(TPI*60);
double RetractRate = RetractRPM/(TPI*60.0);
printf("TPI = %f\n",TPI);
printf("FeedRate = %f\n",FeedRate);
printf("RetractRate = %f\n",RetractRate);
printf("ZDist = %f\n",ZDist);
printf("ZForward= %f\n",ZForward);
printf("ZReverse = %f\n",ZReverse);
// Slave the Z Axis to the Spindle
SlaveGain = Z_CNTS_PER_INCH/(CNTS_PER_REV * TPI);
Z0 = chan[ZAXIS].Dest;
S0 = chan[SPINDLE_AXIS].Dest;
// in case there is significant spindle position error move there first
Move(ZAXIS,(chan[SPINDLE_AXIS].Position-S0)*SlaveGain+Z0);
while (!CheckDone(ZAXIS)) ;
TotalCut=0.0;
while (TotalCut < ZDist)
{
if (TotalCut + ZForward > ZDist) // last feed
{
// yes, do any remaining
DoTap(ZDist-TotalCut, FeedRate, TPI);
// retract fully
DoTap(-ZDist, RetractRate, TPI);
TotalCut=ZDist;
}
else
{
// no, just cut a bit
DoTap(ZForward, FeedRate, TPI);
DoTap(-ZReverse, RetractRate, TPI);
TotalCut+=ZForward-ZReverse;
}
}
Delay_sec(1.0);
Move(ZAXIS,Z0); // move back to where we started
while (!CheckDone(ZAXIS));
double *)&persist.UserData[30]=1.0; // set flag that we are complete
printf("Tap Complete\n");
}
void DoTap(double Dist, double Rate, double TPI)
{
// Tap down
MoveRelAtVel(SPINDLE_AXIS, Dist*TPI*CNTS_PER_REV, Rate*TPI*CNTS_PER_REV);
while (!CheckDone(SPINDLE_AXIS))
DoSlave();
}
void DoSlave(void)
{
MoveExp(ZAXIS,(chan[SPINDLE_AXIS].Dest-S0)*SlaveGain+Z0, TAU);
WaitNextTimeSlice();
}