Give the element the Execute ST Code input action in CODESYS and write the call as ClassObject.Method();, with Ctrl+Enter for each new line. Method calls compile when the screen runs as the target visualization; anywhere else the action takes assignments only, so the button writes a flag and the program makes the call. Show the result with %s and %5.2f placeholders in the Text property.
Give the button the Execute ST Code input action in CODESYS and write the call exactly as you would in the program: fbPump.Cmd_Start();, instance name, dot, method, parentheses, semicolon. That one line is the whole job when the screen runs as the target visualization. When it does not, the compiler tells you in plain words, and you fall back to assignments. This page walks the job in the order you meet it: the instance, the input action, the editor quirk, the placeholders that show the result, and the check before the machine runs.
How do I call a method from an HMI button with ST code?
Set the element's input configuration to the Execute ST Code action and write the call in function block notation, for example fbPump.Cmd_Start();, with the instance name, a dot, the method name, empty parentheses and a semicolon.
The action hangs on an input event. For a command button, use OnMouseClick: the call runs once per completed click. If the method declares inputs, pass them inside the parentheses exactly as in the program editor, and the input assistance shows the parameter list the moment you type the opening parenthesis. The instance has to be reachable from the screen: declare it in a global variable list, or in a POU the visualization can see.
What do I need in the project before the button works?
You need three things in the logic before the screen has anything to call: an instance of the function block that owns the method, the method itself with its inputs declared, and a global variable list holding every value the screen displays.
The instance is the object the method runs on. If you build instances at runtime instead of declaring them statically, creating function block instances dynamically walks that path. Put the display values, the state string and the weight real used below into a global variable list, so the program and the screen reach the same storage with no copying. A method with VAR_INPUT parameters reads them on the click that fires the call.
How do I configure the input action step by step?
Select the element, open Input configuration in its properties, choose the event, add the Execute ST Code action, type the call, and confirm with OK: five steps from a blank rectangle to a working button.
- Draw a rectangle where the button belongs, or drop in a button element, and give it the label text.
- Select the element and open Input configuration in its property list.
- Choose the event: OnMouseClick for a normal command.
- Add the Execute ST Code action.
- Type
fbPump.Cmd_Start();with your instance and method names, then confirm.
The statements run in the order written, top to bottom, on that single click. Keep the action to a handful of statements; anything longer belongs behind one call.
How do I type more than one line in the Execute ST Code editor?
Press Ctrl+Enter for a new line; Enter on its own closes the dialog and drops you back in the properties, which is why engineers got used to pasting single lines.
Both routes work: Ctrl+Enter inside the field, or write the lines in the program editor and paste them in. End every statement with a semicolon either way, and the multiline action behaves like a small program body.
Why does the compile fail with "statements which are no assignments"?
That message means the visualization is not running as the target visualization, because statements that are not assignments, a method call first among them, are supported there only; in any other context the Execute ST Code action accepts plain assignments.
Treat the message as a routing instruction. Where the call will not compile, write an assignment in the button:
GVL.bStartCmd := TRUE;
and make the call in the cyclic program code:
IF GVL.bStartCmd THEN
fbPump.Cmd_Start();
GVL.bStartCmd := FALSE;
END_IF
The edge is clean: one click sets the flag once, the program consumes it on the next cycle and resets it, so a held finger cannot stack calls.
Recommendation: keep fbPump.Cmd_Start(); in the button when the screen is the target visualization, and switch to the flag-and-assignment pattern the moment the compiler prints that message; the pattern compiles in every context and keeps the command one-shot.
How do I display the value the method call changed?
Declare the variable globally, link it as the element's text variable, and put a placeholder in the Text property: %s for a string, %5.2f for a real printed five characters wide with two decimals, filled with the current value while the screen runs.
A text element with Text State: %s and text variable GVL.strState prints State: RUNNING on the cycle after the string changes. The same Execute ST Code action can set it with the assignment GVL.strState := "RUNNING";, which compiles in every context. For the wider job of putting process values on a screen, displaying PLC configuration values in a visualization covers the bindings.
How large should the button and its label be on the panel?
Size the label to the distance the operator reads it from: the FHWA planning figure is 30 ft of viewing distance per inch of capital letter, so 0.4 in capitals stay legible to about 12 ft, and the safer 20 ft per inch figure cuts that to 8 ft.
An operator at the panel stands 2 to 3 ft away, so 0.25 in capitals already clear the requirement with room to spare; 0.4 in is the comfortable choice for a glance from a step back. Give the touch target about 20 mm on the side for a gloved finger, which is where usability practice lands for factory panels, and keep the lines of a two-line label 1.7 x capital height apart. The sizing logic behind touchscreen keyboard design for reliable operator input applies to command buttons too, and small screen text readability for a signage display carries the full table. A Start command from a screen is an operator command, not a safety function: stops that protect people belong in the machine's safety circuit, never in button code.
What does a complete example look like?
One filler station needs a Start button, a Stop button and a weight readout: Start calls fbFiller.Cmd_Start(); and sets the state string, Stop calls fbFiller.Cmd_Stop(); the same way, and one text element shows Weight: %5.2f kg from a global real.
The project pieces: the function block instance fbFiller, its two methods, and a global variable list holding strState (STRING) and rWeight (REAL).
The Start rectangle carries OnMouseClick with Execute ST Code:
fbFiller.Cmd_Start();
GVL.strState := "RUNNING";
The Stop rectangle carries:
fbFiller.Cmd_Stop();
GVL.strState := "IDLE";
The readout is a text element with Text Weight: %5.2f kg and text variable GVL.rWeight. At rWeight = 12.5 it prints Weight: 12.50 kg, five characters wide with the two decimals fixed. Run the legibility check on the labels: 0.4 in capitals x 30 ft per inch = 12 ft of clear reading at the FHWA planning figure, and 0.4 x 20 = 8 ft at the safer figure, both far past the operator's reach of about 2 ft.
If the compile throws the statements error on this project, the two button actions become GVL.bStartCmd := TRUE; and GVL.bStopCmd := TRUE;, and the program makes both calls on the edges.
How do I check the button works before the machine runs?
Compile, then run in simulation or on the bench with the outputs disconnected, and click each button once: the compile must report zero errors, the state string must change on the same click, and the weight readout must print to two decimals.
The failure paths have names:
- The compile stops on
statements which are no assignments: the screen is not the target visualization, so apply the flag pattern above. - The click does nothing: the event is missing or the instance name in the call is misspelled. Check that the action sits on OnMouseClick of this element.
- The element prints
State: %sliterally: the Text property has the placeholder but the text variable link is empty. LinkGVL.strState.
For the wall board that shows status only and takes no input, a screen from our shop-floor range plays a playlist from a card with no code at all; the andon board guide says where that fits and where it does not.
Questions
Does the ST code run when the operator presses or releases the button?
Tie the action to OnMouseClick and it runs once when the click completes; tie it to OnMouseDown and it runs the instant contact lands. Use OnMouseDown for jog-style commands where reaction speed matters, and OnMouseClick for normal commands so a finger resting on the glass fires nothing.
Can I open an input dialog and run code after the operator closes it?
Yes. The input configuration holds an ordered list of actions: put the dialog action first and the Execute ST Code action after it, and the code runs with the values the operator just entered. That replaces the older two-step pattern of a dialog that only writes a variable and leaves the follow-up to the program.
Where should long logic live when the button only needs one call?
In a POU that a task starts. Keep the button's Execute ST Code to a single call into that POU, an action or a method, and put the sequence inside it. The button stays readable on the screen, and the logic runs where you can time it, monitor it and reuse it from other screens.
Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.