DIY Collet-Spinning ATC - Adapting Linear ATC C Programs?
Moderators: TomKerekes, dynomotion
Re: DIY Collet-Spinning ATC - Adapting Linear ATC C Programs?
I've continued troubleshooting and doing code rewrites with Grok to see if the AI could actually come up with code for me based upon what I was trying to accomplish. I've invested hours of time tweaking things with Grok, but the process has been very promising! I've made a ton of headway. It was even able to diagnosed a hardware wiring change I needed to make with the tool setter switch to get it working, adding a pull-up resistor to trigger high in the normally closed state. The tool change program is now fully functional, with the each tool touching off on the tool setter every time it's loaded. The work flow is to use the z touch plate to establish the workpiece Z zero first, then when you run your job, it will establish an offset by comparing the z touch plate zero point and the tool setter trigger point. There's still something a little off happening when I switch to the next tool, where the zero point is a little above or below where intended, but I think I have an idea of how to tweak things to fix that.
I'll put another update here after I've got it functioning the way I want, but figured I'd post this in case others out there who have very low experience with C code want to tackle a C-heavy project like this. Grok is certainly up for the task of coding machine functions for you provide it with accurate information and you don't mind spending time troubleshooting with it. You can just follow it's suggestions to provide console readouts to help it debug issues, and supply appropriate information about your machine setup and goals, as needed. It will use all of that info to spit out updated files for you to try until you get a fully functional one. Very cool! Just be sure to make a backup copy of all your original files in case things don't go the way you hoped.
I'll put another update here after I've got it functioning the way I want, but figured I'd post this in case others out there who have very low experience with C code want to tackle a C-heavy project like this. Grok is certainly up for the task of coding machine functions for you provide it with accurate information and you don't mind spending time troubleshooting with it. You can just follow it's suggestions to provide console readouts to help it debug issues, and supply appropriate information about your machine setup and goals, as needed. It will use all of that info to spit out updated files for you to try until you get a fully functional one. Very cool! Just be sure to make a backup copy of all your original files in case things don't go the way you hoped.
- TomKerekes
- Posts: 2868
- Joined: Mon Dec 04, 2017 1:49 am
Re: DIY Collet-Spinning ATC - Adapting Linear ATC C Programs?
Wow great progress. Did you resolve all your questions?
Regards,
Tom Kerekes
Dynomotion, Inc.
Tom Kerekes
Dynomotion, Inc.
Re: DIY Collet-Spinning ATC - Adapting Linear ATC C Programs?
Thanks! Sadly, I ran into a bit of a brick wall right at the finish line, so to speak. The tool changer setup is changing tools, returning them to the correct slots, etc, and I've got the tool setter working now, but I'm about 35 iterations deep on the code for the tool setter, trying to get the calculations to do what I want. I can't tell if it's my thinking that's off or my inability to get Grok to understand my thinking;).
I've got a z probing file set up to manually probe the workpiece with whatever bit happens to be in the spindle when I turn the machine on and then go off to the tool setter. It first sets z zero on the workpiece surface, then rapids up and over to the tool setter to do a touch off there as well. This establishes the distance between the tool setter triggering point and the z-zero work surface, and then stores that measurement in a persist var. When I go to run my job, every time it changes tools, it does a touch off on the tool setter and then applies that offset from the persist var to zero the new bit to the work surface. My thinking there is that no matter what length bit is put into the spindle, the tool tip has to go to the exact same trigger point on the tool setter, so if I can just apply the known distance to the work surface stored in the persist var as the new tool triggers the tool setter, that should make the new tool tip exactly that far above the work surface (establishing work surface zero).
I thought I'd do that instead of a more traditional method of storing tool lengths, since those will likely change due to bit slippage in the collets while they're stored. The problem is every time I think I've gotten the code correct with Grok, I run through a few tool changes and the tool tips end up in different places when commanded to z zero. What's confusing to me is that they seem to be off by the exact amount of tool length difference there is between bits. For example, if the new bit sticks out of the collet 0.5" less than the previous one, it hovers above the work surface about 0.5" when at z zero. I'm having trouble wrapping my head around how that's happening given how I've told Grok to make the code behave. I'm a bit brain-fried by it all at this point, by I'll keep at it when my mind is fresh again.
In case you're curious, here's what Grok came up with so far. The first code block is for the probing file and the second one is for the tool changer.
ProbeZandOffset.c
Linear16ToolHolders.c
I've got a z probing file set up to manually probe the workpiece with whatever bit happens to be in the spindle when I turn the machine on and then go off to the tool setter. It first sets z zero on the workpiece surface, then rapids up and over to the tool setter to do a touch off there as well. This establishes the distance between the tool setter triggering point and the z-zero work surface, and then stores that measurement in a persist var. When I go to run my job, every time it changes tools, it does a touch off on the tool setter and then applies that offset from the persist var to zero the new bit to the work surface. My thinking there is that no matter what length bit is put into the spindle, the tool tip has to go to the exact same trigger point on the tool setter, so if I can just apply the known distance to the work surface stored in the persist var as the new tool triggers the tool setter, that should make the new tool tip exactly that far above the work surface (establishing work surface zero).
I thought I'd do that instead of a more traditional method of storing tool lengths, since those will likely change due to bit slippage in the collets while they're stored. The problem is every time I think I've gotten the code correct with Grok, I run through a few tool changes and the tool tips end up in different places when commanded to z zero. What's confusing to me is that they seem to be off by the exact amount of tool length difference there is between bits. For example, if the new bit sticks out of the collet 0.5" less than the previous one, it hovers above the work surface about 0.5" when at z zero. I'm having trouble wrapping my head around how that's happening given how I've told Grok to make the code behave. I'm a bit brain-fried by it all at this point, by I'll keep at it when my mind is fresh again.
In case you're curious, here's what Grok came up with so far. The first code block is for the probing file and the second one is for the tool changer.
ProbeZandOffset.c
Code: Select all
#include "KMotionDef.h"
#define TMP 10
#include "C:\Users\NUA_TIM\Desktop\KMotion5.4.0\C Programs\KflopToKMotionCNCFunctions.c"
#define AXISZ 3
#define AXISX 2
#define AXISY 0
#define CNT_PER_INCH_Z 10000
#define CNT_PER_INCH_X 3175
#define CNT_PER_INCH_Y 3180.3
#define Z_PROBE_BIT 7
#define TOOL_HEIGHT_BIT 29 // Bit to read tool height plate (KONNECT INPUT 31)
#define WORKPIECE_ZERO_VAR 12
#define REF_TOOL_OFFSET_VAR 11 // Stores job-specific G54 Z DRO (counts)
#define TOOL_HEIGHT_PLATE_X 23.5613
#define TOOL_HEIGHT_PLATE_Y 30.1336
#define MAX_Z_PROBE_DEPTH -6.0 // Safety limit to prevent over-travel (inches)
#define TOUCH_PLATE_THICKNESS 0.51
// Function prototypes
int MoveXY(float x, float y, float Speed);
int MoveZ(float z, float Speed);
int ProbeToolSetter(float *z_position);
main()
{
SetBitDirection(Z_PROBE_BIT, 0);
ch3->LimitSwitchOptions = 0;
FPGA(STEP_PULSE_LENGTH_ADD) = 63 + 0x80;
Jog(AXISZ, -3000);
while (ReadBit(Z_PROBE_BIT));
Jog(AXISZ, 0);
while (!CheckDone(AXISZ));
float z_position = chan[AXISZ].Dest / CNT_PER_INCH_Z;
float workpiece_zero = z_position + TOUCH_PLATE_THICKNESS;
persist.UserData[WORKPIECE_ZERO_VAR] = (int)(workpiece_zero * CNT_PER_INCH_Z);
printf("Z probe triggered at %.4f, workpiece zero set to %.4f\n", z_position, workpiece_zero);
DoPCFloat(PC_COMM_SET_Z, TOUCH_PLATE_THICKNESS); // Set Z=0 at workpiece surface
MoveRelAtVel(AXISZ, 4840, 12000);
while (!CheckDone(AXISZ));
ch3->LimitSwitchOptions = 0x11a;
// Tool setter probing
float z_toolsetter, dro_value;
// Verify tool setter bit state
printf("Bit 29 (TOOL_HEIGHT_BIT) initial state: %d\n", ReadBit(TOOL_HEIGHT_BIT));
// Move to machine Z=0
if (MoveZ(0, 4)) {
printf("Error: Failed to move to machine Z=0. Halting.\n");
DoPC(PC_COMM_HALT);
return;
}
// Push tool table out
SetBit(19);
printf("Pushed tool table out\n");
// Probe tool setter
if (ProbeToolSetter(&z_toolsetter)) {
printf("Error: Failed to probe tool setter. Halting.\n");
DoPC(PC_COMM_HALT);
return;
}
// Pull tool table back in
ClearBit(19);
printf("Pulled tool table back in\n");
// Store job-specific G54 Z DRO as tool setter trigger height minus touchplate surface
dro_value = z_toolsetter - z_position;
persist.UserData[REF_TOOL_OFFSET_VAR] = (int)(dro_value * CNT_PER_INCH_Z);
printf("Stored job-specific G54 Z DRO: %.4f inches at G53 Z=%.4f, touchplate surface=%.4f\n", dro_value, z_toolsetter, z_position);
}
// Probe tool setter. Return 0=Success, 1=Failure
int ProbeToolSetter(float *z_position)
{
int SaveZLimits;
// Move to tool setter position
if (MoveXY(TOOL_HEIGHT_PLATE_X, TOOL_HEIGHT_PLATE_Y, 10)) return 1;
// Save limit switch settings and disable limits
SaveZLimits = ch3->LimitSwitchOptions;
ch3->LimitSwitchOptions = 0;
FPGA(STEP_PULSE_LENGTH_ADD) = 63 + 0x80;
// Jog Z down until tool setter is triggered or safety limit reached
Jog(3, -3000); // Jog at 3000 counts/sec
while (ReadBit(TOOL_HEIGHT_BIT)) {
float current_z = chan[AXISZ].Dest / CNT_PER_INCH_Z;
if (current_z < MAX_Z_PROBE_DEPTH) {
Jog(3, 0); // Stop
while (!CheckDone(3)); // Wait for motion to complete
printf("Error: Tool setter not triggered, exceeded max depth %.4f inches. Halting.\n", MAX_Z_PROBE_DEPTH);
ch3->LimitSwitchOptions = SaveZLimits;
return 1; // Failure
}
}
Jog(3, 0); // Stop
while (!CheckDone(3)); // Wait for motion to complete
// Get current Z position
*z_position = chan[AXISZ].Dest / CNT_PER_INCH_Z;
printf("Tool setter triggered at %.4f inches\n", *z_position);
// Move back up to machine Z=0
if (MoveZ(0, 4)) return 1; // Move at 4 inch per second
// Restore limit settings
ch3->LimitSwitchOptions = SaveZLimits;
return 0; // Success
}
// Move Axis XY at specified Speed and wait until complete
int MoveXY(float x, float y, float Speed)
{
MoveAtVel(AXISX, x * CNT_PER_INCH_X, Speed * CNT_PER_INCH_X);
MoveAtVel(AXISY, y * CNT_PER_INCH_Y, Speed * CNT_PER_INCH_Y);
while (!CheckDone(AXISX) || !CheckDone(AXISY))
{
if (!chan[AXISX].Enable)
{
printf("Error X Axis Disabled. Halting.\n");
return 1;
}
if (!chan[AXISY].Enable)
{
printf("Error Y Axis Disabled. Halting.\n");
return 1;
}
}
return 0; // success
}
// Move Axis Z at specified Speed and wait until complete
int MoveZ(float z, float Speed)
{
MoveAtVel(AXISZ, z * CNT_PER_INCH_Z, Speed * CNT_PER_INCH_Z);
while (!CheckDone(AXISZ))
{
if (!chan[AXISZ].Enable)
{
printf("Error Z Axis Disabled. Halting.\n");
return 1;
}
}
return 0; // success
}
Code: Select all
#include "KMotionDef.h"
#define TMP 10 // which spare persist to use to transfer data
#include "C:\Users\NUA_TIM\Desktop\KMotion5.4.0\C Programs\KflopToKMotionCNCFunctions.c"
#include "C:\Users\NUA_TIM\Desktop\Machine Programs\CorrectAnalogFunction.c"
#define RPM_FACTOR 22200.0 // RPM for full duty cycle (max analog out)
//-----------------------------------------
// LINEAR TOOL CHANGING
//-----------------------------------------
#define AXISX 2
#define AXISY 0
#define AXISZ 3
//---------Absolute position of tool holders
#define HOLDER_X_1 1.7333
#define HOLDER_X_2 3.9833
#define HOLDER_X_3 6.2333
#define HOLDER_X_4 8.4833
#define HOLDER_X_5 12.0893
#define HOLDER_X_6 14.3393
#define HOLDER_X_7 16.5893
#define HOLDER_X_8 18.8393
#define HOLDER_X_9 28.2833
#define HOLDER_X_10 30.5333
#define HOLDER_X_11 32.7833
#define HOLDER_X_12 35.0333
#define HOLDER_X_13 38.6393
#define HOLDER_X_14 40.8893
#define HOLDER_X_15 43.1393
#define HOLDER_X_16 45.3893
#define HOLDER_Y 30.1336
#define HOLDER_Z 0
// absolute position of the tool height setting plate
#define TOOL_HEIGHT_PLATE_X 23.5613
#define TOOL_HEIGHT_PLATE_Y 30.1336
#define TOOL_VAR 9 // Tool changer desired new tool Var
// Tool changer Last tool loaded is saved globally in this Var
#define LAST_TOOL_VAR 8 // -1=Spindle empty, 0=unknown, 1-16 Tool Slot loaded into Spindle
#define TOOL_DISK_FILE "C:\\Users\\NUA_TIM\\Desktop\\Machine Programs\\ToolChangerData.txt"
#define TOOL_HEIGHT_BIT 29 //bit to read tool height plate (KONNECT INPUT 31)
#define CNT_PER_INCH_X 3175
#define CNT_PER_INCH_Y 3180.3
#define CNT_PER_INCH_Z 10000
#define MAX_Z_PROBE_DEPTH -6.0 // Safety limit to prevent over-travel (inches)
#define REF_TOOL_OFFSET_VAR 11 // Job-specific G54 Z DRO (counts)
// function prototypes
int DoToolChange(int ToolSlot);
int GetCurrentTool(int *tool);
int SaveCurrentTool(int tool);
BOOL ToolNumberValid(int tool);
float ToolPositionX(int tool);
int MoveXY(float x, float y, float Speed);
int MoveZ(float z, float Speed);
int UnloadTool(int CurrentTool);
int LoadNewTool(int Tool);
int ProbeToolSetter(float *z_position);
main()
{
int ToolSlot = persist.UserData[TOOL_VAR]; // Requested tool to load (value stored an integer)
if (DoToolChange(ToolSlot)) // perform Tool Change
{
// error, Halt Job
DoPC(PC_COMM_HALT);
}
}
// Perform Tool Change. Return 0=Success, 1=Failure
int DoToolChange(int ToolSlot)
{
int CurrentTool;
if (GetCurrentTool(&CurrentTool)) return 1; // -1=Spindle empty, 0=unknown, 1-16 Tool Slot loaded into Spindle
printf("Load Tool Slot %d requested, Current Tool %d\n",ToolSlot, CurrentTool);
if (!ToolNumberValid(ToolSlot)) // check if invalid
{
char s[80];
sprintf(s,"Invalid Tool Change Number %d\n",ToolSlot);
printf(s);
MsgBox(s, MB_ICONHAND | MB_OK);
return 1;
}
if (CurrentTool!=-1) // is there a tool in the Spindle??
if (UnloadTool(CurrentTool)) return 1; // yes, unload it
// Now Spindle is empty, load requested tool
if (LoadNewTool(ToolSlot)) return 1;
// Probe tool setter to locate tool tip
float z_toolsetter;
if (ProbeToolSetter(&z_toolsetter)) {
char s[80];
sprintf(s,"Error: Failed to probe tool setter for tool %d. Halting.\n", ToolSlot);
printf(s);
MsgBox(s, MB_ICONHAND | MB_OK);
return 1;
}
// Set G54 Z DRO to job-specific offset from persist.UserData[11]
float dro_value = persist.UserData[REF_TOOL_OFFSET_VAR] / (float)CNT_PER_INCH_Z;
DoPCFloat(PC_COMM_SET_Z, dro_value);
printf("Set G54 Z DRO to %.4f inches (job-specific offset) at G53 Z=%.4f\n", dro_value, z_toolsetter);
printf("Tool change succeeded, saving new tool %d\n", ToolSlot);
SaveCurrentTool(ToolSlot); // save the one that has been loaded
return 0; // success
}
// Probe tool setter. Return 0=Success, 1=Failure
int ProbeToolSetter(float *z_position)
{
int SaveZLimits;
// Ensure tool table is out
SetBit(19);
// Move to tool setter position
if (MoveXY(TOOL_HEIGHT_PLATE_X, TOOL_HEIGHT_PLATE_Y, 10)) return 1;
// Save limit switch settings and disable limits
SaveZLimits = ch3->LimitSwitchOptions;
ch3->LimitSwitchOptions = 0;
FPGA(STEP_PULSE_LENGTH_ADD) = 63 + 0x80;
// Jog Z down until tool setter is triggered or safety limit reached
Jog(3, -3000); // Jog at 3000 counts/sec
while (ReadBit(TOOL_HEIGHT_BIT)) {
float current_z = chan[AXISZ].Dest / CNT_PER_INCH_Z;
if (current_z < MAX_Z_PROBE_DEPTH) {
Jog(3, 0); // Stop
while (!CheckDone(3)); // Wait for motion to complete
char s[80];
sprintf(s,"Error: Tool setter not triggered, exceeded max depth %.4f inches.\n", MAX_Z_PROBE_DEPTH);
printf(s);
MsgBox(s, MB_ICONHAND | MB_OK);
ch3->LimitSwitchOptions = SaveZLimits;
return 1; // Failure
}
}
Jog(3, 0); // Stop
while (!CheckDone(3)); // Wait for motion to complete
// Get current Z position
*z_position = chan[AXISZ].Dest / CNT_PER_INCH_Z;
printf("Tool setter triggered at %.4f inches\n", *z_position);
// Move back up to machine Z=0
if (MoveZ(0, 4)) return 1; // Move at 4 inch per second
// Pull tool table in
ClearBit(19);
// Restore limit settings
ch3->LimitSwitchOptions = SaveZLimits;
return 0; // Success
}
// - Load new Tool (Spindle must be empty)
int LoadNewTool(int Tool)
{
SetBit(19); // Move tool table out
MoveZ(0, 4); // Move Z at 5 inch per second (300 in/minute)
MoveXY(ToolPositionX(Tool),HOLDER_Y, 10); // Move XY at 10 inch per second (600 in/minute)
MoveZ(-3, 2); // Move Z to tool bay at 5 in per second (300 in/minute) - Tool lowers into bay 1 inch above engagement with socket bearings
float speed = 1500.0; // Hardcoded speed value in RPM
SetBitDirection(26,1); // define bit as an output
FPGA(IO_PWMS_PRESCALE) = 46; // divide clock by 46 (1.4 KHz)
FPGA(IO_PWMS+1) = 1; // Enable
FPGA(IO_PWMS) = CorrectAnalog(speed/RPM_FACTOR); // Set PWM
ClearBit(0);
MoveZ(-4, 1); // Move Z at 1 inch per second (60 in/min) to engage collet nut
MoveZ(-3, 3); // Move Z at 3 inch per second (180 in/min) upward by an inch to disengage collet nut from socket
MoveZ(-4, 1); // Move Z at 1 inch per second (60 in/min) to engage/tighten collet nut
MoveZ(-3, 3); // Move Z up 1 inch to disengage collet nut from socket
SetBit(0);
MoveZ(0, 4); // Move Z at 5 inch per second (300 In/min) to machine coordinates Z zero (fully up and clear of tool bays)
Delay_sec(0.5);
ClearBit(19); // Move tool table in
return 0;
}
// - Remove tool in spindle by going to holder of current tool
int UnloadTool(int CurrentTool)
{
SetBit(19); // Move tool table out
Delay_sec(1.0);
MoveZ(0, 4); // Move Z at 5 inch per second (300 in/minute)
MoveXY(ToolPositionX(CurrentTool),HOLDER_Y,10); // Move XY at 10 inch per second (600 in/minute)
MoveZ(-3, 2); // Move Z to tool bay at 5 in per second (300 in/minute) - Tool lowers into bay 1 inch above engagement with socket bearings
float speed = 1600.0; // Hardcoded speed value in RPM
SetBitDirection(26,1); // define bit as an output
FPGA(IO_PWMS_PRESCALE) = 46; // divide clock by 46 (1.4 KHz)
FPGA(IO_PWMS+1) = 1; // Enable
FPGA(IO_PWMS) = CorrectAnalog(speed/RPM_FACTOR); // Set PWM
SetBit(45);
MoveZ(-4, 1); // Move Z at 1 inch per second (60 in/min) to engage collet nut
MoveZ(-3, 1); // Move Z at 1 inch per second (180 in/min) upward by an inch to disengage collet nut from socket
ClearBit(45);
MoveZ(0, 4); // Move Z at 5 inch per second (300 In/min) to machine coordinates Z zero (fully up and clear of tool bays)
return 0;
}
//return x position of tool holder as a function of the tool
float ToolPositionX(int tool)
{
if (tool == 1) return HOLDER_X_1;
if (tool == 2) return HOLDER_X_2;
if (tool == 3) return HOLDER_X_3;
if (tool == 4) return HOLDER_X_4;
if (tool == 5) return HOLDER_X_5;
if (tool == 6) return HOLDER_X_6;
if (tool == 7) return HOLDER_X_7;
if (tool == 8) return HOLDER_X_8;
if (tool == 9) return HOLDER_X_9;
if (tool == 10) return HOLDER_X_10;
if (tool == 11) return HOLDER_X_11;
if (tool == 12) return HOLDER_X_12;
if (tool == 13) return HOLDER_X_13;
if (tool == 14) return HOLDER_X_14;
if (tool == 15) return HOLDER_X_15;
if (tool == 16) return HOLDER_X_16;
return 0; // should never happen
}
// Get the last loaded tool. Parameter points to where to return tool
// First try to get from KFLOP memory
// if memory is invalid, try to read from disk
// if can't read disk then ask Operator
// returns 0 on success, 1 on fail or Operator asked to abort
int GetCurrentTool(int *ptool)
{
int success,Answer,result,tool;
float value;
tool = persist.UserData[LAST_TOOL_VAR];
printf("Persist var 8 value: %d\n", tool);
success = ToolNumberValid(tool); // check if valid
if (!success) // invalid after power up, try to read from PC Disk File
{
// Try to open file
FILE *f=fopen(TOOL_DISK_FILE,"rt");
if (f) // did file open?
{
// read a line and convert it
result=fscanf(f,"%d",&tool);
fclose(f);
if (result==1 && ToolNumberValid(tool))
{
printf("Read Disk File Value of %d\n",tool);
success=TRUE; // success if one value converted
}
}
if (!success) printf("Unable to open/read file:%s\n",TOOL_DISK_FILE);
}
if (!success) // if still no success ask Operator
{
Answer = InputBox("Tool in Spindle or -1",&value);
if (Answer)
{
printf("Operator Canceled\n");
return 1;
}
else
{
tool=value;
printf("Operator Entered Value of %d\n",tool);
}
}
if (!ToolNumberValid(tool)) // check if invalid
{
char s[80];
sprintf(s,"Invalid Current Tool Number %d\n",tool);
printf(s);
MsgBox(s, MB_ICONHAND | MB_OK);
return 1;
}
printf("Current tool = %d\n",tool);
*ptool = tool; // return result to caller
return 0; //success
}
// save the tool number to KFLOP global Variable and to PC Disk file in case we loose power
int SaveCurrentTool(int tool)
{
persist.UserData[LAST_TOOL_VAR] = tool;
FILE *f = fopen(TOOL_DISK_FILE, "wt");
if (f == NULL) {
printf("Error: Unable to open/write to file %s\n", TOOL_DISK_FILE);
// Optionally add: MsgBox("Error saving tool data to file!", MB_ICONHAND | MB_OK);
return 1; // Failure
}
if (fprintf(f, "%d\n", tool) < 0) { // Add this to check write
printf("Error: fprintf failed for file %s\n", TOOL_DISK_FILE);
fclose(f);
return 1;
}
fclose(f);
printf("Saved tool %d to file %s\n", tool, TOOL_DISK_FILE); // For debugging
return 0; // Success
}
// check if Current Tool number Valid
// -1 = no tool loaded
// 1-16 = valid tool
BOOL ToolNumberValid(int tool)
{
return tool == -1 || (tool>=1 && tool<=16);
}
// Move Axis XY at specified Speed and wait until complete
// return 0 = success, 1 if axis disabled
int MoveXY(float x, float y, float Speed)
{
MoveAtVel(AXISX, x * CNT_PER_INCH_X, Speed * CNT_PER_INCH_X);
MoveAtVel(AXISY, y * CNT_PER_INCH_Y, Speed * CNT_PER_INCH_Y);
while (!CheckDone(AXISX) || !CheckDone(AXISY))
{
if (!chan[AXISX].Enable)
{
printf("Error X Axis Disabled\n");
MsgBox("Error X Axis Disabled\n", MB_ICONHAND | MB_OK);
return 1;
}
if (!chan[AXISY].Enable)
{
printf("Error Y Axis Disabled\n");
MsgBox("Error Y Axis Disabled\n", MB_ICONHAND | MB_OK);
return 1;
}
}
return 0; //success
}
// Move Axis Z at specified Speed and wait until complete
// return 0 = success, 1 if axis disabled
int MoveZ(float z, float Speed)
{
MoveAtVel(AXISZ, z * CNT_PER_INCH_Z, Speed * CNT_PER_INCH_Z);
while (!CheckDone(AXISZ))
{
if (!chan[AXISZ].Enable)
{
printf("Error Z Axis Disabled\n");
MsgBox("Error Z Axis Disabled\n", MB_ICONHAND | MB_OK);
return 1;
}
}
return 0; //success
}
- TomKerekes
- Posts: 2868
- Joined: Mon Dec 04, 2017 1:49 am
Re: DIY Collet-Spinning ATC - Adapting Linear ATC C Programs?
Hi Tim,
The technique and code seems correct to me.
Your technique does not use tool length offsets it rather shifts the origin to compensate. Do you possibly have tool length and tool length compensation turned on to give an additional unwanted offset? Make sure tool length compensation is turned off with G49.
Otherwise please run a tool of one length and then a tool with a different length and post what is printed in the Console for both.
The technique and code seems correct to me.
Your technique does not use tool length offsets it rather shifts the origin to compensate. Do you possibly have tool length and tool length compensation turned on to give an additional unwanted offset? Make sure tool length compensation is turned off with G49.
Otherwise please run a tool of one length and then a tool with a different length and post what is printed in the Console for both.
Regards,
Tom Kerekes
Dynomotion, Inc.
Tom Kerekes
Dynomotion, Inc.
Re: DIY Collet-Spinning ATC - Adapting Linear ATC C Programs?
I don't believe I have any sort of tool length compensation turned on, but I'm not sure how to check. There are no tool offsets listed in the tool table currently. I attempted to have a G49 command integrated into the code, but the logic Grok came up with kept throwing errors for undefined commands, until it finally suggested I just issue the command manually. I typed "G49" into the text window in KmotionCNC and hit send. Then I did the probe file, followed by a tool change to compare the tool tip height. Unfortunately, the longer tool still goes down further than the establish Z work surface by an amount that looks equivalent to the additional length of the tool compared to the previous one. The machine (G53) z height for the axis was the same for both tools when positioned at the work surface zero point (-6.4065).
Here are the console messages that were printed and thanks a ton for helping me troubleshoot this:
Z probe triggered at -5.8965, workpiece zero set to -5.3865
Bit 29 (TOOL_HEIGHT_BIT) initial state: 1
Pushed tool table out
Tool setter triggered at -2.0287 inches
Pulled tool table back in
Stored job-specific G54 Z DRO: 3.8678 inches at G53 Z=-2.0287, touchplate surface=-5.8965
Persist var 8 value: 0
Read Disk File Value of 5
Current tool = 5
Load Tool Slot 1 requested, Current Tool 5
Tool setter triggered at -1.5936 inches
Set G54 Z DRO to 3.8678 inches (job-specific offset) at G53 Z=-1.5936
Tool change succeeded, saving new tool 1
Saved tool 1 to file C:\Users\NUA_TIM\Desktop\Machine Programs\ToolChangerData.txt
Here are the console messages that were printed and thanks a ton for helping me troubleshoot this:
Z probe triggered at -5.8965, workpiece zero set to -5.3865
Bit 29 (TOOL_HEIGHT_BIT) initial state: 1
Pushed tool table out
Tool setter triggered at -2.0287 inches
Pulled tool table back in
Stored job-specific G54 Z DRO: 3.8678 inches at G53 Z=-2.0287, touchplate surface=-5.8965
Persist var 8 value: 0
Read Disk File Value of 5
Current tool = 5
Load Tool Slot 1 requested, Current Tool 5
Tool setter triggered at -1.5936 inches
Set G54 Z DRO to 3.8678 inches (job-specific offset) at G53 Z=-1.5936
Tool change succeeded, saving new tool 1
Saved tool 1 to file C:\Users\NUA_TIM\Desktop\Machine Programs\ToolChangerData.txt
- TomKerekes
- Posts: 2868
- Joined: Mon Dec 04, 2017 1:49 am
Re: DIY Collet-Spinning ATC - Adapting Linear ATC C Programs?
I think I see it. Probe ToolSetter is moving up to Z=0 before returning. So when the PC_COMM_SET_Z happens it is set up at zero instead down with the tool tip at the setter.
Either do the PC_COMM_SET_Z before moving back up or factor in the distance that was moved up (z_toolsetter).
Either do the PC_COMM_SET_Z before moving back up or factor in the distance that was moved up (z_toolsetter).
Regards,
Tom Kerekes
Dynomotion, Inc.
Tom Kerekes
Dynomotion, Inc.
Re: DIY Collet-Spinning ATC - Adapting Linear ATC C Programs?
Thanks! I tried it like this:
Sadlly, It still seems to be moving the tools to the exact same Machine (G53) point, so the longer tool bit went down further again. I still can't make sense of how the two different tools can trigger the tool setter at different machine Z height, have the same offset applied, yet end up zeroed to the same position (G53 for Z = -6.9279). Very confusing!
Here's the console output this time. I started with Tool 5, changed to Tool 1, then Back to Tool 5 again:
Persist var 8 value: 0
Read Disk File Value of 5
Current tool = 5
Load Tool Slot 1 requested, Current Tool 5
Tool setter triggered at -1.6156 inches
Set G54 Z DRO to 4.3977 inches (job-specific offset) at G53 Z=-1.6156
Tool change succeeded, saving new tool 1
Saved tool 1 to file C:\Users\NUA_TIM\Desktop\Machine Programs\ToolChangerData.txt
Persist var 8 value: 1
Current tool = 1
Load Tool Slot 5 requested, Current Tool 1
Tool setter triggered at -2.0274 inches
Set G54 Z DRO to 4.3977 inches (job-specific offset) at G53 Z=-2.0274
Tool change succeeded, saving new tool 5
Saved tool 5 to file C:\Users\NUA_TIM\Desktop\Machine Programs\ToolChangerData.txt
Code: Select all
Jog(AXISZ, -3000);
while (ReadBit(Z_PROBE_BIT));
DoPCFloat(PC_COMM_SET_Z, TOUCH_PLATE_THICKNESS); // Set Z=0 at workpiece surface
Jog(AXISZ, 0);
while (!CheckDone(AXISZ));
Here's the console output this time. I started with Tool 5, changed to Tool 1, then Back to Tool 5 again:
Persist var 8 value: 0
Read Disk File Value of 5
Current tool = 5
Load Tool Slot 1 requested, Current Tool 5
Tool setter triggered at -1.6156 inches
Set G54 Z DRO to 4.3977 inches (job-specific offset) at G53 Z=-1.6156
Tool change succeeded, saving new tool 1
Saved tool 1 to file C:\Users\NUA_TIM\Desktop\Machine Programs\ToolChangerData.txt
Persist var 8 value: 1
Current tool = 1
Load Tool Slot 5 requested, Current Tool 1
Tool setter triggered at -2.0274 inches
Set G54 Z DRO to 4.3977 inches (job-specific offset) at G53 Z=-2.0274
Tool change succeeded, saving new tool 5
Saved tool 5 to file C:\Users\NUA_TIM\Desktop\Machine Programs\ToolChangerData.txt
- TomKerekes
- Posts: 2868
- Joined: Mon Dec 04, 2017 1:49 am
Re: DIY Collet-Spinning ATC - Adapting Linear ATC C Programs?
No I think you changed the wrong program. The issue is with changing to a new tool:
On a separate note doing the PC_COMM_SET_Z before the axis has stopped is not a good idea. The communication time to the PC can be significant and vary. As it was before the probed position is after the axis stopped not at the trigger point. A better approach is to sample the Dest at the trigger, then move back to that position. We can discuss that later after it is working.
Code: Select all
DoPCFloat(PC_COMM_SET_Z, dro_value);Regards,
Tom Kerekes
Dynomotion, Inc.
Tom Kerekes
Dynomotion, Inc.
Re: DIY Collet-Spinning ATC - Adapting Linear ATC C Programs?
Oops, thanks! I changed the probezandoffset.c program back to the way it was. I'm not sure I understand well enough how to accomplish what you mentioned, so I turned again to Grok, ha! I put what Grok came up with below for moving the DoPCFloat(PC_COMM_SET_Z, dro_value); command right after the tool setter is trigger, before moving back up in Z. Unfortunately, the tool tips were still in different places after a tool change and seem to be off by about the amount they differ in tool height again.
Console Messages:
Tool change succeeded, saving new tool 5
Saved tool 5 to file C:\Users\NUA_TIM\Desktop\Machine Programs\ToolChangerData.txt
Persist var 8 value: 5
Current tool = 5
Load Tool Slot 1 requested, Current Tool 5
Tool setter triggered at -1.7027 inches
Set G54 Z DRO to 3.8688 inches (job-specific offset) at G53 Z=-1.7027
Tool change succeeded, saving new tool 1
Saved tool 1 to file C:\Users\NUA_TIM\Desktop\Machine Programs\ToolChangerData.txt
Persist var 8 value: 1
Current tool = 1
Load Tool Slot 5 requested, Current Tool 1
Tool setter triggered at -2.0413 inches
Set G54 Z DRO to 3.8688 inches (job-specific offset) at G53 Z=-2.0413
Tool change succeeded, saving new tool 5
Saved tool 5 to file C:\Users\NUA_TIM\Desktop\Machine Programs\ToolChangerData.txt
Console Messages:
Tool change succeeded, saving new tool 5
Saved tool 5 to file C:\Users\NUA_TIM\Desktop\Machine Programs\ToolChangerData.txt
Persist var 8 value: 5
Current tool = 5
Load Tool Slot 1 requested, Current Tool 5
Tool setter triggered at -1.7027 inches
Set G54 Z DRO to 3.8688 inches (job-specific offset) at G53 Z=-1.7027
Tool change succeeded, saving new tool 1
Saved tool 1 to file C:\Users\NUA_TIM\Desktop\Machine Programs\ToolChangerData.txt
Persist var 8 value: 1
Current tool = 1
Load Tool Slot 5 requested, Current Tool 1
Tool setter triggered at -2.0413 inches
Set G54 Z DRO to 3.8688 inches (job-specific offset) at G53 Z=-2.0413
Tool change succeeded, saving new tool 5
Saved tool 5 to file C:\Users\NUA_TIM\Desktop\Machine Programs\ToolChangerData.txt
Code: Select all
// Perform Tool Change. Return 0=Success, 1=Failure
int DoToolChange(int ToolSlot)
{
int CurrentTool;
if (GetCurrentTool(&CurrentTool)) return 1; // -1=Spindle empty, 0=unknown, 1-16 Tool Slot loaded into Spindle
printf("Load Tool Slot %d requested, Current Tool %d\n",ToolSlot, CurrentTool);
if (!ToolNumberValid(ToolSlot)) // check if invalid
{
char s[80];
sprintf(s,"Invalid Tool Change Number %d\n",ToolSlot);
printf(s);
MsgBox(s, MB_ICONHAND | MB_OK);
return 1;
}
if (CurrentTool!=-1) // is there a tool in the Spindle??
if (UnloadTool(CurrentTool)) return 1; // yes, unload it
// Now Spindle is empty, load requested tool
if (LoadNewTool(ToolSlot)) return 1;
// Probe tool setter to locate tool tip
float z_toolsetter;
if (ProbeToolSetter(&z_toolsetter)) {
char s[80];
sprintf(s,"Error: Failed to probe tool setter for tool %d. Halting.\n", ToolSlot);
printf(s);
MsgBox(s, MB_ICONHAND | MB_OK);
return 1;
}
printf("Tool change succeeded, saving new tool %d\n", ToolSlot);
SaveCurrentTool(ToolSlot); // save the one that has been loaded
return 0; // success
}
// Probe tool setter. Return 0=Success, 1=Failure
int ProbeToolSetter(float *z_position)
{
int SaveZLimits;
// Ensure tool table is out
SetBit(19);
// Move to tool setter position
if (MoveXY(TOOL_HEIGHT_PLATE_X, TOOL_HEIGHT_PLATE_Y, 10)) return 1;
// Save limit switch settings and disable limits
SaveZLimits = ch3->LimitSwitchOptions;
ch3->LimitSwitchOptions = 0;
FPGA(STEP_PULSE_LENGTH_ADD) = 63 + 0x80;
// Jog Z down until tool setter is triggered or safety limit reached
Jog(3, -3000); // Jog at 3000 counts/sec
while (ReadBit(TOOL_HEIGHT_BIT)) {
float current_z = chan[AXISZ].Dest / CNT_PER_INCH_Z;
if (current_z < MAX_Z_PROBE_DEPTH) {
Jog(3, 0); // Stop
while (!CheckDone(3)); // Wait for motion to complete
char s[80];
sprintf(s,"Error: Tool setter not triggered, exceeded max depth %.4f inches.\n", MAX_Z_PROBE_DEPTH);
printf(s);
MsgBox(s, MB_ICONHAND | MB_OK);
ch3->LimitSwitchOptions = SaveZLimits;
return 1; // Failure
}
}
Jog(3, 0); // Stop
while (!CheckDone(3)); // Wait for motion to complete
// Get current Z position
*z_position = chan[AXISZ].Dest / CNT_PER_INCH_Z;
printf("Tool setter triggered at %.4f inches\n", *z_position);
// Set G54 Z DRO to job-specific offset from persist.UserData[11]
float dro_value = persist.UserData[REF_TOOL_OFFSET_VAR] / (float)CNT_PER_INCH_Z;
DoPCFloat(PC_COMM_SET_Z, dro_value);
printf("Set G54 Z DRO to %.4f inches (job-specific offset) at G53 Z=%.4f\n", dro_value, *z_position);
// Move back up to machine Z=0
if (MoveZ(0, 4)) return 1; // Move at 4 inch per second
// Pull tool table in
ClearBit(19);
// Restore limit settings
ch3->LimitSwitchOptions = SaveZLimits;
return 0; // Success
}
}- TomKerekes
- Posts: 2868
- Joined: Mon Dec 04, 2017 1:49 am
Re: DIY Collet-Spinning ATC - Adapting Linear ATC C Programs?
Hi Tim,
I commented out tool change stuff and faked out the trigger points so I was able to run the code here. I found two bugs.
The Z Position isn't at workspace zero it is at the TOUCH_PLATE_THICKNESS.
Furthermore the workspace zero would be lower than the touch plate, not positive, so it should be negative TOUCH_PLATE_THICKNESS like this:
And so the dro_value should be:
Other than that it seems to work for me. When loading the 2nd tool was it above the stock by the TOUCH_PLATE_THICKNESS? And not the tool length difference?
I've attached FakeProbe and FakeToolChange programs with stuff commented out to just do the probing. The Probe pobes until Z reaches -10 inches + TOOL_PLATE_THICKNESS as if the tool tip would touch the stock at -10. Then the tool setter triggers at -4 inches. The dro_offset is then 6 inches.
After running this I see the G92 Z offset of -10 inches
Z probe triggered at -9.4901, workpiece zero set to -10.0001
Bit 29 (TOOL_HEIGHT_BIT) initial state: 0
Pushed tool table out
Tool setter triggered at -4.0000 inches
Pulled tool table back in
Stored job-specific G54 Z DRO: 6.0000 inches at G53 Z=-4.0000, touchplate surface=-9.4901
Then the Tool Change triggers at -3 inches as if the tool was 1 inch longer.
After running this I see the G92 Z offset of -9 inches which seems correct to me.
Load Tool Slot 1 requested, Current Tool 126
Tool setter triggered at -3.0001 inches
Set G54 Z DRO to 6.0000 inches (job-specific offset) at G53 Z=-3.0001
Tool change succeeded, saving new tool 1
I also changed the code to capture the Dest quickly after the trigger to avoid stopping distance errors. It then instead of just stopping it commands an absolute move back to the trigger point which will do a small reversal and then stop.
I commented out tool change stuff and faked out the trigger points so I was able to run the code here. I found two bugs.
Code: Select all
// Store job-specific G54 Z DRO as tool setter trigger height minus touchplate surface
dro_value = z_toolsetter - z_position;
Furthermore the workspace zero would be lower than the touch plate, not positive, so it should be negative TOUCH_PLATE_THICKNESS like this:
Code: Select all
float workpiece_zero = z_position - TOUCH_PLATE_THICKNESS;Code: Select all
// Store job-specific G54 Z DRO as tool setter trigger height minus touchplate surface
dro_value = z_toolsetter - workpiece_zero;
I've attached FakeProbe and FakeToolChange programs with stuff commented out to just do the probing. The Probe pobes until Z reaches -10 inches + TOOL_PLATE_THICKNESS as if the tool tip would touch the stock at -10. Then the tool setter triggers at -4 inches. The dro_offset is then 6 inches.
After running this I see the G92 Z offset of -10 inches
Z probe triggered at -9.4901, workpiece zero set to -10.0001
Bit 29 (TOOL_HEIGHT_BIT) initial state: 0
Pushed tool table out
Tool setter triggered at -4.0000 inches
Pulled tool table back in
Stored job-specific G54 Z DRO: 6.0000 inches at G53 Z=-4.0000, touchplate surface=-9.4901
Then the Tool Change triggers at -3 inches as if the tool was 1 inch longer.
After running this I see the G92 Z offset of -9 inches which seems correct to me.
Load Tool Slot 1 requested, Current Tool 126
Tool setter triggered at -3.0001 inches
Set G54 Z DRO to 6.0000 inches (job-specific offset) at G53 Z=-3.0001
Tool change succeeded, saving new tool 1
I also changed the code to capture the Dest quickly after the trigger to avoid stopping distance errors. It then instead of just stopping it commands an absolute move back to the trigger point which will do a small reversal and then stop.
- Attachments
-
- FakeToolChange.c
- (12.31 KiB) Downloaded 164 times
-
- FakeProbe.c
- (5.27 KiB) Downloaded 165 times
Regards,
Tom Kerekes
Dynomotion, Inc.
Tom Kerekes
Dynomotion, Inc.