LEGO MINDSTORMS Robots Manual
LEGO MINDSTORMS Robots Manual

LEGO MINDSTORMS Robots Manual

Unofficial guide
Table of Contents

Advertisement

Page iii
The Unofficial Guide to LEGO® MINDSTORMS™ Robots
Jonathan B. Knudsen
Beijing • Cambridge • Farnham • Köln • Paris • Sebastopol • Taipei • Tokyo
Page iv
The Unofficial Guide to LEGO® MINDSTORMS™ Robots
by Jonathan B. Knudsen
Copyright: © 1999 O'Reilly & Associates, Inc. All rights reserved.
Printed in the United States of America.
Published by O'Reilly & Associates, Inc., 101 Morris Street, Sebastopol, CA 95472.
Editor: Mike Loukides
Production Editor: Nicole Arigo
Printing History:
October 1999:
First Edition.

Advertisement

Table of Contents
loading
Need help?

Need help?

Do you have a question about the MINDSTORMS Robots and is the answer not in the manual?

Questions and answers

Summary of Contents for LEGO MINDSTORMS Robots

  • Page 1 Page iii The Unofficial Guide to LEGO® MINDSTORMS™ Robots Jonathan B. Knudsen Beijing • Cambridge • Farnham • Köln • Paris • Sebastopol • Taipei • Tokyo Page iv The Unofficial Guide to LEGO® MINDSTORMS™ Robots by Jonathan B. Knudsen Copyright: ©...
  • Page 2: Table Of Contents

    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.
  • Page 9: Welcome To Mindstorms

    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.
  • Page 10: What Is A Robot

    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.
  • Page 12: What Is Mindstorms

    • 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...
  • Page 16: What Now

    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™.
  • Page 18: Hank, The Bumper Tank

    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.
  • Page 19: About The Building Instructions

    • 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.
  • Page 21: Building Instructions

    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.
  • Page 29: A Simple Program

    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.
  • Page 31: Wheels

    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.
  • Page 33: Bumpers And Feelers

    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.
  • Page 34: Gears

    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.
  • Page 37: Multitasking

    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:...
  • Page 38: Online Resources

    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.
  • Page 39: Trusty, A Line Follower

    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.
  • Page 40: Building Instructions

    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 41 Page 41...
  • 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.
  • Page 50: Idler Wheels

    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.
  • Page 51: Online Resources

    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.
  • Page 52: Not Quite C

    • 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.
  • Page 53: A Quick Start

    (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 54: Rcx Software Architecture

    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.
  • Page 56: Nqc Overview

    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 67 #define SIXTH 12 #define HALF 3∗SIXTH #define BEAT 2∗HALF #define GRACE 6 task main() { PlayTone(330, 2∗BEAT); Wait(2∗BEAT + 2∗SIXTH); PlayTone(115, SIXTH); PlayTone(208, SIXTH); PlayTone(247, SIXTH); PlayTone(330, SIXTH); PlayTone(311, 2∗BEAT); Wait(4∗SIXTH + 2∗BEAT + 2∗SIXTH); PlayTone(115, SIXTH); PlayTone(208, SIXTH); PlayTone(247, SIXTH); Page 70 PlayTone(311, SIXTH);...
  • 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.
  • Page 73: Trusty Revisited

    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;...
  • Page 77: Online Resources

    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 78: Minerva, A Robot With An Arm

    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 84 Page 89...
  • Page 85 Step 14 is similar to Step 11; take a deep breath and go slowly.
  • Page 86 Page 90 Grabber Arm In Step 17, the half-bushings go between the center block and the cams (pear-shaped pieces).
  • Page 87 Page 91...
  • Page 88 Page 92 Make sure that the two sides are at the same angle. They should mirror each other.
  • Page 89 Page 93 Page 94...
  • Page 90 Structural Support Page 95...
  • Page 91 Idler Wheel Page 96...
  • Page 92 Page 97 Drive Motor...
  • Page 93 While you're putting the motor in, hold on to the worm gear so it doesn't slip off. Page 98...
  • Page 94 Grabber Arm Motor...
  • Page 95 Page 99...
  • 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 99: Programming

    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.
  • Page 102: Directional Transmission

    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 104: Pulleys

    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.
  • Page 105: Mechanical Design

    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.
  • Page 106: Two Sensors, One Input

    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"...
  • Page 107: Where Am I

    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.
  • Page 108: Pbforth

    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 129 Page 139 DECIMAL 42 CONSTANT TURNAROUND_TIME 10 CONSTANT NUMBER_OF_SAMPLES VARIABLE threshold VARIABLE returnTime : sensorValue BEGIN DUP SENSOR_READ 0= UNTIL SENSOR_VALUE : calibrate NUMBER_OF_SAMPLES 0 DO 2 sensorValue + 1 sleep LOOP NUMBER_OF_SAMPLES / threshold ! threshold @ showValue : forward 7 1 2 MOTOR_SET ; : spin 7 2 2 MOTOR_SET ;...
  • Page 130 Page 140 : seek forward 0 1 TIMER_SET BEGIN 2 sensorValue threshold @ 3 - < UNTIL 2 sleep 1 TIMER_GET returnTime ! stop : return forward returnTime @ sleep stop : retrieve seek grab turnAround return release turnAround : Minerva initialize calibrate 5 0 DO...
  • 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 132: Debugging

    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 - <...
  • Page 133: Online Resources

    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 134: A Remote Control For Minerva

    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.
  • Page 135: The Allure Of Telerobotics

    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.
  • Page 139: Programming The Remote Control

    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 140 #define FORWARD_MESSAGE 16 #define SPIN_MESSAGE 17 #define STOP_MESSAGE 18 #define GRAB_MESSAGE 19 #define RELEASE_MESSAGE 20 #define HEARTBEAT_MESSAGE 21 #define HEARTBEAT_TIME 20 task main() { SetSensor(SENSOR_1, SENSOR_LIGHT); SetSensor(SENSOR_2, SENSOR_TOUCH); SetSensor(SENSOR_3, SENSOR_TOUCH); Page 152 start lightWatcher; start touchWatcher; start heartbeat; task touchWatcher() { while (true) { if (SENSOR_2 == 1) { SendMessage (FORWARD_MESSAGE);...
  • 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 142: Programming Minerva

    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.
  • Page 145: Online Resources

    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 146: Using Spirit.ocx With Visual Basic

    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 147: About Spirit.ocx

    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...
  • Page 149: Immediate And Delayed Gratification

    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 150: Programs, Tasks, And Subroutines

    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.
  • Page 151: Tips

    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.
  • Page 153: Retrieving The Datalog

    .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...
  • Page 155: Online Resources

    ' 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 157: Robotag, A Game For Two Robots

    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.
  • Page 160 Page 176...
  • Page 161 Page 177 Attach the motors to output A and output C as shown. Page 178...
  • Page 162 The light sensor, which is mounted on the bumper, is attached to input 2. The touch sensor goes on input 1. Page 179...
  • Page 163: Subsumption Architecture

    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();...
  • Page 171: Online Resources

    Page 188 sub initialize() { SetSensor(BUMP_SENSOR, SENSOR_TOUCH); SetSensor(LIGHT_SENSOR, SENSOR_LIGHT); ClearMessage(); score = 0; Fwd(OUT_B); SelectDisplay(5); calibrateLightSensor(); #define NUMBER_OF_SAMPLES 10 int i; int runningTotal; void calibrateLightSensor() { // Take an average light reading. i = 0; runningTotal = 0; while (i < NUMBER_OF_SAMPLES) { runningTotal += LIGHT_SENSOR;...
  • Page 172: About Legos

    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 186 Page 206 #define COMMAND_REVERSE 2 #define COMMAND_LEFT 3 #define COMMAND_RIGHT 4 #define COMMAND_STOP 5 int avoid_command; int avoid(int argc, char ∗∗argv) { avoid_command = COMMAND_NONE; while(1) { if (SENSOR_1 <0xf000) { avoid_command = COMMAND_REVERSE; msleep(BACK_TIME); avoid_command = COMMAND_RIGHT; msleep(TURN_TIME); avoid_command = COMMAND_NONE; if (SENSOR_3 <...
  • 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.
  • Page 190: Development Tips

    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;...
  • Page 191: Online Resources

    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.
  • Page 194: Make Your Own Sensors

    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...
  • Page 196: Passive Sensors

    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.
  • Page 198: Powered Sensors

    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.
  • Page 200: Touch Multiplexer

    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.
  • Page 201: Other Neat Ideas

    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.
  • Page 202: What About Actuators

    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();...
  • Page 210: Index

    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.

Table of Contents