Hi Ryan,
Updated documentation should be coming in the next three weeks depending on my workload.
That Error can be avoided by adding an Imports line to the top of your file that is the class that has the ambiguous name.
I see you figured out DRO position, that's awesome!
Below is my clsPipeManager that should show you how to do the other tasks you asked about with a bonus, how to start whatever job is loaded (because I assumed that might be your next step after loading the job). Instead of using Job.Load you could also use Job.RunCommand() and send a G65 call with your CNC File. See the manual for more information there.
You can copy the code below into a new class or place it at the bottom of an existing class (after the End Class) or just take the relevant parts out, whatever you want to do.
Code: Select all
'****************************************************************************
'
' Title: clsPipeManager.vb
' Author(s): Jacob Holes
' Start Date: 11-04-24
' Purpose: Class that manages a single pipe connection so we don't exceed the CNC12 pipe limit by reconnecting
' and offers some helpful functions when working with cnc12
'
' Environment/platform ( Windows 10/11, Visual Basic .net)
'
' Last Update: 10-17-24 - JDH - Added RunJob, LoadJob, and IsRunningJob
' Prior Update: 11-06-24 - JDH - Added GetCNC12WorkingDirectory()
' Prior Update: 11-05-24 - JDH - Added header and comments
' Prior Update: 11-04-24 - JDH - Created clsPipeManager, added Pipe and GetCNC12WorkingDirectory()
'****************************************************************************
Imports System.IO
' Import class to avoid ambiguous issue
Imports CentroidAPI.CNCPipe.Plc
Imports CentroidAPI.CNCPipe.Job
Public Class PipeManager
' our pipe holder
Private m_pipe As CNCPipe
''' <summary>
''' Class New() Initilization, creates new pipe for communicating with CNC12
''' </summary>
Sub New()
' when we initilize a new pipe manager, give it a new pipe
m_pipe = New CNCPipe
End Sub
''' <summary>
''' Gets the currently active cnc pipe
''' </summary>
''' <returns>Returns the currently active cnc pipe</returns>
Public Property Pipe As CNCPipe
Get
' return our pipe holder
Return m_pipe
End Get
Set(value As CNCPipe)
' assign the set value to our pipe holder
m_pipe = value
End Set
End Property
''' <summary>
''' This function checks to see if any of oour known processes are running, then extracts the working directory from the process
''' </summary>
''' <returns>The directory our current version of CNC12 (Normal, or Offline) is running from</returns>
Public Function GetCNC12WorkingDirectory() As String
' Define the list of process names to check
Dim processNames As String() = {"cncm", "cnct", "cncr", "cncp", "MillDemo", "LatheDemo"}
Dim allProcesses As Process() = Process.GetProcesses
For Each processName As String In processNames
' Get all processes with the specified name
Dim processes As Process() = Process.GetProcessesByName(processName)
' Loop through each instance of the process
For Each proc As Process In processes
Try
' Attempt to get the executable path and working directory
Dim executablePath As String = proc.MainModule.FileName
Dim workingDirectory As String = Path.GetDirectoryName(executablePath)
Return workingDirectory
Catch ex As Exception
End Try
Next
Next
Return "Unknown"
End Function
''' <summary>
''' Checks the connection status of the CNC12 pipe and tries to recreate it when it fails.
''' </summary>
''' <returns>True if connected to CNC12 Pipe; False otherwise.</returns>
Public Function ConnectedToCNC12() As Boolean
' IMPORTANT: On Error Resume Next tells the compiler to ignore errors, be careful as it may cause unintended side effects.
' A Try Catch would be better here but the debugger breaks on errors inside of the try catch and this bypasses that
' Since param.GetMachineParameterValue(1, paramValue) will cause an 'object reference not set to instance of an object'
' error when called on a dead pipe.
On Error Resume Next
' Check if the pipe exists and is constructed
If m_pipe IsNot Nothing AndAlso m_pipe.IsConstructed Then
Dim paramValue As Double = 0
Dim param As New CentroidAPI.CNCPipe.Parameter(m_pipe)
Dim returnCode As CentroidAPI.CNCPipe.ReturnCode = param.GetMachineParameterValue(1, paramValue)
Select Case returnCode
Case CNCPipe.ReturnCode.SUCCESS
' Successfully connected to CNC12
Return True
Case CNCPipe.ReturnCode.ERROR_PIPE_IS_BROKEN
' Recreate the pipe if it is broken
m_pipe = New CentroidAPI.CNCPipe()
Case CNCPipe.ReturnCode.ERROR_CLIENT_LOCKED
' client locked means we are still connected but the client is locked, don't treat this as a disconnection
Return True
Case Else
' Any other error means disconnection
Return False
End Select
Else
' Pipe is not constructed; try to recreate it
m_pipe = New CentroidAPI.CNCPipe()
End If
' Return false if connection is not established
Return False
End Function
''' <summary>
''' This function checks the PLC to see if a program is running
''' </summary>
''' <returns>Returns true if program is running per pc system variable bit</returns>
Function IsRunningJob() As Boolean
If ConnectedToCNC12() Then
Dim CNCPLC As New CentroidAPI.CNCPipe.Plc(m_pipe)
Dim programRunning As CentroidAPI.CNCPipe.Plc.IOState
CNCPLC.GetPcSystemVariableBit(PcToMpuSysVarBit.SV_PROGRAM_RUNNING, programRunning)
Select Case programRunning
Case IOState.IO_LOGICAL_0
' return false if we aren't running a job
Return False
Case IOState.IO_LOGICAL_1
' return true if we are running a job
Return True
Case IOState.IO_STATE_UNKNOWN
' return true for safety
Return True
End Select
End If
' return false because we're not connected
Return False
End Function
''' <summary>
''' Loads a job into CNC12 but does not start the job.
''' </summary>
''' <param name="jobLocation">The full or relative path of the file</param>
''' <returns>Returns a ReturnCode</returns>
Function LoadJob(ByVal jobLocation As String) As CentroidAPI.CNCPipe.ReturnCode
' check that the file exists and that we are connected to CNC12
If IO.File.Exists(jobLocation) Then
If ConnectedToCNC12() Then
' reference to Job class
Dim cmd As New CentroidAPI.CNCPipe.Job(m_pipe)
' return the return code for Load, check it for SUCCESS
Return cmd.Load(jobLocation, GetCNC12WorkingDirectory)
Else
' warn that we aren't connected to cnc12
MessageBox.Show("Error: Not Connected to CNC12")
' return error code if we want to check against SUCCESS or other code instead of handling error with a messagebox here
Return CNCPipe.ReturnCode.ERROR_SEND_COMMAND
End If
Else
' warn that file not found
MessageBox.Show("Error: Job File Not Found")
' return error code if we want to check against SUCCESS or other code instead of handling error with a messagebox here
Return CNCPipe.ReturnCode.ERROR_SEND_COMMAND
End If
End Function
''' <summary>
''' Uses Skinning Events to emulate cycle start, warning this will start the job if CNC12 is on a screen that allows cycle start.
''' Use with Caution. Operators should have to press cycle start to being machine motion.
''' </summary>
''' <returns>Returns a ReturnCode</returns>
Function RunJob() As CentroidAPI.CNCPipe.ReturnCode
' reference to Plc class
Dim cncPLC As New CentroidAPI.CNCPipe.Plc(m_pipe)
' we are using SetSkinEventState to simulate a button press of cycle start by passing the state of 1 (pressed)
If cncPLC.SetSkinEventState(50, 1) = CNCPipe.ReturnCode.SUCCESS Then
'then we sleep for 50 miliseconds so the PLC has a chance to see the button press
Threading.Thread.Sleep(50)
' then we return the result of setting the state to 0 (unpressed)
Return cncPLC.SetSkinEventState(50, 0)
End If
End Function
End Class
The PipeManger replaces your pipe, CNC12 has a limited number of API pipes available so the PipeManager allows you to keep the same pipe in a class that can be passed to other forms.
Use it like so:
Code: Select all
' create pipe
Dim CNCPipeManager As PipeManager
' create thread for monitoring if cnc12 is running
Dim cnc12_isRunning_thread As Threading.Thread
''' <summary>
''' This sub is called when this form is created, we use it to initialize the cnc pipe
''' </summary>
Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
' initialize pipe so we can communicate with CNC12
CNCPipeManager = New PipeManager()
End Sub
''' <summary>
''' Sends a G1 command using xDistance as X axis distance and FeedRate as desired FeedRate
''' </summary>
''' <param name="xDistance">Distance to move X Axis</param>
''' <param name="FeedRate">Speed at which to move X Axis</param>
''' <returns></returns>
Function SendXMoveCommand(ByVal xDistance As Double, Optional ByVal FeedRate As Double = 50)
' check that pipe is initialized
If CNCPipeManager.ConnectedToCNC12 Then
' reference to Job class
Dim cmd As New CentroidAPI.CNCPipe.Job(CNCPipeManager.Pipe)
' return the result of the command after building the command and sending it to cnc12
Return cmd.RunCommand("G1 X" & xDistance & " F" & FeedRate, CNCPipeManager.GetCNC12WorkingDirectory, False)
End If
' if we failed, send back an unknown error
Return CentroidAPI.CNCPipe.ReturnCode.ERROR_UNKNOWN
End Function
I will push these changes to the GitHub tomorrow.