Usage

See Cross System Communication for more usage and full examples.

Overview

This section provides usage examples and walkthroughs to implement various proposed models. The GettingStarted section below is a good place to start if you’ve never used ATN before and want to get a simple example up and running quickly. If you’re looking for more specific examples, you can reference the individual pages in the ATNTools section at the bottom of this page.

Background

Topics as Global Strings

Each ATN function call that is referencing an individual topic uses a variable of type STRING to specify the topic name. This is typically the first argument passed in to ATN functions. For example:

PROGRAM _INIT

    // Passing a string directly to an ATN function call (less common, prone to typos).
    registerStateBool( 'gCommandsApi.powerAllAxes', 'Axis Module', localInterface.cmd.powerOn );

    // Passing a global STRING variable to ATN function call.
    // The 'populate' function is used first to populate the string names. 
    varPopulateMemberNames('gCommandsApi', 0);
    registerStateBool( gCommandsApi.powerAllAxes, 'Axis Module', localInterface.cmd.powerOn );

END_PROGRAM

The two calls to registerStateBool are equivalent, but the second one is usually preferred to avoid typos and centralize string assignments. The strings used need to match on the registration and subscription sides for the logic to function.

Note that the varPopulateMemberNames is a utility function from the VarTools library that takes in as its first parameter the name of an existing global structure, and populates all of that structure’s children with string values equal to the names of their variables. In a Watch window, this would look something like the following:

WatchWindowPopulate

Stateless Function Calls

Once ATN is initialized by calling atninit, the majority of its functionality is handled via stateless function calls from the modules, and there is no need to cyclically call any function blocks to manage the ATN core. This makes it a very lightweight broker that does not require a central management task, and can instead have all of its function calls fully distributed among applications modules.

Getting Started

This section walks you through setting up a simple “Hello World” example using ATN. It features two Modules, A and B, that exchange state information.

Global Variable Setup

In order to follow best-practices, define the string for the state that will be shared between modules as an element in a global structure in the Global.var file. In that same file, define a console buffer that will be used to store the overall status strings for the ATN core.

VAR
	gCommandsApi : CommandApi_typ;
	gConsole : Console_typ;
END_VAR

The two structures referenced above should get defined in the Global.typ file as follows:

TYPE
    Console_typ : 	STRUCT 
		Command : STRING[80];
		Console : ARRAY[0..100]OF STRING[80];
	END_STRUCT;
	CommandsApi_typ : 	STRUCT 
		testCommand : STRING[80];
	END_STRUCT;
END_TYPE

Calling atninit()

The atninit function initializes the ATN core, and should be called before any other ATN functions. Because of this, it is recommended to call this in the INIT section of the first task that is deployed in cyclic #1.

PROGRAM _INIT

	atninit(ADR(gConsole.Console), SIZEOF(gConsole.Console));

END_PROGRAM

Setup for Module A (source)

Module A acts as the source in this example, meaning that it registers a local status to ATN. The only required code here is performed in the INIT section of the task, and serves to link the local BOOL variable stateFlagModuleA to the gCommandsApi.testCommand state.

PROGRAM _INIT

	registerStateBool(gCommandsApi.testCommand, 'Module A', stateFlagModuleA);

END_PROGRAM

Setup for Module B (subscriber)

Module B acts as the subscriber in this example, meaning that it reads the value of a state from ATN. The read is performed cyclically, and the ATN state is stored locally in the BOOL variable stateFlagModuleB. This BOOL can be used as the basis for conditionally executing other logic.

PROGRAM _CYCLIC

	stateFlagModuleB := stateAnyTrue(gCommandsApi.testCommand, 0);

END_PROGRAM

Testing it out

With this code in place, the behavior can be tested by setting stateFlagModuleA to TRUE in Module A and observing that stateFlagModuleB then gets set to TRUE as a result.

ATN Tools

These are collections of functions that enable certain design patterns. The sections below describe each of these in more detail.