G-codes/offsets/tools with .Net

Moderators: TomKerekes, dynomotion

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

Re: G-codes/offsets/tools with .Net

Post by Moray » Sat Dec 26, 2020 10:19 pm

I may have to dig into the interpreter :/

I can handle populating the interpreter tool/offsets in suitable units when via my app, but the problem is if the running g-code switches G20/21, then I have no way of controlling what the interpreter does.

The easiest 'bodge' I can think would be to pre-scan the loaded file for G20/21, then prompt the user that units need to switched prior to running the file to ensure tools/offsets are in units to match the file.

I'll have a think about this.



Next query I have.
I'm working on the whole KFlop/PC communications. I'm working through the list of possible options (can so far Halt, EStop, Single Step and Run via a basic C program), but I'm needing a bit help to understand the conditions KMotionCNC applies to reading the MainStatus and calling ServiceKFlopCommands.-

Code: Select all

if (result == KMOTION_LOCKED)
			{
				m_ConnectedForStatus=true;

				// Note only service the console 
				// after we have the token so we
				// are sure of no getting blocked

				TheFrame->KMotionDLL->ServiceConsole();
			
				// upload bulk status

				if (GetStatus())
				{
					Interpreter->Abort();

					// error reading status
					TheFrame->KMotionDLL->Failed();
					m_ConnectedForStatus=false;
				}
				
				TheFrame->KMotionDLL->ReleaseToken();

				UpdateScreen(m_ConnectedForStatus);

				if (m_ConnectedForStatus)
					ServiceKFLOPCommands();
			}
			else
			{
				m_ConnectedForStatus=false;
				UpdateScreen(false);
			}
The above I kind of understand, but I'm struggling with the GetStatus()

Code: Select all

int CKMotionCNCDlg::GetStatus()
{
	int i,result,n;
	CString s;
	int *p=(int *)&MainStatus;

	int HostStatus=0;

	if (ThreadIsExecuting) HostStatus += HOST_JOB_ACTIVE_BIT;


	// KMotion is available read the status, include Job Status, and screen changes count
	s.Format("GetStatus %x %x",HostStatus, Screen.EditScreenChangesCount);  
	if (TheFrame->KMotionDLL->WriteLine(s)) return 1;

	n=sizeof(MainStatus)/sizeof(int);

	s.Empty();

	for (i=0; i<n; i++)
	{
		if (s.IsEmpty())
		{
			if (TheFrame->KMotionDLL->ReadLineTimeOut(s.GetBuffer(257),5000))
			{
				return 1;
			}

			s.ReleaseBuffer();

			// change the CRLF at the to a space

			s.Delete(s.GetLength()-2,2);

			s += ' ';
		}

		// get a hex 32 bit int which may really be anything
		
		result = sscanf(s.GetBuffer(0),"%8X",p++);

		if (result!=1)
		{
			return 1;
		}

		if (s.GetLength() >=9)
		{
			s.Delete(0,9);
		}
		else
		{
			return 1;
		}

		// check if first word contains version

		if (i==0)
		{
			if ((p[-1]>>16)==306)  // check for previous version
			{
			}

			if ((p[-1]>>16)==0)
			{
				// probably old version of DSP Code

				// set version to something

				MainStatus.VersionAndSize=0;
				MainStatus.ThreadActive=0;

				p[0] = p[-1];
				p++;
				n=n-2;
			}
			else
			{
				// update number of words to read
				if (n!=(MainStatus.VersionAndSize & 0xffff))
				{
					int result = AfxMessageBox("Error: Status Record Size mismatch\r\r"
						"Disable further status updates?",MB_ICONSTOP|MB_YESNO);

					if (result == IDYES)
						ReadStatus=false;
				}
			}
		}
	}
Is this something I need to implement somehow, or is this handled simpler when using dotNet?

At the moment I have-

Code: Select all

if (!KFlopCommandInProgress)
                    {
                        int pc_comm = MainStatus.GetPC_comm(0);
                        if (pc_comm > 0)
                        {
                            KFlopCommandInProgress = true;
                            ServiceKFlopCommands(pc_comm);
                        }
                            
                    }
I added the KFlopCommandInProgress condition to kind of mimic m_ConnectedForStatus, as I was having a crash issue after calling PC_COMM_ESTOP, which I thought was being caused by ServiceKFlopCommands() being called multiple times before the initial call finished.

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

Re: G-codes/offsets/tools with .Net

Post by TomKerekes » Sat Dec 26, 2020 10:37 pm

Hi Moray,

There is a .NET KM.GetStatus() method. See how it is used in SimpleFormsCS example timer1_Tick.
Regards,

Tom Kerekes
Dynomotion, Inc.

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

Re: G-codes/offsets/tools with .Net

Post by Moray » Sat Dec 26, 2020 11:50 pm

Thanks for that Tom.
I'm sure I've looked at that example program in the past, but I used the SimpleGCodeWPF as the base for this.

Turns out I already use GetStatus, but hadn't actually realised the names were the same.

To show my full code -

Code: Select all

if (Connected && KM.WaitToken(100) == KMOTION_TOKEN.KMOTION_LOCKED)
            {
                try
                {
                    
                    MS = KM.GetStatus(false);  // we already have a lock
                    //MS = MainStatus;
                    KM.ReleaseToken();
                    if (!KFlopCommandInProgress)
                    {
                        int pc_comm = MS.GetPC_comm(0);
                        if (pc_comm > 0)
                        {
                            KFlopCommandInProgress = true;
                            ServiceKFlopCommands(pc_comm);
                        }
                            
                    }
                    
                }
                catch (DMException) // in case disconnect in the middle of reading status
                {
                    KM.ReleaseToken();  // make sure token is released
                }
            }
            else
            {
                Connected = false;
            }
Although I use GetStatus to get the MainStatus (MS), I don't actually run a test to see if there's a problem with getting the MainStatus.

So I'm assuming I need to add a test, and abort if GetStatus returns 1, in a similar way to KMotionCNC?

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

Re: G-codes/offsets/tools with .Net

Post by TomKerekes » Sun Dec 27, 2020 1:43 am

So I'm assuming I need to add a test, and abort if GetStatus returns 1, in a similar way to KMotionCNC?
Well, no. GetStatus doesn't return an error code. Rather it throws an exception.
Regards,

Tom Kerekes
Dynomotion, Inc.

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

Re: G-codes/offsets/tools with .Net

Post by Moray » Sun Dec 27, 2020 12:09 pm

TomKerekes wrote:
Sun Dec 27, 2020 1:43 am
So I'm assuming I need to add a test, and abort if GetStatus returns 1, in a similar way to KMotionCNC?
Well, no. GetStatus doesn't return an error code. Rather it throws an exception.
I was looking at https://dynomotion.com/KMotion_dotNet/D ... Status.htm
Which with a fresh set of eyes, I see is for creating a MainStatus.

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

Re: G-codes/offsets/tools with .Net

Post by Moray » Sun Dec 27, 2020 10:36 pm

Tom, just to check how I'm reading the variables attached to MS.GetPC_comm() calls.
I know the variables can be accessed by increasing the index as required, but in the case of floats after a PCDoFloat() call, that results in the wrong value being read, GetPC_comm only returns ints.

Is using GetUserDataFloat() and accessing the relevant location a suitable work around?
I've got my code working via this method, but I just want to check there's not more suitable method.

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

Re: G-codes/offsets/tools with .Net

Post by TomKerekes » Mon Dec 28, 2020 3:11 pm

Hi Moray,

The disadvantage of using GetUserDataFloat() is that it involves around trip interaction with KFLOP rather than getting the data from main status that we may already have. Any round trip interaction with KFLOP has an overhead on the order of 1millisecond where getting the data from the main status would be on the order of 1 us. But if this is only occurring say every 100 milliseconds the difference will be fairly insignificant.

We should have a float method for that but you can do the conversion yourself like GetUserDataFloat() does with:

Code: Select all

            Byte[] bytes = BitConverter.GetBytes(retval);
            return BitConverter.ToSingle(bytes, 0);
Regards,

Tom Kerekes
Dynomotion, Inc.

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

Re: G-codes/offsets/tools with .Net

Post by Moray » Mon Dec 28, 2020 5:17 pm

Thanks for that Tom. That worked well, and I've wrapped it up into the following function for anybody dealing with this-

Code: Select all

private double GetPC_commFloat(int idx)     // This gets a Float value from the bulk status, and outputs it as a double (avoids the comm/time penalty of using KM.GetUserDataFloat
        {
            Byte[] bytes = BitConverter.GetBytes(MS.GetPC_comm(idx));
            return BitConverter.ToSingle(bytes, 0);
        }

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

Re: G-codes/offsets/tools with .Net

Post by Moray » Mon Dec 28, 2020 11:59 pm

I'm gradually working my way through the list of KFlop to PC commands, and can see my next stumbling block.

How do I retrieve strings from the gather buffer?

I've found the function in KMotionCNC that achieves this, but I'm not sure how you'd handle this via dotNet, as I can't find anything in the dotNet help about the gather buffer.

Code: Select all

int CKMotionCNCDlg::GetStringFromGather(int WordOffset, CString *msg, int nWords)
{
	CString s;

	TheFrame->KMotionDLL->WaitToken("KMCNCGetStrGath");
	s.Format("GetGatherHex %d %d",WordOffset,nWords);  
	TheFrame->KMotionDLL->WriteLine(s);

	for (int i=0;i<nWords;i++)  // convert hex to 32 bit words
	{
		if ((i%8)==0)  // every 8 hex get a new line
		{
			s.Empty();
			if (TheFrame->KMotionDLL->ReadLineTimeOut( s.GetBuffer(MAX_LINE+1),5000)) return 1;  
			s.ReleaseBuffer();
		}

		int result = sscanf(s.GetBuffer(0),"%8X ",(int*)(msg->GetBufferSetLength(nWords*4+8)+i*4));

		if (result!=1)
		{
			TheFrame->KMotionDLL->ReleaseToken();
			return 1;
		}

		s.Delete(0,9);  // delete hex value
	}
	TheFrame->KMotionDLL->ReleaseToken();

	msg->GetBufferSetLength(nWords*4+1)[nWords*4]=0;  // make sure it is terminated
	msg->ReleaseBuffer();

	return 0;
}

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

Re: G-codes/offsets/tools with .Net

Post by TomKerekes » Tue Dec 29, 2020 5:48 pm

Try this:


Code: Select all

        // Get a string from KFLOP gather buffer
        // return true if successful
        //
        // words are sent up to 8 per line like this:
        // 6C6C6548 6F57206F 00646C72 00000007 30016001 0000000B 30012001 00803F2D\r\n

        private bool GetStringFromGather(int WordOffset, out String  msg, int nWords)
        {
            String s="";
            byte val = 1; // start not terminated

            msg = "";

            if (KM.WaitToken(1000000) != KMOTION_TOKEN.KMOTION_LOCKED) return false;  //lock KFLOP

            KM.WriteLine(String.Format("GetGatherHex {0} {1}", WordOffset, nWords));  // request data

            for (int i = 0; i < nWords*4; i++)  // loop through each byte
            {
                if ((i % 32) == 0)  // every 8 hex words (32 bytes) get a new line
                    if (!KM.ReadLineTimeout(ref s, 5000)) return false;

                if (val != 0)  // convert if not yet terminated
                {
                    int k = 3 - (i % 4);    // byte of word (reversed for little-endian)
                    int w = (i / 4) % 8;    // word
                    int n = w * 9 + k * 2;  // first char position
                    if (s.Length < n + 2) return false; // stay in bounds

                    //  get 2 hex characters and convert to byte
                    if (!byte.TryParse(s.Substring(n, 2), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val))
                    {
                        KM.ReleaseToken();
                        return false;
                    }

                    msg += Convert.ToChar(val);  // add to string
                }
            }
            KM.ReleaseToken();
            return true;
        }

Regards,

Tom Kerekes
Dynomotion, Inc.

Post Reply