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
|