Contents

This page contains examples of the RCX specific extensions to pbForth. You should have a basic grasp of Forth terminology and programming, but if you're just looking to see how pbForth can control the RCX, the examples are still be easy to follow.

It would be a good idea to have a look at the pbForth RCX Word List before starting this tutorial. The "dictionary" is used to remind you what the parameters for each word are. Recall that Forth needs to have the parameters on the stack before the word is called.

Another point worth mentioning is that the RCX is a complex little beast, and it's best to bite off small chunks of knowledge instead of trying to digest the whole thing. I'd recomment working through the sample code at your computer with your RCX already running pbForth. It's not easy, and it's not foolproof, but if you stick with it, pbforth will be up to many of the challenges that you can find for it.

To get the most up to date version of pbForth firmware and the example scripts, you can get the pbForth Scripts as a zip archive or the pbForth Scripts as a tar.gz archive.

Motor Control

Forth has been called the LEGO of programming languages because you tend to build functionality from the bottom up. That means that you get the low-level words working first, test them, and then use them later with a high degree of confidence. To get going with this tutorial, it would be a good idea to build a simple differential drive robot. I'll assume that you've got the left side of the 'bot on MotorA and the right side on MotorC.

Turning MotorA on is pretty simple:

7 1 0 MOTOR_SET

In this case, were asking for power level 7, direction 1 (forward), for motor index 0 (A). This is the basic level that you will be working at when building your robot. It's usually a good idea to put your robot up on a stand to keep it from driving off the edge of your table.

Admittedly, using MOTOR_SET is a bit awkward, because putting the motor in each of the states requires a new set of parameters. Instead, we can factor the motor controls into general motions that we want the robot to do. Assuming that the robot will be a differential drive, we can ask it to go forward and backward, turn left or right, spin left or right, coast to a stop, or stop dead in its tracks.

The difference between turning and spinning a differential drive robot is subtle. When turning, one side of the robot will stop or float and the other side will continue to drive. The result is that the robot pivots around the side that is stopped. If we turn the stopped side in the opposite direction, the robot will tend to spin around a point halfway between the drive points.

We can make our robot do this by defining new words for each action as follows:

\ ---------------------------------------------------------
\ MOTOR1.TXT - Simple motor controls for differential drive

: BOT_FORWARD
  7 1 0 MOTOR_SET
  7 1 2 MOTOR_SET ;

: BOT_REVERSE
  7 2 0 MOTOR_SET
  7 2 2 MOTOR_SET ;

\ ... and so on

: BOT_STOP
  7 4 0 MOTOR_SET
  7 4 2 MOTOR_SET ;
\ ---------------------------------------------------------

Incidentally, the memory requirements for Forth words are pretty easy to calculate. Each call to a word like MOTOR_SET takes up 2 bytes (1 cell). A constant takes up 4 bytes (2 cells). Each definition of a word uses up about 8 bytes plus the number of bytes in the word's name.

I cut the example short because the more observant programmers among you will notice that the only thing that ever changes is the direction parameter. The power level is always 7, the motor numbers are always 0 and 2. Is there any way we can make this look neater? Can we factor these words even further? Of course we can.

Anyways, here is a more "efficient" way of writing the control words:

\ ---------------------------------------------------------
\ MOTOR2.TXT - Factored motor controls for differential
\              drive

: BOT_MOTOR_SET ( dir_a dir_b -- )
  7 SWAP 0 MOTOR_SET
  7 SWAP 2 MOTOR_SET ;

: BOT_FORWARD    1 1 BOT_MOTOR_SET ;
: BOT_REVERSE    2 2 BOT_MOTOR_SET ;
: BOT_TURN_LEFT  3 2 BOT_MOTOR_SET ;
: BOT_TURN_RIGHT 2 3 BOT_MOTOR_SET ;
: BOT_SPIN_LEFT  1 2 BOT_MOTOR_SET ;
: BOT_SPIN_RIGHT 2 1 BOT_MOTOR_SET ;
: BOT_COAST      3 3 BOT_MOTOR_SET ;
: BOT_STOP       4 4 BOT_MOTOR_SET ;
\ ---------------------------------------------------------

Notice how the direction parameters are all lined up in columns. This is a good idea because you can change the behaviour of the robot by changing the direction parameters. If you find that one of the motors is hooked up backwards, you can either turn the connector around, or fix the source code.

Another neat thing is that if you change the motor output connections, all you need to change is the BOT_MOTOR_SET word to use the right motor ports.

Display Control

After you figure out how the motors work, the next thing you'll want to do is get the display working. There are a number of display control words that are built into pbForth that have one thing in common - they don;t actually update the display until LCD_REFRESH is called. That's becuase the display control words just fiddle with some bits in the display buffer, and the LCD_REFRESH word actually writes the buffer to the LCD controller chip.

As you might already know, there are lots of different LCD segments on the RCX display, and you can set or clear them at will. In practice, I only use the LCD for simple debugging output, so I rarely write very sophisticated display operations. One of the most basic things is displaying a number on the 5 digit display section.

\ ---------------------------------------------------------
\ DISPLAY1.TXT - Simple display control words

BASE @ HEX

: SHOW_NUMBER ( n -- )
  3002 SWAP 301F LCD_NUMBER ;

BASE !
\ ---------------------------------------------------------

Note that I've given the same example of SHOW_NUMBER using either decimal or hexadecimal numbers. It is very important to realize that the RCX always displays numbers in decimal, regardless of the currently selected BASE.

After you have figured out how to do basic number displays, you might want to add signed number display or add some decimal places. All of these can be added quite easily if you read the definitions for the LCD_NUMBER word.

The next thing you're likely to want to do is change the little indicators for motors and sensors. I've put together a simple script from the Extreme Mindstorms book that updates the display.

But I'll leave this for another day...:-)