Ol' Blue's Mind

EBFORTH

The RTXEB came with EBFORTH programmed into the Waferscale Integration MAP168. EBFORTH is based on the Forth 83 standard with extension words that take advantage of unique features on the RTX2001A. There are plenty of references on the Internet for general Forth language programming, so no Forth tutorials will be provided here. Below is a list of RTX-specific Forth words used in the software modules described below. This is not a complete list of all of the RTX-specific Forth words, though. The information within the parenthesis are the content of the data stack before (left) and after (right) the word is executed (--).

CR! ( n -- )
Writes a value n on the stack to the configuration register and removes the value from the stack.
CR@ ( -- n )
Reads the contents of the configuration register and pushes it onto the stack.
G! ( n g -- )
Writes a value n on the stack into a specified G-bus port address g and removes the value from the stack.
G@ ( g -- n )
Read a value from a specified G-Bus port address g and pushes it onto the stack.
IBC! ( n -- )
Writes a value n on the stack to the Interrupt Base/Control register and removes the value from the stack.
IBC@ ( -- n )
Reads the contents of the Interrupt Base/Control register and pushes it onto the stack.
IMR! ( n -- )
Writes a value n on the stack to the Interrupt Mask Register and removes the value from the stack.
IMR@ ( -- n )
Reads the contents of the Interrupt Mask Register and pushes it onto the stack.
TC0! ( n -- )
Writes the value n to the pre-load register of Timer/Counter 0 and removes the value from the stack.
TC0@ ( -- n )
Reads the contents of Timer/Counter 0 and pushes it onto the stack
TC2! ( n -- )
Writes the value n to the pre-load register of Timer/Counter 2 and removes the value from the stack.
TC2@ ( -- n )
Reads the contents of Timer/Counter 2 and pushes it onto the stack.
UCODE ( n -- )
Allow a user to generate application specific FORTH words which may be compiled into a single RTX instruction. This code is executed at compile time in the form n UCODE name, where name is the name of the new RTX-specific word.

As I started getting back up to speed with EBFORTH, I discoverd some shortcomings that threatened to make my programming activities much more difficult. I was trying to create new defining words using CREATE and DOES>. It turned out that DOES> in EBFORTH does not function correctly. Fortunately, a search of Google Groups found some code patches that fixed the problem. These code patches were originally written by Jack Woehr during the RTX Contest. The patches fix bugs in the DOES>, GOES>, HALIGN, DUP>R, and C, words. I've placed the patches into the file rtxeb_patches.fs, which I download into the RTXEB prior to other code modules.

Hardware Control Functions

The following Forth code modules are low-level interfaces to the hardware. They enable software abstraction of the sensors and motors of the robot. The high-level autonomous code contols the robots hardware via these software interfaces. Hopefully, future changes to Ol' Blue's hardware will be hidden by changes to the interface software. This will minimize impact on the autonomous software.

Real Time Clock Functions (rtc.fs)
A set words to setup, shutdown, and interact with a basic real time clock. The clock uses Timer/Counter 2 on the RTX2001A, which is set up to generate an interrupt every 5 milliseconds. This assumes a ICLK frequency of 4 MHz. A 32-bit variable holds the absolute tick value, which will wrap back to zero after 248.551 days. These functions are required by any other functions that need real time clock support.
Sensor Functions (sensors.fs)
A defining word was created to access the individual bits of the sensors read from G-bus (or ASIC bus) address 0x19. Six words were then created that return boolean flags according to the states of the low battery, turret home index, and bump sensors. These functions are required by any other functions that want to virtualize these sensors.
Drive Motors Control Functions (drive.fs)
A defining word was created to objectify to control of the drive motors. Ten words were created to control all activities of the drive motors.
Turret Motor Control Functions (turret.fs)
One word was created to activate to stepper motor of the turret to a known, saved phase state. Another word was created to shut down the stepper motor after saving its current phase state. These functions help to prevent jerking of the stepper motor between power-ups and power-downs. A defining word was created to objectify to stepping of the turret motor. From this, a word was created that rotates the motor by one step depending upon a direction flag. Another pair of words encapsulate the process of aligning the turret to a forward-facing directions, from an unknown orientation, using the turret home index sensor.
Infra-Red Ranger Control Functions (ranger.fs)
One word disables the RTX2001A EI5 interrupt input and sets up the EI3 interrupt input to feed into Timer/Counter 0. Another word restores these hardware elements back to their original settings. A third word performs the ranger function, generating 70 range values for a 360-degree sweep. A fourth word normalizes the 70 range values. Words are also provides to exercise the ranging function and dump the 70 range values.

Ol' Blues Autonomous Programs

Random Runner #1 (random_runner-1.fs)
This is a high-level set of routines that implement an automaton the travels in random directions based on feedback from the turret ranger and the front bump sensors. This code requires the RTXEB patches (rtxeb_patches.fs), real time clock functions (rtc.fs), sensor functions (sensors.fs), drive functions (drive.fs), turret control functions (turret.fs), and ranger control functions (ranger.fs) to be loaded first.

Once the real-time clock is initialized, the robot tries to align the turret three times; aborting the function if alignment fails. If alignment succeeds, the process loop is entered. The process loop first tests for turret alignment. If not aligned, the robot tries to align the turret three times; aborting the function if alignment fails. If alignment succeeds, then a 360-degree ranging is performed. The 70 ranges are normalized and then the best direction (left, forward, or right) is determined. If left or right is chosen, then the robot is turned in that direction for two seconds (about 180 degrees). The loop is repeated until a best direction of "forward" is chosen.

When the best direction is "forward", the robot drives forward for eight seconds or until one of the front bump sensors are activated. If a front bump sensor is activated, then the robot drives in reverse for one second. Once the driving is completed the main loop is repeated until the lifespan time is passed.

At the time that Random Runner #1 was written, Ol' Blue was in its original form. As was expected, the whisker bump senors were too finicky and fragile for the robot. It was also determined that the two-second turn time was too long. The robot essentially paced back and forth, retracing the same route.

Another problem was the alignment of the turret. Either the turret did not reach the alignment point after a ranging operation or the turret was shaken out of alignment each time the robot moved. It was necessary to check for turret alignment prior to every ranging operation. It was not feasible to lock the turret in position by maintaining power to the windings. This drew too much power from the batteries.

Random Runner #2 (random_runner-2.fs)
At the time that Random Runner #2 was written, Ol' Blue Mod 1 had been made. The problems with the bump sensors had been solved.

The code for Random Runner #2 is modified slightly from Random Runner #1. The turning time is decreased from two seconds to one second. This results in direction changes of about 90 degrees. The turret realignment code is moved into the inner loop. This was done in order to bring the turret back into alignment after every turret ranging activity and turn, instead of only after every forward run.

The one-second turning time yielded better performance, but there were still situations where the robot became "trapped" by turning too much. Lowering the turing time to about 1/2 second would yield a direction change of about 45 degrees. This begged the question as to whether it is possible to obtain relatively accurate turns using only motor running times. This would then require a change in the BEST-DIRECTION word so that it gives a relative heading value that is more fine-grained than "left-forward-right".

Random Runner #3 (random_runner-3.fs)
The code for Random Runner #3 is modified somewhat from Random Runner #2. The turning time is decreased from one second to 1/2 second. This results in direction changes of about 45 degrees. Turret alignment is checked before and after every ranging operation. If reqired, turret alignment is performed. This is to ensure that the data obtained from each ranging operation is consistently aligned. If turret alignment cannot be accomplished after three tries, the processing loop is aborted.

The turning performance now appears to be optimum. The main problem appears to be situations where the robot is trapped in a corner or inset. The rangering results are such that the robot is fooled into thinking that the best direction is always to go forward. The forward direction keeps the robot trapped in the corner or inset. A "back out" strategy is needed to solve this situation.

Random Runner #4 (random_runner-4.fs)
The code for Random Runner #4 is modified significantly from Random Runner #3. The STEER-ROBOT word is changed to allows timed spins to the left or right in 1/2-second increments. This generalizes the robot turning function somewhat, to allow the robot to use each ranging operation more efficiently. After each successful ranging operation, the 70 ranges are normalized and then the best direction (hard-left, left, forward, right, or hard-right) is determined. If left or right is chosen, then the robot is turned in that direction for one-half second (about 45 degrees). If hard-left or hard-right is chosen, then the robot is turned in that direction for one second (about 90 degrees) If a best direction of "forward" is chosen, then the turning operation is skipped.

After the optional turning operation is performed, the robot drives forward for eight seconds or until one of the front bump sensors are activated. If a front bump sensor is activated, then the robot drives in reverse for one second or until one of the rear bumper sensors are activated. If a rear bump sensor is activated, the robot stops immediately. If collisions occurs after three consecutive "forward" best directions, then the robot drives in reverse for four seconds or until a rear bump sensor is activated. If a rear bump sensor is activated, the robot stops immediately. After this reverse travel ends the robot is turn left for four seconds (about 180 degrees).

I'm quite pleased with this version of Random Runner. Once I figure out how to easily place video clips onto the website, I'll upload a video of Ol' Blue running its paces.

© 2005, 2006, 2007 Mac A. Cody

Last updated Friday, March 9, 2007