advertisement

Print

Lego MindStorms: Programming with NQC
by Jonathan Knudsen | Pages: 1, 2, 3



Going out with a bang

Parts of this article:

An introduction to NQC (Not Quite C)

Program flow, reading inputs, and variables

A sample program

As a final example, let's develop a dark seeking program for RoboTag. We'll make the robot roam around on the floor, avoiding obstacles. When it gets to some place dark, like under a piece of furniture, it will stop.

The light sensor returns a value from 0 (dark) to 100 (light). In theory, the whole range of values can be returned. In practice, you'll probably never see readings outside the 30-70 range. We could hardcode a threshold into our program so the robot knows when it's in a dark place. But this is not very reliable; the same program might not work at different times of day. Instead, we'll take a baseline reading of the light sensor when the program starts. We'll stop the robot when the light sensor value falls significantly below this baseline.

The obstacle avoidance is similar to what you saw before, with a twist. This time, the robot picks a random direction to turn when it bumps into something. It turns for a random amount of time, too, from 0.5 s to 2.5 s. The key to this is the Random() command, as you'll see.

The program is split across three different tasks for clarity. The main task initializes the inputs and starts up the other tasks. The avoid task takes care of obstacle avoidance, responding to pushes on the bumper. The dark task shuts down the robot's motors, and the program, when the robot moves into a dark place.

Here's the whole program:

int baseline;

task main() {
  // Initialize.
  SetSensor(SENSOR_1, SENSOR_TOUCH);
  SetSensor(SENSOR_2, SENSOR_LIGHT);
  baseline = SENSOR_2;
  
  // Start tasks.
  start avoid;
  start dark;
}

task avoid() {
  On(OUT_A + OUT_C);
  while (true) {
    if (SENSOR_1 == 1) {
      // Back away.
      Rev(OUT_A + OUT_C);
      Wait(50);
      // Turn a random direction.
      if (Random(1) == 0) {
        Fwd(OUT_A);
        Rev(OUT_C);
      }
      else {
        Rev(OUT_A);
        Fwd(OUT_C);
      }
      // Turn for a random duration.
      Wait(50 + Random(200));
      // Go forward again.
      Fwd(OUT_A + OUT_C);
    }
  }
}

task dark() {
  until (SENSOR_2 <= baseline - 5)
    ;
  Off(OUT_A + OUT_C);
  stop avoid;
}

New directions

Now that you've got a feel for NQC, there are all sorts of interesting things you can try. NQC lets you do things like send and receive data with the infrared port (to communicate with other robots or PCs), play sounds, control the display, use timers, and store data in a datalog. Here are three suggestions:

  • Write a wall-following program. The algorithm is straightforward: drive forward in a gently turning arc. When you hit the wall, turn away from it a little. Then start over with the forward arc. You'll need to modify RoboTag's bumper a little to make this work -- the current design isn't very good at detecting collisions at the front corners of the robot.
  • Write a line-following program. This behavior causes the robot to move along a path marked on the floor. (If you don't want to mark up your carpets with electrical tape, you can just use the test pad that comes with the Robotics Invention System.) Line following is surprisingly hard. For two different approaches, see Chapter 3 of my book and Chapter 8 of Dave Baum's book.
  • Add sound to your program. This is useful for debugging; you can play different sounds to signify different parts of your program.

I hope you've enjoyed this quick tour through NQC. It's a great way to get involved with robot programming.

Building a robot of your own? Creating interesting programs for it? Tell us what you're up to in our Mindstorms forums.

Pages: 1, 2, 3


Jonathan Knudsen is an author at O'Reilly & Associates. His books include The Unofficial Guide to Lego MindStorms Robots, Java 2D Graphics, and Java Cryptography.