This example shall implement the following functionality: if a rising edge of a Boolean input is detected, the output shall be set to true. After a defined delay, the output shall be set to false again. If the output is currently set to true and another rising edge at the input is detected, the time delay for setting the output to false shall be reset. The following figure shows the functionality mentioned above.
Creating the command
Within the BMS Studio, start the XLogic Editor using the corresponding icon in the toolbar. Then select the entry "New Command ..." from the menu "File". A new dialog opens that is used to define the name of the command as well as its inputs, outputs, and parameters.
Within this dialog, set the name to "Delayed Off" and define the following input:
- Input: this is the item ID that specifies the input that shall be monitored.
Then, define the following output:
- Output: this is the item ID that specifies the output where the result shall be written.
Finally, define the following parameter:
- Delay: this parameter of type "NUMBER" specifies the delay in seconds.
The dialog with all correct values is shown in the figure above.
Command flow
As next the command flow has to be defined. The proposed command shall be split into two different parts -- one part that processes the input and one part that process the output. To achieve this, insert two ``CMD BLOCK''s and set the comment of the first one to ``Process input'' and the comment of the second one to ``Process output''. Figure \ref{fig:delayed_off_flow} shows the final command flow.
"Process input"
As next the "Process input" block shall be implemented. By doing a double click on the corresponding block, the work sheet of the "CMD BLOCK" opens. Within this work sheet, define the command flow that is shown in the following figure.
The command flow of the "Process input" block consists of the following blocks:
- "Edge detection": this block of type "CMD BLOCK" performs the detection of the rising edge of the input.
- "Is edge detected?": after having performed the edge detection, it has to be verified whether a edge currently exists or not.
- ''Set counter'': if an edge was detected, the time delay is reset to the initial value (i.e. to the specified delay).
- "Is output false?": this condition verifies whether the output is current set to "false".
- "Write true to output": if the output is currently "false", it is set to "true".
In the following, the above mentioned blocks are explained in more detail.
"Edge detection"
The command flow of the ``Edge detection'' block is shown in the following figure.
It consists of the following blocks:
"Is edge detected?"
This condition verifies whether a positive edge is detected at the input. The condition is shown in here.
"Set edge'"
Here, the variable "edge" is set which indicates that an edge has been detected. The implementation is shown in the following figure.
"Reset edge"
This block is used to reset the variable ``edge''. The implementation is shown in the following figure.
"Set last value edge"
Here, the current value of the input is stored in the variable ``last input'' which is used in the next command execution to perform the edge detection. The implementation is shown in the following figure.
"Is edge detected?"
This condition verifies whether an edge has been detected in the previous ``CMD BLOCK''. Using an ``EQUAL'' block, the current value of the variable ``edge'' (retrieved by the ``VARIABLE VALUE'' block in combination with a ``VARIABLE NAME'' block) is compared to the constant ``TRUE'' (provided by a ``BOOL'' block). The implementation of the ``Is edge detected'' condition is shown in figure \ref{fig:delayed_off_is_edge_detected}.
\nxagraphic
{examples/fig/delayed_off_is_edge_detected.png}
{examples/fig/delayed_off_is_edge_detected.png}
{``Is edge detected?'' condition}
{``Is edge detected?'' Bedingung}
{delayed_off_is_edge_detected}
{300pt}
{0.5pt}
"Set counter"
This block resets the counter to the value that is specified by the ``Delay'' parameter. The implementation of the ``Set counter'' block is shown in figure \ref{fig:delayed_off_set_counter}.
\nxagraphic
{examples/fig/delayed_off_set_counter.png}
{examples/fig/delayed_off_set_counter.png}
{``Set counter'' block}
{``Set counter'' Block}
{delayed_off_set_counter}
{200pt}
{0.5pt}
\subsubsection{``Is output false?'}
After having reset the counter, the output shall be set to true if it is not already true. To achieve this, the output has to verified. Figure \ref{fig:delayed_off_is_output_false} shows the implementation of the required condition.
\nxagraphic
{examples/fig/delayed_off_is_output_false.png}
{examples/fig/delayed_off_is_output_false.png}
{``Is output false?'' condition}
{``Is output false'' Bedingung}
{delayed_off_is_output_false}
{200pt}
{0.5pt}
\subsubsection{``Write true to output'}
Figure \ref{fig:delayed_off_write_true_to_output} shows how the output is set to true. Note that a ``WRITE OUTPUT ITEM'' block also forwards the value to the bus if a physical data point is behind the server item.
\nxagraphic
{examples/fig/delayed_off_write_true_to_output.png}
{examples/fig/delayed_off_write_true_to_output.png}
{``Write true to output'' block}
{``Write true to output'' Block}
{delayed_off_write_true_to_output}
{150pt}
{0.5pt}
\subsection{``Process output''}
\nxatext
{
After having finished the ``Process input'' block, the ``Process output'' block has to be implemented. By doing a double click on the corresponding block, the work sheet of the ``CMD BLOCK'' opens. Within this work sheet, define the command flow that is shown in figure \ref{fig:delayed_off_process_output}.
}
{
Im nächsten Schritt muss der ``Process output'' Block implementiert werden. Mit einem Doppelklick auf den entsprechenden Block wird der Arbeitsbereich des ``CMD BLOCK''s geöffnet. Innerhalb des Arbeitsbereich muss der Kommandoablauf, wie in Abbildung \ref{fig:delayed_off_process_output} ersichtlich, definiert werden.
}
\nxagraphic
{examples/fig/delayed_off_process_output.png}
{examples/fig/delayed_off_process_output.png}
{Process output}
{Verarbeiten des Outputs}
{delayed_off_process_output}
{350pt}
{0.5pt}
\nxatext
{
The command flow of the ``Process output'' block consists of the following blocks:
}
{
Der Kommandoablauf des ``Process output'' Blocks enthält folgende Blöcke:
}
\begin{compactitem}
\item ``Is counter 0?'': \nxatext{this condition verifies whether the current counter value is zero.}{Diese Bedingung überprüft, ob der momentane Zählerwert 0 entspricht.}
\item ``Is output true?'': \nxatext{if the counter is zero, the output shall be reset to false again. However, this shall only be done if the output is currently set to true. The required test is done within this block.}{Wenn der Zähler 0 ist, soll der Output auf ``False'' rückgesetzt werden. Dies soll allerdings nur initiiert werden, wenn der Output im Moment auf ``True'' gesetzt ist. Die notwendige Prüfung ist in diesem Block enthalten.}
\item ''Write false to output'':\nxatext{Within this ``CMD'' block, the output is set to false.}{Innerhalb diese ``CMD'' Blocks wird der Output auf ``False'' gesetzt.}
\item ``Decrement counter'': \nxatext{if the counter is not yet zero, it is decremented by one within this block.}{Wenn der Zähler noch nicht 0 erreicht hat, wird er in diesem Block um 1 dekrementiert.}
\end{compactitem}
\nxatext
{
In the following, the above mentioned blocks are explained in more detail.
}
{
Als nächstes werden die oben erwähnten Blöcke detailliert erklärt.
}
\subsubsection{``Is counter 0?'}
\nxatext
{
Using a ``LESS OR EQUAL'' block, the current counter value which is stored within the variable ``counter'' is compared with zero. To get the value of the variable, a ``VARIABLE VALUE'' block is used. Since the variable may be uninitialized after server startup, zero is specified as default value. The implementation of this condition is shown in figure \ref{fig:delayed_off_is_counter_zero}.
}
{
Mithilfe eines ``LESS OR EQUAL'' Blocks wird der momentane Zählerwert, der in der Variable ``counter'' gespeichert ist, mit 0 verglichen. Um den Wert der Variable zu erhalten wird ein ``VARIABLE VALUE'' Block verwendet. Da die Variable nach Serverstart uninitialisiert sein kann, wird 0 als Standardwert spezifiziert. Die Implementierung dieser Bedingung ist in Abbildung \ref{fig:delayed_off_is_counter_zero} zu sehen.
}
\nxagraphic
{examples/fig/delayed_off_is_counter_zero.png}
{examples/fig/delayed_off_is_counter_zero.png}
{``Is counter 0?''}
{``Is counter 0?''}
{delayed_off_is_counter_zero}
{250pt}
{0.5pt}
\subsubsection{``Is output true?'}
\nxatext
{
If the current counter value is zero, the delay interval is elapsed and the output shall be reset to false again. However, to avoid that multiple ``false'' telegrams are sent to the bus, the output shall only be set to false if the output is currently true. The implementation of the required test is shown in figure \ref{fig:delayed_off_is_output_true}.
}
{
Wenn der momentane Zählerwert 0 ist, ist die Verzögerungszeit abgelaufen und der Output soll auf ``False'' rückgesetzt werden. Um allerdings zu verhindern, dass mehrfache ``False'' Telegramme auf den Bus gesendet werden, soll der Output nur dann auf ``False'' gesetzt werden, wenn er im Moment ``True'' ist. Die Implementierung des notwendigen Tests ist in Abbildung \ref{fig:delayed_off_is_output_true} zu sehen.
}
\nxagraphic
{examples/fig/delayed_off_is_output_true.png}
{examples/fig/delayed_off_is_output_true.png}
{``Is output true?''}
{``Is output true?''}
{delayed_off_is_output_true}
{250pt}
{0.5pt}
\subsubsection{``Write false to output'}
\nxatext
{
Figure \ref{fig:delayed_off_write_false_to_output} shows how the output is set to false. To forward the value also to the bus if the output is a physical data point, a ``WRITE OUTPUT ITEM'' is used\footnote{If the value shall only be set internally and not forwarded to the bus, a ``SET OUTPUT VALUE'' block has to be used instead.}.
}
{
Abbildung \ref{fig:delayed_off_write_false_to_output} zeigt, wie der Output auf ``False'' gesetzt wird. Um den Wert auch auf den Bus weiterleiten wenn der Output ein physikalischer Datenpunkt ist, wird ein ``WRITE OUTPUT ITEM'' Block verwendet\footnote{Wenn der Wert nur intern gesetzt und nicht auf den Bus weitergeleitet werden soll, muss ein ``SET OUTPUT VALUE'' Block verwendet werden.}.
}
\nxagraphic
{examples/fig/delayed_off_write_false_to_output.png}
{examples/fig/delayed_off_write_false_to_output.png}
{``Write false to output''}
{``Write false to output''}
{delayed_off_write_false_to_output}
{200pt}
{0.5pt}
\subsubsection{``Decrement counter'}
\nxatext
{
If the current counter value is not zero, the delay interval has not been elapsed and thus the counter value has to be decremented by one. Figure \ref{fig:delayed_off_decrement_counter} shows the implementation of this functionality. Decrementing the value is done using a ``SUB'' block. The incoming ``Input 1'' connector is connected to outgoing ``VALUE'' connector of the ``VARIABLE VALUE'' block that provides the current counter value. The ``Input 2'' connector is connected to the ``NUMBER'' block that provides the constant value 1. The result of the subtraction is stored in the ``counter'' variable again using a ``SET VARIABLE'' block.
}
{
Wenn der momentane Zählerwert nicht 0 ist, ist die Verzögerungszeit noch nicht abgelaufen und der Zählerwert muss um 1 dekrementiert werden. Abbildung \ref{fig:delayed_off_decrement_counter} stellt die Implementierung dieser Funktionalität dar. Das Dekrementieren des Wertes wird mithilfe eines ``SUB'' Blocks bewerkstelligt. Der eingehende Konnektor ``Input 1'' wird dabei mit dem ausgehenden Konnektor ``VALUE'' des ``VARIABLE VALUE'' Blocks, der den momentanen Zählerwert liefert verbunden. Der eingehende Konnektor ``Input2'' wird mit dem ``NUMBER'' Block, der den konstanten Wert 1 liefert, verknüpft. Das Resultat der Subtraktion wird schließlich mittels ``SET VARIABLE'' Block in der Variable ``counter'' gespeichert.
}
\nxagraphic
{examples/fig/delayed_off_decrement_counter.png}
{examples/fig/delayed_off_decrement_counter.png}
{``Decrement counter''}
{``Decrement counter''}
{delayed_off_decrement_counter}
{250pt}
{0.5pt}
\subsection{\nxatext{Saving the command and using the command within the \productbmsserver}{Speichern und Verwenden des Kommandos innerhalb des \productbmsserver s}}
\nxatext
{
To provide the command to the \productbmsserver, it has to be compiled. This can be done by clicking the ``Save'' icon within the toolbar which saves and compiles the current command. In addition, it is possible to change several options of a command. To open the ``Options'' dialog, the entry ``Options ...'' within the menu ``File'' has to be selected (cf. figure \ref{fig:delayed_off_compile}). Within this dialog, basic information about the command can be specified. The flag ``Add to Catalog'' defines whether the command shall be visible within the catalog of the \productname. If activated, the command can be reused in other commands. If the option ``Auto-Compile'' is set, the command is automatically compiled whenever the project is saved.
}
{
Um das erstellte Kommando dem \productbmsserver\ zur Verfügung zu stellen, muss dieses kompiliert werden. Durch Betätigen des ``Save'' Icons in der Toolbar wird das momentane Kommando kompiliert und gespeichert. Zusätzlich ist es möglich, diverse Einstellungen eines Kommandos zu ändern. Um den ``Options'' Dialog zu öffnen, muss der Eintrag ``Options ...'' im Menü ``File'' gewählt werden (siehe Abbildung \ref{fig:delayed_off_compile}). In diesem Dialog können zusätzliche Informationen hinterlegt werden. Die Markierung ``Add to Catalog'' definiert ob das Kommando im Katalog des \productname\ sichtbar sein soll.
}
\nxagraphic
{examples/fig/delayed_off_compile.png}
{examples/fig/delayed_off_compile.png}
{Compiling the command}
{Kompilieren des Kommandos}
{delayed_off_compile}
{150pt}
{0.5pt}
\nxatext
{
After having compiled the command successfully, close the \productname\ and go back to the \productbmsstudio. Afterwards, the new command has to be loaded before it can be used. This can be done by restarting the \productbmsserver\ or by loading the command manually by selecting the entry ``Load logic module'' within the ``Tools'' menu of the \productbmsstudio (cf. section \ref{sec:execute_command}). Then, open the ``XCommand event definitions'' via the menu ``Extensions''. Add a new definition and enter a name for the command within the first column. The next column can be left empty since all variables shall only be used locally. Within the third column, select ``ON\_TIMER\_AND\_INPUT''. This indicates that the command shall be invoked whenever one of the inputs changes and/or after a predefined timer interval has elapsed. To specify the timer interval, enter ``1'' in the ``Options'' column. This indicated that the command shall be executed every second in addition to a change of value of an input. Then, press the ``...'' button within the ``XCommand'' column. A dialog appears where the command can be selected and configured. Select the ``Delayed Off'' command from the drop down list. Afterwards, specify the different inputs, outputs, and parameters. A possible configuration is shown in figure \ref{fig:delayed_off_bms}.
}
{
Nachdem das Kommando erfolgreich kompiliert wurde, kann der \productname\ geschlossen und zum \productbmsstudio\ zurückgekehrt werden. Vor Verwendung muss das neue Kommando geladen werden. Dies erfolgt mittels Neustart des \productbmsserver s oder durch manuelles Laden des Kommandos mithilfe des Eintrags ``Load logic module'' innerhalb des ``Tools'' Menüs des \productbmsstudio s (vgl. Kapitel \ref{sec:execute_command}). Anschließend muss die ``XCommand event definitions'' Tabelle über den Menüeintrag ``Extensions'' geöffnet und eine neue Definition hinzugefügt werden. In der ersten Spalte muss ein Name für das Kommando vergeben werden. Die nächste Spalte muss leer bleiben, da alle Variablen nur lokal verwendet werden. Innerhalb der dritte Spalte ist ``ON\_TIMER\_AND\_INPUT'' zu wählen. Diese Option legt fest, dass das Kommando bei jeder Änderung eines Inputs und beim Ablaufen eines vordefinierten Timerintervalls ausgeführt wird. Um das Timerintervall zu spezifizieren, muss ``1'' in der Spalte ``Options'' eingetragen werden. Dies definiert, dass das Kommando zusätzlich zu einer Werteänderung jede Sekunde ausgeführt wird. Anschließend ist auf den ``...'' Button in der ``XCommand'' Spalte zu klicken. Nun öffnet sich ein Dialog, in dem das Kommando selektiert und konfiguriert werden kann. Das ``Delayed Off'' Kommando ist aus dem Auswahlmenü zu selektieren. Anschließend müssen noch Definitionen für die Inputs, Outputs und Parameter vergeben werden. Eine mögliche Konfiguration ist in Abbildung \ref{fig:delayed_off_bms} dargestellt.
}
\nxagraphic
{examples/fig/lock_bms.png}
{examples/fig/lock_bms.png}
{Defining the command within the \productbmsstudio}
{Definieren des Kommandos im \productbmsstudio}
{delayed_off_bms}
{200pt}
{0.5pt}
\nxatext
{
After having saved the ``XCommand event definition'', restart the \productbmsserver\ and test the command.
}
{
Nachdem die ``XCommand event definition'' gespeichert wurde, muss der \productbmsserver\ zum Testen des Kommando neu gestartet werden.
}