G-codes/offsets/tools with .Net

Moderators: TomKerekes, dynomotion

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

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

Post by TomKerekes » Mon Mar 16, 2020 12:04 am

Hi Moray,
I'm not specifying any files in the interpreter, so I'm assuming it's using default.set, as it does have units set to default to MM.
I don't think any settings file is used if none is specified. But it should initialize to something regardless.

Now I've learnt this, how do I get around the problem of external offsets being used?
Do I need to initialise things in a different order, or just send some kind of command to the interpreter prior to loading my settings?
I think you could just specify a different Vars file. Make a copy of emc.var with offsets of zero.


Also, during all this, I've noticed that any changes to offsets using SetOrigin, don't take effect until the related offset is requested again. Do I need to explicitly call the offset again, or is there some method I'm missing?
Here is some code from SimpleGCodeWPF example to force an update:

Code: Select all

        private void Set_Fixture_Offset(int Fixture_Number, double X, double Y, double Z)
        {
            // Set GVars for Offsets
            KM.CoordMotion.Interpreter.SetOrigin(Fixture_Number,
                KM.CoordMotion.Interpreter.InchesToUserUnits(X),
                KM.CoordMotion.Interpreter.InchesToUserUnits(Y),
                KM.CoordMotion.Interpreter.InchesToUserUnits(Z), 0, 0, 0);

            KM.CoordMotion.Interpreter.SetupParams.OriginIndex = -1;  // force update from GCode Vars
            KM.CoordMotion.Interpreter.ChangeFixtureNumber(Fixture_Number);  // Load offsets for fixture
        }
HTH
Regards,

Tom Kerekes
Dynomotion, Inc.

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

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

Post by Moray » Mon Mar 16, 2020 4:42 pm

Thanks for that Tom, I'll try it later.

There is one thing I'm curious about, is at what point does the interpreter get initialised?
In my code I transfer the offsets once my program loads, but then they are getting overwritten by the var file once I try running GCode.

Should I call the InitializeInterpreter method before setting any values?


Also, how do I force the offsets to be saved to the var file?

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

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

Post by TomKerekes » Mon Mar 16, 2020 5:51 pm

Hi Moray,
There is one thing I'm curious about, is at what point does the interpreter get initialised?
In my code I transfer the offsets once my program loads, but then they are getting overwritten by the var file once I try running GCode.
InitializeInterpreter gets called when the Interpreter is called to execute if it hasn't already been initialized. Or if the Restart parameter is set when called to execute.

Should I call the InitializeInterpreter method before setting any values?
probably if you want to override the values in the files.

Also, how do I force the offsets to be saved to the var file?
The Interpreter has a method:
int CGCodeInterpreter::rs274ngc_save_parameters()

But it isn't currently exposed to .NET. We can add that if necessary.
Regards,

Tom Kerekes
Dynomotion, Inc.

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

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

Post by Moray » Mon Mar 16, 2020 7:53 pm

I am getting frustrated with this now.


I am now calling InitializeInterpreter, just after the main KM_Controller is created, I then transfer my offsets using SetOrigin, then using ChangeFixture to select the active offset, the active offset is now updating as expected, with the expected value.


However, G92 is proving to be a problem.
It is definitely being set to all 0's (I've deliberately left the random values in the var file to test this, as I'd like to not rely on the varfile), but I'm struggling to get those 0s to actually happen.

I have tried adding an MDI during initialisation to do G92 X0 Y0 Z0, just before the ChangeFixture line, but the X offset goes to -0.801102 (this is not in the var file, but I suspect it's a result of some calculation, as it is consistent), and trying G92 X0... via MDI once loaded, the value does not move from -0.801102.

However if I comment out the MDI during initialisation, the X offset loads as 5.119598 (which is the value in the var file), if I then do the G92 X0... via MDI once loaded, the X offset zeroes as expected.

Any ideas?

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

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

Post by TomKerekes » Mon Mar 16, 2020 9:35 pm

Hi Moray,
G92 X0... via MDI once loaded, the value does not move from -0.801102.
I don't completely follow all that, but G92 X0... shouldn't set the G92 offset to zero. Instead it calculates what the G92 offset should be to make the GCode Position 0. So it is dependent on many things. Current machine position, fixture offset, and possibly Tool Offset. G52 X0 should set the Axis Offset to 0 directly.

trying G92 X0... via MDI once loaded, the value does not move from -0.801102
What "value" are you referring to? Your DRO? GCode variable?
Regards,

Tom Kerekes
Dynomotion, Inc.

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

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

Post by Moray » Mon Mar 16, 2020 10:23 pm

Thanks for that.
Turns out I'm an idiot :roll:

However, to answer your questions, I've got two labels set up to monitor X_OriginOffset, and X_AxisOffset. It was the X_AxisOffset that was showing the random value.


I have however hit my next snag.
Having added DoGCodeLine to change the interpreter distance mode, and set G52 during initialisation, I've just realised by doing so, trying to do any MDIs after that, any moves don't happen. G20/21s and G5x's work, but any G0/1 don't, and useractions stop working.
If I comment out the DoGCodeLine's in the initialisation, everything works.

I'm assuming the previous MDIs during initialisation are causing something to prevent movement?

This is how I've implemented DoGCodeLine-

Code: Select all

private void DoGCodeLine (String gcode)
        {
            // we need to generate a temp file (and disable button when running)
            String file = "Temp_MDI.ngc";
            //TextBlock_Debug.

            using (StreamWriter writer = new StreamWriter(file))
            {
                writer.WriteLine(gcode);
                writer.WriteLine();
            }
            string readText = File.ReadAllText(file);
            //RichTextBox_GCode.Document.Blocks.Clear();
            RichTextBox_GCode.AppendText(readText);
            if (!Connected) KM.CoordMotion.IsSimulation = true;
            LaunchExecution(file, 0, 0);
            
            //KM.CoordMotion.Interpreter.Interpret(file,0,0,0);
        }

        private void LaunchExecution(String file, int begin, int end)
        {
            KM.CoordMotion.Interpreter.Interpret(file, begin, end, 0);
        }

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

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

Post by TomKerekes » Tue Mar 17, 2020 6:06 pm

Hi Moray,

I can't see a reason for that. Possibly something not initialized that results in a movement with 0 speed or something? You will probably need to debug it by stepping through to see what is occurring.

It seems like your code doesn't close the StreamWriter file after writing to it but can't see why all GCode wouldn't work/fail if that was the issue.
Regards,

Tom Kerekes
Dynomotion, Inc.

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

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

Post by Moray » Tue Mar 17, 2020 7:58 pm

Debugging in VS is something I'm horrendous at. I'll have to go and do some reading up on that.


However, I have tried moving the code around, and I've discovered if I do an MDI before the KFlop has connected, movement is locked out.
But if I move the MDI to a point in the code where the KFlop has connected, everything works.
I.e. If I move it to a point in the timer tick so the DoGCode only happens after the KFlop has connected, it works.

I did use SimpleGCodeWPF as a base to start from, so all I've done is expand the mainwindow code to read more values from a settings file, and copy those settings to a settings tab and load them to the interpreter.
So if I put code to do a single DoGCode in either the if (nBoards > 0) or if (Connected && KM.WaitToken(100) == KMOTION_TOKEN.KMOTION_LOCKED) clauses of dispatchTimer_Tick, it works. If I put it out with those clauses, things lock up.

I have just tested loading my program before connecting the KFlop, and the same lockup issue occurs.

I'm guessing there is some kind of conflict issue if the interpreter receives a MDI before the program has connected to the KFlop?
If it helps, I can ZIp up my code and email it across, so you can laugh at my amateur attempts at this..

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

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

Post by Moray » Tue Mar 17, 2020 10:35 pm

I've just discovered what's causing the issue.

While going back over DoGCode to add the line to close the streamwriter, I noticed the line that it puts the interpreter in simulation mode if there is no KFlop connected. Comment out that code, and no mystery lockups, or at least no activating simulation. :-)

I've just done a quick bit testing, and looking at the KMotionCNC code to get my head around this, I see KMotionCNC deactivates simulation after execution completes, if no KFlop is connected and the simulation box isn't ticked.

If I activate simulation mode, and run some MDI commands (i.e. change mode/offsets), do those changes stick when simulation mode is exited?
I.e. does simulation mode simply prevent motion, or does it also affect non-motion commands?

Demondor
Posts: 16
Joined: Fri Mar 22, 2019 8:49 am

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

Post by Demondor » Wed Mar 18, 2020 8:28 am

Hi Moray.
If you need to run some kind of g code after starting the program without human participation, then you need to create a connection event and trigger the necessary actions after connecting. I would also recommend that you have several variables to control the current state. For example, if at startup you need to execute the code once, while if the connection with the board is accidentally broken and then restored, then the event will fire again and execute the code again. I monitor connection, code execution, line of code, pause state. In the timer, I read the status of the bits used (read from the settings file) and the commands from the files. In addition, in order not to display a change in the line of the executed code when executing the MDI command, there is also a variable. And use try and catch to handle possible errors.
My TimerTick.

Code: Select all

private void Timer_Tick(object sender, EventArgs e)
{
      int[] List;
      int nBoards = 0;

      // Проверка связи с kflop
      /************************************************************************************************************************/
       if (!Connect && ++skip == 10)
       {
            skip = 0;

            // узнаем количество подключенных плат
            List = KM.GetBoards(out nBoards);
            if (nBoards > 0)
            {
                Connect = true;

		//!!! Here you can substitute your code for execution after connecting !!!
                if (!GetAxisState)
                {
                    try
                    {
                         KM.CoordMotion.GetAxisDefinitions(ref axisChannel.X, ref axisChannel.Y, ref axisChannel.Z, ref axisChannel.A, ref axisChannel.B, ref axisChannel.C); // узнаем соответствие ось канал
                         GetAxisState = true;
                    }
                    catch (Exception ex)
                    {
                         MessageEvent("Ошибка при попытке считать привязку осей " + ex.ToString(), "Сообщение об ошибке");
                    }
                }
                //!!! Here you can substitute your code for execution after connecting !!!
            }
            else
             {
                 Connect = false;
             }
      }


      // Если подключение установлено получаем текущее состояние
      /************************************************************************************************************************/
      if (Connect)
      {
           if (KM.WaitToken(100) == KMOTION_TOKEN.KMOTION_LOCKED)
                {
                    try
                    {
                        MainStatus = KM.GetStatus(false);                   // получаем состояние kflop
                        KM.ReleaseToken();

                        // Была остановка по ошибке показываем
                        if (MainStatus.StopImmediateState > 2 && !Excecute)
                        {
                            if (!AlarmFeedHold)
                                AlarmFeedHold = true;
                        }
                        else
                        {
                            if (AlarmFeedHold)
                                AlarmFeedHold = false;
                        }

                        // проверяем состояние битов
                        UserButtonBitState();       // для userButton
                        DacControlBitDacState();    // для DacControl

                        // проверяем на наличие команд Kflop-PC
                        int pc_comm = MainStatus.GetPC_comm(0);
                        if (pc_comm > 0)
                            ServiceKFLOPCommands(pc_comm);


                        // получаем положение осей в координатах двигателей
                        // KM.CoordMotion.UpdateCurrentPositionsABS(ref machineCoordinates.M1, ref machineCoordinates.M2, ref machineCoordinates.M3, ref machineCoordinates.M4, ref machineCoordinates.M5, ref machineCoordinates.M6, false);
                        CANON_UNITS currentUnits = KM.CoordMotion.Interpreter.SetupParams.LengthUnits;
                        offsetID = KM.CoordMotion.Interpreter.SetupParams.OriginIndex;

                        KM.CoordMotion.Interpreter.ReadCurInterpreterPosition(ref machineCoordinates.M1, ref machineCoordinates.M2, ref machineCoordinates.M3, ref machineCoordinates.M4, ref machineCoordinates.M5, ref machineCoordinates.M6);

                        PreparationAxisValue();

                        // обрабатываемую узнаем строку
                        if (!fMDI)
                        {
                            // Время выполнения кода
                            TimeExcecute = KM.CoordMotion.TimeExecuted;
                            // Строка выполнения
                            realLine = KM.CoordMotion.Interpreter.SetupParams.CurrentLine;
                           /* if (fileWorks.currBackMappingTable != null)
                            {
                                if (realLine < fileWorks.currBackMappingTable.Length)
                                {
                                    VirtualLine = fileWorks.currBackMappingTable[realLine];
                                }
                            }*/
                        }
                    }
                    catch (DMException) // ошибка при получении информации
                    {
                        KM.ReleaseToken();  // обработали
                    }

        }
        else
        {
             Connect = false;
        }
}

Post Reply