|Get started programming LEGO MINDSTORMS with this article that shows you how to get set up and introduces the key components you need to program LEGO MINDSTORMS with Visual Studio Express.|
Time Required: 1-3 hours
April 19, 2006
MINDSTORMS are products from LEGO that include everything a developer needs to physically build and program real robots. The typical MINDSTORMS product includes an array of building blocks, motors, sensors, and a central controller, known as the LEGO RCX.
To get started, you'll need to download and install the free LEGO MINDSTORMS SDK 2.5. This will install the drivers required to send commands to the LEGO MINDSTORM via infrared tower. You'll also need to install a Visual Studio 2005 product, such as Visual Basic Express Edition 2005.
Programming the LEGO RCX
The LEGO RCX is a brick-shaped component that handles all of the processing and command routing required for the MINDSTORMS robot to function. It makes use of the LEGO assembly instruction set (LASM) to interpret and execute both onboard programs and PC-driven requests. LASM bytecode is sent to the RCX from a PC via infrared data transfer, usually from a tower connected to the PC via USB or RS-232 (serial) cable.
Developers planning to build RCX-based applications have two models to choose from:
- Download LASM bytecode to the RCX and execute it as a complete application. In this model the entire program is sent to the RCX and it is run independently by the RCX's processor. This scenario is known as "autonomous" programming, since the RCX executes independent of the PC.
- Send a series of requests from a driver (typically a PC) that instructs the RCX on which actions it must take. In this model the business logic occurs on the PC and only imperative commands are sent to the RCX for processing, such as requests to change motor speed. This scenario is known as "integrated" programming since the RCX can be integrated easily with other applications.
In either model, the driver PC is responsible for assembling LASM bytecode and deploying it to the RCX. This bytecode can be compiled by any model (whether hand-assembled or automated via compiler) but is generally deployed using LEGO's provided infrastructure.
To deploy a list of instructions or requests, a developer will hook LEGO's GhostAPI.dll, a native Win32 DLL that offers an array of low-level functionality designed to simplify the process of queuing and deploying LASM commands. GhostAPI.dll is dependent on one of two native LEGO DLLs for communicating with the infrared tower: PbkComm32.dll (for RS-232) or PbkUsbPort.dll (for USB). The protocol for the tower itself is handled through TowerAPI.dll, another GhostAPI.dll dependency required with deployment. The tower communicates directly with the RCX via infrared, which reaches from several inches to several (around 15) feet. When deploying applications, be sure to include all four DLLs to support either type of port (GhostAPI.dll, PbkComm32.dll, PbkUsbPort.dll, and TowerAPI.dll).
While LEGO offers several solid solutions for developing autonomous applications, the Microsoft .NET Interface for LEGO MINDSTORMS project was designed to enable easy development of integrated applications using Visual Studio 2005 and the .NET Framework 2.0.
With the Microsoft .NET Interface for LEGO MINDSTORMS, a developer can use the .NET Framework language of their choice to develop against a high-level class library that closely resembles the physical model of the MINDSTORMS robots. It includes classes for the RCX, as well as classes for the motors and sensors.
The Microsoft .NET Interface for LEGO MINDSTORMS was designed with developer simplicity in mind. Under this design philosophy, any developer should be able to use the class library to develop an RCX application without having any knowledge of LASM, or of any of the underlying APIs used to communicate with the device, whether at the application or data layers.
The Microsoft .NET Interface for LEGO MINDSTORMS wraps LEGO's GhostAPI.dll and emulates a real-time controller model. Although the RCX itself does not provide event notifications to the driver PC, the Microsoft .NET Interface for LEGO MINDSTORMS library simulates this functionality by polling the RCX regularly on a separate thread, and then invoking changes through an abstract proxy class. The result is that developers are able to enjoy first class .NET support, including support for properties and events, without having to implement the low-level interoperability mechanisms or manage timing.
All types exposed by the Microsoft .NET Interface for LEGO MINDSTORMS are available from the C4F.LegoRcx.dll assembly.
The GhostApiWrapper Class
Although hidden from developers consuming the library, the GhostApiWrapper class is probably the most important type in the assembly. It exposes all of LEGO's GhostAPI.dll functionality required to send requests to the RCX. It is used exclusively by classes in the Microsoft .NET Interface for LEGO MINDSTORMS and isn't intended to be publicly accessible to developers.
In order to emulate real-time eventing, the GhostApiWrapper spawns a command thread, which requests values for active sensors as often as possible and sends other commands issued through higher-level classes. Although it does have a throttling mechanism to prevent hyper spinning, infrared commands tend to take so long that the command loop doesn't spin too quickly. The throttle mechanism is mostly useful when no sensors are being polled to ensure that the CPU isn't 100% "floored" during the loop.
In order to provide the highest level of performance and realism, the GhostApiWrapper does not directly execute commands upon receipt. Instead, there are three ways commands are sent to the RCX, depending on whether the developer is setting motor properties, retrieving data, or sending other commands. Note that each way is transparent to the developer, who only interacts with higher-level classes.
Setting Motor Properties
In order to move the RCX, its motors must be manipulated through their power and direction settings. Doing this serially, such as setting Motor A's power to 5, followed by Motor C's power to 5, would result in jerky movement that doesn't move the RCX in a straight line (assuming the standard RoverBot configuration). To mitigate this, the GhostApiWrapper class doesn't directly accept commands to manipulate the motors. Instead, a developer will change the value of the motor's power in a shared class derived from RcxBase, which the GhostApiWrapper's command thread will poll and update as necessary in its next iteration. This enables the wrapper to take advantage of packing requests where multiple motors may be manipulated within a single command.
Since infrared is used to retrieve data from the device, it can be quite slow at times. As a result, the GhostApiWrapper polls the RCX as often as possible on its command thread and caches the results in the shared RcxBase-based class. Developer access to RCX data is therefore virtually immediate and the results are expected to be fresh within a few hundred milliseconds, except in the case of some properties, such as battery power, which is polled less often (every few seconds).
When a data request response is received from the RCX by the GhostApiWrapper, it updates the RcxBase class shared between the Ghost API wrapping layer and the library's application layer. Some values, such as sensor values, will raise events if the value has changed.
Sending Other Commands
Outside of manipulating motors and retrieving data, there are a set of requests that can be sent to the RCX to perform certain tasks, such as playing tones with the RCX speaker. When these requests are sent to GhostApiWrapper, they are queued with the other pending commands and sent on the command thread in the order they were received.
While there are many classes in C4F.LegoRcx.dll that are used to abstract the Ghost API functionality, the public classes in C4F.LegoRcx.dll are designed to provide a smooth interface for external developers to interact with the RCX itself. As such, only a few select types are exposed publicly, and even those types have a subset of their respective properties, methods, and events available for use. Minimizing the surface area of programming enables developers to understand and implement applications more quickly and easily using the interface.
The flagship class, Rcx, provides a handful of methods used to manipulate certain properties of the RCX, such as the power down delay time, display, or the speaker, as well as RcxMotor properties that represent each motor and RcxSensor properties for each sensor. When created, the Rcx class will automatically attempt to connect to the device via USB, then via RS-232. If both are unsuccessful, the constructor will still succeed, but the developer is responsible for plugging in a tower and calling the Connect method.
' Create a new Rcx to play with Me._rcx = new Rcx() ' Play a low C note for 200 ms (these two are functionally equivalent) Me._rcx.PlayTone(33, 20) Me._rcx.PlayTone(RcxNote.C1, 20) ' Set the RCX display to show "99" Me._rcx.SetDisplay(99) ' Send the message "47" to other RCX devices via our RCX device Me._rcx.SendMessage(47)
The RcxMotor class is designed to emulate a physical RCX motor. In order to keep the developer experience as simple as possible, there are only two ways to manipulate the motor: via the Power property and the Off method. Setting the Power property to a positive or negative value ensures the motor is on and sets its direction forward or backward, respectively. Setting a Power of 0 puts the motor in float mode, where the motor is not locked off, but does not have any power. Calling the Off method sets the Power to 0 and locks the motor in the off state.
All access to RcxMotor objects must be through an Rcx class. Here are a few examples of using the RcxMotor:
' Full speed ahead on motor A Me._rcx.MotorA.Power = 8 ' Back up and to the right (assuming the RoverBot configuration) Me._rcx.MotorA.Power = -8 Me._rcx.MotorC.Power = -4 ' Turn off all motors Me._rcx.MotorA.Power.Off() Me._rcx.MotorB.Power.Off() Me._rcx.MotorC.Power.Off()
The RcxSensor class is designed to emulate a physical RCX sensor. By default, each sensor is set to the RcxSensorType.None type. In order to use the sensor, set it to the appropriate type, such as RcxSensorType.Touch for a touch sensor. Setting the type to something other than None indicates that there is an active sensor attached to the port, which lets the Ghost API wrapper layer know to poll the sensor for its latest value. The current value of an RcxSensor can be read from its Value property, and a developer can subscribe to the ValueChanged event to receive real-time notifications of when the value changes.
All access to RcxSensor objects must be through an Rcx class. Here is an example of configuring a touch sensor and handling its event:
' Configure our sensor 1 as a Touch sensor Me._rcx.Sensor1.SensorType = RcxSensorType.Touch ' Set up Sensor1_ValueChanged as the event handler for this sensor AddHandler Me._rcx.Sensor1.ValueChanged, AddressOf Sensor1_ValueChanged ' Handles value changes for sensor 1 Private Sub Sensor1_ValueChanged(ByVal sender As Object, _ ByVal e As RcxSensorValueChangedEventArgs) Dim pressed As Boolean = (e.Value == 1) ' Do something based on whether the sensor is pressed or not End Sub
Applications written using the Microsoft .NET Interface for LEGO MINDSTORMS have all the deployment benefits of .NET Framework 2.0 applications. To begin with, the target machine requires the .NET Framework 2.0 to be installed. Please note that the .NET Framework 2.0 is automatically installed by Visual Studio 2005. In addition, the target machine will require the LEGO MINDSTORMS SDK 2.5 to be installed as well.
Once the target machine has been set up, the easiest way to deploy these applications is to copy the executable and resource files, along with the required DLLs, to a folder on the target machine. While the executable and resource files will vary depending on your particular application, the executable directory will always need to contain C4F.LegoRcx.dll. In addition, this folder will also require GhostApi.dll and either PbkUsbPort.dll (for USB towers) or PbkComm32.dll (for serial towers), which can be found at [Program Files]\LEGO Software\LEGO Mindstorms SDK\Bin\GhostAPI on the target machine after the LEGO MINDSTORMS SDK has been installed.
Illustrates working with RcxMotors. Note that this sample requires the RovertBot configuration from LEGO's Constructopedia.
Illustrates handling RcxSensor events to maneuver the RCX around obstacles. Note that this sample requires the RovertBot configuration from LEGO's Constructopedia.
Illustrates working with the Rcx's speaker via the PlayTone method.
All the different language sample code downloads include a copy of the Microsoft .NET Interface for LEGO MINDSTORMS as a compiled assembly. The managed C++ download also includes the project source code for C4F.LegoRcx.dll.
The Microsoft .NET Interface for LEGO MINDSTORMS provides enough functionality to allow hobbyists and students to begin experimenting with robotics and was designed with simplicity in mind as the key focus. A number of example applications were developed to showcase the features of the library and to give programmers a quick start. There are several ways you can use this library to create great new uses for your LEGO MINDSTORMS kits by controlling them with a Microsoft .NET application. For example, maybe you want to program multiple MINDSTORMS to "work together" and share information about a maze? Or recreate the famous LEGO MINDSTORMS Rubik's Cube solver? Or build Web services interfaces to control a LEGO MINDSTORM from on the road? The possibilities are endless. We're excited to see what you'll build.