Nondeterministic "error loading file"

Moderators: TomKerekes, dynomotion

gui_marchioro
Posts: 59
Joined: Sun Aug 21, 2022 11:22 pm

Nondeterministic "error loading file"

Post by gui_marchioro » Wed Dec 07, 2022 2:43 am

Hello,

Sometimes when a G code program call an M6 command I get the following error that says "error loading file".
1.png
By clicking Ok another message box appears stating that there is an error when compiling the M6 c program.
2.png
And then a message saying that G code was aborted.
3.png
To re-establish the system it is required to reset the board power and re-open KMotionCNC

I've checked KMotion and there is no output in the console, just a message box stating "Read failed - Auto disconnect".

It is not clear for me how can a c program not compile sometimes. I thought that this was not even possible. Have you experienced something like this?
The specific c program can be found here: https://github.com/gui-marchioro/Morbid ... lChanger.c

This error causes KFLOP board to be disconnected from the PC, and all 3 axes start to move randomly (I think that it is because the axes become disabled), while all other IOs from KONNECT board are not affected (stays in the exact state), and this could be a problem if the spindle is on for example.

Is there a way to notice this kind of disconnection problem when it happens? For safety I would like to switch off the power from the motor drivers.

I checked the KFLOP/KANALOG boards and realize that when this situation happens the led pointed below becomes off.
4.jpg
Thanks in advance for any replies.

Sincerely,
Guilherme

User avatar
TomKerekes
Posts: 2540
Joined: Mon Dec 04, 2017 1:49 am

Re: Nondeterministic "error loading file"

Post by TomKerekes » Wed Dec 07, 2022 11:39 pm

Hi

I’d need a way to reproduce the problem to help. You might post the C Program you are using and not a link to all your files.

One way Kanalog can be disabled is if your program modifies the IO used to communicate with Kanalog.

To avoid drift when you axes are disabled see here:
https://www.dynomotion.com/wiki/index.p ... _up_Issues
Regards,

Tom Kerekes
Dynomotion, Inc.

gui_marchioro
Posts: 59
Joined: Sun Aug 21, 2022 11:22 pm

Re: Nondeterministic "error loading file"

Post by gui_marchioro » Thu Dec 08, 2022 1:56 am

Hello,
One way Kanalog can be disabled is if your program modifies the IO used to communicate with Kanalog.
I am not sure I understand what do you mean by a "program that modifies the IO used to communicate with Kanalog".

Here is my program that runs when an M6 is called:

Code: Select all

#include "Drill.c"
#include "MillChanger.c"
#include "Spindle.c"
#include "KMotionDef.h"

#ifndef TMP
#define TMP 10 // which spare persist to use to transfer data
#include "KflopToKMotionCNCFunctions.c"
#endif

#define TOOL_VAR 9

// Routine to be executed when M6 TX is called in a G program. (X is the tool number)
void main ()
{
    // int previousSlot = persist.UserData[PREVIOUS_TOOL_VAR];
    int slot = persist.UserData[TOOL_VAR];  // Requested tool slot. Value stored is an int 
	// int id = persist.UserData[TOOL_VAR+1];  // value stored is an int 
	// printf("Tool Set to slot %d id %d\n",slot,id);  // print the slot and id

    // Turn off drill box if it is on.
    if (GetDrillBoxStatus() == 1)
    {
        ClearDrillOutputs();
    }

    // Turn off spindle if it is on.
    if (GetSpindleStatus() != SPINDLE_OFF)
    {
        StopSpindle();
    }

    if(slot >= MILL_TOOL_SLOT_MIN && slot <= MILL_TOOL_SLOT_MAX)
    {
        if (MillExchangeRoutine(slot))
        {
            // error, Halt Job
		    DoPC(PC_COMM_HALT);
        }
    }
    // Drill box routine
    else if (slot >= DRILL_BOX_SLOT_MIN && slot <= DRILL_BOX_SLOT_MAX)
    {
        DrillRoutine(slot);
    }
    else
    {
        MsgBox("The selected tool is out of the range. Please select one that is defined inside the tool table.", MB_ICONEXCLAMATION);
    }
}
And here are the programs that are called by the main M6 program:

Drill.c

Code: Select all

#include "KMotionDef.h"

#define DRILL_STATUS_VAR 193

#define DRILL_BOX_SLOT_MIN 11
#define DRILL_BOX_SLOT_MAX 20

#define DRILL_1_SLOT 11
#define DRILL_2_SLOT 12
#define DRILL_3_SLOT 13
#define DRILL_4_SLOT 14
#define DRILL_5_SLOT 15
#define DRILL_6_SLOT 16
#define DRILL_7_SLOT 17
#define DRILL_8_SLOT 18
#define DRILL_9_SLOT 19
#define DRILL_10_SLOT 20

#define DRILL_MOTOR_OUTPUT 1133
#define DRILL_1_PISTON_OUTPUT 48
#define DRILL_2_PISTON_OUTPUT 49
#define DRILL_3_PISTON_OUTPUT 50
#define DRILL_4_PISTON_OUTPUT 51
#define DRILL_5_PISTON_OUTPUT 52
#define DRILL_6_PISTON_OUTPUT 53
#define DRILL_7_PISTON_OUTPUT 54
#define DRILL_8_PISTON_OUTPUT 55
#define DRILL_9_PISTON_OUTPUT 56
#define DRILL_10_PISTON_OUTPUT 57

void SetDrillBoxStatus()
{
    persist.UserData[DRILL_STATUS_VAR] = 1;
}

void ResetDrillBoxStatus()
{
    persist.UserData[DRILL_STATUS_VAR] = 0;
}

int GetDrillBoxStatus()
{
    return persist.UserData[DRILL_STATUS_VAR];
}

// Clear all outputs related to the drill operation
void ClearDrillOutputs()
{
    ResetDrillBoxStatus();
    ClearBit(DRILL_MOTOR_OUTPUT);
    ClearBit(DRILL_1_PISTON_OUTPUT);
    ClearBit(DRILL_2_PISTON_OUTPUT);
    ClearBit(DRILL_3_PISTON_OUTPUT);
    ClearBit(DRILL_4_PISTON_OUTPUT);
    ClearBit(DRILL_5_PISTON_OUTPUT);
    ClearBit(DRILL_6_PISTON_OUTPUT);
    ClearBit(DRILL_7_PISTON_OUTPUT);
    ClearBit(DRILL_8_PISTON_OUTPUT);
    ClearBit(DRILL_9_PISTON_OUTPUT);
    ClearBit(DRILL_10_PISTON_OUTPUT);
}

// Select and detach the selected drill
void DrillRoutine(int drillSlot)
{
    SetDrillBoxStatus();
    Delay_sec(0.25);
    SetBit(DRILL_MOTOR_OUTPUT);
    Delay_sec(0.25);
    switch (drillSlot)
    {
        case DRILL_1_SLOT:
                SetBit(DRILL_1_PISTON_OUTPUT);
            break;

        case DRILL_2_SLOT:
                SetBit(DRILL_2_PISTON_OUTPUT);
            break;
        
        case DRILL_3_SLOT:
                SetBit(DRILL_3_PISTON_OUTPUT);
            break;

        case DRILL_4_SLOT:
                SetBit(DRILL_4_PISTON_OUTPUT);
            break;

        case DRILL_5_SLOT:
                SetBit(DRILL_5_PISTON_OUTPUT);
            break;

        case DRILL_6_SLOT:
                SetBit(DRILL_6_PISTON_OUTPUT);
            break;

        case DRILL_7_SLOT:
                SetBit(DRILL_7_PISTON_OUTPUT);
            break;

        case DRILL_8_SLOT:
                SetBit(DRILL_8_PISTON_OUTPUT);
            break;

        case DRILL_9_SLOT:
                SetBit(DRILL_9_PISTON_OUTPUT);
            break;

        case DRILL_10_SLOT:
                SetBit(DRILL_10_PISTON_OUTPUT);
            break;

        default:
            break;
    }
}
MillChanger.c

Code: Select all

#include "KMotionDef.h"

#define PISTONS_ENABLE_OUTPUT 1127
#define PISTONL_ENABLE_OUTPUT 1128

#define MILL_TOOL_SLOT_MIN 1
#define MILL_TOOL_SLOT_MAX 10
#define TOOL_PRESENT_INPUT 1049
#define CLOSE_MAGAZINE_OUTPUT 1125
#define MAGAZINE_CLOSED_INPUT 1040
#define OPEN_MAGAZINE_OUTPUT 1126
#define MAGAZINE_OPENED_INPUT 1041
#define PISTON_TOOL_OUTPUT 1132
#define SPHERE_GRIPPER_OUTPUT 1129
#define PANTOGRAPH_OFF_SENSOR_INPUT 1042 //Pantografo recuado/alto
#define PANTOGRAPH_MOVING_SENSOR_INPUT 1043 //Pantografo baixo
#define PANTOGRAPH_ON_SENSOR_INPUT 1044 //Pantografo baixo

#define OFFSET_X 20
#define OFFSET_Y -20
#define OFFSET_Z -7.5

#define SLOW_SPEED 60 // mm/sec

// Outputs to be controled for tool exchange
#define EXTRACT_OUTPUT 1130
#define OPEN_TOOL_GRIPPER_OUTPUT 1131
// Vars
#define PREVIOUS_TOOL_VAR 191
#define PREVIOUS_TOOL_LABEL_VAR 192

#define TOOL_DISK_FILE "c:\\Kmotion434\\KMotion\\Data\\ToolChangerData.txt"

#define X_AXIS 0
#define Y_AXIS 1
#define Z_AXIS 2

// Each axis have 2000 counts per revolution
// Resolution of X axis = 20 mm per revolution
// Resolution of Y axis = 20 mm per revolution
// Resolution of Z axis = 7.5 mm per revolution
// FACTOR_X = 20 /2000 = 0.01000 mm/counts
// FACTOR_Y = 20 /2000 = 0.01000 mm/counts
// FACTOR_Z = 7.5/2000 = 0.00375 mm/counts
#define FACTOR_X 0.01000
#define FACTOR_Y 0.01000
#define FACTOR_Z 0.00375

// Routine responsible for exchange mill tool.
// Return 0=Success, 1=Failure
int MillExchangeRoutine(int millSlot)
{
    int currentTool;

    //  -1=Spindle empty, 0=unknown, 1-4 Tool Slot loaded into Spindle
    if (GetCurrentTool(&currentTool))
    {
        return 1;
    }

    printf("Load Tool Slot %d requested, Current Tool %d\n",millSlot, currentTool);
	
	if (!ToolNumberValid(millSlot))  // check if invalid
	{
		char s[80];
		sprintf(s,"Invalid Tool Change Number %d\n", millSlot);
		printf(s);
		MsgBox(s, MB_ICONHAND | MB_OK);
		return 1;
	}

    // If the tool requested is already in the spindle return.
    if (millSlot == currentTool)
    {
        return 0;
    }

    printf("Open Magazine. MillChanger.\n");
    OpenMagazine();
	
	if (currentTool != -1) // is there a tool in the Spindle??
    {
        printf("Unload tool. MillChanger.\n");
        if (UnloadTool(currentTool)) // yes, unload it
        {
            return 1;
        }
    }
		
	// Now Spindle is empty, load requested tool
    printf("Load new tool. MillChanger.\n");
	if (LoadNewTool(millSlot))
    {
        return 1;
    }

    printf("Close Magazine. MillChanger.\n");
    CloseMagazine();
	
	SaveCurrentTool(millSlot);  // save the one that has been loaded
	return 0;  // success
}

// Opens the tool magazine.
void OpenMagazine()
{
    SetBit(OPEN_MAGAZINE_OUTPUT);
    while(!ReadBit(MAGAZINE_OPENED_INPUT));
    //Delay_sec(4);
    ClearBit(OPEN_MAGAZINE_OUTPUT);
}

// Closes the tool magazine.
void CloseMagazine()
{
    SetBit(CLOSE_MAGAZINE_OUTPUT);
    while(!ReadBit(MAGAZINE_CLOSED_INPUT));
    //Delay_sec(4);
    ClearBit(CLOSE_MAGAZINE_OUTPUT);
}

// save the tool number to KFLOP global Variable and to PC Disk file in case power is lost.
void SaveCurrentTool(int millSlot)
{
    persist.UserData[PREVIOUS_TOOL_VAR] = millSlot;
	FILE *f=fopen(TOOL_DISK_FILE,"wt");
	fprintf(f,"%d\n", millSlot);
	fclose(f);
    UpdateCurrentToolLabel(millSlot);
	return 0;
}

void UpdateCurrentToolLabel(int currentTool)
{
    char s[80];
    // Now compute and form result
	sprintf(s,"%d",currentTool);
    // Put it onto the Screen
	DROLabel(1000, PREVIOUS_TOOL_LABEL_VAR, s);
}

// 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[PREVIOUS_TOOL_VAR];
	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
}

// check if Current Tool number Valid
// -1 = no tool loaded
// 1-10 = valid tool
BOOL ToolNumberValid(int tool)
{
	return tool == -1 || (tool>=1 && tool<=10);
}

// Remove tool in spindle by going to holder of current tool.
int UnloadTool(int currentTool)
{
    // - Rapid to Z Home to clear any work that may be on the table
	if (MoveZ(0.0, SLOW_SPEED))
    {
        return 1;
    }

    // - Rapid to current tool position to execute Z move
	if (MoveXY(ToolPositionX(currentTool), ToolPositionY(currentTool), SLOW_SPEED))
    {
        return 1;
    }

	// - Approach tool holder by matching Z height of tool flange currently in spindle with tool holder                            claw
	if (MoveZ(ToolPositionZ(), SLOW_SPEED))
    {
        return 1;
    }

    if (!JOB_ACTIVE)
    {
        ClearStopImmediately(); // Clear Stop Condition without resuming
        return 1;  // if Job was terminated/halt exit - return error.
    }

    // Activate piston actuators to approach tool in z axis.
    EnablePistons();

    if (!JOB_ACTIVE)
    {
        DisablePistons();
        ClearStopImmediately(); // Clear Stop Condition without resuming
        return 1;  // if Job was terminated/halt exit - return error.
    }

    // - Eject tool
	if (EjectTool())
    {
        return 1;
    }

    if (!JOB_ACTIVE)
    {
        ClearStopImmediately(); // Clear Stop Condition without resuming
        return 1;  // if Job was terminated/halt exit - return error.
    }

    DisablePistons();

    if (!JOB_ACTIVE)
    {
        ClearStopImmediately(); // Clear Stop Condition without resuming
        return 1;  // if Job was terminated/halt exit - return error.
    }

    // - Rapid to Z Home
	if (MoveZ(0.0, SLOW_SPEED))
    {
        return 1;
    }

	return 0; //success
}

// Load new Tool (Spindle must be empty).
int LoadNewTool(int newTool)
{
    // - Rapid to Z Home to clear any work that may be on the table
	if (MoveZ(0.0, SLOW_SPEED))
    {
        return 1;
    }

    // - Rapid to new tool position to execute Z move
	if (MoveXY(ToolPositionX(newTool), ToolPositionY(newTool), SLOW_SPEED))
    {
        return 1;
    }

    if (MoveZ(ToolPositionZ(), SLOW_SPEED))
    {
        return 1;
    }

    if (!JOB_ACTIVE)
    {
        ClearStopImmediately(); // Clear Stop Condition without resuming
        return 1;  // if Job was terminated/halt exit - return error.
    }
    
    // Activate piston actuators to approach tool in z axis.
    EnablePistons();

    if (!JOB_ACTIVE)
    {
        ClearStopImmediately(); // Clear Stop Condition without resuming
        DisablePistons();
        return 1;  // if Job was terminated/halt exit - return error.
    }

    // - Grab tool
	if (GrabTool())
    {
        return 1;
    }

    if (!JOB_ACTIVE)
    {
        ClearStopImmediately(); // Clear Stop Condition without resuming
        return 1;  // if Job was terminated/halt exit - return error.
    }
    
    DisablePistons();

    if (!JOB_ACTIVE)
    {
        ClearStopImmediately(); // Clear Stop Condition without resuming
        return 1;  // if Job was terminated/halt exit - return error.
    }

    // - Rapid to Z Home
	if (MoveZ(0.0, SLOW_SPEED))
    {
        return 1;
    }

	return 0; //success
}

// Return x position of tool holder as a function of the tool in mm.
float ToolPositionX(int tool)
{
    float xOffset = 0.0;

    if (tool % 2 == 0)
    {
        xOffset = 120.0;
    }

    float xPosition = -13.5 + OFFSET_X + xOffset;

    return xPosition;
}

// Return y position of tool holder as a function of the tool in mm.
float ToolPositionY(int tool)
{
    float yOffset = 0;

    if (tool > 6)
    {
        yOffset = 160*3;
    }
    else if (tool > 4)
    {
        yOffset = 160*2;
    }
    else if (tool > 2)
    {
        yOffset = 160*1;
    }

    float yPosition = -868.3 + OFFSET_Y + yOffset;
    return yPosition;
}

// Return z position of tool holder in mm.
float ToolPositionZ()
{
    float zPosition = -10 + OFFSET_Z;
    return zPosition;
}

// 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(X_AXIS, x / FACTOR_X, Speed / FACTOR_X);
	MoveAtVel(Y_AXIS, y / FACTOR_Y, Speed / FACTOR_Y);
	
	while (!CheckDone(X_AXIS) || !CheckDone(Y_AXIS))
	{
		if (!chan[X_AXIS].Enable)
		{
			printf("Error X Axis Disabled\n");
			MsgBox("Error X Axis Disabled\n", MB_ICONHAND | MB_OK);
			return 1;
		}

		if (!chan[Y_AXIS].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(Z_AXIS, z / FACTOR_Z, Speed / FACTOR_Z);
	
	while (!CheckDone(Z_AXIS))
	{
		if (!chan[Z_AXIS].Enable)
		{
			printf("Error Z Axis Disabled\n");
			MsgBox("Error Z Axis Disabled\n", MB_ICONHAND | MB_OK);
			return 1;
		}
	}
	return 0;  //success
}

// Activate piston actuators to approach tool holder in z axis.
void EnablePistons()
{
    SetBit(PISTONS_ENABLE_OUTPUT);
    SetBit(PISTONL_ENABLE_OUTPUT);
    Delay_sec(2.0);
}

// Disable piston actuators.
void DisablePistons()
{
    ClearBit(PISTONS_ENABLE_OUTPUT);
    ClearBit(PISTONL_ENABLE_OUTPUT);
    Delay_sec(2.0);
}

// Eject milling tool.
// return 0 = success, 1 if sensor points that the tool is still grabbed.
int EjectTool()
{
    SetBit(SPHERE_GRIPPER_OUTPUT);
    Delay_sec(1.0);
    SetBit(OPEN_TOOL_GRIPPER_OUTPUT);
    Delay_sec(0.5);
    SetBit(EXTRACT_OUTPUT);
    Delay_sec(1.0);
    ClearBit(EXTRACT_OUTPUT);
    SetBit(PISTON_TOOL_OUTPUT);
    Delay_sec(2.0);
    ClearBit(SPHERE_GRIPPER_OUTPUT);

    // - Wait for time in seconds defined by CLAMP_TIME
	Delay_sec(1.0);

    // - Read TOOL_PRESENT_INPUT bit to see whether the tool is loose, to make a safe Z move without  
    //      destroying tool holder
	// - If TOOL_PRESENT_INPUT bit is high, something has gone wrong;
	//		halt everything and display message indicating failure
	if (ReadBit(TOOL_PRESENT_INPUT))
	{
		printf("Claw Loose Error\n");
		MsgBox("Claw Loose Error\n", MB_ICONHAND | MB_OK);
		return 1;
	}

    SaveCurrentTool(-1);
  
    ClearBit(PISTON_TOOL_OUTPUT);
    Delay_sec(2.0);
    ClearBit(OPEN_TOOL_GRIPPER_OUTPUT);
    Delay_sec(1.0);

    return 0; // success
}

// Grab milling tool.
// return 0 = success, 1 if sensor points that the tool is not grabbed.
int GrabTool()
{
    SetBit(OPEN_TOOL_GRIPPER_OUTPUT);
    SetBit(PISTON_TOOL_OUTPUT);
    Delay_sec(2.0);
    SetBit(SPHERE_GRIPPER_OUTPUT);
    Delay_sec(0.5);
    ClearBit(PISTON_TOOL_OUTPUT);
    Delay_sec(2.0);
    ClearBit(OPEN_TOOL_GRIPPER_OUTPUT);
    Delay_sec(1.0);
    ClearBit(SPHERE_GRIPPER_OUTPUT);

    // - Wait for time in seconds defined by CLAMP_TIME
	Delay_sec(1.0);

    // - Read TOOL_PRESENT_INPUT bit to see whether the tool is loose, to make a safe Z move without  
    //      destroying tool holder
	// - If TOOL_PRESENT_INPUT bit is high, something has gone wrong;
	//		halt everything and display message indicating failure
	if (!ReadBit(TOOL_PRESENT_INPUT))
	{
		printf("Error while grabbing tool\n");
		MsgBox("Error while grabbing tool\n", MB_ICONHAND | MB_OK);
		return 1;
	}

    return 0; // success
}
Spindle.c

Code: Select all

#include "KMotionDef.h"

// Outputs to be controled for spindle interaction
#define CW_ENABLE_OUTPUT 1121
#define CCW_ENABLE_OUTPUT 1122
#define PISTONS_ENABLE_OUTPUT 1127
#define PISTONL_ENABLE_OUTPUT 1128
// Inputs to be monitored for spindle interaction
#define VELOCITY_CONFIRMATION_INPUT 1158
#define STOP_CONFIRMATION_INPUT 1159
//#define PISTONS_SENSOR_INPUT 1042
//#define PISTONL_SENSOR_INPUT 1044
// seconds of delay before execute other G code
#define DELAY_BEFORE_MACHINING 1
// Persist variable to sign the status of the spindle
#define SPINDLE_STATUS_VAR 190 // 0 indicates that spindle is off, 1 CW, 2 CCW
#define SPINDLE_OFF 0
#define SPINDLE_ON_CW 1
#define SPINDLE_ON_CCW 2

void SetSpindleStatus(int Status)
{
    persist.UserData[SPINDLE_STATUS_VAR] = Status;
}

int GetSpindleStatus()
{
    return persist.UserData[SPINDLE_STATUS_VAR];
}

void StopSpindle()
{
    ClearBit(PISTONS_ENABLE_OUTPUT);
    ClearBit(PISTONL_ENABLE_OUTPUT);
    ClearBit(CCW_ENABLE_OUTPUT);
    ClearBit(CW_ENABLE_OUTPUT);
    // Blocks the execution before the velocity is zero
    // Use Exec/Wait on KMotionCNC for this behavior
    while (ReadBit(STOP_CONFIRMATION_INPUT))
    {
        WaitNextTimeSlice();
    }

    SetSpindleStatus(SPINDLE_OFF);
}
Sincerely,
Guilherme

User avatar
TomKerekes
Posts: 2540
Joined: Mon Dec 04, 2017 1:49 am

Re: Nondeterministic "error loading file"

Post by TomKerekes » Fri Dec 09, 2022 4:19 pm

Hi Guilherme,
It is not clear for me how can a c program not compile sometimes. I thought that this was not even possible.
I don't think the problem is with compiling. Rather the problem is loading the program into KFLOP because of being disconnected or unresponsive.
I am not sure I understand what do you mean by a "program that modifies the IO used to communicate with Kanalog".
The IO on KFLOP JP7 is used to communicate with Kanalog. Basically IO 0-15. If a User modifies this IO the communication to Kanalog will fail and Kanalog will become disabled.
Here is my program that runs when an M6 is called:
I can't see anything specifically wrong.

What is printed on the KMotion Console Screen when the failure occurs?

Has KFLOP been reset?

How is KFLOP/Kanalog powered?
Regards,

Tom Kerekes
Dynomotion, Inc.

gui_marchioro
Posts: 59
Joined: Sun Aug 21, 2022 11:22 pm

Re: Nondeterministic "error loading file"

Post by gui_marchioro » Sun Dec 11, 2022 2:41 am

Hello Tom,
The IO on KFLOP JP7 is used to communicate with Kanalog. Basically IO 0-15. If a User modifies this IO the communication to Kanalog will fail and Kanalog will become disabled.
Good to know. I have reviewed the code just to make sure, but I am not using any of those.

I can't see anything specifically wrong.
Right, me neither.

What is printed on the KMotion Console Screen when the failure occurs?
As I have said in my first post nothing is printed in the console, just the message box about disconnection.
I've checked KMotion and there is no output in the console, just a message box stating "Read failed - Auto disconnect".

Has KFLOP been reset?
The board does not reset by itself, but I need to manually do this to make the system work again. From my first post:
To re-establish the system it is required to reset the board power and re-open KMotionCNC

How is KFLOP/Kanalog powered?
The KFLOP board is powered by JR1 using a PC power supply (the same used to power the Host PC).

User avatar
TomKerekes
Posts: 2540
Joined: Mon Dec 04, 2017 1:49 am

Re: Nondeterministic "error loading file"

Post by TomKerekes » Sun Dec 11, 2022 5:18 pm

Hi Guilherme,

I did use the TI Compiler and received a lot of warnings on functions being called before being declared. I added prototypes for all functions to declare them explicitly. See attached files. That can sometimes have nondeterministic results. You might try these files.

So it seems like KFLOP crashes and can no longer communicate? After the error and after clicking OK to the disconnect message what happens? Can you see status or anything before resetting KFLOP?

You might add diagnostic printouts especial at the beginning.

What is the Initialization Program doing?
Attachments
Drill.c
(2.71 KiB) Downloaded 29 times
MillChanger.c
(13.1 KiB) Downloaded 26 times
Spindle.c
(1.27 KiB) Downloaded 24 times
M6.c
(1.4 KiB) Downloaded 22 times
Regards,

Tom Kerekes
Dynomotion, Inc.

gui_marchioro
Posts: 59
Joined: Sun Aug 21, 2022 11:22 pm

Re: Nondeterministic "error loading file"

Post by gui_marchioro » Tue Dec 13, 2022 12:08 am

Hello Tom,
That can sometimes have nondeterministic results.
Interesting, maybe that is the problem then. I'll try with your files and update here if it works. Thanks!
So it seems like KFLOP crashes and can no longer communicate? After the error and after clicking OK to the disconnect message what happens? Can you see status or anything before resetting KFLOP?
Yes, after the error KFLOP crashes and can no longer communicate. After clicking ok a message stating that KFLOP is present but not responds is showed.

Below there is a video from a test I have done, trying to isolate the problem by executing M6 commands repeatedly.
In the video you will notice the following points:
- The M6 command runs quickly because I request for a tool that is already loaded (tool 1). This is not a prerequisite to the error to occur, it was just an optimization to execute the command as many times as possible in the shortest time.
- The bug is not to easy to reproduce. I had to execute the command more than 60 times before the compilation problem to happen.
- KMotion console does not report anything.
- KFLOP and KMotionCNC does not respond anymore, both needing to be restarted to work again.

You might add diagnostic printouts especial at the beginning.
Do you mean in the beggining of the M6 command execution?
What is the Initialization Program doing?
Basically it is just looping to read an MPG controller and other external buttons inputs.

Sincerely,
Guilherme

User avatar
TomKerekes
Posts: 2540
Joined: Mon Dec 04, 2017 1:49 am

Re: Nondeterministic "error loading file"

Post by TomKerekes » Tue Dec 13, 2022 10:17 pm

Hi Guilherme
You might add diagnostic printouts especially at the beginning.

Do you mean in the beginning of the M6 command execution?
Yes
The bug is not to easy to reproduce. I had to execute the command more than 60 times before the compilation problem to happen.
I think that is somewhat easy to re-produce and should allow you to find the cause relatively quickly. Its not like it takes days to occur.
What is the Initialization Program doing?

Basically it is just looping to read an MPG controller and other external buttons inputs.
You might post it and also disable it to see if the problem goes away.

You might also change to a non-custom screen to see if it is somehow related to the screen script.

I executed M6 500 times and I didn't receive an error.
Regards,

Tom Kerekes
Dynomotion, Inc.

gui_marchioro
Posts: 59
Joined: Sun Aug 21, 2022 11:22 pm

Re: Nondeterministic "error loading file"

Post by gui_marchioro » Wed Dec 28, 2022 10:08 am

Hello Tom,

I had a break on this project in the last weeks, but now I'm back.
You might add diagnostic printouts especial at the beginning.
When the problem occur some garbagge string is printed in the console.

I've tried to execute the M6 command with a non-blocking Init (without the for(;;) loop), and with a default screen from KMotionCNC, but the compilation error keep occurring.
Anyway, that is my Init program:

Code: Select all

#include "KMotionDef.h"
#include "InitConfig.c"
#include "MPGWatch.c"
#include "EmergencyWatch.c"
#include "ManualToolExchangeWatch.c"
#include "Homing.c"
#include "Spindle.c"
#include "MillChanger.c"
#include "TableSelectionWatch.c"

// Initialization program that runs when the Init button is pressed inside KMotionCNC
// It initializes the boards, monitors alarms and listen to the IOs of the machine
main()
{
    IOboardsConfig();
    InitialEmergencyMonitoring();
    // Confirms if there is an emergency to be solved before init.
    if (GetEmergencyState() == 1)
	{
		MsgBox("Solve the emergency problem before Initialize", MB_ICONEXCLAMATION);
        return;
	}

    // Initializes KFlop and Kanalog board
    InitConfig();
    // Updates current milling tool in use
    int currentTool;
    GetCurrentTool(&currentTool);

    // monitor external buttons, MPG and Emergency variables
    for(;;)
    {
        ManualToolExchangeWatch();
        BasicServiceMPG();
        LoopEmergencyMonitoring();
        Table1SelectionWatch();
        Table2SelectionWatch();
        Table1And2SelectionWatch();
        
        WaitNextTimeSlice();
    }
    
}
I was not able to find the problematic part in the code yet. An alternative that seems to solve the problem is to use an already compiled code (.out file) in the Tool Setup for the M6 command.

Sincerely,
Guilherme

User avatar
TomKerekes
Posts: 2540
Joined: Mon Dec 04, 2017 1:49 am

Re: Nondeterministic "error loading file"

Post by TomKerekes » Wed Dec 28, 2022 7:20 pm

Hi Guilherme,
When the problem occur some garbagge string is printed in the console.
What does the garbage look like? Hexadecimal numbers?

I've tried to execute the M6 command with a non-blocking Init (without the for(;;) loop), and with a default screen from KMotionCNC, but the compilation error keep occurring.
That would tend to eliminate much and point to the M6 program. However after eliminating the forever loop and changing the screen did you reboot KFLOP and restart KMotionCNC before running the test? Otherwise whatever is potentially being corrupted might have already occurred.

I assume you are using the files I modified?
An alternative that seems to solve the problem is to use an already compiled code (.out file) in the Tool Setup for the M6 command.
That's very interesting. That would just skip the compile step and shouldn't change anything with regard to the download or execution. Maybe change the timing?

I don't think this code does anything. It just gets the current tool which is then never used.

Code: Select all

    // Updates current milling tool in use
    int currentTool;
    GetCurrentTool(&currentTool);
This is really a strange one.
Regards,

Tom Kerekes
Dynomotion, Inc.

Post Reply