Multiple MsgBoxNoWait

Moderators: TomKerekes, dynomotion

Post Reply
Moray
Posts: 282
Joined: Thu Apr 26, 2018 10:16 pm

Multiple MsgBoxNoWait

Post by Moray » Sat Mar 28, 2020 6:44 pm

Tom,

I'm just looking to have this confirmed, but if a C Program triggers more than one MsgBoxNoWait, would it result in only one of them being shown?

The reason I ask, is I was using my mill last night, and had an issue initialising the Tool Changer with a generic failure message I'd coded. I eventually traced the issue to a slot sensor not being aligned, which should have triggered an error specific MsgBoxNoWait, but only the later generic MsgBoxNoWait was shown.
I'm guessing the later one overwrote the first one, as there would only be a few lines of code between them getting triggered?

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

Re: Multiple MsgBoxNoWait

Post by TomKerekes » Sat Mar 28, 2020 9:09 pm

Hi Moray,

Yes you are correct MsgBoxNoWait is completely non-blocking. It doesn't wait in any case either for a previous command to be completed or for the new message to be acknowledged.

Here is an example of a non-blocking state-machine approach to wait for an acknowledge. Note the printf and Delay are only for demonstration and should be removed when in use.

Code: Select all

#include "KMotionDef.h"

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

#define IDLE 0
#define WAITING_RESPONSE 1

int MessageState=IDLE;

main()
{
	int Response;
	
	MsgBoxNoWait("ESTOP!! E-stop activated, or Axis drive in error",MB_OK|MB_ICONEXCLAMATION);
	MessageState=WAITING_RESPONSE;
	
	for (;;)
	{
		WaitNextTimeSlice();
		
		if (MessageState==WAITING_RESPONSE)
		{
			printf("Here\n");
			Delay_sec(1);
			if (MsgBoxGetResponse(&Response)==0)  //Communication successful?
			{		
				// yes, show response
				printf("Message Response was %d\n", Response);
				MessageState=IDLE;
			}
		}		
	}
}
Regards,

Tom Kerekes
Dynomotion, Inc.

Moray
Posts: 282
Joined: Thu Apr 26, 2018 10:16 pm

Re: Multiple MsgBoxNoWait

Post by Moray » Sat Mar 28, 2020 9:48 pm

Thanks Tom, that's what I guessed.
This is part of my tool changer initialisation code, so there are a few prompts to get information, then various messages if something specific fails, followed by a generic failed message, and it's mostly done with non-blocking message boxes and state machines where needed.

The code is below for reference.
If I get time, I'll fix it, but I've added some printfs, so I'll at least get the real problem via the console for now.

Code: Select all

#include "KMotionDef.h"
#include "Triac.h"
#include "KflopToKMotionCNCFunctions.c"

#define IDLE 0
#define WAITING_RESPONSE 1

enum {TC_START, TC_CHKCRSLFLAT, TC_CHKDRBR, TC_CHKCRSLOUTUP, TC_CRSLPOSVALID, TC_TOOLVALID, TC_GETTOOLID, TC_CHKSTATE, TC_GETCRSLPOS, TC_GETPOS, TC_INDEX, TC_FAILED, TC_COMPLETE};
int TCStatus = TC_START;
float inputResult;
float awaitingResult = IDLE;
int Response = FALSE;
int Answer;
int *ChangerState 	= &persist.UserData[TOOL_STATE_VAR];
int *Tool     		= &persist.UserData[TOOL_VAR];
int *LastTool 		= &persist.UserData[LAST_TOOL_VAR];
int *CrslPos		= &persist.UserData[CRSL_POS];

void tc_init(void)
{
	switch(TCStatus)
	{
		case TC_START:
		{
			printf("TC_START\n");
			// is TCINIT TRUE?
			// If it is, then tool changer has already been initialised at some point, and nothing should of caused it now not to be,
			// so we ask the operator if they really want to re-run init.
			if(ReadBit(TCINITOK)){
				if(awaitingResult == IDLE){
					char MyMessage[80];  // String to be created and displayed
					double CrslP = *CrslPos/4.0;
					sprintf(MyMessage,"Tool Changer already initialized, with tool %d in spindle\n Carousel at position %.1f\n Are you sure you want to run Tool Changer Intialisation?",*Tool,CrslP);  // build the message we want to show
					MsgBoxNoWait(MyMessage,MB_YESNO);
					awaitingResult = WAITING_RESPONSE;
					printf("awaitingResult WAITING\n");
				} else {
					if (MsgBoxGetResponse(&Response)==0)  //Communication successful?
					{		
						printf("Response Succesful\n");
						printf("Message Response was %d\n", Response);
						// yes, show response
						if(Response == IDYES){	// if yes, we want to re-run init
							printf("Yes\n");
							ClearBit(TCINITOK);		// unset that we're initialised
							TCStatus = TC_CHKCRSLFLAT;	// move onto first step of initialisation
						} else if (Response == IDNO){		// else we don't want to re-run init
							printf("No\n");
							TCStatus = TC_COMPLETE;	// move onto the final state
						} else {
							printf("Invalid response\n");	// we shouldn't get here, but if we do, die!
							ThreadDone();
						}
						awaitingResult = IDLE;
						printf("awaitingResult IDLE\n");
					}
				}
			} else {
				TCStatus = TC_CHKCRSLFLAT;
			}
			break;
		}
		case TC_CHKCRSLFLAT:		// Is carousel geneva mechanism on position, or transitioning?
		{
			printf("TC_CHKCRSLFLAT\n");
			if(ReadBit(CRSLIDX)){	// if bit is high, then we're not on the flat, so quit and tell user to use TC Recovery
				MsgBoxNoWait("Carousel not at index. Use TC Recovery",MB_OK|MB_ICONEXCLAMATION);
				TCStatus = TC_FAILED;
			} else {
				TCStatus = TC_CHKDRBR;
			}
			break;
		}
		case TC_CHKDRBR:		// Is carousel geneva mechanism on position, or transitioning?
		{
			printf("TC_CHKDRBR\n");
			if(ReadBit(DRBR)){	// if bit is high, then drawbar is active (released) so quit and tell user to use TC Recovery
				TCStatus = TC_FAILED;
				MsgBoxNoWait("Drawbar Released. Use TC Recovery",MB_OK|MB_ICONEXCLAMATION);
			} else {
				TCStatus = TC_CHKCRSLOUTUP;
			}
			break;
		}
		case TC_CHKCRSLOUTUP:		// Is carousel out/up?
		{
			if(ReadBit(CRSLINR) || ReadBit(CRSLDWNR)){	// if in or down relays active, quit and tell user to use TC Recovery
				TCStatus = TC_FAILED;
				MsgBoxNoWait("Carousel In and/or Down commanded. Use TC Recovery",MB_OK|MB_ICONEXCLAMATION);
			} else if((!(ReadBit(CRSLOUT) && ReadBit(CRSLUP))) || awaitingResult == WAITING_RESPONSE) {	// if we're still not out/up, or we've already prompted user
				if(awaitingResult == IDLE){
					MsgBoxNoWait("Carousel not Out and Up.\n Is air supply connected?\nPress OK after connecting air, or cancel to quit and use TC Recovery",MB_OK|MB_ICONEXCLAMATION);
					awaitingResult = WAITING_RESPONSE;
					printf("awaitingResult WAITING\n");
				} else {
					if (MsgBoxGetResponse(&Response)==0)  //Communication successful?
					{		
						// yes, show response
						if(Response==IDOK){	// if OK, then we need to retrigger check, so we simply do nothing, and it'll get rechecked when 
							printf("OK\n");
						} else {		// else we want to quit TC Initialisation
							printf("Cancel\n");
							TCStatus = TC_FAILED;	// so set flag to Failed
						}
						awaitingResult = IDLE;
						printf("awaitingResult IDLE\n");
					}
				}
			} else {	// else carousle is out and up, so move on
				TCStatus = TC_CRSLPOSVALID;
				printf("TC_CHCKCRSLOUTUP complete. Moving to TC_CRSLPOSVALID\n");
			}
			break;
		}
		case TC_CRSLPOSVALID:
		{
			if((*CrslPos >= 1) && (*CrslPos<=24) && ((*CrslPos % 2) == 0 )){	// is carousel position is between 1 and 24, and it's equally divisable by 2, it's valid but maybe not correct
				if(awaitingResult == IDLE){
					char MyMessage[80];  // String to be created and displayed
					double CrslP = *CrslPos/4.0;
					printf("CrslPos = %d\n", *CrslPos);
					printf("CrslP = %.1f\n", CrslP);
					sprintf(MyMessage,"Is carousel at position %.1f",CrslP);  // build the message we want to show
					MsgBoxNoWait(MyMessage,MB_YESNO|MB_ICONEXCLAMATION);
					awaitingResult = WAITING_RESPONSE;
					printf("awaitingResult WAITING\n");
				} else {
					if (MsgBoxGetResponse(&Response)==0)  //Communication successful?
					{		
						// yes, show response
						printf("Carousel position valid?\n");
						printf("Message Response was %d\n", Response);
						if(Response == IDYES){	// if Yes, then move onto Tool checks 
							printf("Yes\n");
							printf("TC_CRSLPOSVALID complete, moving to TC_TOOLVALID\n");
							TCStatus = TC_TOOLVALID;
						} else if(Response == IDNO) {		// else we need to prompt user for position
							printf("No\n");
							printf("TC_CRSLPOSVALID failed, moving to TC_GETCRSLPOS\n");
							TCStatus = TC_GETCRSLPOS;
						} else {
							printf("Invalid response\n");
							ThreadDone();
						}
						awaitingResult = IDLE;
						printf("awaitingResult IDLE\n");
					}
				}
			} else {
				printf("CrslPos not valid, move to TC_GETCRSLPOS\n");
				TCStatus = TC_GETCRSLPOS;
			}
			break;
		}
		case TC_GETCRSLPOS:
		{
			//printf("TC_GETCRSLPOS - ask operator for carousel position\n");
			Answer = InputBox("Enter Carousel position (use 0.5 for mid positions)",&inputResult);
			if (Answer){
				printf("Operator Canceled\n");
				TCStatus = TC_FAILED;
			} else {
				printf("Operator Entered Value of %.3f\n",inputResult);
				int CrslP = inputResult * 4;
				if((CrslP % 2) != 0) {
					printf("Invalid value entered");
					// display message box
				}
				if(CrslP == 26)	// if user entered 6.5, we change it to 0.5
					CrslP = 2;
				*CrslPos = CrslP;
				printf("Carousel position=%d",*CrslPos);
				TCStatus = TC_CRSLPOSVALID;	// we'll go back a step to confirm position with operator
			}
			break;
		}
		case TC_TOOLVALID:
		{
			if((*LastTool >= 1) && (*LastTool<=99)){	// is Lsst tool from 1 to 99?
				if(awaitingResult == IDLE){
					char MyMessage[80];  // String to be created and displayed
					if(*LastTool != 99) {			// is tool less than 99 (99 indicates no tool in spindle)
						sprintf(MyMessage,"Is Tool %d in spindle?",*LastTool);  // build the message we want to show
					} else {
						sprintf(MyMessage,"Is spindle empty?");  // build the message we want to show
					}
					MsgBoxNoWait(MyMessage,MB_YESNO|MB_ICONEXCLAMATION);
					awaitingResult = WAITING_RESPONSE;
					printf("awaitingResult WAITING\n");
				} else {
					if (MsgBoxGetResponse(&Response)==0)  //Communication successful?
					{		
						// yes, show response
						printf("Tool valid?\n");
						printf("Message Response was %d\n", Response);
						if(Response == IDYES){	// if Yes, then move onto final completetion
							printf("Yes\n");
							TCStatus = TC_COMPLETE;
						} else if(Response == IDNO){		// else we need to prompt user for tool
							printf("No\n");
							TCStatus = TC_GETTOOLID;
						} else {
							printf("Invalid response\n");
							ThreadDone();
						}
						awaitingResult = IDLE;
						printf("awaitingResult IDLE\n");
					}
				}
			} else {
				printf("LastTool not valid, move to TC_GETTOOLID\n");
				TCStatus = TC_GETTOOLID;
			}
			break;
		}
		case TC_GETTOOLID:
		{
			printf("TC_GETTOOLID - ask operator for current tool\n");
			Answer = InputBox("Enter current slot tool is stored\n or 99 if no tool in spindle",&inputResult);
			if (Answer){
				printf("Operator Canceled\n");
				TCStatus = TC_FAILED;
			} else {
				printf("Operator Entered Value of %.3f\n",inputResult);
				*LastTool = (int)inputResult;
				printf("Tool position=%d",*LastTool);
				TCStatus = TC_TOOLVALID;	// we'll go back a step to confirm position with operator
			}
			break;
		}
		case TC_FAILED:
		{
			printf("TC_FAILED - TC either failed or cancelled\n");
			MsgBoxNoWait("Tool change initialidation failed. Please Re-try",MB_OK);
			ThreadDone();
			break;
		}
		case TC_COMPLETE:
		{
			printf("TC_COMPLETE:Changer Intialised\n");
			*Tool = *LastTool;
			*ChangerState = T_IDLE;
			double CrslP = *CrslPos/4.0;
			SetBit(TCINITOK);
			char MyMessage[80];  // String to be created and displayed
			sprintf(MyMessage,"Tool Changer initialisation complete.\n Tool %d in spindle\n Carousel at position %.1f\n(If incorrect, rerun initialisation)",*Tool,CrslP);  // build the message we want to show
			MsgBoxNoWait(MyMessage,MB_OK);
			ThreadDone();	// set TC as intialised and quit
			break;
		}
	}
	
}

main()
{
	printf("TCinit launched\n");
	//printf("awaitingResult=%d\n",awaitingResult);
	for(;;)	// loop forever
	{
		WaitNextTimeSlice();
		// we continually monitor for Z axis being homed, and exit thread with warning message if it's not homed
		// (should an Estop occur, Z gets flagged as being unhomed, so we don't need to monitor anything else)
		if(!ReadBit(ZHOMED))
		{
			MsgBox("Z axis not homed.\nHome Z axis before initialising Tool Changer",MB_OK);
			ThreadDone();
		}
		tc_init();
	}
}

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

Re: Multiple MsgBoxNoWait

Post by TomKerekes » Sun Mar 29, 2020 4:53 pm

Hi Moray,

Yes I see code such as below that does a MsgBoxNoWait then transitions to state TC_FAILED which immediately does a MsgBoxNoWait.

Maybe make a new state that waits for the Message response and then transitions to TC_FAILED ?

Code: Select all

	case TC_CHKCRSLFLAT:		// Is carousel geneva mechanism on position, or transitioning?
		{
			printf("TC_CHKCRSLFLAT\n");
			if(ReadBit(CRSLIDX)){	// if bit is high, then we're not on the flat, so quit and tell user to use TC Recovery
				MsgBoxNoWait("Carousel not at index. Use TC Recovery",MB_OK|MB_ICONEXCLAMATION);
				TCStatus = TC_FAILED;
			} else {
Regards,

Tom Kerekes
Dynomotion, Inc.

Moray
Posts: 282
Joined: Thu Apr 26, 2018 10:16 pm

Re: Multiple MsgBoxNoWait

Post by Moray » Sun Mar 29, 2020 6:39 pm

I'll probably take the easy option, and just change it to a blocking message box, as nothing should be moving during this program.

Post Reply