CNC Example 17: Read G-Code from Strings
See the CNC17_ReadGCodeFromStrings.project sample project in the installation directory of CODESYS under ..\CODESYS SoftMotion\Examples.
The sample project shows how to use SMC_StringStream2 to read G-code from a string.
This example can be seen as a starting point and used to read G-code from other sources, for example via network communication (sockets). In this case, a function block needs to be implemented which implements the SMC_ITextStream interface and reads the text (for example, from a socket). This is similar to how SMC_StringStream2 implements this interface to read the G-code from a string.
Structure of the application
The structure is typical for CNC applications. The G-code is read in the background task (PathTask), and path preprocessing also takes place here. The interpolation is performed in the bus task.
In the Path program, the SMC_ReadNCFromStream function block is used to read the G-code. For technical reasons, not only a stream of type SMC_StringStream2 is passed to this function block, but also an array whose size depends on the parameter SMC_CNC_LibParams.MAX_SUBPROGRAM_NESTING_DEPTH. The first stream in the array is used for the main program, while the other streams are used for possible subprogram calls.
At the beginning, the main program is loaded into the first stream of the array:
// Load G-Code into first stream aStringStream[0].Init(sProgramName) ; aStringStream[0].AppendData(sGCode) ; aStringStream[0].SetEndOfData() ;
Then everything is prepared for reading the usual G-code programs. The example also shows how subprogram calls can be supported.
To do this, it is necessary to create a function block which implements the SMC_INCLookup interface. This function block is responsible for returning the G-code of a subprogram when it is read by SMC_ReadNCFromStream. The Lookup method receives the name of the subprogram and initializes an incoming stream with the G-code:
METHOD LookUp : SMC_ERROR VAR_IN_OUT CONSTANT programName : STRING; END_VAR VAR_INPUT stream : SMC_ITextStream; END_VAR VAR i : UDINT ; pStringStream : POINTER TO SMC_StringStream2 ; END_VAR
This example searches through an array of subprograms. The array is defined in the Path program as VAR_INPUT:
// The table of subprograms.
aSubs : ARRAY[0..0] OF SubProgram := [
(stName := 'SUB1',
stContent := '
SUBPROGRAM SUB1{#p1 : LREAL, #p2 : LREAL, #p3 : LREAL}
N10 G1 X#p1
N20 G1 X#p2
N30 G1 X#p3
END_SUBPROGRAM')
] ;In Lookup, the array is iterated through until a subprogram with a matching name is found:
i := 0 ;
WHILE i < nNumSPs DO
IF psp[i].stName = programName THEN
IF NOT __QUERYPOINTER(stream, pStringStream) OR_ELSE
pStringStream = 0
THEN
// A stream of the wrong type has been passed by SMC_ReadNCFromStream.
LookUp := SMC_CNC_INTERNAL_ERROR ;
ELSE
pStringStream^.Init(sName := psp[i].stName) ;
LookUp := pStringStream^.AppendData(psp[i].stContent) ;
pStringStream^.SetEndOfData() ;
END_IF
RETURN ;
END_IF
i := i + 1 ;
END_WHILE
// No subprogram with name programName has been found in the array psp.
LookUp := SMC_RNCF_SUBPROGRAM_FILE_NOT_FOUND ;Commissioning
Build the application and download it to a controller.
Open the visualization.
Press Start to start the G-code processing.