Logo

Jupiter CNC software for milling machine control

Intro

PLC: Language of electrical automation


1. Introduction

2. PLC program structure

3. PLC objects

1. Timers

2. Inputs

3. Outputs

4. Machine systems

5. Message

4. Declaration of PCL objects

1. Declaration of PLC settings

2. Reading PLC settings

3. Setting PLC settings

4. Declaration of a constant NC variable

5. Reading a constant NC variable

6. Setting a constant NC variable

7. Declaration of an M command of the NC, executed in the PLC

8. Declaration of Reference Point

5. Interaction with CNC

1. Group of exchange objects Machine

2. Group of exchange objects Machine.UP

3. Group of exchange objects Machine.Mode

4. Group of exchange objects Channel

5. Group of exchange objects Channel.CurrentTool

6. Group of exchange objects Channel.Feed

7. Group of exchange objects Channel.Mcode

8. Group of exchange objects Channel.Spindle

9. Group of exchange objects Channel.Probe

10. Group of exchange objects Axis

11. Group of exchange objects Axis.Settings

12. Group of exchange objects Axis.Pos

13. Group of exchange objects Axis.Grab

14. Group of exchange objects Axis.Home

6. Software panels

Panel objects:

1. PlcButton

2. PlcSwitch

3. PlcWell

4. PlcSlider

5. PlcText

Declaration and filling of the panel:

7. Panel declaration

8. Filling the panel with objects

9. Help on panels



1. Introduction


The PLC language of electrical automation (hereinafter simply PLC) of the JupiterCNC® CNC system (hereinafter JupiterCNC) is designed for software binding of machine electrical equipment to the system. The PLC language is code in C#.
It is assumed that the user already has knowledge of programming in C# and understands the basics of PLC programming (state machines).
The PLC program is executed in parallel with the CNC software module.
ATTENTION!
After debugging the PLC program, setting parameters and adjusting the equipment, the person who made these changes is fully responsible for any changes to the program and parameters!


2. PLC program structure


The PLC program consists of six parts, which are combined in one file.

Example of an empty module:


    namespace PLC;

    public partial struct TDM : COM.TDM {

    }

    public class PlcNameModule : PlcModule {
        // Variable initialization for the module here
        //(not visible in other PLC modules)

        // Module registration in PLC
        static PlcModule PlcNameModule = PlcEngine.AddOwnerPlcModule(new PlcNameModule());

        public void Init() {
        }
        public void BuildCommand(ref TDM DT) {
        }
        public void Execution(ref TDM DT) {
        }
        public void OutPut(ref TDM DT) {
        }
    }
    

struct TDM:

    
    public partial Struct TDM : COM.TDM {
    }
    

This is a description of the structure of parameters and statuses - passed to various PLC modules
This structure exists in a single instance.
And it is passed to all modules.
And with its help, modules can exchange commands and statuses

In this structure, you can declare commands for other modules.
Example:

    
    // Command declaration: Command to go to zero on the Z axis
    public bool CM_CoordZ; 

    // Command call
    if (DT.CM_CoordZ == true) {...}
    

Commands are reset at each new PLC cycle

In this structure, you can declare statuses.
Example:

    
    // Status declaration: Zeroing started on the Z axis
    public static bool St_IsWorkG28Z { get; set; } = false;

    // Status call
    if (TDM.St_IsWorkG28Z == true) {...}
    

Statuses retain their value when switching between PLC cycles.

Commands must be strictly primitive types.
It is STRICTLY forbidden to make the command type a class. (as a last resort, a structure)
Classes are allowed for statuses - strictly for "static" variables!

Variable initialization:

    
    // Variable initialization for the module here
    //(not visible in other PLC modules)
    

Here you can create any variables.
These variables will only be visible in this module.
It is also allowed to allocate memory - creating objects using "New"

Example:

    
    static readonly PlcButton BtReset = new(Translate("СБРОС", "RESET"), EnumPlcImage.Reset);
    

Init():

    
    public void Init() {
    }
    

This function is called once when the CNC system starts.
Here you can perform initialization calculations,
work with memory allocation, string initialization, etc.

BuildCommand():

    
    public void BuildCommand(ref TDM DT) {
    }
    

This function is called for each PLC cycle - the very first.
It is assumed that this function will perform calculations of what needs to be done.
Since the same commands can come from different panels (both software and physical),
as well as from other systems - then:
Accordingly, in this procedure, you need to "arm" the necessary command if necessary.
At the same time, you need to take into account that the command could have been "armed" in a neighboring module.
Example of "arming" a command:

    
    DT.CM_ModeM1 |= BtModeM1.Front;
    

An instance of struct TDM - DT is passed to the function input
In this instance, commands are "armed" and various statuses are changed and read
ATTENTION! This function is prohibited from:
- creating objects, strings, Task, etc.,
- no long calculations and cycles
- the calculation needs to be as fast as possible

Execution():

    
    public void Execution(ref TDM DT) {
    }
    

This function is called for each PLC cycle.
The call follows the call to the BuildCommand() function. It is assumed that this function will perform the main calculations.
Ultimately, everything will come down to calculating certain statuses.
In this function, you need to check the commands for permission to execute them according to CNC modes and other parameters.
Example:

    
    TDM.IsJogMode = TPLC.Machine.Mode.Mode == CncMode.MDI && AllDriversOn();
    

An instance of struct TDM - DT is passed to the function input
In this instance, previously calculated commands are read and various statuses are changed
The order of calculation matters.
First, this function is called for regular CNC modules.
And only then is the call to "user" modules - so that they can override the calculations of regular modules
ATTENTION! This function is prohibited from:
- creating objects, strings, Task, etc.,
- no long calculations and cycles
- the calculation needs to be as fast as possible

OutPut():

    
    public void OutPut(ref TDM DT) {
    }
    

This function is called for each PLC cycle.
The call follows the call to the Execution() function. It is assumed that this function will output calculations to actuators.
I.e. writing the results of calculated statuses.
Example:

    
    TDM.IsJogMode = TPLC.Machine.Mode.Mode == CncMode.MDI && AllDriversOn();
    

An instance of struct TDM is passed to the function input – DT
First, this function is called for regular CNC modules.
And only then is the call to "user" modules - so that they can override the calculations of regular modules
ATTENTION! This function is prohibited from:
- creating objects, strings, Task, etc.,
- no long calculations and cycles
- the calculation needs to be as fast as possible


3. PLC objects

3.1 Timers

The Timer object is designed to initiate the execution of any actions after a certain time or after a certain number of PLC cycles
The timer must be declared in the Variable Initialization section
Examples of timer declarations:

    
    // Timer declaration for 4.5 seconds
    public static PlcTimer TimerPowerOn { get; set; } = new(4.5d);
    
    // Timer declaration for 20 PLC cycles
    public static PlcTimer TimerDrivesOn { get; set; } = new(20);
    

Initialization parameters • First parameter double - then the timer will trigger after the specified number of seconds.
• First parameter int - then the timer will trigger after the specified number of PLC cycles.

Timer properties and functions:
• Start() - Starts a stopped timer
• Start(true) - Reset and start the timer
• Front() - returns true once when the timer value is reached • Rear() - Inverted from Front()
• Reset() - Resets the timer count while stopping it
• Stop() - Stops the timer. Can be continued using Start()

Example:

    
    // Start the timer
    TimerPowerOn.Start();
    ...
    // Timer trigger check
    if (TimerPowerOn.Front()) { 
        // Restart the timer.
        TimerPowerOn.Start(true);
    };
    ...
    // Reset the timer
    TimerPowerOn.Reset();
    

3.2 Inputs

Input objects are designed to read values from input ports.
There are three types of inputs:
• InputBit - discrete input
• InputInt - digital input - integer
• InputDouble - digital input - floating point number
Inputs must be declared in the Variable Initialization section
Examples of input declarations:

    
    // Input of the machine emergency stop button
    readonly InputBit EmergencyStop = new(
        "In_Machine_EmergencyStop", 
        Translate("Станок", "Machine"), 
        Translate("Кнопка Аварийной остановки", "Emergency stop button"));
    
    // Wheel input declaration
    readonly InputInt Wheel = new(
        "Out_WHB_Wheel", 
        Translate("Пульт WHB04B", "Remote WHB04B"), 
        Translate("Маховик", "Wheel"));
    

Initialization parameters:
• string Id input, must be unique, this string can be used to access the input from the NC
• string Group - inputs are grouped by this string for ease of configuration when selecting
• string Name - input name - which will be visible in the interface
• bool Required - Mandatory binding of the input to the physical input

Input properties and functions:
all input types: • bool/int/double Value - input value. Does not change during the PLC section.
• bool/int/double OldValue - input value during the previous section.
• bool IsSettings - a sign that the input is bound to the physical input.
If not set, it usually means that this system is not in the machine.
discrete inputs InputBit:
• bool Front - Triggered on the rising edge (from the previous section). Does not change during the PLC section.
• bool Rear - Triggered on the falling edge (from the previous section). Does not change during the PLC section.
• int DelayTime - You can set the dead time in milliseconds after the input is triggered. To eliminate bounce.
digital inputs InputInt/InputDouble:
• int/double Difference - Difference compared to the previous section. Does not change during the PLC section.
Examples:

    
    // Input of the machine emergency stop button
    DT.CM_EmergencyStop |= EmergencyStop.Value;

    // Triggering on the rising edge of the signal
    DT.CM_StanokOn |= StanokOn.Front;    

    // Checking that the handwheel-encoder is connected
    if (Wheel.IsSettings) {
        // Reading the movement of the handwheel
        DT.WellFeed += Wheel.Value;
    }
    

3.3 Outputs

Output objects are designed to write values to output ports.
There are three types of outputs:
• OutputBit - discrete output
• OutputInt - digital output - integer
• OutputDouble - digital output - floating point number
Outputs must be declared in the Variable Initialization section
Examples of output declarations:

    
    // Output to the power supply relay to the machine
    readonly OutputBit StanokOn = new(
        "Out_Machine_StanokOn", 
        Translate("Станок", "Machine"), 
        Translate("Реле Включения станка", "Machine Enable Relay"));
    
    // Output for adjusting the cooling intensity
    readonly OutputInt СoolantLevel = new(
        "Out_Machine_СoolantLevel", 
        Translate("Станок", "Machine"), 
        Translate("Уровень охлаждения", "Сooling Level"));
    

Initialization parameters:
• string Id output, must be unique, this string can be used to access the output from the NC
• string Group - outputs are grouped by this string for ease of configuration when selecting
• string Name - output name - which will be visible in the interface
• bool Required - Mandatory binding of the output to the physical input

Output properties and functions:
• bool/int/double Value - output value. The output will physically change after the section is finished
• bool/int/double OldValue - output value during the previous section.
• bool/int/double Difference - Difference compared to the previous section. Does not change during the PLC section.
• bool IsSettings - a sign that the output is bound to the physical output.
If not set, it usually means that this system is not in the machine.
Examples:


    // Power supply to the machine
    StanokOn.Value = TPLC.Machine.MachineOn && !TDM.IsDemoMode;

    // Checking that the cooling adjustment system is installed in the machine
    if (СoolantLevel.IsSettings) {
        // Adjusting the cooling intensity
        СoolantLevel.Value = TDM.Machine_СoolantLevel;
    }
    

3.4. Machine systems

The LaunchMap object is designed to indicate the status of one of the machine systems
The list of machine systems is displayed on the "Machine"->"System Readiness" tab:

Allows you to quickly assess the status of all machine systems.
As a rule - for further access to the system from other systems, it must be declared in the TDM structure.
Examples of system declarations:


    public partial struct TDM {
        .....
        // Output of information about the pressure control of the pneumatic system
        public static LaunchMap LcPneumoSystem { get; set; } = LaunchMap(
            IndexLaunchMap1++, 
            1,
            Translate("Нет давления в пневмо-системе", "No pressure in the pneumatic system"),
            Translate("Ожидание набора давления в пневмосистеме", "Waiting for pressure to build up in the pneumatic system"),
            Translate("Давление в пневмосистеме в работе", "The pressure in the pneumatic system in operation"));
        .....
    }
    

Initialization parameters:
• int Id system, must be unique, we recommend assigning id like this: "IndexLaunchMap1++"
• int Colum - column number - in which to display the system, 1 or 2
• string ErrorMessage - Text that is displayed when there is an error in the system (can be overridden)
• string WarningMessage - Text that is displayed when there is a warning in the system (can be overridden)
• string InfoMessage - Text that is displayed when the system is working normally (can be overridden)

System properties and functions:
• MessageStatus Status - System status. Enumeration, possible values:
MessageStatus.Error, MessageStatus.Warning, MessageStatus.Info,
• string ErrorMessage - system status text - which overrides the base message text.
• string WarningMessage - system status text - which overrides the base message text.
• string InfoMessage - system status text - which overrides the base message text.
• string BaseErrorMessage - base system status text - read-only.
• string BaseWarningMessage - base system status text - read-only.
• string BaseInfoMessage - base system status text - read-only.
Example of system status output:


    // Problem with the low-voltage power supply of the machine
    TDM.LcLowVoltage.Status = MessageStatus.Error;

    // The spindle has not reached the specified speed
    TDM.LcCurSpindle..Status = MessageStatus.Error;
    TDM.LcCurSpindle.ErrorMessage = TDM.LcCurSpindle.BaseErrorMessage 
        + Translate(": Шпиндель не достиг заданных оборотов", ": The spindle could not accelerate");
    

3.5. Message

The Message() functions allow you to display messages at the top of the program:


And to the CNC system log page:


Example:


    // Output of a message when a reset event is triggered
    TPLC.PLC.Message(
        DT.NumMessage++, 
        DT.CM_Reset, 
        MessageStatus.Info, 
        Translate("Сброс ЧПУ системы", "Resetting the CInNC system"),
        false);
    

Parameters:
• int Id Message Id (to suppress repeated output of the message in each PLC cycle)
Recommendations:
- The function must be called strictly on each pass. Calling the function inside if and the like is not allowed.
- assign id strictly like this: "DT.NumMessage++"
• int Id Message Id (to suppress repeated output of the message in each PLC cycle)
• bool View - Message output flag. The message will be displayed on the rising edge of this variable
• MessageStatus Status - message status. Enumeration, possible values:
MessageStatus.Error, MessageStatus.Warning, MessageStatus.Info, MessageStatus.Message
• string Text - Message text
• bool IsDebug - Flag for outputting the message to the debug log (NC or PLC)

4. Declaration of PCL objects

4.1. Declaration of PLC settings

The DeclarationPlcSetting function is designed to declare a setting:

The user on the settings page in the "PLC Settings" section can change such a setting without changing the PLC code:



DeclarationPlcSetting must be declared in the Init() section.
Example of calling DeclarationPlcSetting:

        
    DeclarationPlcSetting(
        "Probe_Shutdown", 
        60d, 
        "Время, на которое включается щуп (сек)"
    );
    

Function parameters:
• string Id - Setting identifier
• double DefaultValue - Default value for the setting
• string Description - Text description of the setting


4.2. Reading PLC settings

The GetPlcSetting function is designed to read the setting value in the PLC code:
Example of calling GetPlcSetting:

        
    double Value = GetPlcSetting("Probe_Shutdown");
    

Function parameters:
• string Id - Setting identifier


4.3. Setting PLC settings

The SetPlcSetting function is designed to read the setting value in the PLC code:
Example of calling SetPlcSetting:

        
    SetPlcSetting("Probe_Shutdown", 60d);
    

Function parameters:
• string Id - Setting identifier
• double Value - Value for saving the setting


4.4. Declaration of a constant NC variable

The DeclarationNcVariable function is designed to declare a constant NC variable:

This variable can be read and set both in the PLC code and in the control program.
DeclarationNcVariable must be declared in the Init() section.
Example of calling DeclarationNcVariable:

        
    DeclarationNcVariable(
        "#PROBE_FEED", 
        "Скорость подачи при измерении заготовки", 
        "Feed rate when measuring a workpiece", 
        500
    );
    

Function parameters:
• string Name - Setting identifier
• string CommentRu - Setting description in Russian
• string CommentEn - Setting description in English


4.5. Reading a constant NC variable

The GetNcVariable function is designed to read a variable in the PLC code:
Example of calling GetNcVariable:

        
    double Value = GetNcVariable("#PROBE_FEED");
    

Function parameters:
• string Name - Setting identifier


4.6. Setting a constant NC variable

The SetNcVariable function is designed to read the setting value in the PLC code:
Example of calling SetNcVariable:

        
    SetNcVariable("#PROBE_FEED", 500d);
    

Function parameters:
• string Name - Setting identifier
• double Value - Value for saving the setting


4.7. Declaration of an M command of the NC, executed in the PLC

The DeclarationMCommand function is designed to declare an M command of the NC, executed in the PLC:

DeclarationMCommand must be declared in the Init() section.
Example of calling DeclarationMCommand:

        
    DeclarationMCommand("M7", "M9", "MQL-Масляный туман");
    

Function parameters:
• string MCommand - Symbol and command number
• string Group - Symbol and command number that are included in the modal group
• string Description - Command description


4.8. Declaration of Reference Point

The ReferencePoint object is designed to set a list of reference coordinates
After declaration in the PLC, the name of the reference coordinates will be displayed in the CNC:


As a rule - for further access to the coordinates from other systems, it must be declared in the TDM structure.
Example:

    namespace PLC;

    public partial struct TDM : COM.TDM {

    }

    public class PlcNameModule : PlcModule {
        // Variable initialization for the module here
        // (not visible in other PLC modules)

        // Module registration in PLC
        static PlcModule PlcNameModule = PlcEngine.AddOwnerPlcModule(new PlcNameModule());

        public void Init() {
        }
        public void BuildCommand(ref TDM DT) {
        }
        public void Execution(ref TDM DT) {
        }
        public void OutPut(ref TDM DT) {
        }
    }
    

struct TDM:

    
    public partial Struct TDM : COM.TDM {
    }
    

This is a description of the parameter and status structure - passed to various PLC modules
This structure exists in a single instance.
And is passed to all modules.
And with its help, modules can exchange commands and statuses

In this structure, you can declare commands for other modules.
Example:

    
    // Command declaration: Command to go to zero on the Z axis
    public bool CM_CoordZ; 

    // Command call
    if (DT.CM_CoordZ == true) {...}
    

Commands are reset at each new PLC cycle

In this structure, you can declare statuses.
Example:

    
    // Status declaration: Started going to zero on the Z axis
    public static bool St_IsWorkG28Z { get; set; } = false;

    // Status call
    if (TDM.St_IsWorkG28Z == true) {...}
    

Statuses retain their value when transitioning between PLC cycles.

Commands must be strictly primitive types.
It is STRICTLY forbidden to make the command type a class. (as a last resort, a structure)
Classes are allowed for statuses - strictly for "static" variables!

Variable initialization:

    
    // Variable initialization for the module here
    // (not visible in other PLC modules)
    

You can create any variables here.
These variables will only be visible in this module.
Memory allocation is also allowed - creating objects using "New"

Example:

    
    static readonly PlcButton BtReset = new(Translate("СБРОС", "RESET"), EnumPlcImage.Reset);
    

Init():

    
    public void Init() {
    }
    

This function is called once when the CNC system starts.
Here you can perform initialization calculations,
work with memory allocation, string initialization, etc.

BuildCommand():

    
    public void BuildCommand(ref TDM DT) {
    }
    

This function is called for each PLC cycle - the very first one.
It is assumed that this function will perform calculations of what needs to be done.
Since the same commands can come from different consoles (both software and physical),
as well as from other systems - then:
Accordingly, in this procedure, you need to "arm" the necessary command if necessary.
At the same time, it must be taken into account that the command could have been "armed" in a neighboring module.
Example of "arming" a command:

    
    DT.CM_ModeM1 |= BtModeM1.Front;
    

An instance of struct TDM - DT is passed as input to the function
In this instance, commands are "armed" and various statuses are changed and read
ATTENTION! This function is prohibited from:
- creating objects, strings, Task, etc.,
- no long calculations and cycles
- needs the fastest possible calculation

Execution():

    
    public void Execution(ref TDM DT) {
    }
    

This function is called for each PLC cycle.
The call follows the call to the BuildCommand() function. It is assumed that this function will perform the main calculations.
Ultimately, everything will come down to calculating certain statuses.
In this function, you need to check the commands for permission to execute them according to CNC modes and other parameters.
Example:

    
    TDM.IsJogMode = TPLC.Machine.Mode.Mode == CncMode.MDI && AllDriversOn();
    

An instance of struct TDM - DT is passed as input to the function
In this instance, previously calculated commands are read and various statuses are changed
The order of calculation matters.
First, this function is called for regular CNC modules.
And only then is the call to "user" modules - so that they can override the calculations of regular modules
ATTENTION! This function is prohibited from:
- creating objects, strings, Task, etc.,
- no long calculations and cycles
- needs the fastest possible calculation

OutPut():

    
    public void OutPut(ref TDM DT) {
    }
    

This function is called for each PLC cycle.
The call follows the call to the Execution() function. It is assumed that this function will output calculations to actuators.
I.e. writing the results of calculated statuses.
Example:

    
    TDM.IsJogMode = TPLC.Machine.Mode.Mode == CncMode.MDI && AllDriversOn();
    

An instance of struct TDM – DT is passed as input to the function
First, this function is called for regular CNC modules.
And only then is the call to "user" modules - so that they can override the calculations of regular modules
ATTENTION! This function is prohibited from:
- creating objects, strings, Task, etc.,
- no long calculations and cycles
- needs the fastest possible calculation


3. PLC Objects

3.1 Timers

The Timer object is designed to initiate the execution of any actions after a certain time or after a certain number of PLC cycles
The timer must be declared in the Variable Initialization section
Examples of timer declarations:

    
    // Declaration of a timer for 4.5 seconds
    public static PlcTimer TimerPowerOn { get; set; } = new(4.5d);
    
    // Declaration of a timer for 20 PLC cycles
    public static PlcTimer TimerDrivesOn { get; set; } = new(20);
    

Initialization parameters • First parameter double - then the timer will trigger after the specified number of seconds.
• First parameter int - then the timer will trigger after the specified number of PLC cycles.

Timer properties and functions:
• Start() - Start a stopped timer
• Start(true) - Reset and start the timer
• Front() - returns true once when the timer value is reached • Rear() - Invertible from Front()
• Reset() - Reset the timer count while stopping it
• Stop() - Stops the timer. Can be continued using Start()

Example:

    
    // Start the timer
    TimerPowerOn.Start();
    ...
    // Checking the timer trigger
    if (TimerPowerOn.Front()) { 
        // Restart the timer.
        TimerPowerOn.Start(true);
    };
    ...
    // Reset the timer
    TimerPowerOn.Reset();
    

3.2 Inputs

Input objects are designed to read values from input ports.
There are three types of inputs:
• InputBit - discrete input
• InputInt - digital input - integer
• InputDouble - digital input - floating point number
Inputs must be declared in the Variable Initialization section
Examples of input declarations:

    
    // Input of the machine emergency stop button
    readonly InputBit EmergencyStop = new(
        "In_Machine_EmergencyStop", 
        Translate("Станок", "Machine"), 
        Translate("Кнопка Аварийной остановки", "Emergency stop button"));
    
    // Wheel input declaration
    readonly InputInt Wheel = new(
        "Out_WHB_Wheel", 
        Translate("Пульт WHB04B", "Remote WHB04B"), 
        Translate("Маховик", "Wheel"));
    

Initialization parameters:
• string Id input, must be unique, this string can be used to access the input from the NC program
• string Group - inputs are grouped by this string for ease of configuration when selecting
• string Name - input name - which will be visible in the interface
• bool Required - Mandatory binding of the input to a physical input

Input properties and functions:
all input types: • bool/int/double Value - input value. Does not change during the PLC section.
• bool/int/double OldValue - input value during the previous section.
• bool IsSettings - a sign that the input is bound to a physical input.
If not set, it usually means that this system is not in the machine.
discrete inputs InputBit:
• bool Front - Triggered on the rising edge (from the previous section). Does not change during the PLC section.
• bool Rear - Triggered on the falling edge (from the previous section). Does not change during the PLC section.
• int DelayTime - You can set the dead time in milliseconds after the input is triggered. To eliminate bounce.
digital inputs InputInt/InputDouble:
• int/double Difference - Difference compared to the previous section. Does not change during the PLC section.
Examples:

    
    // Input of the machine emergency stop button
    DT.CM_EmergencyStop |= EmergencyStop.Value;

    // Triggering on the rising edge of the signal
    DT.CM_StanokOn |= StanokOn.Front;    

    // Checking that the handwheel-encoder is connected
    if (Wheel.IsSettings) {
        // Reading the handwheel movement
        DT.WellFeed += Wheel.Value;
    }
    

3.3 Outputs

Output objects are designed to write values to output ports.
There are three types of outputs:
• OutputBit - discrete output
• OutputInt - digital output - integer
• OutputDouble - digital output - floating point number
Outputs must be declared in the Variable Initialization section
Examples of output declarations:

    
    // Output to the power supply relay to the machine
    readonly OutputBit StanokOn = new(
        "Out_Machine_StanokOn", 
        Translate("Станок", "Machine"), 
        Translate("Реле Включения станка", "Machine Enable Relay"));
    
    // Output for adjusting the cooling intensity
    readonly OutputInt СoolantLevel = new(
        "Out_Machine_СoolantLevel", 
        Translate("Станок", "Machine"), 
        Translate("Уровень охлаждения", "Сooling Level"));
    

Initialization parameters:
• string Id output, must be unique, this string can be used to access the output from the NC program
• string Group - outputs are grouped by this string for ease of configuration when selecting
• string Name - output name - which will be visible in the interface
• bool Required - Mandatory binding of the output to a physical input

Output properties and functions:
• bool/int/double Value - output value. The output will physically change after the section is finished
• bool/int/double OldValue - output value during the previous section.
• bool/int/double Difference - Difference compared to the previous section. Does not change during the PLC section.
• bool IsSettings - a sign that the output is bound to a physical output.
If not set, it usually means that this system is not in the machine.
Examples:


    // Power supply to the machine
    StanokOn.Value = TPLC.Machine.MachineOn && !TDM.IsDemoMode;

    // Checking that the cooling adjustment system is installed in the machine
    if (СoolantLevel.IsSettings) {
        // Adjusting the cooling intensity
        СoolantLevel.Value = TDM.Machine_СoolantLevel;
    }
    

3.4. Machine Systems

The LaunchMap object is designed to indicate the status of one of the machine systems
The list of machine systems is displayed on the "Machine"->"System Readiness" tab:

Allows you to quickly assess the status of all machine systems.
As a rule, for further access to the system from other systems, it must be declared in the TDM structure.
Examples of system declarations:


    public partial struct TDM {
        .....
        // Output of information about the pressure control of the pneumatic system
        public static LaunchMap LcPneumoSystem { get; set; } = LaunchMap(
            IndexLaunchMap1++, 
            1,
            Translate("Нет давления в пневмо-системе", "No pressure in the pneumatic system"),
            Translate("Ожидание набора давления в пневмосистеме", "Waiting for pressure to build up in the pneumatic system"),
            Translate("Давление в пневмосистеме в работе", "The pressure in the pneumatic system in operation"));
        .....
    }
    

Initialization parameters:
• int Id system, must be unique, we recommend assigning id like this: "IndexLaunchMap1++"
• int Colum - column number - in which to display the system, 1 or 2
• string ErrorMessage - Text that is displayed when there is an error in the system (can be overridden)
• string WarningMessage - Text that is displayed when there is a warning in the system (can be overridden)
• string InfoMessage - Text that is displayed when the system is working normally (can be overridden)

System properties and functions:
• MessageStatus Status - System status. Enumeration, possible values:
MessageStatus.Error, MessageStatus.Warning, MessageStatus.Info,
• string ErrorMessage - system status text - which overrides the base message text.
• string WarningMessage - system status text - which overrides the base message text.
• string InfoMessage - system status text - which overrides the base message text.
• string BaseErrorMessage - base system status text - read-only.
• string BaseWarningMessage - base system status text - read-only.
• string BaseInfoMessage - base system status text - read-only.
Example of system status output:


    // Problem with the low-voltage power supply of the machine
    TDM.LcLowVoltage.Status = MessageStatus.Error;

    // The spindle has not reached the specified speed
    TDM.LcCurSpindle..Status = MessageStatus.Error;
    TDM.LcCurSpindle.ErrorMessage = TDM.LcCurSpindle.BaseErrorMessage 
        + Translate(": Шпиндель не достиг заданных оборотов", ": The spindle could not accelerate");
    

3.5. Message

The Message() functions allow you to display messages in the upper part of the program:


And on the CNC system log page:


Example:


    // Output of a message when a reset event occurs
    TPLC.PLC.Message(
        DT.NumMessage++, 
        DT.CM_Reset, 
        MessageStatus.Info, 
        Translate("Сброс ЧПУ системы", "Resetting the CInNC system"),
        false);
    

Parameters:
• int Id Message Id (to suppress multiple message output in each PLC cycle)
Recommendations:
- The function must be called strictly on each pass. Calling the function inside if and the like is not allowed.
- id should be assigned strictly like this: "DT.NumMessage++"
• int Id Message Id (to suppress multiple message output in each PLC cycle)
• bool View - Message output flag. The message will be displayed on the rising edge of this variable
• MessageStatus Status - message status. Enumeration, possible values:
MessageStatus.Error, MessageStatus.Warning, MessageStatus.Info, MessageStatus.Message
• string Text - Message text
• bool IsDebug - Flag for outputting a message to the debug log (NC program or PLC)

4. Declaration of PCL Objects

4.1. Declaration of PLC Settings

The DeclarationPlcSetting function is designed to declare a setting:

The user on the settings page in the "PLC Settings" section can change such a setting without changing the PLC code:



DeclarationPlcSetting must be declared in the Init() section.
Example of calling DeclarationPlcSetting:

        
    DeclarationPlcSetting(
        "Probe_Shutdown", 
        60d, 
        "Time for which the probe is turned on (sec)"
    );
    

Function parameters:
• string Id - Setting identifier
• double DefaultValue - Default value for the setting
• string Description - Text description of the setting


4.2. Reading PLC Settings

The GetPlcSetting function is designed to read the setting value in the PLC code:
Example of calling GetPlcSetting:

        
    double Value = GetPlcSetting("Probe_Shutdown");
    

Function parameters:
• string Id - Setting identifier


4.3. Setting PLC Settings

The SetPlcSetting function is designed to read the setting value in the PLC code:
Example of calling SetPlcSetting:

        
    SetPlcSetting("Probe_Shutdown", 60d);
    

Function parameters:
• string Id - Setting identifier
• double Value - Value for saving the setting


4.4. Declaration of a Constant NC Program Variable

The DeclarationNcVariable function is designed to declare a constant NC program variable:

This variable can be read and set both in the PLC code and in the control program.
DeclarationNcVariable must be declared in the Init() section.
Example of calling DeclarationNcVariable:

        
    DeclarationNcVariable(
        "#PROBE_FEED", 
        "Скорость подачи при измерении заготовки", 
        "Feed rate when measuring a workpiece", 
        500
    );
    

Function parameters:
• string Name - Setting identifier
• string CommentRu - Setting description in Russian
• string CommentEn - Setting description in English


4.5. Reading a Constant NC Program Variable

The GetNcVariable function is designed to read a variable in the PLC code:
Example of calling GetNcVariable:

        
    double Value = GetNcVariable("#PROBE_FEED");
    

Function parameters:
• string Name - Setting identifier


4.6. Setting a Constant NC Program Variable

The SetNcVariable function is designed to read the setting value in the PLC code:
Example of calling SetNcVariable:

        
    SetNcVariable("#PROBE_FEED", 500d);
    

Function parameters:
• string Name - Setting identifier
• double Value - Value for saving the setting


4.7. Declaration of an NC Program M Command Executed in the PLC

The DeclarationMCommand function is designed to declare an NC program M command executed in the PLC:

DeclarationMCommand must be declared in the Init() section.
Example of calling DeclarationMCommand:

        
    DeclarationMCommand("M7", "M9", "MQL-Oil mist");
    

Function parameters:
• string MCommand - Command symbol and number
• string Group - Command symbol and number that are in the modal group
• string Description - Command description


4.8. Declaration of Reference Point

The ReferencePoint object is designed to set a list of reference coordinates
After declaration in the PLC, the name of the reference coordinates will be displayed in the CNC:


As a rule, for further access to the coordinates from other systems, it must be declared in the TDM structure.
Example:


    public partial struct TDM {
        .....
        // Reference coordinates for tool change
        public static ReferencePoint G53_4 { get; set; } = new(
            RefPoint.G53_3, 
            "MachinePlusLimitChannal", 
            "Positive axis limit"
        );
        .....
    }
    

Initialization parameters:
• COM.RefPoint RefPoint - G53 number for NC program. Enumeration, possible values:
COM.RefPoint.G28/G53_1/G53_2/G53_3/G30_1..G30_9
• string Id - Id (must be unique)
• string Name - Text that is displayed in the system


5. Interaction with CNC

The interaction of the PCL program with the CNC system occurs through various exchange objects. When the exchange object is changed in the CNC - its transfer to the PLC will occur only at the beginning of the PLC cycle. When the object is changed in the PLC, its transfer to the CNC will occur only after the PLC cycle is completed.

Conditional abbreviations:
• R - read-only object
• W - write-only object
• RW - read and write object

Example of accessing an exchange object:


    TPLC.Machine.MachineOn = false;
    

5.1. Machine Exchange Object Group

Group name: TPLC.Machine
This group contains exchange cells for machine control

TPLC.Machine.MachineOn RW, type bool
- Power supply on flag

TPLC.Machine.DriversOn RW, type bool
- Servo drive on flag

TPLC.Machine.ChannelCount R, type byte
- Number of current channels

TPLC.Machine.NumChannel RW, type NumChannel
- Current channel.
- Enumeration: NumChannel.Channel_1/Channel_2

TPLC.Machine.CncCommand R, type CncCommand
- Command from the CNC system.
- Enumeration: CncCommand.Reset

TPLC.Machine.ButtonInterception R, type bool
- Button interception flag from CNC

TPLC.Machine.ButtonPress RW, type Buttons
- Intercepted button,
- Enumeration: Buttons.UpRun/UpStop

TPLC.Machine.Reset RW, type bool
- CNC reset

TPLC.Machine.AllDisableVoltage R, type bool
- A sign that the power of the output stages is turned off on all servo drivers

5.2. Machine.UP Exchange Object Group

Group name: TPLC.Machine.UP
This group contains exchange cells for NC program control

TPLC.Machine.UP.UpRun R, type bool
- NC program execution flag on CNC

TPLC.Machine.UP.UpStop R, type bool
- NC program pause flag.
- While this cell is set, the NC program will be in a paused state.

TPLC.Machine.UP.UpRunRequest W, type bool
- Request to start the NC program.
- Set for one cycle, automatically reset when the NC program starts.

TPLC.Machine.UP.UpStopRequest W, type bool
- Request to pause the NC program.
- Set for one cycle, automatically reset when the NC program starts.

TPLC.Machine.UP.UpAbortRequest W, type bool
- Request to interrupt the NC program.
- Set for one cycle, automatically reset when the NC program starts.

TPLC.Machine.UP.UpReloadRequest W, type bool
- Re-selection of the NC program by M-command.

TPLC.Machine.UP.UpChosen R, type bool
- The NC program is selected and can be executed in automatic mode.

TPLC.Machine.UP.UpCondStop R, type bool
- Conditional stop by M1 is enabled.

TPLC.Machine.UP.PosUpLine R, type Dictionary‹NumChannel, int›
- Current NC program line in each of the channels
- Enumeration: NumChannel.Channel_1/Channel_2
- Value int - number of the executed NC program line

5.3. Machine.Mode Exchange Object Group

Group name: TPLC.Machine.Mode
This group contains exchange cells for monitoring CNC modes

TPLC.Machine.Mode.Mode R, type CncMode
- Current CNC mode
- Enumeration CncMode.MDI/Zero/Auto/Training

TPLC.Machine.Mode.ModeRequest W, type CncMode
- Request to change the CNC mode.
- Enumeration CncMode.MDI/Zero/Auto/Training

TPLC.Machine.Mode.SingleFrameMode R, type bool
- Single-frame NC program mode.

TPLC.Machine.Mode.SingleFrameModeRequest W, type bool
- Request for Single-frame NC program mode.

TPLC.Machine.Mode.M1Mode R, type bool
- Stop mode by M1.

TPLC.Machine.Mode.M1ModeRequest W, type bool
- Request for stop mode by M1.

TPLC.Machine.Mode.TcpMode R, type bool
- TCP mode of the NC program.

TPLC.Machine.Mode.TcpModeRequest W, type bool
- Request to enable/disable TCP mode.

TPLC.Machine.Mode.DemoMode R, type bool
- CNC demo mode.

TPLC.Machine.Mode.DemoModeRequest W, type bool
- Request to enable/disable demo mode.

5.4. Channel Exchange Object Group

There can be 1 or 2 working channels in the CNC system.

Getting a list of channels:
TPLC.Channels R, Dictionary type‹NumChannel, PLC.PLC_Channel›
- Enumeration: NumChannel.Channel_1/Channel_2
- PLC_Channel - object - in which the channel exchange cells are defined

TPLC.CurChannel R, PLC.PLC_Channel type
- PLC_Channel - object - in which the channel exchange cells are defined

TPLC.Channels[NumChannel.Channel_X].M789Request R, int type
- Request/Notification of enabling M7 M8 M9.

TPLC.Channels[NumChannel.Channel_X].GroupGM R, Dictionary type‹EnumGroupGM, int›
- Active modal commands in groups.
Enumeration: EnumGroupGM.G_0_3/G_17_19/G_40_42/G_43_49/G_52/G_92/G_61_64/G_68/G_69/G_80_85/G_90_91/G_901_911/G_93_95/G_98_99/M_0_1/M_3_5/M_7_9/M_8_9 In the dictionary value for EnumGroupGM - the number of the active command in the group

TPLC.Channels[NumChannel.Channel_X].ContentExpression(string Expression) function, returns double type
- Request to calculate the expression of the control program in the channel.
- Expression - string - which describes the expression for calculation
UP variables can participate in calculations

Example of accessing channel exchange cells:


        // Setting the feed rate in the first channel (The first channel is always there)
        TPLC.Channels[NumChannel.Channel_1].Feed.CorrectorG1 = 1000;

        // Setting the feed rate in the second channel (The second channel may be missing)
        if (TPLC.Channels.ContainsKey(NumChannel.Channel_2)) {
            TPLC.Channels[NumChannel.Channel_2].Feed.CorrectorG1 = 1000;
        } 

        // Setting the feed rate in the current channel (which is selected for control)
        TPLC.CurChannel.Feed.CorrectorG1 = 250;

        // Checking the current modal command in the group
        if (TPLC.Channels[NumChannel.Channel_1].GroupGM[EnumGroupGM.G_0_3] == 1) { .... };

        // Getting the measurement result along the Z axis
        double PosZ = TPLC.Channels[NumChannel.Channel_1].CalсContentExpression("#PROBE_Z");
    

5.5. Channel.CurrentTool Exchange Object Group

Group name: TPLC.Channels[NumChannel.Channel_X].CurrentTool
This group contains the exchange cells for tool control in the desired channel

TPLC.Channels[NumChannel.Channel_X].CurrentTool.Number R, int type
- Tool number

TPLC.Channels[NumChannel.Channel_X].CurrentTool.Id R, int type
- Unique tool identifier

TPLC.Channels[NumChannel.Channel_X].CurrentTool.BindingToolId R, int type
- Tool binding number

TPLC.Channels[NumChannel.Channel_X].CurrentTool.Slot R, int type
- Slot number in the magazine

TPLC.Channels[NumChannel.Channel_X].CurrentTool.Corrector R, int type
- Tool corrector number

TPLC.Channels[NumChannel.Channel_X].CurrentTool.RequestToolChangeForm W, bool type
- Request to open an interactive tool change form

5.6. Channel.Feed Exchange Object Group

Group name: TPLC.Channels[NumChannel.Channel_X].Feed
This group contains the exchange cells for feed control in the desired channel

TPLC.Channels[NumChannel.Channel_X].Feed.Value R, int type
- Calculated feed rate

TPLC.Channels[NumChannel.Channel_X].Feed.ValueReal R, int type
- Actual feed rate

TPLC.Channels[NumChannel.Channel_X].Feed.CorrectorG1 RW, double type
- 100% feed corrector for G1/2/3/4

TPLC.Channels[NumChannel.Channel_X].Feed.CorrectorG0 RW, double type
- 100% feed corrector for G0

5.7. Channel.Mcode Exchange Object Group

Group name: TPLC.Channels[NumChannel.Channel_X].Mcode
This group contains the exchange cells for controlling the execution of M commands in the desired channel

TPLC.Channels[NumChannel.Channel_X].Mcode.Code R, float? type
- The specified M-code is executed if not - then null
- For M5, 5.0 will be transmitted, for M5.23, 5.23 will be transmitted,

TPLC.Channels[NumChannel.Channel_X].Mcode.Done W, bool type
- Termination of the M command. The PLC notifies the CNC that the specified M command has been completed.

TPLC.Channels[NumChannel.Channel_X].Mcode.ParallelCode R, float? type
- The parallel (without stopping the UP) specified M-code is executed if not - then null
- For M5, 5.0 will be transmitted, for M5.23, 5.23 will be transmitted,

TPLC.Channels[NumChannel.Channel_X].Mcode.ParallelDone W, bool type
- Termination of the parallel M command. The PLC notifies the CNC that the specified parallel M command has been completed.

5.8. Channel.Spindle Exchange Object Group

Group name: TPLC.Channels[NumChannel.Channel_X].Spindle
This group contains the exchange cells for spindle control in the desired channel

TPLC.Channels[NumChannel.Channel_X].Spindle.Axis R, EnumAxis type
- Spindle axis identifier
- Enumeration: EnumAxis.NAN/X/Y/Z/A/B/C/U/V/W/Q/E/Ĉ

TPLC.Channels[NumChannel.Channel_X].Spindle.State R, EnumDriverState type
- Spindle servo driver status:
- Enumeration: EnumDriverState.NotReadyToOn/ErrorForToOn/ReadyToOn/Enabled/Run/QuickStop/EmergencyStop

TPLC.Channels[NumChannel.Channel_X].Spindle.SpindleStateRequest W, type
- Request to change the status of the spindle servo driver:
- Enumeration: EnumDriverState.NotReadyToOn/ErrorForToOn/ReadyToOn/Enabled/Run/QuickStop/EmergencyStop

TPLC.Channels[NumChannel.Channel_X].Spindle.SpindleSpeedCorrector RW, double type
- Spindle speed corrector 100%

TPLC.Channels[NumChannel.Channel_X].Spindle.SpindleSpeed R, int type
- Spindle speed

TPLC.Channels[NumChannel.Channel_X].Spindle.SpindAxisMode R, bool type
- Current spindle in axis mode.

5.9. Channel.Probe Exchange Object Group

Group name: TPLC.Channels[NumChannel.Channel_X].Probe
This group contains the exchange cells for controlling the execution of probe commands in the desired channel

TPLC.Channels[NumChannel.Channel_X].Probe.Skip R, bool type
- Interrupt execution by the G31 sensor and go to the next frame.

TPLC.Channels[NumChannel.Channel_X].Probe.Move R, bool type
- G31 command is being executed.

5.10. Axis Exchange Object Group

There can be from 3 to 12 axes in the CNC system.

Getting a list of axes:
TPLC.Axles R, Dictionary type‹EnumAxis, PLC.PLC_Axis›
- Enumeration: EnumAxis.NAN/X/Y/Z/A/B/C/U/V/W/Q/E/Ĉ
- PLC_Axis - object - in which the axis exchange cells are defined

Example of accessing axis exchange cells:


        // Getting the axis position
        TPLC.Axles[EnumAxis.X];
        if (Axles.ContainsKey(EnumAxis.X)) {
            var PosAbs = Axles[EnumAxis.X].Pos.Abs;
        };
    

5.11. Axis.Settings Exchange Object Group

Group name: TPLC.Axles[EnumAxis.X].Settings
This group contains the exchange cells for the settings of the selected axis

TPLC.Axles[EnumAxis.X].Settings.PurposeAxis R, EnumPurposeAxis type
- Axis Purpose
- Enumeration EnumPurposeAxis.Linear_X/Linear_Y/Linear_Z/Rotation_A/Rotation_B/Rotation_C/Spindle/RotSpindle_C/Slave_X/Slave_Y/Slave_Z/NotInterpolated

TPLC.Axles[EnumAxis.X].Settings.IsAxisPurpose R, EnumPurposeAxis type
- Returns one of the values EnumPurposeAxis.Linear_X/Linear_Y/Linear_Z/Rotation_A/Rotation_B/Rotation_C/NotInterpolated

TPLC.Axles[EnumAxis.X].Settings.IsAxis R, bool type
- Returns true - if the axis is an interpolatable axis

TPLC.Axles[EnumAxis.X].Settings.IsSpindle R, bool type
- Returns true - if the axis is a tool spindle

TPLC.Axles[EnumAxis.X].Settings.IsLinear R, bool type
- Returns true - if the axis is linear

TPLC.Axles[EnumAxis.X].Settings.IsRotation R, bool type
- Returns true - if the axis is a rotation axis

TPLC.Axles[EnumAxis.X].Settings.IsXYZ R, bool type
- Returns true - if the axis is either X or Y or Z

TPLC.Axles[EnumAxis.X].Settings.Channel R, NumChannel type
- Axis belonging to the channel
- Enumeration: NumChannel.Channel_1/Channel_2

TPLC.Axles[EnumAxis.X].Settings.FeedRateSec R, double type
- Maximum feed rate for G1 mm*sec

TPLC.Axles[EnumAxis.X].Settings.FeedRateSecG0 R, double type
- Maximum feed rate for G0 mm*sec

TPLC.Axles[EnumAxis.X].Settings.FeedHouming R, double type
- Maximum feed rate when going to zero mm*min

TPLC.Axles[EnumAxis.X].Settings.AccelerationG1 R, double type
- Maximum acceleration for G1 mm*sec*sec/s

TPLC.Axles[EnumAxis.X].Settings.AccelerationG0 R, double type
- Maximum acceleration for G0 mm*sec*sec/s

TPLC.Axles[EnumAxis.X].Settings.TypeHouming R, EnumTypeHouming type
- Type of zero return for the axis
- Enumeration: EnumTypeHouming.Forbidden/NotRequired/Required

5.12. Axis.Pos Exchange Object Group

Group name: TPLC.Axles[EnumAxis.X].Pos
This group contains the exchange cells for the position of the selected axis

TPLC.Axles[EnumAxis.X].Pos.Abs R, double type
- Current absolute (Machine) axis position

TPLC.Axles[EnumAxis.X].Pos.Work R, double type
- Current working axis position.

TPLC.Axles[EnumAxis.X].Pos.Delta R, double type
- Current axis deviation (Mismatch) from feedback

TPLC.Axles[EnumAxis.X].Pos.Feed R, double type
- Current axis speed

TPLC.Axles[EnumAxis.X].Pos.Load R, double type
- Current axis load in %

TPLC.Axles[EnumAxis.X].Pos.Accel R, double type
- Current Axis Acceleration

5.13. Axis.Grab Exchange Object Group

Group name: TPLC.Axles[EnumAxis.X].Grab
This group contains the exchange cells for intercepting control of the selected axis

TPLC.Axles[EnumAxis.X].Grab.On R, bool type
- Axis control mode from PLC is enabled.

TPLC.Axles[EnumAxis.X].Grab.TargetPos W, double type
- Command to move to the position specified by the object

TPLC.Axles[EnumAxis.X].Grab.Ok R, bool type
- The coordinate in the mode from the PLC has been reached - the command has been completed.

TPLC.Axles[EnumAxis.X].Grab.Reset W, bool type
- Reset the last move command.

TPLC.Axles[EnumAxis.X].Grab.Feed RW, int type
- Axis positioning speed in intercept mode

5.14. Axis.Home Exchange Object Group

Group name: TPLC.Axles[EnumAxis.X].Home
This group contains the exchange cells for controlling the zero return of the selected axis

TPLC.Axles[EnumAxis.X].Home.HoumingOk R, bool type
- Zero return completed.

TPLC.Axles[EnumAxis.X].Home.HomeRequest W, bool type
- Request for zero return on the axis.

TPLC.Axles[EnumAxis.X].Home.IsHome R, bool type
- Zero return is in progress on the axis.

TPLC.Axles[EnumAxis.X].Home.HomeAbort W, bool type
- Cancel the zero return command.

6. Software panels

In the PLC code, it is possible to program several panels that will be displayed on the CNC screen.
The output of the panels on the screen will be on the "Panel" tab (Well, that's a surprise)
Example of a software panel:


A list of programmed panels and their selection - on the right panel of the page
A total of 8 panels can be added.
1, 2 and 8 - are programmed in the standard delivery.
3 - reserved for developers.
4,5,6,7 - available to users for programming

Objects that are used for programming panels:

6.1. PlcButton

The PlcButton object is designed to describe a panel button.
PlcButton must be declared in the variable initialization section.
Example of declaring a panel button:

        
    // Declaring a button with a predefined picture
    static readonly PlcButton BtReset = new(
        Translate("СБРОС", "RESET"), 
        EnumPlcImage.Reset,
        false);

    // Declaring a button with a custom picture
    static readonly PlcButton BtReset = new(
        Translate("СБРОС", "RESET"),
        PlcEngine.CreateSvgImage(
            """
            ‹svg›‹defs›‹style›.cls-1 {fill: #4d4d4d;}.cls-1, .cls-2 {stroke: #000;stroke-linecap: round;stroke-linejoin: round;stroke-width: 3.57px;}.cls-2 {fill: #db956f;}‹/style›‹/defs›
              ‹path class="cls-1" d="M424.06,191.41v245.36c0,11.04-8.97,19.98-20.04,19.98h-78.78c-11.07,0-20.04-8.95-20.04-19.98v-81.42c0-11.04-8.97-19.98-20.04-19.98h-48.21c-11.07,0-20.04,8.95-20.04,19.98v81.42c0,11.04-8.97,19.98-20.04,19.98H112.1c-11.07,0-20.04-8.95-20.04-19.98V191.41l166-105.38,166,105.38Z"/›
              ‹path class="cls-2" d="M48.15,249.51c-10.22,0-20.23-5.05-26.11-14.3-9.13-14.36-4.85-33.38,9.55-42.49L241.52,60.03c10.17-6.42,23.19-6.37,33.3,.15l205.83,132.7c14.32,9.24,18.42,28.29,9.17,42.57-9.26,14.26-28.36,18.36-42.69,9.14l-189.22-122L64.65,244.73c-5.13,3.24-10.85,4.78-16.5,4.78Z"/›
              ‹path class="cls-1" d="M92.02,154.53V71.41c0-6.09,4.95-11.03,11.06-11.03h38.94c6.11,0,11.06,4.94,11.06,11.03v44.52l-61.06,38.6Z"/›
            ‹/svg›
            """),
        false);
    

Initialization parameters:
• string Name - Displayed button name
• or: EnumPlcImage Image - Built-in image identifier. Enumeration, possible values are listed in the appendix
• or: SvgImage? Image - svg format image obtained through the function PlcEngine.CreateSvgImage(string SvGString)
• bool DifferentChanel - A sign that the button may have a different action depending on the channel (controls the system for each channel separately)
Example - the channel number appears in a circle on button "4" in the screenshot below.

Button properties and functions:
• bool Front - Triggered by the rising edge of the button press (from the previous section). Does not change during the operation of the PLC section.
• bool Rear - Triggered by the falling edge of the button press (from the previous section). Does not change during the operation of the PLC section.
• bool Press - Button press state. Does not change during the operation of the PLC section.
• bool Enable - Input, if false the button is blocked - "3" in the screenshot below.
• bool Led - Input, if true the button is highlighted - "2" in the screenshot below.



Usage example:

    
    BtMoveSwitch.Enable = TDM.IsJogMode || TDM.IsZeroMode;
    TDM.CommanMove = BtMoveSwitch.Front;
    

6.2. PlcSwitch

The PlcSwitch object is designed to describe a panel switch.
The number of positions can be set for the switch.


The user on the panel screen can click on the left or right part of the switch - decreasing or increasing the value of the switch.
PlcSwitch must be declared in the variable initialization section.
Example of declaring a switch:

        
    // Declaring a feed rate switch
    static readonly PlcSwitch BtFeedSwitch = new(
        "FAST-{0}x", 
        4, 
        1,
        false);
    

Initialization parameters:
• string Name - Displayed switch name. The characters in the name "{0}" will be replaced with a number - the current value of the switch
• int MaxSwitch - Number of switch positions, maximum - 6
• int Switch - Initial switch position • bool DifferentChanel - A sign that the button may have a different action depending on the channel (controls the system for each channel separately)

Switch properties and functions:
• bool Switch - Switch value. Read and write. Does not change during the operation of the PLC section.
• bool Enable - Input, if false the switch is blocked.
• bool Led - Input, if true the switch is highlighted.

Usage example:

    
    BtFeed100.Led = BtFeedSwitch.Switch == 3;
    switch (BtFeedSwitch.Switch) {
        case 1: BtFeedSwitch.Name = "FAST 1x"; break;
        case 2: BtFeedSwitch.Name = "FAST 10x"; break;
        case 3: BtFeedSwitch.Name = "FAST 100x"; break;
        case 4: BtFeedSwitch.Name = "FAST 1000x"; break;
    };
    

6.3. PlcWell

The PlcWell object is designed to describe a panel encoder-handwheel:


The user on the panel screen can "Turn" the encoder-handwheel left and right - decreasing or increasing the value of PlcWell.
PlcWell must be declared in the variable initialization section.
Example of declaring PlcWell:

        
    // Declaring a feed rate encoder-handwheel
    static readonly PlcWell BtWheel = new(
        string.Empty, 
        EnumAxis.X);
    

Initialization parameters:
• string Name - Displayed name
• object AxisImage - predefined axis picture.
Can accept types: EnumAxis, EnumPlcImage, SvgImage
EnumAxis.NAN/X/Y/Z/A/B/C/U/V/W/Q/E/Ĉ

PlcWell properties and functions:
• double Steps - Encoder-handwheel value in steps (4 degrees - 74 steps per revolution).
Reading. Does not change during the operation of the PLC section.
• bool Enable - Input, if false the switch is blocked.
• object AxisImage - Read and write.
Can accept types: EnumAxis, EnumPlcImage, SvgImage

Usage example:

    
    DT.WellFeed += BtWheel.Steps / 5d;
    BtWheel.AxisImage = EnumPlcImage.F;
    BtWheel.Enable = TDM.IsJogMode || TDM.IsWorkMode || TDM.IsZeroMode;
    

6.3. PlcSlider

The PlcSlider object is designed to describe a vertical control slider:


The user on the panel screen can "Move" the slider up and down - decreasing or increasing the value of PlcSlider.
PlcSlider must be declared in the variable initialization section.
Example of declaring PlcSlider:

        
    // Declaring a feed rate Slider
    static readonly PlcSlider SlFeed = new(
        "FEED {0:#.}%", 
        TPLC.MinFeedCorrectorG1, 
        TPLC.MaxFeedCorrectorG1, 
        TPLC.CurChannel.Feed.CorrectorG1, 
        10, 5, 60, 80, 120, 150);
    

Initialization parameters:
• string Name - Displayed name with value output format
• double MinValue - minimum value.
• double MaxValue - maximum value.
• double InitValue - initial value.
• double TickFrequencyView - displayed scale step.
• double TickFrequencySnap - applied discrete scale step.
• double MinRed - minimum value - below which the scale is red.
• double MinYellow - minimum value - below which the scale is yellow (up to MinRed).
• double MaxYellow - maximum value - above which the scale is yellow (up to MaxRed).
• double MaxRed - maximum value - above which the scale is red.
Button properties and functions:
• bool Front - Triggered by the rising edge when moving the slider. Does not change during the operation of the PLC section.
• bool Rear - Triggered by the falling edge when moving the slider. Does not change during the operation of the PLC section.
• bool Enable - Input, if false the slider is blocked.

Usage example:

    
    SlFeed.Enable = TDM.IsJogMode || TDM.IsWorkMode || TDM.IsZeroMode;
    if (SlFeed.Front && SlFeed.Enable) { 
        DT.CM_FeedCorrectorG1 = SlFeed.Value;
    };
    

6.5. PlcText

Object PlcWell Designed to display arbitrary text on the console:

The user on the console screen can "Twist" the encoder-flywheel left and right - decreasing or increasing the value of PlcWell.
PlcText must be declared in the variable initialization section.
Example of PlcText declaration:

        
    static readonly PlcText Text = new(
        Translate("Установите пробник", "Place the probe"),
        10, 
        false, 
        PlcText.BackgroundDefault, 
        PlcText.ForegroundDefault, 
        PlcText.Alignment.Center, 
        PlcText.Alignment.Center);
    

Initialization parameters:
• string Text - Displayed text
• double FontSize - Font size.
• bool SpecialFont - If true - displays in a special font for numbers.
• Color Background - Background color. You can set the default background color: PlcText.BackgroundDefault
• Color Foreground - Text color. You can set the default background color: PlcText.ForegroundDefault
• Alignment VerticalAlignment - Text alignment horizontally, PlcText.Alignment.Center/Right/Left
• Alignment HorizontalAlignment - Text alignment vertically, PlcText.Alignment.Center/Top/Bottom

Properties and functions of PlcText:
• string Name - Displayed button name
• double FontSize - Font size.
• bool SpecialFont - If tue - displays in a special font for numbers.
• Color Background - Background color. You can set the default background color: PlcText.BackgroundDefault
• Color Foreground - Text color. You can set the default background color: PlcText.ForegroundDefault
• Alignment VerticalAlignment - Text alignment horizontally, PlcText.Alignment.Center/Right/Left
• Alignment HorizontalAlignment - Text alignment vertically, PlcText.Alignment.Center/Top/Bottom

You can set your own color, for example:

    
    // Setting arbitrary colors
    PlcText.Name = "Новый цвет";
    PlcText.Color HeadColor = new("#FFFF1F1F", "#FFFF8080");
    

6.6. Console declaration

The console must be declared once at system startup. As a rule, this should be done in the variable initialization section. Example:

    
    // Declaration of the console with a button image from the system
    TabPultProbe = NewTabPult(
        Translate("МОЙ ПУЛЬТ", "USER PULT"), 
        EnumPlcImage.Fack);

    // Declaration of the console with an arbitrary image - button
    TabPultProbe = NewTabPult(
        Translate("МОЙ ПУЛЬТ", "USER PULT"), 
        PlcEngine.CreateSvgImage(
            """
            ‹svg›‹defs›‹style›.cls-1 {fill: #4d4d4d;}.cls-1, .cls-2 {stroke: #000;stroke-linecap: round;stroke-linejoin: round;stroke-width: 3.57px;}.cls-2 {fill: #db956f;}‹/style›‹/defs›
              ‹path class="cls-1" d="M424.06,191.41v245.36c0,11.04-8.97,19.98-20.04,19.98h-78.78c-11.07,0-20.04-8.95-20.04-19.98v-81.42c0-11.04-8.97-19.98-20.04-19.98h-48.21c-11.07,0-20.04,8.95-20.04,19.98v81.42c0,11.04-8.97,19.98-20.04,19.98H112.1c-11.07,0-20.04-8.95-20.04-19.98V191.41l166-105.38,166,105.38Z"/›
              ‹path class="cls-2" d="M48.15,249.51c-10.22,0-20.23-5.05-26.11-14.3-9.13-14.36-4.85-33.38,9.55-42.49L241.52,60.03c10.17-6.42,23.19-6.37,33.3,.15l205.83,132.7c14.32,9.24,18.42,28.29,9.17,42.57-9.26,14.26-28.36,18.36-42.69,9.14l-189.22-122L64.65,244.73c-5.13,3.24-10.85,4.78-16.5,4.78Z"/›
              ‹path class="cls-1" d="M92.02,154.53V71.41c0-6.09,4.95-11.03,11.06-11.03h38.94c6.11,0,11.06,4.94,11.06,11.03v44.52l-61.06,38.6Z"/›
            ‹/svg›
            """),);
    

Initialization parameters:
• string Name - Displayed name in the console selection button
• или EnumPlcImage Image - Predefined picture. Will be displayed on the console selection button.
• или SvgImage Image - An arbitrary image obtained through the functionPlcEngine.CreateSvgImage(string SvGString) Will be displayed on the console selection button.

Properties and functions of PlcText:
• Clear() - Clearing all buttons on the console

6.7. Filling the console with objects

Filling the console with buttons is performed in the AddButton() function.
The console space on the page will be divided into N number of cells.
Example:


    // Filling the console
    CurTabPult.Clear();
    AddButton(CurTabPult,   BtChannelMode,  BtDemoMode,     BtModeM1,   BtModeSingle,   NoBut,          BtModeZero);
    AddButton(CurTabPult,   BtMoveSwitch,   NoBut,          NoBut,      NoBut,          BtCoordZ,       BtCoordXY);
    AddButton(CurTabPult,   BtRotationZp,   BtRotation1p,   BtSpeed,    BtFeed,         BtTooth,        NoBut); 
    AddButton(CurTabPult,   BtRotationXm,   BtRotationXp,   BtWheel,    BtWheel,        BtWheel,        NoBut);
    AddButton(CurTabPult,   BtRotationZm,   BtRotation1m,   BtWheel,    BtWheel,        BtWheel,        NoBut);
    AddButton(CurTabPult,   BtRotation2m,   BtRotation2p,   BtWheel,    BtWheel,        BtWheel,        NoBut);
    AddButton(CurTabPult,   BtMoveX1,       BtMoveX100,     BtFeed1,    BtFeed10,       BtFeed100,      NoBut);
    

The number of cells horizontally will be equal to the maximum number of buttons - passed to the AddButton() function
The number of cells vertically will be equal to the number of calls to the AddButton() function
Filling parameters:
• TabPult TabPult - Console declared by the NewTabPult() function
• object PultObject - Console objects - up to 40 objects.
Accepted types in PultObject: PlcButton, PlcSwitch, PlcWell, PlcText.

Objects passed to the AddButton() function will be located in one line from left to right.
The AddButton() function must be called several times - according to the number of button rows on the console.
If a button is not needed in a specific cell, you need to pass the "NoBut" object

If the same object (button) is passed in two adjacent (or more) positions (both horizontally and vertically) - the object (button) will 'stretch' to these cells as one button.
See the BtWheel object in the example - it is stretched over 3x3 cells
In the code, you can see in an approximate form how the buttons (or other objects) will be located - see the example above.

7. Console Help

In the PLC code, it is possible to program help-hints for console buttons.
Displaying help for consoles - on the "Console" tab, on the right in the panel at the top is the help opening button
Example of console help:


There can be several console helps.
Programming is practically no different from programming a regular console.
Help should be created in the Init() section.
Example of minimal help:


       // Declare help
       PlcButton BImag = new("", EnumPlcImage.HelpWHB04B);

       // Create help objects
       PlcText.Color BacColor = new("#FFA1A1A1", "#FF797979");
       PlcText.Color HeadColor = new("#FFFF1F1F", "#FFFF8080");
       PlcText TxNoF = new(Translate("Без модиф.", "No modifier"), 20, false, null, HeadColor, PlcText.Alignment.Left, PlcText.Alignment.Center);
       PlcText TxYsF = new(Translate("FN (13) зажата.", "FN (13) clamped."), 20, false, null, HeadColor, PlcText.Alignment.Left, PlcText.Alignment.Center);
       PlcText TxYsS = new(Translate("STEP (19) зажата.", "STEP (19) clamped."), 20, false, null, HeadColor, PlcText.Alignment.Left, PlcText.Alignment.Center);

       // Register console help
       var HelpWHB = NewTabPult("", EnumPlcImage.PultWHB, -1);
       AddButton(HelpWHB, NoBut, NoBut, TxNoF, TxNoF, TxNoF, TxNoF, TxNoF, TxNoF, TxNoF, TxNoF);
       AddButton(HelpWHB, TxB01, NoBut, TxYsF, TxYsF, TxYsF, TxYsF, TxYsF, TxYsF, TxYsF, TxYsF);
       AddButton(HelpWHB, TxB02, NoBut, TxYsS, TxYsS, TxYsS, TxYsS, TxYsS, TxYsS, TxYsS, TxYsS);

       // Add help to the list of help (for the possibility of selection)
       new PlcPultHelp.HelpPult(
           String.Empty, //Translate("WHB", "WHB"),
           EnumPlcImage.PultWHB,
           HelpWHB
       );
    

For a complete understanding of the help programming mechanism, see how it is implemented by the developers in the PultWHB.cs module