RCX Digital Input Adapter



Overview

The Lego RCX is a powerful tool for exploring robotics. However, with only 3 input ports, it lacks the flexibility of application that a standard micro-controller provides. This is most apparent when attempting to interface the RCX with a device that provides digital input, such as a smart sensor or another micro-controller.

A naive approach would use the 3 input ports as digital inputs, restricting the input range to numbers from 0-7. Another method, utilizing serial transmission is possible. But, when coupled with the RCX's already low sampling rate, the serial approach results in transmission rates much too slow for many applications, such as interfacing with an external data bus.

To combat these factors, we have chosen to provide digital interface to the LEGO RCX by converting an 8 bit input into a coded voltage level to be read by the brick's internal A/D converter. While this method has the drawback of converting from digital to analog back to digital, it does allow the fastest possible transmission of data while using only a single input port. This provides instant extension of the RCX's range of applications.


D/A Conversion

Here, we'll take a look at the general concepts of digital to analog conversion. In these schemes, a set of digital inputs is taken as a binary number, which is scaled to an equivalent voltage level. A bit of familiarity with the binary number system is helpful -- if you feel rusty, check here for a quick review.

  • Voltage Dividers

    The heart of any D to A conversion is the voltage divider. One of the most common circutis in all of electronics, the voltage divider takes a voltage difference and splits it into two parts. Voltage dividers look like this:

    A voltage divider of two resistors is easy to understand -- the voltages across each resistor are proportional to the values of the two resistors.

    Leaving a few details out, we'll mention that when a voltage divider drives a load, that load can change the operation of the divider. This happens when the resitance (or, more correctly, impedance) of the load circuit not much larger than the value of the divider's resistors in parallel.

    So, a good rule of thumb when using voltage dividers is to either make sure that the load's impedance is more than 10 times the smaller resistor, or to isolate the divider with a buffer.

    If you're interested in learning more about any of the circuits discussed here, the best reference is the all time classic, The Art of Electronics, by Paul Horowitz and David Hill. Online, there's a nice voltage divider calculator

  • Resistor Nets

    It's now easy to see how we can use a set of voltage dividers to encode a voltage level to the RCX. As a starting point, imagine a circuit with difference voltage dividers, each enabled by a given switch:

    Closing S1 will send a signal of 1 volt, and S2 will send 3 volts. However, S3's voltage divider will run into serious trouble, because the real picture of what's going on looks like this:

    The LEGO RCX has an impedance of 10k ohms! So, S3's voltage divider will not send the 5 volt level it should. We can easily fix this by using smaller resistors in S3's divider, but we need to be careful -- setting the values too low will draw excessive current.

    We can make as many of these voltage dividers as we wish, but as some point this becomes impractical. For example, sending numbers between 1 and 255 would require 255 different switches and dividers! Not only is this a pain in the neck, it also runs into the physical limitations of the resistors themselves, which have a tolerance of 1% at best.

    A better plan would be to use an R-2R ladder, which looks like this:

    Leaving the math out, the R-2R ladder makes it easy to encode a binary number as a voltage level. We can extend the ladder to accept as many digits as we wish by repeating the pattern. Now, instead of needing 255 switches, we can do the same job with only 8, and we only need two resistor values. The only limitations now lie in the tolerance of our resistors, and the precision of our input voltage.

    There's a fairly thorough, if technical, reference on R-2R ladders online. And of course there's a good section in The Art of Electronics.

  • D/A Chips

    The problems of resistor tolerance and input voltage precision are solved by using a manufactured D/A chip. Many of these are produced, most within reasonably low cost. A chip that accepts 8 bits in parallel, and uses a laser-trimmed resistor ladder in conjunction with an internally set voltage reference to generate an output voltage costs less than $10.

    Choosing among the different D/A chips can be confusing at first. The main differences are:

    # Bits
    You can get DAC's that accept 8, 10, 12, 14, 16 bits or more. The more bits, the bigger the cost. Since the LEGO RCX can only recognize 1024 different voltage levels, it doesn't make much sense to try for more than 10 bits.

    Parallel/Serial
    A DAC can accept bits in parallel or in serial transmission. Serial transmission means you're probably using a micro-controller or micro-processor to generate the data you wish to send. Parallel is much more intuitive and easy to work with.

    Package
    A DIP package (Dual Inline Package) fits neatly into a solderless breadboard, and is by far the easiest to use for experimenting. A number like 16-DIP means that the chip has 16 pins, 8 on each side. Be aware that a chip advertising 10 bits of input on a 16-DIP likely re-uses several input pins, and thus requires a micro-controller to regulate the transmission of data.

    Voltage/Current Output
    DAC's are available that output current levels instead of voltage levels. The current output DAC's are actually slightly cheaper, but may be less intuitive to work with.

    Internal Voltage Reference
    Some DAC's have an internal voltage reference, which is used to turn an input of, say, 5-6 volts into a reference of 5.00 volts. Since the DAC uses a network of voltage dividers, it's critical to start with a known voltage level. Having a built-in voltage reference makes a DAC very reliable and easy to use. A DAC without an internal voltage reference offers a bit of flexbility for your trouble, but you'll have to construct (or buy, for less than a dollar) a high precision external voltage reference.

    DAC's are available online at DigiKey.com, which has an extensive online catalog. Be sure to check out the datasheet of any chip online before you buy it, to make sure it does what you want it to.


RCX Sensor Ports

The LEGO RCX has three input ports. Each of these share an Analog to Digital Converter (ADC), which takes the voltage level of 0-5 volts across the input port and converts it to a number between 0-1023.

Since the 3 ports share the ADC, which can only look at one port at a time, and since furthermore the ADC process itself takes some actual amount of time, the RCX has a limited sampling rate. This rate, running normal Robolab, turns out to be about 330Hz -- a barrier to keep in mind when constructing a digital interface that requires a large amount of data transfer. Note that the sampling rate may be raised as high as 4 kHz by using Ultimate Robolab.

Each of the input ports also has a 10k pullup resistor, which means that the impedance of the RCX is about 10k ohms. This is critical to account for when feeding it with a circuit that relies on voltage dividers.


The Digital Interface

Now it's time to construct an actual digital interface to the RCX. The interface we'll make accepts 8 bits of input in parallel, converts them to an anlog signal read by an RCX port, and then uses driver code to convert the signal back into a number between 0 and 255.

This interface may be built on a small solderless breadboard in a few hours, for a cost of around $10, and enjoys a huge range of practical applications.

  • Unbuffered design

    The most basic approach would be to take an 8 bit DAC, such as the AD557, and feed its output directly to the RCX. The result would look like this:

    However, in practice, this runs into the problem of impedance -- the relatively low RCX impedance interacts with the voltage dividers of the RCX and throws off the results.

  • Buffered design

    Since we can't get inside the chip to change the resistor values, we will isolate the R-2R network from the RCX by using an op-amp buffer. The op-amp buffer is a simple circuit that looks like this:

    It is an amplifier with a gain of 1: the signal out exactly matches the signal in. This may not seem useful at first, until we realize that the op-amp serves as a clean buffer which isolates the voltage dividers from any interaction with its load.

    Notice that the op-amp has its own V+ and V-. In practice, most op-amps can only generate output signals that fall well within this range. Special op-amps, called rail-to-rail op-amps, can generate signals almost right up to their V+ and V-. However, we'll always do well to make sure that the V+ is safely greater than the maximum signal value we wish to send, and V- is safely less than the lowest value.

    With this knolwedge, we'll use the op-amp buffer to solve the impedance problems we encountered with the DAC and RCX.

    Parts list:

    The DAC input pins are used as follows:

    • The 8 input pins D0-D7 get the digital input coming in. D0 is the least significant bit (the one's place), D7 the most significant bit.
    • +Vcc gets 5.4V, and the two GND's get 0V. See below for more on this.
    • Vout is the output signal that gets sent to the op-amp buffer
    • Vout SENSE A and Vout SENSE B are both connected directly to Vout. These pins allow the user to insert resistors across them, which are used with an internal non-inverting op-amp for scaling. We've chosen not to use this option, since scaling would introduce error from the tolerance of our resistors.
    • CS' is a low-true pin that selects this chip. Since this is the only DAC we're using, we set it to GND, which permanently selects it.
    • CE' is a low-true pin that enables the chip. Again, since we're assuming continuous operation, we set it to GND, which permanently enables it. Note that if we wanted to use mechanical switches to drive the input, we could debounce those switches by driving CE' with a square wave from a 555 timer, set with a period of about 1ms.

    The circuit is driven by a AA battery pack that gives 6 volts of potential. Since both the DAC chip and the op-amp we're using have a maximum difference of 5.5V, we trimmed down the battery voltage using a diode-drop. (The voltage across a diode is always about 0.6V.)

    Note that we used two different diode drops, one to set the DAC potential from 0 to 5.5V, the other to set the op-amp potential from -0.6 to 4.9V. Although the op-amp has rail-to-rail output, it did clip the signal close to 0V, so driving it with a little less than that ensures we'll get our whole output range.

    The op-amp is set up as a classic op-amp buffer: a non-inverting amplifier with a gain of 1. The output of the op-amp provides both the stabilizing negative feedback, and also gives the final buffered output signal to the RCX.

    Since an op-amp does have a fairly slow, by electronic standards, response time, we wouldn't have the option of using this simple solution in a more demanding application. However, given the RCX's slow sampling rate, which will never be more than 4 kHz, the op-amp buffer's propogation delay will never be a limiting factor.

    A simple test circuit for the RCX input adapter can be made with an 8-DIP switch, 8 resistors, and some jumper wires. Wire them up like this:

    The resistors (any value between 1K-50K ohms) act as pull-ip resistors to 5V when the switch is open, sending out a high signal. When the switch closes, the resistors act like top-heavy voltage dividers, which puts the output at 0V for a low signal. You can flip these bits around to send out individual binary numbers between 0-255, and see what the RCX receives by viewing the input port on the LCD display.

  • Driver Code

    In a perfect world, the 2.55V that the digital interface outputs as number 255 would be read as 510 by the RCX, enabling us to simply divide the port value by 2 to recover our original number. This approach is almost correct, and can be used in situations where absolute accuracy is not as important as relative accuracy.

    However, instead of reading 2.55V as value 510, the RCX reads it as value 522, while value 0 read as 0. To make matters worse, a point-by-point analysis of the input showed the scaling to be very slightly non-linear. So, the driver program to decode the values from the digital interface does not use a slope, but instead does a binary search to determine which range the value is in, and applies the appropriate transformation to recover the original number.

    Our ROBOLAB driver code is available here.

  • Performance

    The performance if the digital interface is acceptable for many applications, but is far from perfect. When a single number is sent over a period of time, the RCX will correctly receive that number for the majority of the transmission. However, noise and the apparent instability of the RCX's internal ADC conspire to generate incorrect results for some small fraction of the time. These incorrect results are either one number above or one number below the intended number.

    In applications where the relationship between the data is most important, this is often tolerable. However, in other applications, such as sending precise control codes, an occasional error of +/-1 may be produce erratic behavior. In these applications, it is recommended to use only the 6 most significant bits for data transmission, and tie the two LSB's to ground.

    Additionally, in relative applications, it's important to recognize that the error in transmission is plus or minus one number, not one bit. Sending grey code will not be as effective, therefore, as sending straight binary numbers.


Sample Application: The RCX as a Musical Instrument

To demonstrate the capabilities of the digital interface, we decided to turn the RCX into a musical instrument capabale of playing 36 different notes, while using just a single RCX input port.

Our design used a 12 key input, and 2 octave shift buttons, which were decoded by a BASIC Stamp, which sent a frequency value to the RCX. The RCX scaled the frequency and played the appropriate note.

  • BASIC Stamp

    The BASIC Stamp is a micro-controller package, programed in an intuitive version of the BASIC programming language. Reasonably low in cost, it offers an extremely friendly package for interfacing with a micro-controller.

    We used the Stamp here to drive the keypad and octave shift inputs, and to do some calucation to determine the frequency to be played. It would have been possible to build up an equivalent circuit using discrete combinational logic chips, but this would have resulted in a much less flexible design, and would have required many chips. A compromise solution could have been to use a programmable logic array to cut down on the number of chips, but the result would still not have had the flexiblity of the Stamp design.

    More BASIC Stamp information is available at www.parallax.com.

  • Circuit Design

  • Since we wished to feed 12 keys and 2 octave shifts into the BASIC Stamp, and get 8 bits out, it appeared at first that we would require 22 pins. Since the Stamp only has 16 pins, we devised an arrangement to encode 3 different keys into a single pin, dropping our pin requirements down to 4 + 2 + 8 = 14 pins.

    To encode the keys, we set up the keypad as a 3x4 matrix. The BASIC Stamp has the ability to measure RC time constants, so we gave each of the 3 keys in a given row different resistor values and fed them through the same capacitor on the way to that row's pin. In this way, we can keep track of all 12 keys by checking the RC time constants of 4 pins.

    We also put in two octave shift buttons. These were set up with pull-up resistors, so they gave a high signal when open, and a low signal when pressed.

    We fed the 8 output pins directly to the digital interface, and connected the interface to port 1 of the RCX.

  • Stamp Code

    Click for the full code for the BASIC Stamp .

    The Stamp code had three main parts. The first part checked the RC time constants of the 4 keypad pins to determine which key was pressed. The second computed the frequency for the note, taking any octave shift into account. Finally, the frequency was turned into a binary number and sent to the 8 output pins.

    On the RCX side, the code was a loop which read the value from the digital interface, decoded it, scaled it to an output frequency, and then played it.

  • Performance

    With this system, the RCX plays 36 different notes faithfully and accurately in real time. Very occasionally it will slip slightly flat or sharp. The tone quality is not particularly pleasant -- another project may be to get better audio sound out of the RCX using an output port.

    In sum, however, this example demonstrates the ability of the digital interface to extend the power of the RCX, with minimal cost in processing power and with the use only a single input port.


Other Project Ideas

Here are some other ideas for projects using the digital interface. Note that some of these ideas will require a deeper familiarity with electronics.

RCX Keypad
Hook up a 64-key keyboard to a BASIC Stamp to encode the key pressed as a unique number. Output the number to the RCX via the digital interface, and you'll have real-timekeyboard input to the RCX.

Absolute Position Sensor
Connect a bank of 8 phototransistors to the inputs of the digital interface. Use graph paper to create a bar-code number for the 255 different positions along the length of the paper. Add a small light and some baffling to create a bar-code reader that will determine the absolute position of a robot in one dimension.

Frequency Analyzer
Feed a signral from a microphone through a low-pass filter made with a resistor and capacitor. Send the filtered signal into a BASIC Stamp, and let it determine the frequency of the funadmental by counting the number of zero-crossings in a given time period. Let it output that frequency as a scaled number through the input adapter. Now the RCX can respond to the fundamental frequency of a harmonic sound.

Combinational Logic
The digital interface works well with TTL logic chips, which are available in AND, OR, NOT, and other configurations. You can hook a different combinational logic circuit into each of the 8 digital interface inputs. Model different classifications, like Amy like sandwiches with bacon and lettuce, or cheese and tomatoes, but never with cucumbers. Or, construct a binary adder circuit using combinational logic and use the RCX to convert the output to decimal.

Function Plotter
Build a LEGO robot that moves forward in a straight line, and that carries a pen that can move laterally to a given position. Program a BASIC Stamp to generate a repeating function, like a triangle wave or a sin wave, and feed the Stamp's output through the digitial interface to the LEGO robot, which will now draw the function as it rolls along a piece of butcher paper.

Random Number Generator
Clock an 8 bit binary up counter with a 555 timer, with an RC time constant of about a nano-second. Feed the output of the counter into a latch register, clocked by another 555 timer circuit with an RC time constant of around a millisecond, and put a small bulb in series with the resistor. The uncertainty of the bulb's resistance (which varies with temperature), plus the chaotic interaction of the two 555 phases, will produce a number that is effectively random. Feed the output of the latch register to the digital interface, and sample it whenever a random number is needed.


Conclusions

The digital interface offers a range of possiblities to the RCX, enabling it to be used more like a full micro-controller, while not compromising its ease of use or standard capabilities.

  • Limitations

    The digital interface suffers from some instability in the transmission of its data, due to noise and the varaiance inherent in the RCX ADC. While this instability is never greater than plus or minus one number, it does make the interface unsuitable for the transmission of 8 bit critical data, such as control codes or memory addresses.

    It's possible to work around this issue by limiting data to 6 bits, which will ensure perfect transmission of data without compromising speed. Another approach may be to encorporate an error checking scheme, which would reduce transmission speed, but could help reduce error significantly.

  • Possible Improvements

    Two improvements suggest themselves: noise reduction, and the elimination of battery power.

    Noise could be reduced in a few ways. Shielded transmission lines is one possibility, as is the insertion of a low-pass filter at the RCX input port -- the speed reduction would not be noticable at RCX sampling rates. It's also possible to filter noise by signal processing within the RCX, although this would begin to impinge on speed and tax the RCX's ability to handle other tasks.

    The battery pack could be eliminated by using the RCX's powered sensor capability. In initial tests, we found that this introduced extra noise into the system. However, another design, which we have not yet tested, seems feasible. This design would send data as a varying current, rather than a varying voltage, which may be less susceptible to noise, and would have the added benefit of allowing us to use a current output DAC, which would be slightly cheaper.

  • Future Work

    In the future, we hope to examine the unpowered design outlined above. We also hope to find ways to similarly extend the output capabilities of the RCX, which would then allow it to interface with the full array of digital devices, including a data bus and external memory.


D. Sculley

for Prof. Chris Rogers
TUFTL LAB
Tufts University
Spring, 2004