Multiple Dialogs

We have a diagnostics page for the axes on our HMI/visualization. I would like a dialog window to open when I click on an axis, displaying the jog buttons for that specific axis so that I can jog the axis from there.

I currently see two possible approaches.

1. Only one jog dialog can be open at a time

If I want to jog a different axis, I must first close the current dialog window and then click on the next axis. The advantage is that I only need a single dialog in the project and can simply switch its content using LoadContentInDialog. However, I would still need separate content with jog buttons for each axis.

2. Modeless dialogs

The dialogs are modeless, and whenever an axis is clicked, its own jog window opens. This allows multiple jog dialogs for different axes to be open simultaneously, meaning several axes can be displayed and operated at the same time. The disadvantage is that I need a separate dialog, including its content, for every axis. I actually prefer this approach, but it would require creating a very large number of dialogs for a project.

Does anyone have a better solution for implementing something like this while keeping the engineering effort to a reasonable level?

Hi @Stefan_Ruttimann

not sure if my solution works with your layout and source values/ widgets but I put together a quick example how I would approach this.

The end result looks like this.

2026-09-04_09-25-09

and the basic thought was

  1. Click the GroupBox (Axis) and assign a number to a session variable (AxisSel)
  2. Open DialogboxAtTarget
  3. The up/down (jog) button changes a session variable (AxisPos)
  4. Session variable is bound to each axis position variable (Axis1-4) via a list binding with the selector being the session variable assigned as (AxisSel)

I did all this locally with session variables so here is the general workflow.

<Binding mode="twoWay">
	<Source xsi:type="listElement">
		<Selector xsi:type="session" refId="AxisSel" attribute="value" />
		<be:List xmlns:be="http://www.br-automation.com/iat2015/bindingListEmbedded/engineering/v2" xsi:type="be:session" attribute="value">				
			<bt:Element index="1" refId="Axis1" />
			<bt:Element index="2" refId="Axis2" />
			<bt:Element index="3" refId="Axis3" />
			<bt:Element index="4" refId="Axis4" />
		</be:List>
	</Source>
	<Target xsi:type="session" refId="AxisPos" attribute="value" />
</Binding>				
<Binding mode="twoWay">
	<Source xsi:type="session" refId="Axis1" attribute="value" />
	<Target xsi:type="brease" contentRefId="HD_LS1_contentService3" widgetRefId="NumericOutput1" attribute="value" />
</Binding>
<Binding mode="twoWay">
	<Source xsi:type="session" refId="Axis2" attribute="value" />
	<Target xsi:type="brease" contentRefId="HD_LS1_contentService3" widgetRefId="NumericOutput2" attribute="value" />
</Binding>
<Binding mode="twoWay">
	<Source xsi:type="session" refId="Axis3" attribute="value" />
	<Target xsi:type="brease" contentRefId="HD_LS1_contentService3" widgetRefId="NumericOutput3" attribute="value" />
</Binding>
<Binding mode="twoWay">
	<Source xsi:type="session" refId="Axis4" attribute="value" />
	<Target xsi:type="brease" contentRefId="HD_LS1_contentService3" widgetRefId="NumericOutput4" attribute="value" />
</Binding>

The dialog opens at target = origin and is set to autoClose so it closes when another “axis” is selected. I’ll admit that you have to click the new “axis” twice.

This eventbinding repeats for all “axis” and only the assigned number changes.

Again not sure if this can work in your structure and setup but you wanted ideas, here is one.

Take care!

@marcel.voigt thanks very much for your idea

I had something similar in mind if only one axis dialog should be possible to be open at a time. - Option 1
Do you have any idea how we could solve the approach for Option 2? To have multiple Jog dialogs open at a time?

Thx

Hi @Stefan_Ruttimann

I’ve already created this type of UI component for axis diagnostics, and I found something very useful:

  • The first thing to do is create a structure array that contains the commands and statuses for each of your axes.

  • From there, you can create a Compound Widget that takes a structure binding of this structure as input; you can bind the commands to buttons and the statuses to Numeric Outputs, for example.

  • To select the axis, you can use a session variable. If you have multiple sessions running in parallel, this allows you to control multiple sessions; this session variable will be stored in an array on the PLC side.

  • Create pointers for the maximum number of sessions you’ll have on your HMI. On the PLC side, using the selected axis number, you can perform an ACCESS on the desired structure, which allows you to declare only the pointers in OPC UA.

  • You can now bind the pointer directly to the Compound widget!

It’s fairly simple to set up, and it also makes it easy to add sessions; if the maximum number of axes changes, there’s no need to modify the mappView section.

Here is an example:

The declaration of the session variable, you can modify this variable by using a list for example:

<Variable name="sAxisselectedString" xsi:type="ANY_STRING" value="0" />

Binding of the session variable to the PLC variable that will be needed for the pointers selection

<!-- selected list value -->
<Binding mode="twoWay">
	<Source xsi:type="listElement">
		<Selector xsi:type="session" refId="::SYSTEM:clientInfo.slotId" attribute="value" />
		<be:List xsi:type="be:opcUa" attribute="value">
			<bt:Element index="0" refId="::P812_MappV:AxisSelected[0]" />
			<bt:Element index="1" refId="::P812_MappV:AxisSelected[1]" />
			<bt:Element index="2" refId="::P812_MappV:AxisSelected[2]" />
			<bt:Element index="3" refId="::P812_MappV:AxisSelected[3]" />
			<bt:Element index="4" refId="::P812_MappV:AxisSelected[4]" />
			<bt:Element index="5" refId="::P812_MappV:AxisSelected[5]" />
		</be:List>
	</Source>
	<Target xsi:type="session" refId="sAxisselectedString" attribute="value" />
</Binding>

Structured text snippet for my 6 pointers to access the correct axis.

// Widget Axis manual commands
WidgetPilotAxisAdrSelected[i]	:= ADR(gAxisList[STRING_TO_INT(AxisSelected[i])]);	
CASE i OF
	0:	pWidgetPilotAX_c0 ACCESS WidgetPilotAxisAdrSelected[i];
	1:	pWidgetPilotAX_c1 ACCESS WidgetPilotAxisAdrSelected[i];
	2:	pWidgetPilotAX_c2 ACCESS WidgetPilotAxisAdrSelected[i];
	3:	pWidgetPilotAX_c3 ACCESS WidgetPilotAxisAdrSelected[i];
	4:	pWidgetPilotAX_c4 ACCESS WidgetPilotAxisAdrSelected[i];
	5:	pWidgetPilotAX_c5 ACCESS WidgetPilotAxisAdrSelected[i];
END_CASE;

Binding of the pointers to the compound widget structured property

<!-- Pointers to function blocks of AxisManagement -->
<Binding mode="twoWay">
	<Source xsi:type="listElement">
		<Selector xsi:type="session" refId="::SYSTEM:clientInfo.slotId" attribute="value" />
		<be:List xmlns:be="http://www.br-automation.com/iat2015/bindingListEmbedded/engineering/v2" xsi:type="be:opcUa" attribute="value">				
			<bt:Element index="0" refId="::P812_MappV:pWidgetPilotAX_c0" />
			<bt:Element index="1" refId="::P812_MappV:pWidgetPilotAX_c1" />
			<bt:Element index="2" refId="::P812_MappV:pWidgetPilotAX_c2" />
			<bt:Element index="3" refId="::P812_MappV:pWidgetPilotAX_c3" />
			<bt:Element index="4" refId="::P812_MappV:pWidgetPilotAX_c4" />
			<bt:Element index="5" refId="::P812_MappV:pWidgetPilotAX_c5" />
		</be:List>
	</Source>
	<Target xsi:type="brease" widgetRefId="compoundwidget_PilotingAX" contentRefId="ContentAxis" attribute="pAxisManagement" />
</Binding>

So if the number max of axis changed, you have nothing to handle except the way you handle the session variable that store the selected Axis.
The only change are made if you have to handle more session:

  • Increase the array that store the selectedAxis per session
  • Add a new line in the binding of the session variable to the array
  • Create a new pointer and declare it in the OPCUA
  • Add a new line in the CASE
  • Add a new line in the binding from the pointer to the compound widget

PS: In my example I didn’t create a specific structure I use my array of AxisManagement function block and it’s working pretty good and I reduce the number of variables used in the OpcUa and so the memory used by AR!

I hope it helps!

Regards,
Florent