This book is published solely by O'Reilly & Associates, Inc., and its purpose is to enable you to creatively program LEGO® MINDSTORMS™ brand robots. This book is not sponsored by The LEGO® Group. Nutshell Handbook, the Nutshell Handbook logo, and the O'Reilly logo are registered trademarks of O'Reilly & Associates, Inc. The association of the image of a mechanical toy rabbit with the topic of LEGO®...
Page 3
A Simple Program Wheels Bumpers and Feelers Gears Multitasking Online Resources 3. Trusty, a Line Follower Building Instructions Some Tricky Programming The Light Sensor Idler Wheels Using Two Light Sensors Online Resources Page viii 4. Not Quite C A Quick Start RCX Software Architecture NQC Overview Trusty Revisited...
Page 4
Programming Directional Transmission Pulleys Mechanical Design Two Sensors, One Input Where Am I? Online Resources 6. pbFORTH Replacement Firmware pbFORTH Overview About Forth pbFORTH Words An Expensive Thermometer Minerva Revisited Debugging Online Resources 7. A Remote Control for Minerva Two Heads Are Better Than One The Allure of Telerobotics Building Instructions Programming the Remote Control...
Page 5
Online Resources 8. Using Spirit.ocx with Visual Basic You May Already Have Visual Basic About Spirit.ocx Calling Spirit.ocx Functions Immediate and Delayed Gratification Page ix Programs, Tasks, and Subroutines Tips Retrieving the Datalog Online Resources 9. RoboTag, a Game for Two Robots Building Instructions Subsumption Architecture Online Resources...
Page 6
About This Book For many of us, plastic LEGO bricks are the best toy money can buy. When I was five and broke my leg, a little LEGO set was the high point of my six-week convalescence. I grew up building spaceships and planetary rovers, wearing grooves in the ends of my fingernails from endlessly putting together and taking apart my creations.
Page 7
Here's a description of each chapter in this book: Chapter 1, Robotics and MINDSTORMS, introduces the field of mobile robotics and describes how the LEGO MINDSTORMS Robotic Invention System fits in the larger picture of the field. Chapter 2, Hank, the Bumper Tank, is the first building project—a tank-style robot that avoids obstacles in its path. This chapter discusses basic mechanical features like gears and bumpers.
Page 8
pbFORTH Version 1.0.7 legOS The March 30, 1999 build, a patched version of 0.1.7 Downloading All of the examples in this book can be downloaded from http://www.oreilly.com/catalog/lmstorms/. This site also provides a listing of the "Online Resources" that appear at the end of each chapter.
Many thanks go to my wife, Kristen, for helping to create this book. She first suggested its project-oriented organization; she gave me excellent feedback on many of its chapters; she got me RolyKits to help organize my pieces; she is able to keep a straight face when we tell people I'm writing a book about LEGO robots; she stayed up late nights helping me finish the book.
Internet; working computer peripherals like a plotter and an optical scanner; and robots that simulate a Tsunami and a tornado.∗ You can build anything you can imaging. RIS gives you a chance to breathe life into LEGO creations, making them move and respond to their surroundings.
Page 11
Page 3 Mobile robots actually come in two varieties: tethered and autonomous. A tethered robot "cheats" by dumping its power supply and brain overboard, possibly relying on a desktop computer and a wall outlet. Control signals and power are run through a bundle of wires (the tether) to the robot, which is free to move around, at least as far as the tether will allow. Autonomous mobile robots are even more challenging.
• You could use a modular construction kit to build the robot's body. LEGO® bricks are one possibility—in fact, researchers and students at the Massachusetts Institute of Technology (MIT) have been using LEGO bricks for mechanical prototyping for over a decade.
Page 13
MINDSTORMS is the name of a product line sold by The LEGO Group. The LEGO Group has a handful of product lines that cater to different age groups, some of which are shown in Table 1-1. Table 1-1. Representative LEGO Product Lines...
Page 14
Meet the RCX The RCX is a robot brain in the form of a bulky LEGO brick. Figure 1–2 shows a photograph of the top of the RCX. Page 8 Figure 1-1. Basic MINDSTORMS setup Figure 1-2. The RCX, a robot brain...
Page 15
There's one final wrinkle if you want to program from MacOS: you'll need a suitable cable. The following web page describes the issues of programming the RCX from MacOS, including cables: http://www.enteract.com/~dbaum/lego/macmind/index.html. You can purchase a Macintosh IR tower cable from Pitsco LEGO DACTA for $15US. See Appendix A for details. Expansion Sets...
Extreme Creatures This set comes with about 150 LEGO pieces and is designed so you can add decorative jaws and claws to your robots. It includes a light that can be attached to one of the output ports of the RCX.
Page 17
This page presents the results of Kekoa Proudfoot's reverse engineering efforts on the RCX, which enabled the development of interesting technologies like NQC. pbFORTH, and legOS. For hard- core geeks, this page is fascinating reading. Kekoa is, to quote Russell Nelson, a ''minor deity" in the online MINDSTORMS world. LEGO on my mind: Roboworld http://homepages.svc.fcj.hvu.nl/brok/legomind/robo/ This comprehensive unofficial site contains a helpful section that introduces MINDSTORMS RIS and its TECHNIC doppelgänger, CyberMaster™.
If MINDSTORMS robots aren't small enough for you, take a look at Crickets, another project from the fine people at MIT. Hardly larger than a nine-volt battery, Crickets are a very tiny mobile robot platform. Crickets are not publically available, but this site can give you the inspiration to build your own tiny robots.
• Various means of locomotion • Bumper design • The use of gears • Motors • Software multitasking Figure 2-1 shows a picture of the completed robot. I suggest you begin by building and programming Hank. Let him run around your floor for a while. Then come back and read the rest of the chapter, where I'll talk about some of Hank's interesting features.
Page 20
Figure 2-2. Some beams, plates, and shafts and their lengths Gears, for the most part, are described by the number of teeth they have. A 24t gear, for example, has 24 teeth. (The "t" stands for "teeth.") Figure 2-3 shows a photograph of the various types of gears that come with the RIS kit.
Figure 2-5. A wire brick Page 17 Building Instructions∗ Create Hank's main chassis as shown in the next two steps; this will hold the RCX, the motors, and the bumpers. Attach the shafts as shown. Hank's treads will be mounted on these shafts. The front pair do not rotate, while the rear pair should. Don't push the front pair all the way in; you'll need to fit the tread wheel and another bushing on the end.
Page 22
Page 18 The back tread wheels are anchored to the shafts with the 16t gears.
Page 23
Page 19 Page 20 Next, start building support for the drive motors.
Page 24
Page 21 Place the wire bricks on the motors, then anchor them down with the yellow plates. The wires themselves will fit into the grooves on the top of the motors.
Page 25
Page 22 Attach the motor wires to output A and output C. Next, build the platform for the front bumpers.
Page 26
Page 23 The touch sensors are attached only by the shaft that runs through them.
Page 27
Page 24 Hank's left bumper is next. A light touch on the bumper pushes the touch sensor. Hank's right bumper works exactly the same way.
Page 28
The bushings are pushed onto the plate in the next step. Note that the bushings are not symmetrical; one side will push into the plate, and the other side won't. Page 25 Finish Hank by attaching the bumper touch sensors to input 1 and input 3. Slide the blue rubber bands onto the bumpers and anchor them to the bushings from the last step. The rubber bands keep the bumpers from swinging forward.
A Simple Program Now that you've built a robot, you need a program to make it work. Hank's mission in life is to explore the world. Page 26 His basic program works something like this: go forward if I've bumped into something back up turn away from the obstacle start over...
Page 30
To create this program, enter the RIS software. Choose Program RCX from the main menu, then RCX Code. Use the menus on the left side of the screen to click and drag out different program ''blocks." If you're not familiar with this process, you should probably go back and take a look at LEGO's official documentation, either the printed material or the computer-based tutorial.
Differential Drive Treads are a special kind of differential drive, in which two wheels are each driven by a motor. The wheels are mounted on either side of the robot, like the treads. Figure 2-7 shows a top view of such a robot.
Page 32
Page 29 Cars Modern automobiles demonstrate another popular approach to locomotion. Cars have four wheels, two in front and two in back. The back wheels drive the robot (or car) forward and reverse, while the front wheels are used for steering. Figure 2-9 shows how this looks. Figure 2-9.
IR link. The key to building synchro drive robots is a piece called a large turntable. You can order these pieces from Pitsco® LEGO DACTA®; see Appendix A, Finding Parts and Programming Environments, for details.
The Palette of LEGO Gears LEGO offers an impressive array of gears. The LEGO community has adopted names for these gears, which I will use throughout this book. Refer back to Figure 2-3; it shows the gears that come with RIS and their names. For the most part, gears are named based on the number of teeth they have. The 40t gear, for example, has 40 teeth. The number of teeth is directly proportional to the gear's radius, so the 24t gear has a radius exactly three times as large as the 8t gear.
Page 35
Page 33 Do the Math The mathematics of gears can be described in a high school physics class. The two important equations have to do with torque and angular velocity. Here's the equation for torque, which is a measure of the power in a turning shaft: In this case, τ...
Page 36
LEGO sells an entire line of train sets. The train motor can be controlled by your RCX; as a matter of fact, you can make an "intelligent" train by mounting the RCX in one of the cars. For a Rainy Day To see exactly how efficient the geared motors are, try this experiment.
How can you get more motors? RIS comes with two motors, but there are three outputs on the RCX. You can get another motor in the RoboSports expansion set, but it'll cost you $50. You can order extra motors from the LEGO Shop-at-Home service, one of The LEGO Group's best-kept secrets. This service is available in the United States at (800) 835-4386. They have a variety of sets and spare parts—the item numbers for the motors are as follows:...
This is an outstanding paper about building with LEGO parts. It includes helpful tips on making strong structures and using gears. The paper is written by Fred Martin, one of the people at the MIT Media Lab whose programmable brick work formed the basis of the RCX. I highly recommend this paper, especially if you are having trouble getting things to fit together.
This is the official home page of Pitsco LEGO DACTA. Many of the interesting things that Pitsco LEGO DACTA sells are not listed online, but you can call and order a catalog. Make sure you get the LEGO DACTA catalog, as Pitsco has an entirely different catalog that doesn't have anything to do with LEGO. This is the place to order the Robolab software that allows you to program your RCX from a Macintosh.
In this chapter, you'll build Trusty, a simple robot that exhibits a behavior called line following. This means that Trusty, shown in Figure 3-1, can drive along a sort of ''track" defined by a thick black line on the floor. Your RIS kit includes a "Test Pad," which is simply a large piece of white paper with some black lines and other marks on it. Trusty will follow the large black oval on this paper faithfully until he runs out of battery power.
Page 42
In Step 4, make sure the top bushing allows the idler wheel to rotate freely by putting the round side next to the plate. If you put it on the other way, the idler wheel will be locked in place. Be sure to attach the wire bricks to the motors before putting them on Trusty.
Page 43
Next, build the support for the light sensor.
Page 44
Page 43 The 2u beams between the motors will hold the ends of the drive shafts. Make sure that you can see the holes.
Page 45
Page 44 Flip the robot over and attach the wires as shown. The motors are attached to output A and output C, while the light sensor is attached to input 2. Some Tricky Programming It's surprisingly hard to convince our robot to follow a black line on the floor. (A lot of things in mobile robotics are surprisingly hard, as we discussed in Chapter 1, Robotics and MINDSTORMS.) The simplest way to describe the program is this:...
Page 46
Page 45 if I'm on the line, go straight forward if I'm off the line, find the line and start over It's the "find the line" part that's difficult. When Trusty's light sensor goes off the black line, Trusty has no way of knowing if he's on the right or the left side of the line. Ideally, Trusty would turn back to the line and start going straight again.
Page 47
Page 46 The environment does provide a counter, which we'll use in lieu of a variable to hold the turning direction. Although you can't assign values directly to the counter, you can do two things: reset it to zero and add one to it. Trusty will use just two values, 0 and 1, to mean turn left and turn right, respectively. Coping with Failure Our basic assumption about Trusty is that he will drive off the black line on alternating sides.
Page 48
Figure 3-4. Details of Trusty's software Figure 3-4 also shows the toggle subroutine itself. All it does is examine the value of the counter. If it's 0, then the robot is set to turn left and the counter value is changed to 1. The next time toggle is called, the robot turns right and the counter value is reset to 0.
Page 49
Page 49 Figure 3-5 shows a hypothetical graph of the light sensor value, along with the times when the dark and bright commands will be executed. Nothing happens until the sensor value enters either the dark or bright value ranges. Figure 3-5.
Idler Wheels Trusty's two main drive wheels determine whether he moves forward, backward, or turns. But without at least one more wheel, Trusty can't balance and will tip forward or backward. Trusty's third wheel is a good example of an idler wheel. An idler wheel provides support for the robot but doesn't constrain its motion. It does this by rotating freely on a vertical axis. The front wheels on shopping carts are idler wheels, as are the casters under furniture.
LEGO Light Sensor http://www.plazaearth.com/usr/gasperi/light.htm For the real skinny on LEGO's light sensor, check out this page. It includes a photograph of the circuit board inside the sensor, a schematic diagram, and graphs of the sensor's response with and without the LED.
• You can't control the RCX's display very well. It would be really nice, for debugging purposes, to be able to show values on the display. The LEGO Group aimed the Robotics Invention System at people who had never programmed before. For this group, RCX Code is a gentle way to get started with programming mobile robots.
(http://www. enteract.com/~dbaum/lego/nqc/), and follow the instructions to download and install the latest version. The examples in this book were written with the NQC version 2.0b1. Once it's installed, enter the following program using a text editor. This program operates Hank, the robot from Chapter 2, Hank, the Bumper Tank. Save the program in a file called Hank.nqc.
Page 55 Now compile the source code using the nqc command: C:\>nqc Hank.nqc C:\> If you made a mistake typing in the program, nqc gives you a list of errors. Otherwise, you're ready to download the program with the -d option: c:\>nqc -d Hank.nqc Downloading Program:…..complete c:\>...
Page 55
Page 56 Access Memory (RAM). As its name implies, ROM cannot be written. It is programmed at the factory and cannot be changed. RAM, on the other hand, can be written and read as many times as you want, with one catch: it needs power. If you take the batteries out of your RCX, the contents of the RAM are erased. Under normal circumstances, however, the batteries preserve the contents of the RAM.
Windows.∗ NQC was developed by Dave Baum, who maintains the official web site at http://www.enteract.com/~dbaum/lego/nqc/. His web site also includes pithy documentation for the language. If you're using NQC on Windows, you might want to also use RCX Command Center (RcxCC). RcxCC is a Windows application that wraps around NQC. It provides a syntax-colored program editor, push-button compilation and downloading, real-time control of the RCX, and a host of other useful features.
Page 57
Page 59 Output Commands NQC includes several commands for controlling the outputs of the RCX. You've already seen one of these, OnFwd, in our first simple example. On(const outputs) This command turns on the specified outputs. The outputs should be some combination of the constant values OUT_A, OUT_B, and OUT_C. Multiple outputs can be specified by adding them together, as shown in the first example.
Page 58
Page 60 These commands set the mode and direction of the outputs in one fell swoop, but you should still set the power level explicitly with a call to SetPower(). For timed actions, the following command will come in handy: OnFor(const outputs, expression time) This command turns on the specified outputs for the given time, measured in hundredths of a second.
Page 59
Table 4-1. NQC Sensor Modes Configuration Sensor Type Input Value ClearSensor() SENSOR_TOUCH Touch 1 (pressed) or 0 (not pressed) SENSOR_LIGHT Light 0 (dark) to 100 (bright) SENSOR_ROTATION Rotation 16 units per full rotation SENSOR_CELSIUS Temperature Celsius degrees times 10 SENSOR_FAHRENHEIT Temperature Fahrenheit degrees times 10 SENSOR_PULSE...
Page 60
The transitions from 0 to 1 and from 1 to 0 are called edges. A transition from 0 to 1 is a rising edge, while a transition from 1 to 0 is a falling edge. The SENSOR_EDGE configuration counts all edges, rising or falling. SENSOR_PULSE is a little more selective—it counts rising edges only.
Page 61
Table 4-2. Input Type Constants Type Constant Sensor Type SENSOR_TYPE_TOUCH Touch sensor SENSOR_TYPE_TEMPERATURE Temperature sensor SENSOR_TYPE_LIGHT Light sensor (powered) SENSOR_TYPE_ROTATION Rotation sensor (powered) SetSensorMode(expression sensor, const mode) Use this command to set the mode of the given input. While the SetSensorType() command is used to specify the electrical characteristics of the input, the SetSensorMode() command specifies how the input value should be processed.
Page 62
Page 64 If you wanted to attach a temperature sensor to input 2 and measure Celsius values, you would do the following: SetSensorType(SENSOR_2, SENSOR_TYPE_TEMPERATURE); SetSensorMode(SENSOR_2, SENSOR_MODE_CELSIUS); The SetSensor() command, which I described first in this section, is a convenient way of specifying both an input type and an input mode. Table 4-4 shows what types and modes correspond to the configurations that SetSensor() recognizes.
Page 63
Page 65 Program Flow You've seen how to control the RCX's outputs and inputs. But robot programs aren't very interesting unless they can make decisions and repeat actions. In this section, I'll sketch out NQC's program control commands. NQC supports a standard set of conditional branches and loops; if you've ever programmed in other languages (particularly C), this will look familiar. Waiting Although it might not seem important, NQC includes a command that tells the robot to do nothing for a certain amount of time.
Page 64
while (SENSOR_3 < 35) { PlaySound(0); Wait(50); Notice how curly braces are used to bracket the statements that belong to the while loop. If you have only one command in the body of the while, you can omit the braces like this: while (SENSOR_3 <...
Page 65
i = 0; You can also assign input values to variables, like this (not part of the example): i = SENSOR_2; In the following line, one is added to the value in variable i: i++; This is really shorthand for the following: i += 1;...
Page 66
The preceding example shows off two features of macros. First, each macro has a parameter, power, that is used in the body of the macro. Second, the macros are split out to multiple lines by using a backslash. Sounds and Music Your RCX can play various prepackaged sounds, using the following command: PlaySound(const n) This command plays the sound represented by n.
Page 68
Message() Use this command to return the last byte of data received on the IR port. ClearMessage() This command clears the incoming message. You may want to do this after responding to an incoming message, to avoid responding more than once. The Display Although you can't control the display directly in NQC, you can configure it to some degree: SelectDisplay(expression v)
Page 69
int count; task main() { CreateDatalog(20); ClearTimer(0); SetSensor(SENSOR_1, SENSOR_TOUCH); count = 0; until (count == 20) { until(SENSOR_1 == 1); AddToDatalog(Timer(0)); Page 72 count++; until(SENSOR_1 == 0); When you run this program, you'll notice the RCX shows the status of the datalog on the right side of the display. It looks kind of like a pie; as you add values to the datalog the pie fills up. To upload a datalog to the PC, you can use nqc's -datalog option, which simply dumps the values to the screen: C:\>nqc -datalog C:\>...
Page 70
Page 73 start taskname This command starts the named task. stop taskname Use this command to stop the named task. The following program controls its outputs from main and uses another task, sing, to play some music. The sing task has to be started from main; otherwise, its commands will never be executed.
Page 71
Page 74 PlayTone(277, HALF); PlayTone(330, GRACE); PlayTone(311, HALF); PlayTone(277, HALF); Wait (2∗HALF); PlayTone(247, HALF); PlayTone(311, HALF); PlayTone(208, HALF); PlayTone(208, 2∗BEAT); Wait(GRACE + 5∗HALF + 2∗BEAT + HALF); stop main; Float(OUT_A + OUT_C); When the sing task is done playing music, it stops the main task with the stop command. Then it turns the motors off. The order is critical. If we turned off the motors and then stopped the main task, it's possible that main would turn on the motors again before it was stopped.
Page 72
Page 75 efficient because the code is just compiled once. With a macro, the entire macro body would be placed at each point where it was called. The RCX imposes three crippling restrictions on subroutines. First, you can't call another subroutine from within a subroutine. As a consequence, a subroutine also cannot call itself. Second, you can't pass parameters to a subroutine or get a return value.
If you pass int by value, the parameter's value is copied into a temporary variable (from the pool of 31) and used in the inline. const int passes by value, but the value must be a constant at compile time. If you pass by reference, the variable that is passed in can actually be modified in the inline.
Page 74
while (true) { if (SENSOR_2 < DARK2) OnFwd(OUT_A + OUT_C); The DARK2 and POWER constants are determined using #defines; this means it's easy to fiddle with their values, and our program is easy to read. The second task takes care of things when the light sensor leaves the black line. Whenever the robot leaves the line, the toggle() subroutine is called. toggle() starts the robot turning. Then we wait a little while;...
Page 75
if (SENSOR_2 > LIGHT2) { toggle(); Wait(TIMEOUT); if (SENSOR_2 > LIGHT2) { toggle(); Wait(TIMEOUT ∗ 2); sub toggle() { if (state == LEFT) { OnRev(OUT_A); OnFwd(OUT_C); state = RIGHT; else { OnFwd(OUT_A); OnRev(OUT_C); state = LEFT; The main task performs three important initializations which I haven't mentioned yet. First, main initializes the value of the state variable. It just uses LEFT Page 79 arbitrarily.
Page 76
while (true) { if (state == BOTH_ON) OnFwd(OUT_A + OUT_C); else if (state == LEFT_ON) { Off(OUT_A); OnFwd(OUT_C); else if (state == RIGHT_ON) { Off(OUT_C); OnFwd(OUT_A); A separate task, watcher, examines the light sensor values and sets the state variable. Here is the entire source code for the two sensor version of Trusty: int state;...
This is the official site for NQC. You can download the current release, read the documentation, or browse a FAQ. Dave Baum has packed a lot of useful information into this site, including such gems as how to create a cable to connect your Macintosh to the IR tower. This site also includes the definitive NQC documentation. Lego Robots: RCX Command Center http://www.cs.uu.nl/people/markov/lego/rcxcc/ RCX Command Center (RcxCC), developed by Mark Overmars, is built on top of NQC.
Page 82 Minerva, a Robot with an Arm In this chapter: • Building Instructions • Programming • Directional Transmission • Pulleys • Mechanical Design • Two Sensors, One Input • Where Am I? • Online Resources Minerva is a mechanical marvel. Although she has the same wheel layout as Trusty, Minerva's drivetrain is radically different. In addition, she has a simple arm with a grabber, which allows her to pick up and drop small objects.
Page 79
∗ Minerva uses almost all of the gears that come with RIS 1.0. Unfortunately, RIS 1.5 comes with fewer gears (five 12t gears instead of eight). To get the extra gears you'll need for Minerva, you can order the #5229 Gears & Differentials parts pack from the LEGO Shop At Home Service, (800) 453–4652. Cost is $4.50 including shipping.
Page 80
Page 85 Make sure the bump on the long pin is up against the 4u beam.
Page 81
Before you put all of Step 7 together, make sure the swiveling parts from Steps 1 and 2 are pointing up, as shown. Page 86...
Page 83
Page 87 Page 88 Step 11 is tricky. You'll need to slide the 8u shaft into the structure, adding bushings and gears as you go. The swiveling pieces from Steps 1 and 2 are now anchored.
Page 96
Page 100 Attach the RCX on both sides as shown. Page 101...
Page 97
Wiring First, attach the left motor, which powers the arm, to output A. Then use a wire brick to attach the right motor (the drive motor) to output C.
Page 98
Page 102 Attach the light sensor to the front of the arm. The wire attaches to Minerva's side as shown. Next, use a wire brick to attach the touch sensor to the light sensor wire. Then use a longer wire brick to attach both wires to input 3.
Page 103 Programming Minerva's basic program is straightforward: find something to pick up bring it back to the starting point The program assumes that the objects to pick up will be dark and that the surface Minerva is driving on is light. To return to the starting point, Minerva measures how long it has to drive forward to pick something up.
Page 100
Page 104 sub calibrate() { // Take an average light reading. i = 0; runningTotal = 0; while (i < NUMBER_OF_SAMPLES) { runningTotal += SENSOR_3; Wait(10); i += 1; threshold = runningTotal / NUMBER_OF_SAMPLES; void grab() { // Run the motor until we hit the limit switch. OnFwd(OUT_A);...
Page 101
Page 105 release(); // Turn around. OnRev(OUT_C); Wait(TURNAROUND_TIME); Let's look at the simple parts first. The grab() and release() inline subroutines take care of the grabber arm. All they do is run the arm motor in one direction until the limit sensor is pressed. Running the motor forward causes the arm to descend, the grabber to close, and the arm to lift again.
release(); OnRev(OUT_C); Wait(TURNAROUND_TIME); The main task configures Minerva's inputs and then calls retrieve() five times in a row. If everything works perfectly, which it probably won't, Minerva finds five dark objects and brings them back to her starting point. In the next section, I'll explore some of the things that can confuse Minerva. Try It Out! To take Minerva out for a spin, I suggest using the back of the Test Pad that comes with RIS.
Page 103
The bottom shaft is the input. A 24t gear mounted on this shaft drives another gear that is mounted on a beam that rotates on the input shaft. Depending on which direction the input shaft turns, the beam swings to the left or right; the top gear on the beam engages the gear on either the far left or far right. These gears are on the output shafts. You could create variations on this configuration, using different combinations of gears, but the idea is the same.
Page 109 Figure 5-5. Minerva's directional transmission has four outputs The basic directional transmission designs I've described are quite simple. Try to use one of these to drive a robot, however, and things get a little more complicated. Minerva, as you've seen, is a gear hog.
Figure 5-6. Linking shafts with pulleys and a band On the other hand, you can use pulley slippage to your advantage. If part of your robot should have a limited range of motion, like a trap door that opens and closes, a pulley can be very useful. You can run the motor for longer than it actually takes to open or close the door—when the door has gone as far as it can go, the pulley band will simply slip.
A single touch sensor can be used to detect when the arm is fully raised, either with the gripper open or the gripper closed. Picking up an object is simply a matter of running the motor in the right direction and waiting for the touch sensor to be pressed. Releasing an object is just as simple. The "fingers"...
Where Am I? You've probably discovered that Minerva gets lost easily. If she drives over anything, or if her wheels slip in any way, she can't find her way back to her starting point. Minerva, basically, is trying to answer the question "Where am I?" Unfortunately, she can't answer it very well. Timing Minerva uses a fairly unreliable technique, called timing, to determine her current position.
This page, created by Michael Powell, describes the basic principle of the directional transmission with detailed photographs. Ben's Lego Creations http://www.pobox.com/~benw/lego/ This page contains some fascinating robots created by Ben Williamson. A modified version of Ben's FetchBot arm was used as Minerva's grabber arm. These robots are mechanically superlative;...
Page 109
• An overview of the pbFORTH software architecture • Obtaining and installing pbFORTH • A brief description of Forth • Listings of RCX-specific words defined in pbFORTH • Example programs Replacement Firmware Later, in Chapter 10, legOS, I'll talk about another popular programming environment. legOS and pbFORTH are both replacement firmware, which means they actually replace the software on the RCX.
Page 110
Installing pbFORTH Installing pbFORTH is a simple process: 1. Obtain pbFORTH from http://www.hempeldesigngroup.com/lego/pbFORTH/. It's available as an archive that contains the pbFORTH replacement firmware, the source code, and example scripts. 2. Install pbFORTH on the RCX. To do this, you'll need a firmware downloader. The firmware downloader is a piece of software that knows how to transmit firmware over the IR link to the RCX.
Page 111
Page 119 pbFORTH from your RCX, you'll need to remove the batteries to clear the memory. Then you can use nqc or firmdl to download a different set of firmware. If you want to reinstall the default firmware, you can use the RIS software. Talking to pbFORTH To interact with pbFORTH, you need to use a terminal emulator to exchange data with the RCX over the IR link.
Page 112
First, the terminal emulator needs to know how long to wait after sending each character. In HyperTerminal (in Windows 95, 98, or NT), this setting is available in the File > Properties menu option. In the window that appears, choose the Settings tab and press the ASCII Setup button. You should set the Line delay to 100 milliseconds and the Character delay to 20 milliseconds, as shown in Figure 6-2.
Page 113
77 12 55 55 12 ok 77 ok If you understand the stack, you know almost everything there is to know about Forth. Words and the Dictionary The other important concept in Forth is the dictionary. This is simply a list of words and what they mean. A word is a simply a program with a name. To run it, Page 122 you just type its name.
Page 114
Bitwise operators are also defined: AND, OR, XOR. You can change the number base you're working in using the HEX and DECIMAL words. For example, if you wanted to work in hexidecimal (base 16), you would type HEX. Base 10 is represented by DECIMAL.
Page 115
Page 124 Here's another simple example that demonstrates how to print messages from within a word. Be careful about the spacing: the actual string to be printed is framed by the .“ and ” words, which are separate from the string. : helloWorld ."...
Page 116
Page 125 Conditionals and Loops Forth supports a standard IF statement, though the order is switched around from what you might be used to. The IF word comes in two different varieties: condition IF body THEN The IF word looks at the condition on the stack. If the condition is true, the body between IF and THEN is executed. Table 6-3 lists some of the mathematical condition words that are available.
Page 117
Page 126 value of the loop index on the stack with the I word. For example, the following shows how to define a word that prints the numbers from 1 to 10. : oneToTen 11 1 DO I . LOOP ; oneToTen 1 2 3 4 5 6 7 8 9 10 ok limit start DO words delta +LOOP...
Page 118
Page 127 After MOTOR_SET runs, the stack is empty. The first thing you need to push on the stack is power; the last thing is index. In your code, it comes out in the same order: 7 2 0 MOTOR_SET In this case, 7 is power, 2 is mode, and 0 is index.
Page 119
Page 128 BUTTON_INIT ( -- ) This word initializes pbFORTH's button-handling system. Make sure to call it once before you try to call BUTTON_GET. BUTTON_GET (address -- ) This word places the current button state into the variable address. pbFORTH provides a variable, RCX_BUTTON, that you can use for this purpose. The value placed in the variable tells which buttons are pressed and is a combination (boolean OR) of the values shown in Table 6-4.
Page 120
Figure 6-3. The RCX's display pbFORTH can display a number from the stack with the following word: LCD_NUMBER (decimal value signed -- ) This word shows the number value on the display. The decimal parameter controls the location of the decimal point, if there is one, while the signed parameter determines whether value is shown as signed or unsigned.
Page 121
Page 130 Note that we've specified the value in hexadecimal (-1066) but the display always shows decimal (-4198). pbFORTH provides two words that show or hide individual display segments, basically everything except the numbers: LCD_SHOW (segment -- ) LCD_HIDE (segment -- ) These words show or hide the given display segment.
Page 122
301B Low battery indicator 301C Short range download indicator (table continued on next page) Page 131 (table continued from previous page) Table 6-7. LCD Segment Numbers (continued) Segment Number Sequence? Description (hexadecimal) 301D Long range download indicator 3020 All segment ( LCD_SHOW only) Conveniently, you can clear the entire display with a single word:...
Page 123
Table 6-8. Input Type Values Value Description Touch senso Temperature sensor (table continued on next page) Page 132 (table continued from previous page) Table 6-8. Input Type Values (continued) Value Description Light sensor Rotation sensor SENSOR_MODE (mode index -- ) This word sets the mode of the given input.
Page 124
2 CONSTANT INPUT_3 SENSOR_INIT INPUT_3 SENSOR_ACTIVE 3 INPUT_3 SENSOR_TYPE 80 INPUT_3 SENSOR_MODE Reading input values Reading input values in pbFORTH is a two-step process. First, you need to tell pbFORTH to go and read the input values: SENSOR_READ (index -- code) This word tells pbFORTH to read the value of the specified input.
Page 125
timer_SET (value index--) This word sets the timer described by index to the supplied value. timer_GET (index--value) This word places the current value of the timer described by index on the stack. Page 134 Power Management pbFORTH includes a simple power management scheme that allows you to turn the unit off. It doesn't actually turn off completely; it just goes into a low power consumption mode until you press the On-Off button to turn it on.
Page 126
Page 135 (table continued from previous page) Table 6-11. SOUND_PLAY Sounds (continued) Sound Number Description Descending arpeggio Ascending arpeggio Long low note Quick ascending arpeggio (same as 3 but faster) The sounds can be either unqueued or queued. Unqueued sounds will be played right away if no sound is currently playing. If a sound is currently playing (i.e., the sound system is already busy), then the unqueued sound will not be played at all.
Page 127
MOTOR_TASK BUILD TIMER_TASK BUILD SENSOR_TASK BUILD DISPLAY_TASK BUILD 3. Next, you need to actually define what each task does. This is done with the ACTIVATE word, which can be used only inside a definition. Consider, for example, the MOTOR_TASK. Basically, we want it to look like this: BEGIN UPDATE_MOTORS PAUSE AGAIN The real work of the task is in UPDATE_MOTORS, a word that examines some other values in the system and sets the state of the motors.
Page 128
If you bought LEGO's temperature sensor, you now have yourself a $225 digital thermometer. Chapter 11, Make Your Own Sensors, shows how you can build your own temperature sensor. You could use that code to make a digital thermometer for only about $202.
Page 131
Page 141 grab turnAround return release turnAround I won't describe every word in Minerva's program, but I do want to cover the more interesting ones. First, let's take a look at seek and return. The interesting thing about seek is that it uses one of the RCX's timers to figure out how long Minerva moves forward before finding something to pick up.
Page 142 Finally, as an added bonus, the average value is shown on the RCX's display: threshold @ showValue The average value, threshold, is used in the seek word to find a dark object to pick up. seek drives forward until the light sensor returns a reading that is 3 less than the average: BEGIN 2 sensorValue threshold @ 3 - <...
Another popular firmware downloader is firmdl. Written by Kekoa Proudfoot, the source code is available in C and should compile on most platforms. LEGO World Shop http://www.legoworldshop.com/ This online store offers various useful items like the temperature sensor used in this chapter. You can also get touch sensors, light sensors, rotation sensors, more motors, and extra RCX's.
Page 145 A Remote Control for Minerva In this chapter: • Two Heads Are Better Than • The Allure of Telerobotics • Building Instructions • Programming the Remote Control • Programming Minerva • Online Resources In Chapter 5, Minerva, a Robot with an Arm, you read about a mechanically complex robot that could be built from one RIS kit. One of Minerva's shortcomings, however, is that she isn't very smart about searching out things to pick up.
RCX1 to RCX3 20 to 29 RCX2 to RCX3 A more general solution may someday be supplied by the LEGO Network Protocol, a work in progress in the online MINDSTORMS community (see the "Online Resources" for more information). The Allure of Telerobotics Replacing the function of your robot's brain with that of a human brain is appealing in many situations.
Page 136
Page 148 Attach the light sensor and wire bricks as shown. The light sensor goes on input 1, while the two wire bricks (which will be attached to the touch sensors) go to input 2 and input 3. If you get these two wires backwards, you'll know when you push the joystick backward and the robot moves forward.
Page 137
The two touch sensors are triggered by a joystick-like lever contraption. Only one of the sensors will ever be triggered at a time. Page 149 The next step shows the joystick, which is really a simple lever.
Page 138
Page 150 Put the joystick, from Step 5, into the assemblies from Step 6. Fasten it together with the two yellow plates. Then put the whole thing on the remote assembly. When you wiggle the joystick back and forth, it pushes one or the other touch sensor. Step 8 might not look like much, but it's important.
In Step 9, the slider gets mounted on the remote. Make sure it slides freely, and note that it's upside-down with respect to the rest of the construction. The orientation of the yellow and black bricks in the slider will make a difference in how the arm is controlled.
Page 141
PlayTone(494, 10); PlayTone(660, 10); SendMessage (RELEASE_MESSAGE); lastArmMessage = RELEASE_MESSAGE; if (SENSOR_1 >= (middle + TOLERANCE) && lastArmMessage != GRAB_MESSAGE) { PlayTone(660, 10); PlayTone(494, 10); SendMessage(GRAB_MESSAGE); lastArmMessage = GRAB_MESSAGE; Page 153 task heartbeat() { while (true) { SendMessage (HEARTBEAT_MESSAGE); Wait (HEARTBEAT_TIME); The main task configures the inputs on the remote control and starts up the other tasks.
Page 154 grabber arm command it sent to avoid unnecessarily sending the same command twice. To provide some feedback to the human operator, lightWatcher plays tones when it sends the grab or release commands. The hearbeat task is very simple. It repeatedly sends the heartbeat command to the IR port. Programming Minerva Minerva's program, then, must listen for incoming messages on the IR port and respond to them.
Page 143
task messageWatcher() { while (true) { message = Message(); if (message == FORWARD_MESSAGE) { OnFwd(OUT_C); ClearMessage(); else if (message == SPIN_MESSAGE) { OnRev(OUT_C); ClearMessage(); else if (message == STOP_MESSAGE) { Off(OUT_C); ClearMessage(); else if (message == GRAB_MESSAGE) { start grab; ClearMessage();...
Page 144
task heartbeatWatcher () { while (true) { if (missedBeats > 1) { PlaySound (SOUND_DOWN); stop messageWatcher; Off(OUT_C); until (armLock == 0); Off(OUT_A); until (Message () == HEARTBEAT_MESSAGE); PlaySound(SOUND_UP); missedBeats = 0; start messageWatcher; missedBeats = missedBeats + 1; Wait(HEARTBEAT_TIME); Don't Break That Arm The grab and release tasks, as I said, have the ability to interrupt each other.
180[LEGO Network Protocol discussion thread] http://www.lugnet.com/robotics/rcx/legos/?n=180&t=i&v=c Although the LEGO Network Protocol is not yet mature, you can view its genesis in the discussion groups at LUGNET. This URL points to a lengthy exchange from the middle of 1999. Challenges and Competitions Events http://www.lugnet.com/robotics/events/...
Page 159 Using Spirit.ocx with Visual Basic In this chapter: • You May Already Have Visual Basic • About Spirit.ocx • Calling Spirit.ocx Functions • Immediate and Delayed Gratification • Programs, Tasks, and Subroutines • Tips • Retrieving the Datalog •...
Page 160 with more bells and whistles, is available for $279Us. If you have more money to burn, try the "Enterprise Edition," for $1299US. Don't be alarmed by the price tags. You may already have Visual Basic without knowing it. The applications in the Microsoft Office software include a limited version of Visual Basic, called Visual Basic for Applications (VBA);...
Page 148
A new item with the familiar LEGO logo should now be in your tool palette. Select this item and place it on the form you just created. We won't use the form for anything except as a place to keep...
It's little cumbersome to always refer to the full name of the Spirit.ocx control. A simpler syntax, using With, looks like this: Sub HelloSpiritII () With DummySpiritForm.Spirit1 .InitComm .PlaySystemSound 0 .CloseComm End With End Sub Page 163 Immediate and Delayed Gratification The functions in Spirit.ocx can be immediate, delayed, or both.
Page 164 When you run ChargeProgram, you won't hear anything. But when you select Program 5 and press the Run button, you'll hear the song. You have just downloaded a program to the RCX from Visual Basic! This example uses SelectPrgm to select the RCX's current program number. SelectPrgm expects a zero-based number, from zero to four, representing the RCX's programs from one through five.
Tips You've already seen a lot of the functionality of Spirit.ocx exposed in NQC. Although the syntax in Visual Basic is different, the basic functions are the same. LEGO's official Technical Reference Document (see the ''Online Resources") does a good job describing the syntax of Spirit.ocx commands; I won't attempt to duplicate that work. Instead, this section contains down-to-earth information on using Spirit.ocx.
Page 152
With DummySpiritForm.Spirit1 ' … Result = .Poll(SENSOR_VALUE, SENSOR_2 Result = .Poll (VARIABLE, 11) ' … End With It's a lot more readable with the symbolic constants. If you ever have to look at the code at some later date, you'll really appreciate knowing what's going on. Using If and While The Parameter Table is likewise the key to understanding the If and While functions.
.EndIf ' … .CloseComm End With End Sub Once you've mastered If, the While loop is easy. Like If, it compares two values using an operator. The body of the While (until an EndWhile) is executed until the comparison is false. The body of the following loop, for example, would be executed as long as the value of input 3 was less than 100: While SENSOR_VALUE, SENSOR_3, LESS, CONSTANT, 100 ' Loop body...
Page 154
Page 169 only upload fifty datalog values at a time. If you have larger datalog, it must be uploaded in pieces. The relevant Spirit.ocx function is UploadDatalog, which takes a starting index and a length. The first (zero-th) item of the datalog contains the length of the datalog. It's the first thing SaveDatalog reads: data = .UploadDatalog(0, 1) length = data(2, 0) -1...
' Get the data. data = .UploadDatalog(index + 1, stepSize) ' Write it out to a file. For i = o To stepSize -1 line = getTypeString(data(0, i)) + "," + _ Str (data(1, i)) + "," +_ Str (data(2, i)) Print #out, line Next i index = index + stepSize...
Page 156
This official document from LEGO describes Spirit.ocx in detail. Although LEGO calls it a Software Development Kit (SDK), it's not really a big deal. There's a PDF file of the Technical Reference Document, which is 112 pages of reference material describing every function in Spirit.ocx. There are also some Visual Basic files that you can download and experiment with, including a file of handy constant definitions.
Page 173 RoboTag, a Game for Two Robots In this chapter: • Building Instructions • Subsumption Architecture • Online Resources RoboTag is a game for two robots. The robots drive around in a simple arena; the edge of the arena is marked by a black line. When one robot bumps into the other robot, it shouts "Tag!" by sending a message out its IR port.
Page 159
Page 175 The 16t gears are nestled inside the tread wheels.
Subsumption Architecture The traditional approach to robot programming has been to emulate human thought processes. First, the robot processes its sensor data. Based on the sensor data, the robot constructs or updates a model of the world. Then it decides how to act. This deliberative approach is very complicated; it requires heavy-duty processing power and may not work properly anyway. Overview Subsumption architecture is a radically different paradigm for robot programming developed by Rodney Brooks at MIT in the late 1980s.
Page 164
Figure 9-2. The avoid behavior takes control of the robot when the bumper is pressed There won't always be a one-to-one relationship between inputs and behaviors. It's entirely possible that one behavior will be triggered by some combination of inputs. Likewise, a single input might trigger multiple behaviors, depending on the input's value.
Page 165
int tagCommand; task tag() { while(true) { if (BUMP_SENSOR == 1) { // Say tag! SendMessage(MESSAGE_TAG); // Coast to a stop. tagCommand = COMMAND_FLOAT; Wait(20); // Check to see if we got an acknowledgement. if (Message() == MESSAGE_ACKNOWLEDGE) { ∗ The endless loop isn't strictly necessary, but it makes cruise look more like the other behaviors.
Page 166
If tag sends out a tag message but doesn't receive a reply, it doesn't do anything. The lack of a reply can mean two things: either the other robot did not receive the IR tag message, or the robot bumped into an obstacle, not the other robot. In the original RoboTag by Matthew Miller, the arena contained no obstacles, so it was safe to assume that the other robot didn't "hear" the tag message.
Page 167
Page 184 int motorCommand; task arbitrate() { while(true) { if (cruiseCommand != COMMAND_NONE) motorCommand = cruiseCommand; if (tagCommand != COMMAND_NONE) motorCommand = tagCommand; if (avoidCommand != COMMAND_NONE) motorCommand = avoidCommand; if (taggedCommand != COMMAND_NONE) motorCommand = taggedCommand; motorControl(); Note that the order is important. The commands in the end of the list will overwrite the value of motorCommand and are thus higher-level behaviors. For example, if both the cruise and tagged behaviors are attempting to control the robot, the tagged behavior takes precedence by subsuming the lower-level behavior, cruise.
Page 168
Page 185 task. However, if you do this, the robot "jiggles" badly. The problem is that arbitrate changes the value of motorCommand several times each time it loops. As the value changes, motorControl responds by changing the motors' directions. We're really interested only in the value of motorCommand at the end of each loop in arbitrate. Therefore, motorControl is implemented as a subroutine and is called once each time at the end of the arbitrate loop.
Page 169
Page 186 while(true) { if (BUMP_SENSOR == 1) { // Say tag! SendMessage(MESSAGE_TAG); // Coast to a stop. tagCommand = COMMAND_FLOAT; Wait(20); // Check to see if we got an acknowledgement. if (Message() == MESSAGE_ACKNOWLEDGE) { PlaySound(3); SetPower(OUT_B, score); On(OUT_B); if (score <...
Page 170
Page 187 SendMessage(MESSAGE_ACKNOWLEDGE); PlaySound(4); Wait(800); ClearMessage(); taggedCommand = COMMAND_NONE; int motorCommand; task arbitrate() { while(true) { if (cruiseCommand != COMMAND_NONE) motorCommand = cruiseCommand; if (tagCommand != COMMAND_NONE) motorCommand = tagCommand; if (avoidCommand != COMMAND_NONE) motorCommand = avoidCommand; if (taggedCommand != COMMAND_NONE) motorCommand = taggedCommand; motorControl();...
About legOS legOS is replacement firmware that completely replaces the default RCX firmware that LEGO gives you. Like pbFORTH, it offers full control of the RCX. If you're already familiar with C, you may be more comfortable running legOS than pbFORTH.
Page 173
Figure 10-1. legOS software architecture Development Tools You'll need some heavy-duty tools to work with legOS. (There is another possibility, as described in the sidebar, ''An Innovative Alternative.") The good news is that the tools are free. The basic tool you need is a cross compiler, a tool that runs on one platform but produces executable files for another. In this case, you want a cross compiler that runs on your PC and produces firmware for the RCX.
Page 174
Part of compiling legOS involves running some Perl. You'll need to have Perl installed on your computer to make legOS programs. As before, Linux users probably have Perl lying around already. If you've installed Cygwin on your Windows machine, you'll need to go get Perl. See "Online Resources" for more information. Downloading Firmware Once you have successfully compiled something in legOS, you will need to download it to your RCX to run it.
Page 175
Page 193 your source code.∗ For example, if you saved the source code above in a file called /projects/HellolegOS.cyou would edit the Makefile's TARGET like this: TARGET=/projects/HellolegOS Then type make at the command line. If everything is installed correctly, you'll end up with a HellolegOS.srec file in the same directory as the source file. Trouble with Make If you can't make HellolegOS.c, and you're starting to curse at your computer, take a deep breath.
Page 176
To display a number, use lcd_number(): void lcd_number(int i, lcd_number_style n, lcd_comma_style c) Use this function to show a number, i, on the display. The number style is one of sign, unsign or digit. Signed and unsigned numbers are shown in the main display area, while digitshows a single digit on the right side of the display.
Page 177
void cputc(char c, int pos) Use this method to display a character at the given position. Valid positions are 0 through 4, where 0 is the right-most position (the single digit at the right of the display) and 4 is the left-most position.
Page 178
Page 197 if (SENSOR_1 < 0xf000) { // Touch sensor is pressed. If you're working with light or rotation sensors, legOS does offer some help. First, you can set inputs to be active or passive: void ds_active(unsigned∗ const sensor) void ds_passive(unsigned∗ const sensor) Use these functions to set the specified sensor to active or passive mode.
Page 179
Page 198 The rotation sensor code does not work in the March 30, 1999 build of legOS 0.1.7. Using the Buttons (direct-button.h) legOS provides one function and some other handy definitions to describe the state of the front panel buttons: int button_state(void) This function returns a value that indicates the state of the RCX's four buttons.
Page 180
Page 199 dir_write() function does not work in the March 30, 1999 build of legOS 0.1.7. Two functions are provided for reading data from the IR port: size_t dir_read(void∗ buf, size_t len) This method reads len bytes of data into the supplied buffer. It returns the number of bytes read or -1 if there is an error. void dir_fflush(void) The IR input is buffered, which means incoming data is placed in a buffer.
Page 181
Here is a simple example that uses two tasks. The first task shows "Hello" and "nurse" on the display. The second task just waits for the Run button to be pressed. When it is pressed, the first task is stopped, the second task ends, and control returns to legOS. #include "conio.h"...
Page 182
wakeup_t wait_event(wakeup_t (∗wakeup)(wakeup_t), wakeup_t data) Use this function to wait for a specific event. The function pointed at by wakeup is called, with data as a parameter, until it returns a non-zero result. At this point, wait_event() will return. It's not hard to use wait_event(), but it's certainly not obvious. It helps to look at some of the examples that come with legOS. The following is a rewrite of the previous example that uses wait_event() instead of a while loop: #include "conio.h"...
Page 183
You can request chunks of memory in the RCX using the familiar malloc() and calloc() functions. LegOS, by itself, takes up about 5K or 6K of the RCX's 32K of RAM. You should have about 26K left for your program and its data. void ∗malloc(size_t size) This function allocates a chunk of memory of the given size (in bytes).
Page 184
long int random(void) This function returns a pseudorandom number. void srandom(unsigned int seed) Use this function to provide a new seed for the pseudorandom number generator. Page 204 In string.h There are also functions for working with text strings: char∗ strcpy(char ∗dest, const char ∗src) int strlen(const char ∗s) int strcmp(const char ∗s1, const char ∗s2) These are the standard string copy, length, and compare functions.
Page 185
Page 205 Figure 10-2. Hank, retrofitted with a light sensor • avoid() is the highest-level behavior. It is triggered by the bumpers and does the standard back-up-and-turn. Convincing Hank to seek light is surprisingly hard. You can, of course, implement your own algorithm in seek_enlightenment(). It's a neat feature of subsumption architecture that you can concentrate solely on light-seeking behavior in seek_enlightenment().
Page 187
Page 207 int seek_enlightenment(int argc, char ∗∗argv) { int baseline, current, loop_count, result; seek_command = COMMAND_NONE; // Get a baseline. baseline = process_light(SENSOR_2); loop_count = 0; while(1) { msleep(50); // Slow things down a little. // Every so often, increase the baseline. if (++loop_count == 5) { if (baseline <...
Page 188
Page 208 int motor_command; void motor_control() { motor_a_speed(MAX_SPEED); motor_c_speed(MAX_SPEED); switch (motor_command) { case COMMAND_FORWARD: motor_a_dir(fwd); motor_c_dir(fwd); break; case COMMAND_REVERSE: motor_a_dir(rev); motor_c_dir(rev); break; case COMMAND_LEFT: motor_a_dir(rev); motor_c_dir(fwd); break; case COMMAND_RIGHT: motor_a_dir(fwd); motor_c_dir(rev); break; case COMMAND_STOP: motor_a_dir(brake); motor_c_dir(brake); break; default: break; int arbitrate(int argc, char ∗∗argv) { while(1) { if (avoid_command != COMMAND_NONE) cputc('a', 0);...
Page 189
Page 209 kill(pid[i]); return 0; void exec_helper(int (∗code_start) (int,char∗∗)) { pid[task_index++] = execi(code_start, 0, NULL, 0, DEFAULT_STACK_SIZE); int main() { task_index = 0; exec_helper(&avoid); exec_helper(&seek_enlightenment); exec_helper(&cruise); exec_helper(&arbitrate); execi(&stop_task, 0, NULL, 0, DEFAULT_STACK_SIZE); tm_start(); return 0; LightSeeker.c is a relatively large program, but it consists of easily understandable pieces. As before, I'll start at the bottom and work backwards through the source code. The main() function simply serves to start the other tasks in the program.
The behavior then enters an endless loop, examining the value of the light sensor. If it falls too far below the baseline, seek_enlightenment() asserts control and searches for brighter light: current = process_light(SENSOR_2); if (current < (baseline - FUDGE)) { To search for brighter light, seek_enlightenment() first sets a new baseline from the current light value: baseline = current;...
legOS's development cycle is a little clumsy. You write a program, compile it with the legOS source code, then download the whole thing to the RCX. It's the downloading that takes a long time. Here are some tips to make things go smoother: 1.
Page 192
#include "conio.h" int x; int main(void) { x = 44; lcd_int(x); lcd_refresh(); x++; delay(1000); return 0; If you look back at LightSeeker.c, you'll see that all the variable initialization is done explicitly. In general, it should ring a warning bell in your head when you see variables that are initialized at declaration time.
Page 193
Gavin Smyth wrote this helpful page about installing the legOS development tools under Windows 95, 98, or NT. It includes links to various files you'll need. Page 215 Installing legOS—the unauth, unofficial Lego RCX firmware http://ex.stormyprods.com/lego/legOS.html This page, created by Brain Stormont, also details the steps you'll need to follow to install a legOS development environment under Windows 95. It includes useful links to the relevant software.
The first thing you should think about is how you are going to attach your new sensors to the LEGO world. There are two goals to consider here: 1. The sensor, ideally, should be a LEGO brick itself so you can easily attach it to your robots. The sensors that come with RIS exhibit this property: the touch sensors and the light sensor are simply specialized bricks.
Page 195
3/16" in diameter. You can use pan head or round head machine screws, but the pan head is shaped more like a LEGO stud. Instead of drilling out the stud, just shave off the top...
Another interesting possibility is using a mercury switch as a touch sensor. A mercury switch has a sealed bulb that contains a drop of mercury. When the switch is oriented the right way, the mercury drop connects the two switch leads together. Figure 11-2 shows a photograph of a mercury switch; you may have seen ones with clear bulbs in your thermostat. The LEGO brick is shown...
Page 197
Page 220 Figure 11-2. A mercury switch The mercury switch works just like a contact switch. When the switch is correctly oriented, the two leads are shorted together. It's basically a primitive angle sensor. In a thermostat, for example, the mercury switch is used to indicate two states: either it's less than the desired angle or greater than the desired angle. The desired angle in a thermostat corresponds to the temperature setting you've chosen.
Although LEGO's light sensor is a powered device, the CdS photoresistor is a passive device. This means that you can't blindly configure the photoresistor input as a light sensor input. You should, instead, make sure the sensor is not powered and read the raw input values.
Page 199
The 8V that is supplied to the active sensor is an approximate number; the actual value depends on the juice in your batteries. The difference between fresh and used batteries can produce any voltage in the range from about 6.5V to 8.5V. Many electronic circuits are happy with 5V or more, so this may not be an issue for you.
SetSensorMode(SENSOR_3, SENSOR_MODE_BOOL); How you use this sensor is, of course, up to you. You could build the Hall effect sensor and the signal splitter circuit into a large LEGO brick. Then you could build small permanent magnets into other LEGO bricks. This would give you a flexible system, suitable for building limit switches, counters, or anything you can imagine.
Paul Haas; one implementation is documented nicely at Michael Gasperi's web site. Note that this method uses regular switches, not the LEGO touch sensors. The touch sensors that come with RIS provide a varying resistance as they are pressed. A garden variety switch is much more of a binary device, which is better suited to our touch multiplexer.
The bottom line, however, is that you can get just as much done with a LEGO motor and a LEGO rotation sensor. The whole point of a servo is that it rotates to a precise angular position; but that's just as easy to do with a motor coupled to a rotation sensor. As a matter of fact, the LEGO-only solution is more flexible. While a servo has only a limited range of angular motion, the motor and rotation sensor have no such constraints.
Page 203
Tools Black and Decker http://www.blackanddecker.com/powertools.htm Black and Decker makes a tool called the Wizard. With a cutting disk, it's useful for shaving the studs off LEGO bricks. Welcome to Dremel International http://www.dremel.com/ Dremel makes hand tools that are good for working with small things like LEGO bricks.
Page 204
Parts Table A-2 lists the parts you may wish to buy along with their prices at the three sources shown in Table A-1. This information is current as of mid-1999. (LWS is LEGO World Shop, S@H is LEGO Shop-at-Home Service, and Pitsco is Pitsco LEGO DACTA.) Note that the Shop-at-Home Service does not charge extra for shipping, so the list is not exactly comparing apples to apples.
Page 205
Large turntables N779876 $9.75 Other Suppliers Table A-3 lists suppliers for electronics parts. These are useful sources for the electronics described in Chapter 11, Make Your Own Sensors. Table A-3. Sources for LEGO Parts Name Telephone Web Site Jameco (800) 831 - 4242 http://www.jameco.com/...
Page 206
PRO-RCX http://prelude.psy.umontreal.ca/~cousined/ VB-like free Win32 lego/robot/rcx/rcx_command/ BotCode http://www.desktopmusic.com/botcode.htm VB-like Win32 a. This column assumes you've installed the RIS software. Most of the Win32 packages work with Spirit.ocx, which is installed with the RIS software. b. Win32 means Windows 95, 98, or NT.
Page 207
b. Win32 means Windows 95, 98, or NT. c. VB-like means similar to Visual Basic. Function names are modeled on Spirit.ocx. Page 235 A pbForth Downloader pbFORTH is a interesting, funky programming environment, but there are not many tools available for it. This appendix contains source code for a program downloader, written in Java. A program downloader enables you to develop your pbFORTH programs in a text editor and download them all at once to the RCX.
Page 208
import java.io.∗; import java.util.∗; import javax.comm.∗; public class Download { public static void main (String[] args) { String filename = args[args.length - 1]; String portName = "COM1"; for (int i = 0; i < args.length - 2; i++) { if (args[i].equals("-port")) portName = args[i + 1]; try { new Download (filename, portName);...
Page 209
mPort.setSerialPortParams( 2400, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE Reader in = new InputStreamReader(mPort.getInputStream()); mPortListener = new PortListener (in); mOut = new OutputStreamWriter(mPort.getOutputStream()); public void run() { int c, n = 1; try { sendReturn(); sendReturn(); while ((c = mFileIn.read()) != -1) { if (c == '\r') { sendReturn();...
mPort.close(); catch (IOException ioe) {} System.exit(0); protected void sendReturn() throws IOException, InterruptedException { mOut.write('\r'); mOut.flush(); Thread.sleep(kCharSleep); // Wait for response, or time out. long savedTime = System.currentTimeMillis(); boolean trucking = true; while (trucking) { if (mPortListener.isComplete()) trucking = false; long currentTime = System.currentTimeMillis(); if (currentTime - savedTime >...
Page 211
RIS 1.5 The first thing to look for, of course, is RIS 1.5. As of this writing (August 1999), there's been only a whisper of it, an off-hand mention in the discussion forums at the official LEGO MINDSTORMS web site. It's supposed to be released in the Fall of 1999, but what actually comprises RIS 1.5 is anybody's guess. One person at LEGO technical support did say it is a software- only upgrade, not a change to the RCX.
Page 212
LEGO Network Protocol LEGO Network Protocol (LNP) would allow two or more RCXs to communicate via their IR ports without prior configuration. While it is possible to exchange messages between multiple RCXs by reserving blocks of message numbers for specific RCX-to-RCX conduits, it's not a generalized solution. LNP is a more general approach, but it's still a work in progress. For more information, see the discussion lists at LUGNET.
Page 213
binutils package, web site, BotCode web site, Bot-Kit web site, bouncing, BrainStorm web site, BrickCommand, web site, building projects (see projects) bumpers, bushings, 15-16 buttons, legOS functions for, cars, 29-30 conductor plate, attaching sensors with, constants, copper tubing, attaching sensors with, Crickets web site, cross-compiling, web sites,...
Page 214
differential, differential drives, differential light sensor, directional transmission, web site, display configuring NQC, pbFORTH, functions (legOS), 194-195 Page 244 drives differential, synchro, web site, tri-star, drivetrains, Droid Developer Kit, egcs compiler, web site, E&L Group (Epistemology and Learning Group) web site, emulegOS web site, Epistemology and Learning Group (E&L Group) web site, Eureka web site,...
Page 215
feelers (see touch sensors) firmdl, firmware, downloader, 192-193 web sites, Forth programming language, 121-126 FTP sites, examples in this book, xiii functions legOS, 194-204 Spirit.ocx, gear reduction, geared motors, gearing down, gears, 31-35 worm, grabber arms, web sites, Hall effect sensor, 223-224 Hank, the Bumper Tank, 27-38 instructions for building, 16-25 programming, 204-211...
Page 216
idler wheels, If function (Spirit.ocx), 166-167 immediate functions, infra-red data link, legOS, 198-199 inlines, inputs input values, retrieving, 165-166 legOS, 196-197 web site, instructions for building Hank, the Bumper Tank, 16-25 Minerva, 83-102 remote control, 147-150 RoboTag, 174-179 thermometer, 137-138 Trusty, a Line Follower, 40-44 internal gearing, IR (infra-red) link,...
Page 217
Large Turntable piece, LEGO Group web site, LEGO Network Protocol web site, LEGO Shop at Home, LEGO Users Group Network (LUGNET) web site, legOS, debugging, development cycle, emulator, web site for, functions, 194-204 static variables, web sites, light sensors, adding a second,...
Page 218
Macintosh platform, magnetic compasses, memory, requesting (legOS), micro motors, MindControl web site, MINDSTORMS, history of, xi web sites, Minerva instructions for building, 83-102 programming, 103-107 pbFORTH, 138-142 remote control, 154-157 MIT Programmable Brick web site, mobile robots, 2-6 web sites, wheels, 27-35 motors, 34-35 servo,...
Page 219
(Programmable Brick FORTH), debugging, 142-143 program downloader, 235-239 web sites, words, 126-137 PBTurnOff function (Spirit.ocx), Perl, web site, Pitsco LEGO DACTA web sites, plates, Poll function (Spirit.ocx), 165-166 power management, pbFORTH, powered sensors, 221-224 program downloader, Programmable Brick FORTH (see pbFORTH) programming...
Page 220
debugging, 142-143 Hank, the Bumper Tank, 204-211 legOS (see legOS) light sensors, Minerva, 103-107 pbFORTH, 138-142 remote control, 154-157 multitasking, 72-74 cooperative multitasking, 135-137 in legOS, 199-203 NQC (see NQC) pbFORTH (see pbFORTH) random numbers, remote control, 151-154 RoboTag, 180-188 Trusty, a Line Follower, 77-80 projects Hank, the Bumper Tank, 204-211...
Page 221
RCX Code, limitations of, RCX Command Center (RcxCC), web site, RCX (Robotic Command Explorer), 145-146 programming environment, software architecture, 55-57 turning off, web sites, RCXJVM, remote control instructions for building, 147-150 programming, 151-154 RIS (Robotics Invention System), 6-7 history of, xi software, version web sites,...
Page 222
web sites, Robotics Discovery Set, Robotics Invention System (see RIS) robots, 2-6 balancing, rotation sensors, legOS, SaveDatalog function (RCX), sensor watchers, sensors, legOS, mounting, 217-218 passive, 219-221 powered, 221-224 web site, (see also light sensors; touch sensors) servo motors, shafts, Shape Memory Alloy (SMA) wire, signal splitter, SMA (Shape Memory Alloy) wire,...
Page 223
playing, 68-70 sensors, building, web site, Spirit.ocx, 159-171 web sites, standard motors, subroutines, subsumption architecture, web site, symbolic constants, synchro drives, web site, tasks, 164-165 behaviors, telerobotics, 145-147 (see also remote control) temperature sensors building, web site, Test Panel, tethered robots, thermistor, thermometer, building instructions, 137-138 timing,...
Page 224
40-44 programming, 44-47 in NQC, 77-80 turning radius, 29-30 (see also zero turning radius) Unix, UploadDatalog function (Spirit.ocx), View button (RCX), Visual Basic, 159-171 Visual C++, web sites challenges and competitions, Hitachi H8, Killough platform, LEGO Group,...
Page 225
LUGNET, MINDSTORMS, NQC, parts, electronic, sensors, pbFORTH, Pitsco LEGO DACTA, RCX, RcxCC, RIS, RoboTag, Spirit.ocx, Windows platform, 214-215 wheels, 27-35 idler wheels, While function (Spirit.ocx), 166-167 Windows platform, legOS and, web site for, 214-215 wire brick, attaching sensors, worm gears,...
Page 226
The image on the cover of The Unofficial Guide to LEGO® MINDSTORMS™ Robots is a mechanical toy rabbit or automaton, an automated machine. Biological automata, or androids, are imitations of living beings, animal or human, and have captured the imagination, fears, and hopes of inventors and spectators for many centuries. Especially notable in the long history of automata are the Chinese and Greek cultures.
Need help?
Do you have a question about the MINDSTORMS Robots and is the answer not in the manual?
Questions and answers