Control Freaks Alert
Volume Number: 16
Issue Number: 3
Column Tag: Data Acquisition on the Macintosh
Control Freaks Alert!
by Tom Djajadiningrat
A clean interface to Beehive Technologies' ADB I/O
using object-oriented Lingo
Introduction
The ADB I/O by Beehive Technologies is a device which you can connect to a Macintosh
to communicate with external electronics. Simply put, the ADB I/O provides digital
inputs (to read switches), digital outputs (to switch things on or off) and analog
inputs with 8-bit resolution (to read all kinds of sensors). For the Macintosh
platform, it has opened up areas of application to mainstream users that were
previously the sole territory of electronic hobbyists or users with high end data
acquisition hardware. A few of those areas are home automation, robotics, kiosks,
scientific experiments and product simulation.
Many applications can communicate with the ADB I/O. One particularly powerful
combination is the ADB I/O and Macromedia Director. Even if you intend to control
your ADB I/O through AppleEvents or C/C++, you may find it worthwhile to test your
set-up with Director. Director is easy to program, especially when it comes to the
graphical user interface.
There is of course a downside to Director's ease of use: the temptation of sloppy
programming. Director does not require you to declare local variables or provide
function prototypes. Add Director's cryptic error messages and your program can turn
into a tangled mess which is difficult to debug. While this is of course undesirable for
any program, with a program that communicates with external devices, for example
motors, the consequences of messy programming may be more severe.
This article aims to help you in battling messy Director code. By using Director's
object-oriented features you will get to build a friendly and clean interface to the ADB
I/O. In addition, in this article consistent naming for variables is used, which may be
of help to you in writing your own scripts.
Required Hardware and Software
Required hardware:
• A Macintosh with an ADB port or a Macintosh with a USB port and a
Griffin Technology iMate USB to ADB adapter.
• A Beehive Technologies' ADB I/O.
Required software:
• ADB I/O XCMDs 1.0.1. This file comes with the ADB I/O. It is also
downloadable from the Beehive Technologies website.
• Macromedia Director 5 or 6 (Director 7 is not compatible with the ADB
I/O XCMDs 1.01 file. A Director 7 compatible Xtra for the ADB I/O is
currently in beta and downloadable from the Beehive Technologies website).
Though this article explains things for Director 6, the differences with
Director 5 are minimal and the sample files which accompany this article are
provided in both Director 5 and 6 versions.
What You Need to Know
You need to be familiar with Macromedia Director and its scripting language Lingo. You
need not have worked with object-oriented Lingo. What you need to know about
object-oriented Lingo will be explained. You should be familiar with the capabilities of
the ADB I/O, though a summary of what you need to know is provided.
Contents
We will start with an introduction to object-oriented Lingo. We will then cover the
ADB I/O's hardware and software details relevant to this article. If you are already
comfortable with these subjects, you may wish to skip them. Once we have established
this ground, we start with building a Director Lingo object which forms a friendly and
clean interface to the ADB I/O. At the end of this article you will find a section on
troubleshooting and a section with suggestions for enhancements.
Object-Oriented Lingo
Instead of starting with a theoretical discussion of the advantages of object-oriented
Lingo, we will dive straight in and put together a simple object-oriented Director
movie. I think you will find that the virtues of object-oriented Lingo are much easier
to understand once you have seen a concrete example. Our movie consists of three
scripts: a parent script, a movie script and a frame script. First we will write the
scripts, then we will test and discuss the resulting movie. Don't worry too much if you
don't completely 'get it' when we write the scripts. All will be explained.
The parent script
A Director object is described in a parent script. Create a new movie first, then create
a parent script by choosing Script from the Window menu (Figure 1). The script
window opens. Name the script by typing testParentScript in the field at the top of the
scripting window (Figure 2). To make sure that the script is a parent script, click on
the info button (Figure 3) and choose parent from the type pop-up menu (Figure 4).
Click OK.
Figure 1.Open the script window
Figure 2.Name the script
Figure 3.Press the info button
Figure 4.Make the script a parent script.
Now on to the parent script itself. It consists of three parts: a birthing handler,
message handlers and properties. We will discuss each part in turn.
1. The birthing handler
This is where a child object is created. It typically has the form:
on new me
return me
end
The birthing handler returns a pointer to a newly created child object. We will add one
line of code to our new handler to put a message in the message box telling us that the
birthing handler was indeed called.
on new me
- print some feedback in the message window
put "the birthing handler of testParentScript was called
- return a pointer to the new child object
return me
end
2. Message handler
In a message handler you can specify a behaviour of an object. A message handler has
the form:
on messageHandler me
end
We will create an message handler called hello which beeps and puts a message in the
message box.
on hello me
- beep once
beep
- print some feedback in the message window
put "Hello World!
end
3. Properties
A property is a variable that belongs to an object. It is declared at the top of an object's
parent script, preceded by the Lingo keyword property, like this:
property pProperty
Within the parent script you can set or get a property by just its name:
set pProperty = 1
set lVariable = pProperty
When we test the Director movie, you will see how to get at a property from outside of
the parent script. Notice how, to maintain an overview, we start a property with the
letter p and a local variable with the letter l. For a full description of our naming
convention for variables and parameters, please refer to Table 1.
Prefix Suffix ‹Meaning Example
i ‹input parameter iChannel
l ‹local variable lResult
o ‹child object oADB1
p ‹property variable pUnit
List ‹list variable pChannel
Table 1.Variable and parameter naming conventions.
For now, we will create a single property called pProperty and two member functions.
One to set the value of pProperty and one to get the value of pProperty.
property pProperty
on setProperty me, iValue
set pProperty = iValue
end
on getProperty me
return pProperty
end
The movie script
To create the movie script, bring up the script window if necessary and click on the +
button to create a new script. Name the script movieScript by typing into the field at
the top of the script window. Click on the info button. A dialog box appears. Make sure
that movie is selected in the type popup-menu. Click OK.
In our movie script we will write two handlers. The first one, startMovie, is called
when the movie starts, the second one, stopMovie, is called when the movie stops.
on startMovie
end
on stopMovie
end
In this example we will add some code to the startMovie handler only. First we print
some feedback to the message window to show that the startMovie handler was called.
We then create a global called oTestObject1. Finally, we assign to this global a child
object of the testParentScript that we wrote previously by calling the birthing
handler.
on startMovie
- Print some feedback in the message window
put "startMovie was called.
- create a global oTestObject1
global oTestObject1
- make oTestObject1 a child object of the parentScript
testParentScript
- by calling the birthing handler.
set oTestObject1 = new (script "testParentScript")
end
The frame script
We will now create a simple frame script to make our Director movie loop in frame 1.
In the score window, double click on the score channel of frame 1 and add one line of
code to the exitFrame handler.
on exitFrame
go to the frame
end
Testing our movie
It is time to test our movie. If you get stuck at any point and think it is because you did
not quite get the explanation above, you may wish to look at testOOMovie.dir. Run the
movie and open the message box. Type
put oTestObject1
The message box should display
-
indicating that oTestObject1 is a child object based on our testParentScript. Don't
worry if the alpha-numeric string that you get differs from the one shown above. As
this is a memory address it is in fact highly unlikely that it would be identical.
Now try the hello message handler. The syntax for sending a message to a child object
is .
hello oTestObject1
The Mac should beep and the message box should display
- "Hello World!
Now send the getProperty message to our child object. Since getProperty is a function
(a handler which returns a value), you need to enclose its parameters in round
brackets.
put getProperty (oTestObject1)
The message box shows that pProperty has the value void. No worries, pProperty has
not been set yet. Now type:
setProperty oTestObject1, 1
Now try again:
put getProperty (oTestObject1)
And you will see that pProperty has changed its value from void to 1.
setProperty and getProperty are message handlers which we wrote ourselves. Another
way to set and get properties of a child object outside of its parent script is:
set the of =
set lVariable = the of
Notice how we need to add the Lingo 'the' keyword, now that we try to access a property
outside of its parent script.
Let's try:
set the pProperty of oTestObject1 = 2
put the pProperty of oTestObject1
The message box shows that pProperty of oTestObject1 now has the value 2.
Play around with accessing properties through the message handlers setProperty and
getProperty as well as with accessing the properties directly through the 'the'
keyword. You will find that you can mix both methods.
What's the point of object-oriented Lingo?
Before we answer that question, try creating a second child object:
set oTestObject2 = new (script "testParentScript")