Page 1 of 1

Proper syntax for running g-code in a plugin

PostPosted: Fri Dec 31, 2021 11:42 pm
by ger21
I've searched for hours, and have found minimal information on running g-code in a plugin.
Using UC.Code(), I seemed to have issues with code being skipped.
So I tried using Codelist() and it seems to work fine.
Is this an acceptable way to do this, or should I be doing it another way? This is for the Goto Zero button on my screen.

Code: Select all
            Case (10676) '/// Goto Zero

                    If Not (UC.GetXpos = 0 And UC.GetYpos = 0 And UC.GetZpos = 0 And UC.GetApos = 0) Then

                        Dim gcodelist As New List(Of String)

                        If OrigDistMode = 91 Then
                            gcodelist.Add("G0 G90")
                        End If

                        If GTZUseSafeZ Then
                            gcodelist.Add("G53 G0 Z" + CStr(SafeZ))
                        End If

                        gcodelist.Add("G0 X0 Y0 A0")

                        If Not GTZXYonly Then
                            gcodelist.Add("G0 Z0")
                        End If

                        UC.Codelist(gcodelist)
                        While (UC.IsMoving())
                        End While

Re: Proper syntax for running g-code in a plugin

PostPosted: Sat Jan 01, 2022 4:15 am
by eabrust
Hey Gerry,

This kicked my butt for quite a while too, till Dezsoe showed me the way (http://www.forum.cncdrive.com/viewtopic.php?f=14&t=84&p=15209&hilit=codesync#p15213). The quick and dirty answer is to use 'CodeSync', but you have to call it from new threads, and use a 'is moving' routine which is also threaded. If you call CodeSync from the form directly, it will lock up the program. Doing some of this stuff from macros was far easier than plugins...

Here is an example block of a 'move to 0' code I have in ProbeIt. It probably is sloppy and can be done much cleaner/better, but it works :) This references a number of check boxes and other stuff, but you should be able to weed out what you need from this. You'll also note I leave in plenty of comments on things I tried that didn't work, etc, so I don't accidentally go back to what I did incorrectly at a later time...

First, this is run by the button on the form, to start the routine:
Code: Select all
 Private Sub btnGoToZero_Click(sender As Object, e As EventArgs) Handles btnGoToZero.Click

        If Not cbGoTORot.Checked AndAlso Not cbGoToX.Checked AndAlso Not cbGoToY.Checked AndAlso Not cbGoToZ.Checked Then
            Using New Centered_MessageBox(Me)

                MessageBox.Show(Me, "Appears no axis is set for moving, no move To make!")
            End Using

            Return
        Else



            Try

                If thrMyProc Is Nothing Then

                    abortflag = False

                    thrMyProc = New Thread(AddressOf GoToZeroThread)
                    thrMyProc.CurrentCulture = Thread.CurrentThread.CurrentCulture ' Stay in English
                    thrMyProc.Start()

                    ' Me.btnProbeGrid.Text = "STOP !"
                Else

                    'stop UCCNC first
                    UC.Stop()

                    abortflag = True

                    'thrMyProc.Abort() 'DONT DO THIS
                    thrMyProc = Nothing



                End If
            Catch ex As Exception
                messagebox.show(Me, "Didn't work....")
            End Try
        End If

end sub


The above starts a new thread, pointed at running the 'move' routine, which is full of codesync calls:

Code: Select all
Public Sub GoToZeroThread()

        Dim zstart, xstart, ystart, rotstart, feed, safe, zretract, zend, xend, yend, rotend, xpoint, ypoint, zpoint, rotpoint As Double

        Dim strMoveCode As String




        ' ABORT if needed to
        If UC.GetLED(25) Or UC.GetLED(36) Or UC.GetLED(217) Or abortflag Then ' Check for feedhold and cycle stop and reset
            Try
                Using New Centered_MessageBox(Me)

                    MessageBox.Show(Me, "Aborting offset move, UCCNC in reset!")
                End Using

                UC.AddStatusmessage("Aborting offset move!")
                thrMyProc = Nothing
                Return
                'thrMyProc.Abort()

                Exit Sub
            Catch ex As Exception

            End Try

        End If
'End abort block

        xstart = UC.GetXpos
        ystart = UC.GetYpos
        zstart = UC.GetZpos

        Try

            If cbGoToX.Checked Then
                xpoint = 0

            End If

            If cbGoToY.Checked Then
                ypoint = 0

            End If


            If cbGoToZ.Checked Then
                zpoint = 0

            End If


            If cbGoTORot.Checked Then
                rotpoint = 0

            End If


            feed = nudGoTOVel.Value
        Catch ex As Exception

        End Try



        strMoveCode = "F" & feed

        'messagebox.show(me, strMoveCode)


        UC.Codesync(strMoveCode)
        While IsMoving()
            Thread.Sleep(5)
        End While

        ' Lift Z to safe height
        If cbZSafeLift.Checked Then

            GoToSafeZ()

        Else

        End If



        'Z First:



        If cbGoToZ.Checked AndAlso (zpoint > UC.GetZpos) Then

            If feed <> 0 Then
                strMoveCode = "G1 "
            Else
                strMoveCode = "G0 "
            End If

            strMoveCode = strMoveCode & " Z" & fn(zpoint)

            UC.Codesync(strMoveCode)

            While IsMoving()
                Thread.Sleep(5)
            End While

        End If


        'Move to location
        If feed <> 0 Then
            strMoveCode = "G1 "
        Else
            strMoveCode = "G0 "
        End If


        If cbGoToX.Checked Then
            strMoveCode = strMoveCode & " X" & fn(xpoint)
        End If

        If cbGoToY.Checked Then
            strMoveCode = strMoveCode & " Y" & fn(ypoint)
        End If


        'If cbGoToZ.Checked Then
        '    strMoveCode = strMoveCode
        'End If


        If cbGoTORot.Checked Then


            If comboRotoraySelected.Text = "A" Then

                strMoveCode = strMoveCode & " A" & fn(rotpoint)


            ElseIf comboRotoraySelected.Text = "B" Then
                strMoveCode = strMoveCode & " B" & fn(rotpoint)


            ElseIf comboRotoraySelected.Text = "C" Then
                strMoveCode = strMoveCode & " C" & fn(rotpoint)

            End If

        End If


        'strMoveCode = strMoveCode & " F" & fn(feed)

        UC.Codesync(strMoveCode)

        While IsMoving()
            Thread.Sleep(5)
        End While





        'strMoveCode = "G1 X" & fn(xpoint) & " Y" & fn(ypoint) & " F" & fn(feed)



        If (cbZSafeLift.Checked AndAlso cbZSafeReturn.Checked) Or (Not cbZSafeLift.Checked AndAlso Not cbZSafeReturn.Checked) Then
            If feed <> 0 Then

                If cbGoToZ.Checked Then
                    strMoveCode = "G31 z" & fn(zpoint) & " F" & fn(feed)
                Else
                    strMoveCode = "G31 z" & fn(zstart) & " F" & fn(feed)

                End If

            Else

                If cbGoToZ.Checked Then
                    strMoveCode = "G0 z" & fn(zpoint)
                Else
                    strMoveCode = "G0 z" & fn(zstart)

                End If

            End If

            UC.Codesync(strMoveCode)

            While IsMoving()
                Thread.Sleep(5)
            End While
        End If



        thrMyProc = Nothing


    End Sub


    Sub GoToSafeZ()
        strMoveCode = "m216"
        UC.Codesync(strMoveCode)

        'UC.Callbutton(216) ' skips ahead..., don't use...



        While IsMoving()
            Thread.Sleep(5)
        End While
    End Sub





The above code also makes calls to a version of 'is moving' that is also threaded:
Code: Select all
  Private Function IsMoving() As Boolean
        Dim thrIsMoving As New Thread(Sub() CheckIsMoving())
        thrIsMoving.CurrentCulture = Thread.CurrentThread.CurrentCulture
        thrIsMoving.Start()
        While thrIsMoving.IsAlive
            Thread.Sleep(1)
        End While
        Return IsMovingFlag
    End Function



    Private Sub CheckIsMoving()
        IsMovingFlag = UC.IsMoving
    End Sub




Note, I use thrMyProc as the name of the thread for any code that does a moving routine, and you'll notice I check to make sure it is 'nothing' before starting a new thread, and at the end of the routine, I kill thrMyProc and set it to nothing (or if an abort is needed, etc).

Let me know if that helps or any questions.

I'm not sure if codelist has a 'sync' version or not, ive not used the codelist. You may have to iterate over each item in the list and do a 'codesyn' on it instead for a plugin. something similar to:
Code: Select all
        for each str as string in gcodelist
        codesync(str)

        While IsMoving()
            Thread.Sleep(5)
        End While

        next




Good luck!

regards,
Eric

Re: Proper syntax for running g-code in a plugin

PostPosted: Sat Jan 01, 2022 3:04 pm
by ger21
I did see their replies to you with the example code, but was hoping to make it simpler.
I spent a few hours researching before I got the codelist working, and it seems to work fine for situations where I can pre-determine all of the code. But I don't have an actual machine to test. I should have my AXBB-E wired up on my test today for testing, but no motors.

I'll look through the code you posted and decide on which direction to go. I'd like to put everything for the screenset in the plugin, which eliminates 250 macros I used before. But I'll probably just keep using macros for the auto zero, where G31 is involved. Time is a factor here. It sucks spending 3 hours to write 20 lines of code, even though the learning is very beneficial.

Thanks for all your help, and what you give to the community.
Happy New Year!!

Re: Proper syntax for running g-code in a plugin

PostPosted: Sat Jan 01, 2022 6:18 pm
by eabrust
Happy New Year to you as well!

There is no easy answer to what the right direction for you is that I can help with :), all I can confirm from my own learning is there is a lot of time and pain getting that first routine to run right, and after that, its very quick copy/pasting and tweaking for all your routines. Its getting past that first routine that skips code and doesn't run quite right that takes forever... I know the pain!!

The whole threading thing was new to me and was a big learning curve. But once you get it to run right once on one routine, really all you're doing is copy/pasting the code to spool up a thread again and again for every single button event, and just aiming it at a different sub for the 'address of' part of the thread. Then all your routines look identical to what you probably have now, except you'll replace 'code' with 'codesync'. At a high level, all it does is add one more layer of a 'sub' call to your routine, but that added layer which creates the thread is basically identical for every routines except for the sub it will be calling, so you just copy paste again and again and again.

I figured it may be easier if you had all those chunks of code thrown together in a small demo solution file, so take a look at the attached. It may give a better reference to start from and play with.

JogCodeDemo.zip
(179.92 KiB) Downloaded 428 times


regards
Eric

Re: Proper syntax for running g-code in a plugin

PostPosted: Sat Jan 01, 2022 7:08 pm
by ger21
Thanks for that.
Before you posted, I realized I could just past Dezsoe's code into the plugin, and call the sub with the g-code.

I'm studying your code to get a better idea of how you start the new thread, rather then just calling the simple sub with codesync.
I also realized I need to check for certain conditions before running motion routines in the plugin, as they'll still run when in Reset, but nothing actually happens.

Is there an error log anywhere for the plugin? Little things like trying to add an integer or double to a string without converting it first has left me scratching my head for 10 minutes or so a few times.
I'll probably spend a few hours here playing around with your examples to get a better understanding of the threading.

Very much appreciated.

Re: Proper syntax for running g-code in a plugin

PostPosted: Thu Jan 06, 2022 11:23 am
by dezsoe
Hello Gerry and Eric and Happy New Year!

Codesync and Codelist works the same way (Codelist could be named Codelistsycn), so you don't need to extract the lines from the list. If you have more lines of code to run then it's better to run Codelist because the movements will not be separated, the list runs like a piece of g-code file. Also, you should check for stop condition after all Code/Codesync/Codelist calls so the fewer calls result the fewer checks. To optimize code I usually call a subroutine to do the job and in that after all Codexxx calls I check for Ismacrostopped and return false if stop was pressed. At the end when all was finished (no stop was pressed) I return true. This way I can write only one block of code to display a message.

Code: Select all
If Not DoAllMyMovements() Then UC.AddStatusmessage("Stop pressed")

Re: Proper syntax for running g-code in a plugin

PostPosted: Thu Jan 06, 2022 11:59 am
by eabrust
[quote="Codesync and Codelist works the same way (Codelist could be named Codelistsycn)[/quote]

Dezsoe, welcome back and happy new year to you! Hope you had a great holiday.

Thanks for the above clarification on Codelist!

regards
Eric

Re: Proper syntax for running g-code in a plugin

PostPosted: Thu Jan 06, 2022 1:43 pm
by ger21
Thank you for that. I'll try it tonight, and have more questions if I can't figure it out. So far everything is working well.