• No results found

Amx Netlinx Programming Ba01

N/A
N/A
Protected

Academic year: 2021

Share "Amx Netlinx Programming Ba01"

Copied!
87
0
0

Loading.... (view fulltext now)

Full text

(1)

AMX University

Introduction to

(2)

July 2004

Copyright

AMX Corporation, 2004. All rights reserved. No part of this publication may be reproduced, transcribed, stored in a retrieval system or translated into any language in any form by any means without the written permission of AMX.

Credits

Written by AMX University.

Printed in Dallas, Texas.

For additional questions or suggestions, feel free to call us.

AMX University 3000 Research Drive Richardson, TX 75082 Phone 469.624.8000 Fax 469.624.7192

(3)

Copyright

AMX Corporation, 2004. All rights reserved. No part of this publication may be reproduced, transcribed, stored in a retrieval system or translated into any language in any form by any means without the written permission of AMX.

Credits

Written by AMX University.

Printed in Dallas, Texas.

For additional questions or suggestions, feel free to call us.

AMX University 3000 Research Drive Richardson, TX 75082 Phone 469.624.8000 Fax 469.624.7192

(4)

Table of Contents

Table of Contents

Welcome ...1

Course Objectives ...1

Introduction ...2

The AMX Language Course... 2

What is NetLinx? ... 2

Unit 1: Language Basics ...3

Chapter 1 - Simply the Basics ...3

Introduction... 3

Format of the Language ... 3

Statements and Compound Statements ... 4

Comments Within the Program ... 5

Identifiers... 6

Reserved Words... 6

Special Characters and Operators ... 6

Chapter 2 - The Definition Sections ...7

Starting a New Program ... 7

Defining Devices ... 7

Defining Constants ... 9

Defining Variables ... 10

Startup Code ... 11

DEFINE_EVENT and Mainline in NetLinx... 11

Chapter 3 - Using Input and Output ...13

Controlling Something Over There... 13

The Device-Channel Concept ... 13

All About the Channel... 13

Changing the State of a Channel ... 15

Putting Input and Output Together ... 18

Chapter 4 - Channel Characteristics ...19

The Parts of an Output Channel... 19

Mutually Exclusive... 19

Putting it All to Work ... 21

Programming Feedback ... 23

Grouping Feedback Statements... 24

(5)

Chapter 5 – Conditional Expressions ... 25

Introduction ... 25

Conditional Expressions... 33

The IF Statement ... 33

The IF...ELSE Set of Statements ... 33

Repeating IF...ELSE Set of Statements... 34

Nesting ... 34

The SELECT...ACTIVE Statement... 35

Trying it Out... 36

Conditional Operators ... 39

Chapter 6 – The Wait Keywords ... 41

Controlling Time Within the AMX System ... 41

The WAIT List ... 41

Multiple Wait Statements ... 43

Special Uses of Wait ... 45

Naming Wait Statements ... 45

Canceling, Pausing, and Restarting Wait Statements ... 46

The WAIT_UNTIL Keyword... 46

Misusing WAIT_UNTIL... 47

Naming and Removing WAIT_UNTIL Statements ... 47

Unit 3: Levels ... 49

Chapter 7 – Creating and Using Levels ... 49

Introduction ... 49

What is a Level?... 49

Creating Levels ... 49

Reading Levels ... 52

Making a Preset ... 52

Using Bar Graphs... 53

Connecting Levels... 53

Unit 4: Arrays and Sending and Receiving Strings ... 55

Chapter 8 – Arrays and Strings ... 55

Introduction ... 55

Defining Arrays... 55

Accessing and Storing Array Values... 56

Data Types... 59

Strings ... 60

(6)

Table of Contents

String Elements ... 61

String Lengths ... 62

Sending Strings and Arrays... 63

ASCII Codes... 64

Integer Arrays... 64

Chapter 9 – Working with Arrays ...67

Grouping Data ... 67

Conversion keywords ... 67

Array Manipulation Keywords... 69

UPPERCASE vs. lowercase ... 71

Setting Uppercase and Lowercase ... 71

Chapter 10 – Receiving Strings ...73

Listening to the Outside World ... 73

Receiving Strings ... 73

Storing characters ... 73

Retrieving Characters... 74

Appendix: Troubleshooting ...75

ESCAPE... 75

Appendix: Standard IR Function Order ...77

(7)
(8)

Welcome

Welcome

Welcome to Introduction to AMX Programming. This self-paced course is for new Programmers, Installers who want to learn AMX programming, and Technical Support Personnel and teaches the basic techniques for programming an AMX Control System. A person completing this self-paced course will be able to understand a basic AMX program and have the basis for successful completion of subsequent AMX programming classes.

This manual is designed to be both a reference for on the job and a tool for self-paced training. White space is available on every page for taking notes. There is references to programming code that accompanies this manual. The companion code files are in the zip file that also contains this manual. Good luck!

Course Objectives

Upon completion of this self-paced course you will be able to: ! Understand the basic principles of AMX Programming ! Understand the core components of AMX devices

! Understand how to program channels, levels, and strings related to each device ! Understand Buffer/ String Processing functions

(9)

Introduction

The AMX Language Course

This self-paced course takes the approach of teaching the common elements of AMX Programming languages while developing real world AMX Control System programs. You will start with the basic commands and simple control scenarios, and progress on to more complex programming as you discover new programming functions and techniques. With the exception of additional keywords and objects in the NetLinx programming language, there are very few differences in many programs.

What is NetLinx?

In the continuing evolutionary process of control systems AMX introduced the NetLinx Control System. NetLinx is the most advanced control system developed in that process. The NetLinx system can not only control devices connected directly to it’s control ports and local control networks but can control and communicate seamlessly to other control systems and devices on Ethernet networks and the Internet. The NetLinx hardware takes the experience gained from more than a decade of Axcess system installations to make a more powerful control system.

To enable this giant step in system development the Axcess programming language, the basis of the Axcess control system, was enhanced and supplemented to provide the programming power for NetLinx.

The NetLinx system is an Event driven system. As inputs come into the system that input is compared against an Event table. This Event table can keep track of things such as button presses on a panel, channels turning on and off, and responses received from connected devices. You will see many Events in examples throughout the tutorial, and this concept will be discussed later in Chapter 2 in DEFINE_EVENT and Mainline in NetLinx on page 11 and in greater detail in AMX Programmer I.

(10)

Unit 1: Language Basics

Unit 1: Language Basics

Chapter 1 - Simply the Basics

Introduction

This unit will help you start writing AMX programs. By the end of this unit you should be familiar with several concepts:

! Basic ground rules for writing AMX programs ! The device channel concept

! The different sections that make up an AMX program ! How NetLinx executes a program

! Basic input and output functions ! Simple feedback.

As you progress through the chapters you will develop a simple Axcess program containing these basic features, and you will build on this program in later units.

Format of the Language

The AMX languages can be written in a free format, meaning that the source code is independent of tabs and carriage returns. Because of this, it is advised to use a consistent method of code

placement in order to make the code more readable. In this manual, an “outline” format is used; that is, each subsection of a section is slightly indented. For example:

BUTTON_EVENT[PANEL,1] { PUSH: { IF (X = 1) { Y = 2 Z = 3 } } }

(11)

Statements and Compound Statements

During programming, most of the keywords and operators require a complete statement. A keyword is a word or series of words that signifies the operation for the system to execute. That keyword and all its parameters form the statement. For example, the keyword to turn a channel on is merely ON. However, the statement to turn on a particular channel (let’s say channel 6) is

ON[RELAY_CARD,6]. Statements can also involve mathematical or logical operations when operators are used. An operator is a character that performs a specific mathematical or relational function. For example, the operator used to set a variable equal to a value is the equal sign (=). As expected, the statement used to set variable X to the number 5 is X = 5.

You will frequently have to group several different statements together into one compound statement. The braces “{ }” are used to enclose this type of statement. Compound statements are used if several statements are to be executed in a situation where program syntax will allow just one. The statements are executed in the sequence in which they are programmed. The number of open braces “{” and close braces “}” must be the same in your program. For each open brace there should be a corresponding close brace. The compiler will point out this error to you if the quantities are different after compiling.

Compound statements give you the ability to group multiple statements together into one unit, much like grouping sentences together into one paragraph. The most common example of compound statements occurs with the PUSH keyword. (This keyword is explained in depth later.)

BUTTON_EVENT[PANEL,1] { PUSH: { ON [RELAY_CARD,5] X = 5 } }

In this example, when button 1 on PANEL is pressed, relay 5 on RELAY_CARD is turned on. Also, the variable X is assigned the value of 5. The open brace indicates the beginning of the compound statement, and the close brace ends it. If you only needed the relay to be turned on, the statement could have been written like this:

BUTTON_EVENT[PANEL,1] { PUSH: { ON [RELAY_CARD,5] } }

(12)

Chapter 1 - Simply the Basics

The code example on the previous page uses two special operators. The chart below list more detail about these operators. You will see these used throughout the manual.

Comments Within the Program

AMX programming languages allow you to place helpful comments inside your program. A comment is a description or remark that is not considered part of the actual program. Once something is marked as a comment it will not be compiled. It exists only to help people read the code. There are three ways to mark something as a comment. The quickest method is to use a //. Any text following // will not be compiled. However, the // only designates that the text until the end of that current line is a comment. The text which would appear on the next line would be compiled.

//This section will define all the devices used. DEFINE_DEVICE

VCR = 1:1:0 // ACME VIDEO CASSETTE RECORDER MODEL 1000 CD = 2:1:0 // ACME COMPACT DISC PLAYER MODEL 2000

In the above code the first line is just a header. It is preceded by a // so it is not compiled. After the devices VCR and CD are addressed there is a comment explaining that line of code. This method requires a // to be entered everywhere you want to make a comment. But, there may be situations where you want to mark several lines as a comment. You could use // but you would have to insert that before each line. To make this easier, NetLinx supports two more methods of making

comments. Both methods work the same way. Any text after (* and before *), or after /* and before */ will also not be compiled, even if the text is separated over several lines. See the following example:

BUTTON_EVENT [T_PANEL,1] // SLIDE PRESET {

PUSH: {

(* HERE IS WHERE I WILL PLACE SEVERAL LINES OF CODE TO BE RUN WHEN BUTTON NUMBER 1 IS PUSHED ON THE PANEL *) }

}

BUTTON_EVENT [T_PANEL,2] // VHS PRESET {

PUSH: {

/* HERE IS WHERE I WILL PLACE SEVERAL LINES OF CODE TO BE RUN WHEN BUTTON NUMBER 2 IS PUSHED ON THE PANEL */ }

}

Special Operators

Operator Name Function

{ } Braces Combine several statements into a compound statement

[ ] Brackets

Enclose the device-channel: [device,channel]

Enclose the size or location of a storage space in an array Enclose the instance number used with a SYSTEM_CALL Enclose a variable to be turned on or off

( ) Parentheses

Enclose the expression after an IF statement Enclose a mutually exclusive set in the Define section Group a mathematical operation

(13)

Here the button is labeled using // but the longer comments are marked using a different (* or */. You can place any number of comments in your program. However, when the program is compiled, they will be passed over. Comments have no effect on the actual operation of the program. It is wise to use comments. They are especially helpful in a long program where you can label each part of the program for future reference. If changes have to be made, you can merely look for the label of the section you need to edit. As illustrated above, descriptions of PUSH statements are very useful.

Identifiers

Identifiers are used to denote a device, constant, or variable. For example, T_PANEL could represent an AMX Touch Panel, PLAY could represent the first channel, and CD_SELECT could represent the current compact disc player. The guidelines for identifiers are as follows:

! They must begin with a letter followed by any combination of letters, numbers, or underscores. No spaces are allowed.

❑Valid identifiers: CD3, TOUCH_PANEL, VCR3_SELECT ❑Invalid identifiers: 3VHS, CD PLAYER, *RGB4 ! The identifier must have less than 26 characters.

! Identifiers are not case sensitive. For example, Touch_Panel is the exact same identifier as TOUCH_PANEL

! The identifier must be unique. Once you define VHS3, do not choose the same name later for a different identifier.

Reserved Words

There are certain words that are reserved as keywords or functions. These are integral to the system and cannot be redefined or used as identifiers. For example, PUSH cannot be used as an identifier, because the system recognizes it as a keyword.

Special Characters and Operators

There is also a complete set of symbols that are used within the program. These symbols represent a wide variety of characters and operators.

Mathematical Operators Relational Operators

Operator Function Operator Function

( ) Parentheses < Less than

* Multiply > Greater than

/ Divide <= Less than or equal to % Modulo >= Greater than or equal to

+ Add <> Not equal to

(14)

Chapter 2 - The Definition Sections

Chapter 2 - The Definition Sections

Starting a New Program

Now that the ground rules are laid out, you can start writing your first program! When you begin a new program, also referred to as a source code file, in NetLinx Studio you are not given an empty file with which to work. Instead, there are several definition headings to signify what should be defined in each section. The definition sections that are given to you are the following:

! DEFINE_DEVICE ! DEFINE_CONSTANT ! DEFINE_TYPE ! DEFINE_VARIABLE ! DEFINE_LATCHING ! DEFINE_MUTUALLY_EXCLUSIVE ! DEFINE_START ! DEFINE_EVENT ! DEFINE_PROGRAM

Feel free to delete any of these headings you do not need, and keep those that you do. If you do not have any statements under one of these headings, your program will not operate any differently. However, you might want to keep the headings there for future reference. Although the definition sections are not used within the main program, they create the materials the main program needs. Devices and their channels are given names, channels are given different characteristics, and variables are formed. Even the immediate startup procedures of the AMX control systems are within a definition section. If you develop a good understanding of the Define statements, you will be able to build an excellent foundation for the main part of your program.

Defining Devices

When you start writing a program, you should first label each device in the system. Each device connected to the master must have a unique device number. Card 1 may have device number 1, and card 2 may have device number 2. Any time these device numbers are referenced in the program, the master checks the corresponding device. However, with a long list of devices connected to the control networks, these numbers can be difficult for a programmer to remember. Assigning actual names to these devices is much easier.

This is the function of the DEFINE_DEVICE section. It is placed at the beginning of the program, and it lets you name the devices. Whenever you use this device name in your program, the compiler will automatically use the corresponding device number to reference the device.

(15)

You should start writing your program by first defining the devices in your system. Suppose you have a VCR, a CD player, and a cassette deck, and you are controlling them with the first three IR outputs on an NI-3000. These IR outputs have device numbers 5001:9:0, 5001:10:0 and 5001:11:0. They will have these device numbers because these devices are connected to ports 9, 10 and 11 on the NI-3000. The program will reference the port that you need to control. You can name that port after the device you are going to connect to it. That way the code will make sense for people who read it. The compiler will continue to reference the full port address. The naming is just for readability.

Additionally, you also want to control a projection screen, some drapes, and lights. The relays of the NI-3000 will control the screen and drapes and the I/O device of the NI-3000 will control the lights. A Touch Panel will be the user interface to control all of these devices (in this instance an NXT-CV15). Here is what your DEFINE_DEVICE section should look like:

DEFINE_DEVICE

RELAY = 5001:8:0 (*NI-3000 RELAY OUTPUTS 1-8 *) VCR = 5001:9:0 (*NI-3000 IR OUTPUT #1*) CD = 5001:10:0 (*NI-3000 IR OUTPUT #2*) CASS = 5001:11:0 (*NI-3000 IR OUTPUT #3*) LIGHTS = 5001:16:0 (*NI-3000 I/O 1-4*) TP = 10128:1:0 (*NXT-CV15 TOUCH PANEL*)

From this point on, you can reference device 9 with the name VCR, device 10 with the name CD, and so on. The compiler will understand that when the code references CD it is actually referring to 5001:10:0 and so everything will work properly.

Notice the Touch Panel is the only device not addressed with 5001. That is because the Touch Panel is an independent device. It is not integrated into the NI-3000 like the other references. Where as the VCR, CD, CASS and LIGHTS are all controlled by different ports on the NI-3000, the Touch Panel is a stand alone device; therefore, the addressing must be different.

FIG. 1 NI-3000 is Device 5001

VCR Port 9 CD Port 10 CASS Port 11 Device 5001

(16)

Chapter 2 - The Definition Sections

Defining Constants

Constants are identifiers whose values remain unchanged throughout the entire program. The process of defining them is very similar to defining devices. Assigning a value to an identifier in this section locks that value to the identifier for the entire program, making it possible to use descriptive names instead of just numbers in your program.

In your system, the VCR, CD player, and cassette deck IR devices have channels that activate the various transport functions, such as Play and Stop. As a general rule, Play is usually channel 1 and Stop is channel 2. You could define these channel numbers as constants in your program to make it more readable.

DEFINE_CONSTANT

(* TRANSPORT (IR DEVICE) CHANNEL NUMBERS *) PLAY = 1

STOP = 2 PAUSE = 3 FFWD = 4 REW = 5

(* THE RELAY DEVICE CHANNEL DEFINITIONS *) SCREEN_UP = 1 SCREEN_DOWN = 2 SYS_POWER = 3 DRAPE_OPEN = 4 DRAPE_CLOSE = 5 DRAPE_STOP = 6

(* THE LIGHTS DEVICE CHANNEL DEFINITIONS *) LIGHT_FULL = 1

LIGHT_MED = 2 LIGHT_LOW = 3 LIGHT_OFF = 4

The value of the constant PLAY is 1. STOP has a value of 2. Both of these values cannot be changed anywhere in the program. Later in your program when you need to activate the Play function of the VCR, you don’t have to remember that it is channel 1 of the device—just use the constant PLAY and the system knows to use channel 1. This works in a similar fashion to the DEFINE_DEVICE section. You don't have to remember the full address of the device just what you called it. So you can write code as:

PULSE [VCR, PLAY]

This used the DEFINE_DEVICE reference and the DEFINE constant reference. Without these references the code would have to be written as:

PULSE [5001:8:0, 1]

If you have a number of devices with varying functions the device and channel numbers could be difficult to remember. DEFINE_DEVICE and DEFINE_CONSTANT can help reduce that confusion.

By definition, the same constant cannot reference more than one number. This may seem obvious, but this type of error could work its way into large programs. If you make this mistake, the compiler will notify you with a “Duplicate symbol” error message upon compiling.

(17)

Defining Variables

Variables are places to store data that will change as the program is executed. Think of a variable as a "storage box;" nearly anything can be placed in here. Variables can hold many types of data. But, any single variable can only hold one type of data. Since a variable can hold only one of several possible types of data, you must specify what type of data is going into the variable when it is defined. This 'box' that we are referring to is really an allocation of memory inside the processor. Inside that memory the processor will store a value that can change based on the events that occur and how the program is written to handle those events. Depending on what you are trying to accomplish you may need to store integer values. An integer is an numeric value between 0 and 65535. Then again, you may have a situation which requires you to store character values. Characters are letters or numbers between 0 and 255. If you do not define the type of data to be stored in a variable when it is defined the processor will default the variable type to Integer.

Just as variables can store different types of data, they have different behavior characteristics. Some variables retain there values even after the Master processor is powered off and some do not. Some variables can be used throughout the whole program and some only in certain subsections. These concepts will be covered in further detail as you get more involved in programming. For now, you just need to understand that variables can hold different types of data and that these values can change while the program is running.

In your first program you will not be using variables, but keep the DEFINE_VARIABLE header because you will be using them in the future. The DEFINE_MUTUALLY_EXCLUSIVE section is also used and explained later.

(18)

Chapter 2 - The Definition Sections

Startup Code

When the AMX Control System is turned on, the program that was last loaded into the system will begin to operate. However, you can tell the system to run a series of statements immediately when the system is turned on. These statements are placed under the DEFINE_START header, and they are run only once on power-up. They cannot be executed again until another system power-up. In your program, you may want to reset all three decks to STOP when the system is powered up. Here is what your DEFINE_START section should look like:

DEFINE_START PULSE[VCR,STOP] PULSE[CD,STOP] PULSE[CASS,STOP]

Remember, code in this section will only run when the Master processor powers up. Typically, control systems will not be rebooted once they are in place. However, they may lose power, have code reloaded, system maintenance, etc. Any of these situations could cause a reboot of the Master which would allow the DEFINE_START code to run.

DEFINE_EVENT and Mainline in NetLinx

The DEFINE_EVENT section and the DEFINE_PROGRAM section is where most of the programming will take place. These two sections run concurrently but in different ways to give the programmer options on how the system could work. The DEFINE_EVENT section allows extremely fast program functions. It makes no difference how large the program is, each button press or other input is immediately accomplished. This section is where the majority of our programming is completed.

The DEFINE_PROGRAM section (also called Mainline) accesses its programming in a loop fashion. The processor continually scans the program looking to keep all of its information current. The processor starts at the beginning runs through the end of the program in order. Because of that, if this section has a very large amount of programming, it could adversely affect the speed or timing of the program. Therefore, it is recommended to put most of our programming in the

DEFINE_EVENT section.

Because the DEFINE_EVENT section is more efficient, when there is programming for a particular button press in both sections, the Master will perform the programming in the DEFINE_EVENT section and the programming in the DEFINE_PROGRAM section will be bypassed. So, the DEFINE_PROGRAM section's primary role is maintaining feedback.

Figure 2, on page 12 illustrates message and mainline processing as it appears in the NetLinx system. Note that bus servicing is taken care of by a separate process thread (Connection Manager

& Message Dispatcher) and therefore is not a task that must follow mainline.

You should avoid putting button presses in both sections of code even though the mainline section will be ignored in this event.

(19)

FIG. 2 Message and Mainline Processing in the NetLinx System

(20)

Chapter 3 - Using Input and Output

Chapter 3 - Using Input and Output

Controlling Something Over There

The basic idea behind remote control is to do something over here to make something happen over there. In an AMX system, the “something over here” is usually some kind of control panel, such as a wireless remote control panel or a Touch Panel to generate an input. The “something over there” can range from a simple relay to a complex lighting system to receive the output from the control system.

In DEFINE_EVENT you define what happens when these inputs occur. But how do you get your inputs in the program? How do you generate an output? The answer: you use devices and channels.

The Device-Channel Concept

Everything that is controlled by an AMX control system is considered to be a device on the system. Each device in that system communicates to the master through control networks. Netlinx used 4 control networks: AXlink, ICSNet, ICSHub and Ethernet. Most devices, such as a Touch Panel or a relay card, have channels which either accept an input, generate an output, or both. These inputs and outputs are referred to in the program as a “device-channel pair,” which is written like this:

[8:1:0,1]

This device-channel references channel 1 of device 8 on port 1 in system 0. If device names and constants are used instead of numbers, the same reference could look like this:

[VCR,PLAY]

Using device names and constants is obviously much more readable. This concept of the device-channel is the most basic concept of the entire AMX control system, as it is the most common way that the program communicates to the outside world.

All About the Channel

Almost all methods of control using an AMX system require the use of channels on devices. Every channel has two aspects: the input function and the output function. When a button is pressed on a control panel, the input function of the button sends an input change to your program. The input change alerts the Master to scan your program for a reference to that input.

In the NetLinx system a device can have multiple ports, therefore each port must be addressed. Additionally, since many NetLinx systems can be connected together, up to 65,535, each device receives the system ID of the connected Master. This addressing scheme is referred to as the Device:Port:System triplet.

(21)

When there is an input change, the Master passes through the EVENT LIST section once to see if the change is referenced. If so, the Master executes the statement(s) in the program associated with the input change. There are 3 keywords used in conjunction with input changes:

PUSH

The PUSH keyword is used to find out if a channel has had an input change from “off” to “on,” such as when a button is pressed. If the channel has been turned on, the corresponding PUSH statement is activated. The operation or operations following this PUSH statement are only executed once after the channel is turned on.

The BUTTON_EVENT/PUSH keyword requires two parameters: a device number and a particular channel enclosed in brackets. A device name or constant can be used in place of a literal number. For example: BUTTON_EVENT [10128:1:0,1] { PUSH: { Y = 2 Z = 3 } }

If PANEL is defined as device number 10128:1:0, and PLAY is defined as a constant with a value of 1, the following is the same:

BUTTON_EVENT [PANEL, PLAY] { PUSH: { Y = 2 Z = 3 } }

Following the PUSH statement is the operation to be executed when the PUSH occurs. If more than one event must happen, a compound statement must follow the PUSH. (See the earlier discussion on compound statements.)

•PUSH •RELEASE •HOLD

(22)

Chapter 3 - Using Input and Output

RELEASE

The RELEASE keyword is used in the same way as a PUSH, except that the statements following a RELEASE statement will be executed if the associated channel is released. For a button on a touch panel this happens when you let up on the button.

BUTTON_EVENT [PANEL, PLAY] { RELEASE: { Y=1 } } HOLD

A HOLD keyword specifies the actions that should be performed when a button is pressed and held for a minimum length of time indicated by the Time Parameter. (TIME is specified in 0.1 second increments). If a repeated action is desired at the same time increment, add the keyword REPEAT within the Time Parameter brackets. Remember, REPEAT is optional.

BUTTON_EVENT [PANEL,PLAY] {

HOLD [TIME PARAMETER,REPEAT]: {

Z=1 } }

All three of the keywords can be placed under the same BUTTON_EVENT. BUTTON_EVENT[PANEL,PLAY] { PUSH: } RELEASE: { Y = 1 } HOLD[5]: { Z = 1 } }

Changing the State of a Channel

So now you can respond to an input change in your program, and you want it to activate a different device-channel. The next series of keywords allow you to activate channels based on an input change. This activation is called an output change, which is a message to the output function of a channel. The keywords to do this are:

•ON •TO

•OFF •PULSE

(23)

When you use one of these keywords to activate a channel in a device, the device starts the operation that is associated with the channel. For instance, activating channel 5 on a relay card activates the physical relay number 5, whereas channel 5 on an infrared/serial card causes it to generate the infrared pattern it has stored at location 5.

Variables can be used as output channels also, but doing so does not actually cause an output change. When a variable is activated as a channel, turning it “on” gives it a value of 1 (or makes it true), and turning it “off” gives it a value of 0 (or makes it false). Remember that in NetLinx programming language off = false = 0 and on = true = any number greater than zero.

Following are brief definitions of each of the output change keywords.

ON

The ON keyword simply turns on a channel or variable. If the channel or variable is already on, its status will remain unchanged. Here are two different examples:

ON[RELAY_CARD,2] //THIS TURNS ON CHANNEL 2 OF RELAY_CARD.

ON[TEMP] //This sets the value of the variable TEMP to 1.

A variable is considered “on” if it contains a nonzero number; in this case, the value is 1. If a variable contains the value zero, it is considered “off.”

OFF

The OFF keyword turns a channel or variable off. The channel or variable will remain off if it is already off. Here are two different examples:

OFF[RELAY_CARD,2] //THIS TURNS OFF CHANNEL 2 OF RELAY_CARD. OFF[TEMP] //This sets the value of the variable TEMP to zero.

TOTAL_OFF

The TOTAL_OFF keyword acts in the same manner as OFF, except that it also turns off the status of a channel or variable that is in a mutually exclusive set. Mutually exclusive sets are discussed later in this unit.

PULSE

The PULSE keyword turns on a channel or variable for a certain amount of time. Once the time elapses, the channel or variable is turned off. As an example, refer back to the discussion on DEFINE_START. The PULSE keyword was used to activate the three decks’ Stop function. The default duration of this pulse is one half-second, but it can be changed if necessary with the SET_PULSE_TIME keyword. The pulse time is measured in tenths of seconds. The pulse time remains the same value until it is changed within the program. For example:

SET_PULSE_TIME (12)

(24)

Chapter 3 - Using Input and Output

TO

The TO keyword is used to activate a channel or variable for as long as the corresponding device-channel of its PUSH statement is activated. When the device-channel referenced by the PUSH statement changes from OFF to ON, the TO starts activating the device-channel or variable in the brackets following it. When the device-channel of its PUSH is released, the TO statement stops activating its device-channel or variable. The TO keyword has several conditions:

! It must be used only below a PUSH statement.

! It cannot be used with the WAIT keyword. (This will be explained later.) ! It cannot be placed within the DEFINE_START section.

The channel or variable will act under the rules set by DEFINE_MUTUALLY_EXCLUSIVE. You will learn what that definition section means later when you add more to your program.

BUTTON_EVENT [PANEL, 6] {

PUSH: {

TO [RELAY, 6] // THE RELAY WILL TURN ON WHILE BUTTON HELD TO [TEMP] // THE VARIABLE WILL BE TRUE WHILE BUTTON HELD }

}

MIN_TO

The MIN_TO keyword is used to activate a channel or variable for at least a minimum amount of time or as long as the corresponding device-channel of its PUSH statement is activated. When the device-channel referenced by the PUSH statement changes from OFF to ON, the MIN_TO starts activating the device-channel or variable in the brackets following it. When the device-channel of its PUSH is released, the MIN_TO statement stops activating its device-channel or variable if the button was held for at least the minimum amount of time as set by the pulse time. The MIN_TO keyword has the same conditions as the TO keyword:

! It must be used only below a PUSH statement. ! It cannot be used with the WAIT keyword.

! It cannot be placed within the DEFINE_START section.

Direct Assignment

There is another method of generating an output change, but it does not involve the use of any keywords. Any reference to a device-channel that does not have the keywords PUSH or RELEASE preceding it is a reference to the output side of the channel. Thus assigning a value directly to a device-channel changes the output of the channel. For example:

[PANEL,1] = 1

This statement will send an output change to channel 1 of device PANEL, telling the channel to turn on since the master interprets any non-zero number as “on.” Putting this statement in mainline will make the channel be forever on. Using direct assignment is only appropriate in feedback

(25)

Putting Input and Output Together

Combining input and output changes into one statement is the basis of most AMX Control System programming. Now that you have these tools, you can write the code that can actually accomplish this. On your Touch Panel, you will have button numbers 1 through 5 activate the five transport functions of the VCR: Play, Stop, Pause, Fast Forward, and Rewind. Here is your first section of program code: BUTTON_EVENT[TP,1] { PUSH: { PULSE[VCR,PLAY] } } BUTTON_EVENT[TP,2] { PUSH: { PULSE[VCR,STOP] } } BUTTON_EVENT[TP,3] { PUSH: { PULSE[VCR,PAUSE] }

In this code, there are actually five separate but similar statements. Examine the first to see how it all fits together. First there is a BUTTON_EVENT, meaning we are programming in the

DEFINE_EVENT section. This is followed by a device-channel reference, in this case [TP,1]. Next, an action takes place on the PUSH. This tells the control system, "If channel 1 on the 10128:1:0 device receives an input change from OFF to ON (i.e. someone pushed a button) execute the statement that follows." If such an input change occurs, the corresponding PULSE statement executes. The PULSE statement tells the control system, “When channel 1 on device 10128:1:0 is activated, PULSE device 5001:8:0, channel 1.” You may be wondering where the numbers came from, since the PUSH and PULSE statements have the words TP, VCR, and PLAY. Remember, TP and VCR are identifiers for devices 10128:1:0 and 5001:8:0 respectively and PLAY is a constant with a value of 1.

Duplicate the above section for the CD player and the cassette deck, replacing VCR with CD and CASS where needed. Also be sure to use different channel numbers for the PUSH statements, or one activation of channel 1 could make all three decks play at the same time. Touch Panel

BUTTON_EVENT numbers for the CD player are 9-13, for the Cassette deck use channels 17-21.

Now that you have the transport functions of your decks programmed, you can add the rest of the functions on your panel to the program. But before you do that, you need to learn about the other definition sections: those that define the characteristics of a channel.

(26)

Chapter 4 - Channel Characteristics

Chapter 4 - Channel Characteristics

The Parts of an Output Channel

An output channel actually has two parts, the physical part and the status part (simply referred to as “status”). The physical part is the device-dependent physical control, such as a relay on a relay card, a button light (“lamp”) on a Touch Panel, or an infrared pattern in an infrared card. The physical part of a channel can be only one of two things, on or off. The status is what records the state of the physical part and reports it to the Master. In most applications, these two parts act exactly the same; when one is on, so is the other.

However, you can change the way the status (or reporting) part of an output channel behaves. In this chapter, you will be shown how to change the status behavior, which in turn changes the way a channel reacts when it is activated by the output change keywords.

All channels are momentary by default.1 When a momentary channel is activated with a TO keyword, it activates its output and status only as long as the button which activated the TO keyword is pressed. For example, the Focus channel for a certain slide projector is momentary. When the corresponding Focus button is pressed, the slide projector will focus. The projector will continue to do so until the button is released.

Mutually Exclusive

Channels can also be defined as mutually exclusive. This will change their functionality somewhat. A mutually exclusive group is a set of channels in which only one channel of the set can be turned on at a time. When a channel is activated in a mutually exclusive set, it turns on its physical output for the time period specified by the keyword being used. However, when the physical output stops the status does not follow as it normally would. Even after the physical output stops, the status still indicates that the channel is on until another channel in the mutually exclusive set is activated. The status is on to let you know which channel in the set was last activated. This is sometimes called “last button pressed” feedback.

Before a channel or variable in this set is activated, all the other members of the set are turned off beforehand. This is called “break before make” logic. This prevents an accidental activation of more than one channel at the same time, which could cause serious damage to some devices.

For example, consider the drape and screen channels of the device RELAY. Since you cannot open and close a drape all at once, and you cannot raise a screen and lower it at the same instant (it could damage some motors if you tried!), only one channel can be turned on at a time. They must be defined as mutually exclusive. When SCREEN_UP is activated, the SCREEN_DOWN channel is turned

1. Actually, the correct terminology here is the status of all channels is momentary by default. However, in the common language of programmers, “status” is understood. From this point on in the manual, the behavior of status will be described in this manner.

(27)

off and SCREEN_UP turns on. The corresponding SCREEN_UP status stays on even though the relay is de-energized when the button is released. When SCREEN_DOWN is activated, SCREEN_UP is turned off. The SCREEN_DOWN status is now the only status turned on.

You also will define the lighting relays as mutually exclusive so that you can utilize the “last button pressed” logic when you program the feedback for these buttons. This will allow the user to look at the panel and know which lighting preset he or she activated last.

Members of a mutually exclusive set are placed in parentheses underneath the

DEFINE_MUTUALLY_EXCLUSIVE keyword. The double period (..) shortcut is used to indicate a range of channels. The example below would be used to define Mutually Exclusive channels for the devices and channels illustrated on FIG. 1 on page 8 of this manual:

DEFINE_MUTUALLY_EXCLUSIVE

([RELAY,SCREEN_UP],[RELAY,SCREEN_DOWN]) // RELAY CHANNELS 1 AND 2 ([RELAY,DRAPE_OPEN]..[RELAY,DRAPE_STOP]) // RELAY CHANNELS 4 - 6 ([LIGHTS,LIGHT_FULL]..[LIGHTS,LIGHT_OFF]) // LIGHTS CHANNELS 1 - 4 ([VCR,PLAY]..[VCR,REW]) // VCR TRANSPORT CHANNELS 1 - 5 ([CASS,PLAY]..[CASS,REW]) // CASS TRANSPORT CHANNELS 1 - 5 ([CD,PLAY]..[CD,REW]) // CD TRANSPORT CHANNELS 1 - 5

The first set defines the two screen channels as mutually exclusive. Using the shortcut, the second set defines the three drape channels as mutually exclusive, and the third set defines the four lighting relays as mutually exclusive. The fourth through the last sets also use the shortcut to define the five transport functions as mutually exclusive. This is done to achieve “last button pressed” status for those decks. When you add the feedback statements to the program, the buttons for the VCR, CD player, and cassette deck will indicate the last button selected from each group.

Once a channel has its status turned on in a mutually exclusive group, there will always be one channel with its status on in that group, unless it is turned off with the TOTAL_OFF keyword. The TOTAL_OFF keyword is used when you need to turn off the physical channel and its status.

(28)

Chapter 4 - Channel Characteristics

Putting it All to Work

Now that you know how all these different types of channels operate, you can skip down to the mainline section of the program and add these lines to activate your system power, screen, drape, and lighting relays:

BUTTON_EVENT[TP,31] { PUSH: { ON[RELAY,SYS_POWER] } } BUTTON_EVENT[TP,32] { PUSH: { OFF[RELAY,SYS_POWER] } } BUTTON_EVENT[TP,33] { PUSH: { PULSE[RELAY,SCREEN_UP] } } BUTTON_EVENT[TP,34] { PUSH: { PULSE[RELAY,SCREEN_DOWN] } } BUTTON_EVENT[TP,41] { PUSH: { ON [RELAY,DRAPE_OPEN] } RELEASE: {

OFF [RELAY, DRAPE_OPEN] } } BUTTON_EVENT[TP,42] { PUSH: { TO[RELAY,DRAPE_CLOSE] } } BUTTON_EVENT[TP,43] { PUSH: { PULSE[RELAY,DRAPE_STOP]

(29)

} RELEASE: { OFF[RELAY,DRAPE_STOP] } } BUTTON_EVENT[TP,45] { PUSH: { ON[LIGHTS,LIGHT_FULL] } } BUTTON_EVENT[TP,46] { PUSH: { ON[LIGHTS,LIGHT_MED] } } BUTTON_EVENT[TP,48] { PUSH[TP,48] { ON[LIGHTS,LIGHT_OFF] } }

This section accomplishes several tasks:

! A press of the System Power On button turns on the SYS_POWER channel on the device RELAY.

! A press of the System Power Off button turns off the SYS_POWER channel on the device RELAY.

! A press of the Screen Up button will pulse the SCREEN_UP channel on device RELAY, after turning off SCREEN_DOWN. The Screen Down button acts the same way as the Screen Up button, but with the opposite channels. Remember that the PULSE command will activate the channel for the specified pulse time. The default pulse time is one half second.

! Pressing Drape Open, Drape Close or Drape Stop does several things. Button event 41 is written

! so that the Drape Open channel will turn on when the button is pressed and off when the button is released.

(30)

Chapter 4 - Channel Characteristics

! If it is off, it makes sure the other drape channels are off (due to its mutually exclusive relationship), before it turns on. Button event 42 accomplishes the same thing but it uses the TO keyword. The TO keyword automatically turns the channel on when the button is pressed and off when it is released. With the TO keyword, the programmer does not have to handle the ON and OFF commands with the PUSH and RELEASE of the button. These two buttons will do the same thing. When the Drape Stop button is pressed it will PULSE the DRAPE_STOP relay on the relay device. The physical relay will only be active for the pulse but its status (feedback) remains on. (Remember, to turn off the status of a channel in a mutually exclusive group, use the keyword TOTAL_OFF.)

! Since the LIGHTS channels are mutually exclusive, a press of the Lights Full button turns on the LIGHT_FULL channel on the device LIGHTS, after turning off any LIGHTS channel that was previously on. The other LIGHTS channels operate in a similar fashion. Since this code is written using the ON command both the physical relay and the status of that relay will stay on indefinitely unless another one of the relays in the Mutually Exclusive Group is pressed. Notice that the program has no way to turn off any of the channels. This is done by the fact that channels are part of a Mutually Exclusive Group.

Programming Feedback

So far you have been shown how a channel’s output is affected in a program. You know what to do with the input changes and how to create output changes, but now you want to see some feedback on your control panel. Feedback refers to the lighting of a button during and after it is pressed. The Master will not do this automatically; you must tell the system how to light the button. Feedback involves only one statement per button. The first part of the statement references the device-channel of the button that is going to be lit. It is followed by an equal sign (=) and the device-channel corresponding to the source of the feedback, this is called Direct Assignment Feedback. For example:

[TP,1] = [VCR,PLAY]

The light of touch panel channel one will be on when VCR channel 1 (constant value of PLAY) is on. When the channel is off, the light will be off. Remember that any reference to a device-channel that does not have the keyword PUSH or RELEASE preceding it is referring to the output side of the channel. This is a very important concept, because it is the basis of how feedback works.

Also recall that one way of creating an output change is to assign a value directly to the device-channel. If the value that you are assigning is another device-channel reference, this is in effect saying to the system, “Take the output status of channel PLAY on device VCR, and send it as an output change to channel 1 of device TP.” (In other words, reading from left to right.) "Make this ([TP,1]) equal to that ([VCR, PLAY])." So the first device-channel pair is going to be changed to equal the state of the second pair. "Since you defined the device-channel [VCR,PLAY] as being Remember that the left side always equals the right side. So, for feedback purposes

you will always need to list the device channel pairing of the touch panel to the left of the device channel pairing that you wish to tie the feedback to. Touch Panel channel 1 must be equal to VCR channel PLAY. If you write the code the opposite way, the meaning changes entirely.

(31)

in a mutually exclusive group, its status will be on if it was the last channel activated in that set, and the feedback assignment will light button 1 on the control panel. Once a channel has feedback on in a mutually exclusive group, there will always be one channel with feedback on in that group, until turned off with TOTAL_OFF.

Grouping Feedback Statements

The feedback statements can be grouped together in a feedback section at the end of the program. as shown below:

[TP,1] = [VCR,PLAY] [TP,2] = [VCR,STOP] [TP,3] = [VCR,PAUSE]

Direct Assignment feedback statements should only be placed in the DEFINE_PROGRAM section of the program, so it will be updated on a regular basis regardless of event status.

It is recommended that you break your feedback into groups with headings. You can create headings by using comments in your program. This will allow the feedback to be broken into groups in the Mainline section of code that corresponds to hoe the code is written in the DEFINE_EVENT section. For smaller programs this may not be necessary.

(32)

Unit 2: Conditionals and Waits

Unit 2: Conditionals and Waits

Chapter 5 – Conditional Expressions

Introduction

While your first program may look complicated at first, it really doesn’t show the power of the AMX programming languages. The program is what we at AMX call “one-to-one.” That means that each button has one and only one function, with no special conditions or considerations. The control panel has a separate section of buttons for each piece of equipment. (See FIG. 1)

FIG. 1 G3 Panel with each button having it’s only one function.

(33)

PROGRAM_NAME='STEP1'

(* DATE:03/15/02 TIME:12:00:00 *)

(***********************************************************) (* DEVICE NUMBER DEFINITIONS GO BELOW *)

(***********************************************************) DEFINE_DEVICE

RELAY = 5001:8:0 (*NI-3000 RELAY OUTPUTS 1-8 *) VCR = 5001:9:0 (*NI-3000 IR OUTPUT #1*) CD = 5001:10:0 (*NI-3000 IR OUTPUT #2*) CASS = 5001:11:0 (*NI-3000 IR OUTPUT #3*) LIGHTS = 5001:16:0 (*NI-3000 I/O 1-4*) TP = 10128:1:0 (*NXT-CV15 TOUCH PANEL*)

(***********************************************************) (* CONSTANT DEFINITIONS GO BELOW *)

(***********************************************************) DEFINE_CONSTANT

(* TRANSPORT CHANNEL NUMBERS *) PLAY = 1

STOP = 2 PAUSE = 3 FFWD = 4 REW = 5

(* THE RELAY CARD CHANNEL DEFINITIONS *) SCREEN_UP = 1 SCREEN_DOWN = 2 SYS_POWER = 3 DRAPE_OPEN = 4 DRAPE_CLOSE = 5 DRAPE_STOP = 6

(* THE LIGHT CARD CHANNEL DEFINITIONS *) LIGHT_FULL = 1

LIGHT_MED = 2 LIGHT_LOW = 3 LIGHT_OFF = 4

(***********************************************************) (* VARIABLE DEFINITIONS GO BELOW *)

(***********************************************************) DEFINE_VARIABLE

(***********************************************************) (* LATCHING DEFINITIONS GO BELOW *)

(***********************************************************) DEFINE_LATCHING

(***********************************************************) (* MUTUALLY EXCLUSIVE DEFINITIONS GO BELOW *)

(***********************************************************) DEFINE_MUTUALLY_EXCLUSIVE ([RELAY,SCREEN_UP],[RELAY,SCREEN_DOWN]) ([RELAY,DRAPE_OPEN]..[RELAY,DRAPE_STOP]) ([LIGHTS,LIGHT_FULL]..[LIGHTS,LIGHT_OFF]) ([VCR,PLAY]..[VCR,REW]) ([CASS,PLAY]..[CASS,REW]) ([CD,PLAY]..[CD,REW]) (***********************************************************) (* STARTUP CODE GOES BELOW *)

(34)

Chapter 5 – Conditional Expressions (***********************************************************) DEFINE_START PULSE [VCR,STOP] PULSE [CD,STOP] PULSE [CASS,STOP] (***********************************************************) (* THE EVENTS GO BELOW *)

(***********************************************************) DEFINE_EVENT BUTTON_EVENT[TP,1] { PUSH: { PULSE[VCR,PLAY] } } BUTTON_EVENT[TP,2] { PUSH: { PULSE[VCR,STOP] } } BUTTON_EVENT[TP,3] { PUSH: { PULSE[VCR,PAUSE] } } BUTTON_EVENT[TP,4] { PUSH: { PULSE[VCR,FFWD] } } BUTTON_EVENT[TP,5] { PUSH: { PULSE[VCR,REW] } } BUTTON_EVENT[TP,9] { PUSH: { PULSE[CD,PLAY] } } BUTTON_EVENT[TP,10] { PUSH:

(35)

{ PULSE[CD,STOP] } } BUTTON_EVENT[TP,11] { PUSH: { PULSE[CD,PAUSE] } } BUTTON_EVENT[TP,12] { PUSH: { PULSE[CD,FFWD] } } BUTTON_EVENT[TP,13] { PUSH: { PULSE[CD,REW] } } BUTTON_EVENT[TP,17] { PUSH: { PULSE[CASS,PLAY] } } BUTTON_EVENT[TP,18] { PUSH: { PULSE[CASS,STOP] } } BUTTON_EVENT[TP,19] { PUSH: { PULSE[CASS,PAUSE] } } BUTTON_EVENT[TP,20] { PUSH: { PULSE[CASS,FFWD] } } BUTTON_EVENT[TP,21]

(36)

Chapter 5 – Conditional Expressions { PUSH: { PULSE[CASS,REW] } } BUTTON_EVENT[TP,31] { PUSH: { ON[RELAY,SYS_POWER] } } BUTTON_EVENT[TP,32] { PUSH: { OFF[RELAY,SYS_POWER] } } BUTTON_EVENT[TP,33] { PUSH: { PULSE[RELAY,SCREEN_UP] } } BUTTON_EVENT[TP,34] { PUSH: { PULSE[RELAY,SCREEN_DOWN] } } BUTTON_EVENT[TP,41] { PUSH: { ON [RELAY,DRAPE_OPEN] } RELEASE: {

OFF [RELAY, DRAPE_OPEN] } } BUTTON_EVENT[TP,42] { PUSH: { TO [RELAY,DRAPE_CLOSE] } } BUTTON_EVENT[TP,43] {

(37)

PUSH: { PULSE[RELAY,DRAPE_STOP] } } BUTTON_EVENT[TP,45] { PUSH: { ON[LIGHTS,LIGHT_FULL] } } BUTTON_EVENT[TP,46] { PUSH: { ON [LIGHTS,LIGHT_MED] } } BUTTON_EVENT[TP,47] { PUSH: { ON [LIGHTS,LIGHT_LOW] } } BUTTON_EVENT[TP,48] { PUSH: { ON[LIGHTS,LIGHT_OFF] } } (***********************************************************) (* THE ACTUAL PROGRAM GOES BELOW *)

(***********************************************************) (* FEEDBACK *) [TP,1] = [VCR,PLAY] [TP,2] = [VCR,STOP] [TP,3] = [VCR,PAUSE] [TP,4] = [VCR,FFWD] [TP,5] = [VCR,REW] [TP,9] = [CD,PLAY] [TP,10] = [CD,STOP] [TP,11] = [CD,PAUSE] [TP,12] = [CD,FFWD] [TP,13] = [CD,REW] [TP,17] = [CASS,PLAY] [TP,18] = [CASS,STOP] [TP,19] = [CASS,PAUSE] [TP,20] = [CASS,FFWD] [TP,21] = [CASS,REW] [TP,31] = [RELAY,SYS_POWER]

(38)

Chapter 5 – Conditional Expressions [TP,33] = [RELAY,SCREEN_UP] [TP,34] = [RELAY,SCREEN_DOWN] [TP,41] = [RELAY,DRAPE_OPEN] [TP,42] = [RELAY,DRAPE_CLOSE] [TP,43] = [RELAY,DRAPE_STOP] [TP,45] = [LIGHTS,LIGHT_FULL] [TP,46] = [LIGHTS,LIGHT_MED] [TP,47] = [LIGHTS,LIGHT_LOW] [TP,48] = [LIGHTS,LIGHT_OFF] (***********************************************************) (* END OF PROGRAM *)

(* DO NOT PUT ANY CODE BELOW THIS COMMENT *)

(39)

But suppose you want the same number of functions with fewer buttons. A common solution is to have several groups of buttons with similar functions reduced to one group, with a set of buttons that selects which piece of equipment the buttons control. In your program, you could have one button for each piece of equipment to select each deck, and one set of transport buttons. Your panel could now look like FIG. 2:

You now have fewer buttons than you did before. What you want to happen with this panel is that the user selects the deck with a Select button, then controls it with the Transport buttons. This will not be a one-to-one program because the Transport buttons each have three possible functions. In the program you will use conditional expressions to select the correct function of the Transport buttons. Additionally, the System Power has been reduced to one toggling button, which will have its feedback turned on when the system is powered and off when the system is not powered. In other words, one button will perform different functions based on a given condition.

FIG. 2 G3 Panel with multi-functional transport buttons

(40)

Chapter 5 – Conditional Expressions

Conditional Expressions

A conditional expression is used to tell the system whether or not to execute a particular function or functions in the program. Picture yourself walking along a path in the country. Suddenly you come upon a fork in the road. Which way should you go? If you guess, you might become lost. Therefore you judge certain conditions before continuing. Is the left road heading north? Is the right road heading east?

This is what the Master must do whenever you branch off in different directions in your program. Either the Master continues in the direction it is going, or it must jump to a different section.

A conditional expression can have one of two results, true or false. In AMX programming, any non-zero value is true and a non-zero value is false. When the Master evaluates a conditional expression, it assigns a 1 for a true result, and a zero for a false result.

The IF Statement

The most common keyword in AMX programming that uses conditional expressions is the IF keyword. Every IF statement must be followed by a conditional expression enclosed in

parentheses. This provides the beginning of a conditional execution of statements. The structure is as follows:

IF(conditional expression) {

Statement 1 }

If the conditional expression is true, the Master executes Statement 1 and then continues with whatever statements follow. If the conditional expression is false, Statement 1 is ignored. The braces indicate that the statement below the condition is a subset. As such, the subset will only be executed if the condition is true.

The IF...ELSE Set of Statements

This is similar to the basic IF statement, with the addition of one more branch. If the conditional expression is false, the Master executes a function independent of the “true” conditional expression. For example: IF(conditional expression) { Statement 1 } ELSE { Statement 2 }

If the conditional statement is true, then Statement 1 is executed. Statement 2, underneath the ELSE statement, is ignored. If the conditional statement is false, then Statement 2 is executed. Remember that Statement 1 is automatically ignored if the expression is false.

(41)

Repeating IF...ELSE Set of Statements

Using IF... ELSE allows two different paths for conditional branching. By repeating the

IF... ELSE statements multiple paths can be created. The Master will stop conditional evaluation at the first true conditional expression and execute the associated statements. After completion, it goes on to the rest of the program. For example:

IF(Conditional expression) { Statement 1 } ELSE { IF(Conditional expression) { Statement 2 } ELSE { IF(Conditional expression) { Statement 3 } ELSE { Statement 4 } } }

The last ELSE statement placed at the end of the conditional branching operates as a default statement. That is, if the Master processor does not find a true IF statement, it executes the final ELSE statement. However, the last ELSE statement is not necessary.

Nesting

Once the Master processor is traversing along an IF branch you can tell it to branch off again with another IF statement. This “branch within a branch” is called nesting. An IF can be within an IF within an IF, and so on. The only restriction is the amount of memory available.

When you are nesting IF... ELSE statements, be sure to use braces. Look at the following incorrect example: IF(X = 5) { Statement 1A IF(Y = 10) { Statement 1B } ELSE { Statement 2 } }

(42)

Chapter 5 – Conditional Expressions

Even though the alignment suggests the ELSE goes with the first IF, the braces force it to go with the second (nested) IF. The second IF statement is not supposed to have an ELSE counterpart in this example. However, such is not the case. The Master pairs the second IF statement with the ELSE, because both are within the compound statement created by the first and last braces. By rearranging the braces you can force the compiler to associate the ELSE with IF(X = 5). For example: IF(X = 5) { Statement 1A IF(Y = 10) { Statement 1B } } ELSE { Statement 2 }

By using the braces, you isolate the IF(Y = 10) statement from the IF... ELSE set of statements.

The SELECT...ACTIVE Statement

There is a way to make nesting easier: the SELECT...ACTIVE statement. This allows the easy placement of several branches from one path. Here is the format:

SELECT { ACTIVE(conditional expression 1): { Statement 1 } ACTIVE(conditional expression 2): { Statement 2 } ACTIVE(conditional expression 3): { Statement 3 } (* ...etc. *) }

Each one of the conditional expressions, in order, is evaluated until one is found to be true. The statements associated with that true expression are then executed, and the path then flows to whatever statements follow the closing brace. So if there are five conditional statements to evaluate and the second one is true, its statements will be executed. The 3rd, 4th and 5th conditional statements will never be checked. The processor will go to the statement following the closing brace of the SELECT...ACTIVE. Using a SELECT...ACTIVE is much preferred to multiple IF...ELSE statements; it uses less memory and it runs faster. If too many IF...ELSE statements are chained together, they can overflow the Master processor memory and crash the

(43)

So what happens in a SELECT...ACTIVE if none of the conditions evaluate as true? In such a case, no code of any ACTIVE statement will be executed, since SELECT...ACTIVE has no default statement. You can, however, create your own default for a SELECT...ACTIVE:

SELECT { ACTIVE(conditional expression 1): { Statement 1 } ACTIVE(conditional expression 2): { Statement 2 } ACTIVE(conditional expression 3): { Statement 3 } ACTIVE(1): { Default statement } }

Here, the last ACTIVE will always be true (remember in AMX programming a 1 is true and a 0 is false), and will execute only if all of the conditions of the previous ACTIVE statements are false. This makes the last ACTIVE statement the default statement.

Trying it Out

Now you can write the code for your new panel layout. Before you do, however, you will need to update your definition sections a little. The preferred method of implementing “select groups” is to use one variable and change its value based on which deck is selected.

The “Variable Assignment” Method

Assigning different values to one variable depending on what is selected is the preferred method of programming select groups. This method is actually more powerful than other methods, as it provides more flexibility while using a lot less code.

First add just one variable, DECK to the program you wrote previously. This will be the select variable. For a NetLinx Master you will define the variable to contain NetLinx device address information by using the DEV keyword as shown below:

! DEFINE_VARIABLE ! DEV DECK

As we learned early in this manual, there are different types of variables. Meaning that variables can hold different types of data. DEV is one type available to you in Netlinx. A DEV variable can hold the Netlinx device address information in it. Meaning that if we create a variable called DECK of type DEV, DECK will be able to store D:P:S info of any of the devices we declared in the DEFINE_DEVICE section.

(44)

Chapter 5 – Conditional Expressions

Based on the code we already wrote in Step 1, DECK would be able to hold the Netlinx address value of RELAY, VCR, CD, CASS, LIGHTS or TP. However, we don't want to hold all of these, we just want to differentiate between which deck we are currently choosing to control.

The code below allows us to use certain buttons to change the value of DECK. Notice there is no way to make DECK equal to TP. Even though our DEV variable can hold that information, that is not what we want. We only want to be able to switch between the VCR, CD or CASS. That is done by using the Device Select buttons on FIG. 2 on page 32 and the code written just below:

BUTTON_EVENT[TP,1] { PUSH: { DECK=VCR } } BUTTON_EVENT[TP,2] { PUSH: { DECK=CD } } BUTTON_EVENT[TP,3] { PUSH: { DECK=CASS } }

(45)

You can reduce the number of transport sections from three to just one by using the variable DECK as the device number in the PULSE statements, instead of using VCR, CD, and CASS. Here’s the section of code: BUTTON_EVENT[TP,17] { PUSH: { PULSE[DECK,PLAY] } } BUTTON_EVENT[TP,18] { PUSH: { PULSE[DECK,STOP] } } BUTTON_EVENT[TP,19] { PUSH: { PULSE[DECK,PAUSE] } } BUTTON_EVENT[TP,20] { PUSH[TP,20] { PULSE[DECK,FFWD] } } BUTTON_EVENT[TP,21] { PUSH: { PULSE[DECK,REW] } }

Notice that no IF statement and no mutually exclusive variables are necessary for the variable DECK, and this is the only deck transport section of programming needed in the whole program! But how does this work? Suppose you want to play the CD player. First you press the CD Select button. This assigns the value 5001:10:0 (the constant value of CD device) to the variable DECK. Now the device-channel references of the PULSE transport statements will reference device number 5001:10:0 (the CD device). Pressing button number 17 on the Touch Panel will activate [DECK,PLAY], which the Master will interpret as [5001:10:0,1].

The feedback for the transport section works in the same manner as the control section. The feedback statements use the DECK variable as the device from which to get the feedback. These statements for the selection buttons, however, are something new:

[TP,1] = (DECK=VCR) [TP,2] = (DECK=CD) [TP,3] = (DECK=CASS)

(46)

Chapter 5 – Conditional Expressions

These statements, like all feedback statements, are direct assignment output changes; however, the source of the assignment is a conditional expression. In interpreting this kind of feedback

statement, the master first evaluates the conditional expression. If the expression is evaluated as true, the expression is replaced with a 1; otherwise it is replaced with a zero. (Remember, only one of these will be evaluated as true because a variable cannot have two different values at one time.) Thus the direct assignment will assign a 1 (”on”) to the Touch Panel button for which the

expression is true, and a zero (”off”) to the false ones. Recall that assigning a 1 to a device-channel is the same as turning the output of a device-channel on

Conditional Operators

The previously discussed IF and IF...ELSE statements can only base the program flow on one condition. You can, however, combine two of these conditions with a conditional operator. This operator sets the rules for determining the end result.

The conditional operators used in AMX systems are AND, OR, XOR, and NOT. These are placed in between the two conditions after the IF statement. For example:

IF((X = 10) AND (Y = 5)) {

Statement 1 }

For this condition to be met, 2 things have to be true. X must be equal to 10 and Y must be equal to 5. If the end result of the conditional expression is true, the system continues with Statement 1. If the end result is false, the system simply ignores Statement 1.

In most conditional expressions, the possible conditions of two statements are analyzed to achieve one result. A text formula can be followed to find that result:

""If <condition 1 (true/false)> <conditional operator> <condition 2 (true/false)>, then the result of the expression is true or false." The result is found by basing the conditions of the statements against the rules set by the

conditional operator. Here are those specific rules:

AND Both statements must be true for the result to be true.

OR At least one of the conditions must be true for the result to be true. XOR Only one statement can be true for the result to be true.

NOT If the statement is true, the result is false. On the contrary, if the condition is false, the result is true. This expression uses only one statement.

Consider the following IF statement:

IF((NUM1 = 5) AND (NUM2 = 4))

Assume that it has been previously defined that NUM1 = 5 and NUM2 = 3. Insert the variables from the example into the text formula:

References

Related documents

This paper explores attempts to use game-based learning techniques in library instruction courses and sessions, specifically highlighting Project Velius (developed by the

Their system lies on an archi- tecture consisting of five layers: (i) the data source layer represented by the available Twitter APIs, (ii) the ETL layer (Extract, Transform, and

This study is concerned with understanding the impact of students’ prior expectations and learning conceptions on their SWE transition and subsequent employability

Parameters affecting on driver seat design are very complex in nature and require detailed study of human anthropometry, seat dimensions, its mechanisms, materials of

Wireless Configuration Utility Wireless Setup Utility Wireless mode Wireless router router WLAN Wireless Local Area Network.

The total return on stock has two parts, current yield plus capital gain, and capital gain rate is equal to growth rate of dividends... Jack's

Most of our experience with love, in either giving it or receiving it, is love with strings attached, and each clan and culture seems to excel at one or more particular types of