I2C Interfacing Part 6: Using Microcontrollers

By Sivan Toledo
March 2007

The most versatile I2C chips that you can connect to the NXT, or to any I2C bus, are microcontrollers. Microcontrollers, or MCUs for short, are chips that include a processor, non-volatile memory for storing programs and data, memory for variables, and some peripheral devices (peripherals), such as analog-to-digital converters, timers, digital input/output controllers, and more. A microcontoller is basically an entire little computer on a single chip. The processor of the NXT, which runs the firmware and your programs, is a microcontoller. In fact, the NXT contains two more MCUs, one to control the motors and perform analog-to-digital conversions, and the other to control the Bluetooth radio. The standard ultrasonic sensor also uses an MCU.

Why would you put a microcontroller in a sensor (or whatever gadget you connect to the NXT) when the NXT already contains a microcontroller? After all, everything the external MCU can do, the NXT's main processor can do too. The main reason for using an MCU in a sensor is speed. The NXT's processor is fast, but its communication with the outside world is not so fast. So a helper processor that can react very quickly can be helpful. The ultrasonic sensor is a good example. It sends a short burst of sound and waits for the echo. The time it takes the echo to come back determines the distance to the object that returned the echo. At at distance of 17cm, for example, the echo would return after one millisecond. The NXT cannot measure external events at this resolution, but an external microcontroller can, and it can later report the measurement to the NXT.

In this project, I use a small MCU to produce remote-control signals. The MCU listens to commands that the NXT sends it via I2C. The I2C command tells it what code to send via the infrared remote control. This allows the NXT to turn off a television, or to turn its volume up and down, etc. The robot that you see in the movie listens to the television (using the sound sensor). If the volume is too loud, it raises its arm, which is fitted with an infrared LED, and sends a remote-control signal to turn the television off. Robots can be very strict.

The NXT cannot control the infrared LED at the required speed to produce remote-control signals. Therefore, using an MCU to perform this task makes sense. I don't think there is a specialized chip that can do this task. Chips that send remote-control signals are designed to be controled by a keypad, not by an I2C bus, so even if you can find such a chip, connecting it to the NXT would be a challenge.

Warning: connecting your NXT to any home-made gizmo (like the one described here) can damage it. Beware.

The Microcontroller and How to Program It

I used for this project an MCU called MSP320F2012. The MSP430 is the family name of the chip. Microcontrollers come in families, often with dozens of different chips. The different chips in a family have different peripherals, different amounts of memory, and so on. The MSP430 is a family of MCUs made by Texas Instruments. These chips are designed mainly for low-cost battery-operated devices. This means that they are cheap (the chip I used costs about $2.50 in small quantities), in many applications they do not require many external components, which also reduces cost, and they use very little power.

There are many families of MCUs: PIC processors from Microchip, AVR from Atmel, ARMs (from many manufacturers), and many more. Within each family there are many different chips. How do you choose one? My considerations in this project were:

The last point is perhaps the most important one for smal projects. You write the program for the MCU on your PC, but you need to somehow download it into the memory of the MCU. This action is called programming. Small MCUs do not have any interfaces that can be directly connected to a PC (say USB interfaces). Some of them have serial interfaces called UARTs that can be connected to a serial port of a PC, but this requires another chip. Only high-end MCUs have USB interfaces. Even when a chip does have a UART or a USB interfaces, it does not mean that a blank chip can be programmed using these interfaces.

Some MCUs require a dedicated piece of hardware called a programmer. You plug the chip into the programmer, download the program to it, and then take it out of the programmer and plug it into your circuit. It is inconvenient to move the chip between the programmer and the circuit, and the programmer is sometimes expensive. A more convenient approach is called in-system programming, or ISP. In this approach the chip has a few pins that are used for programming it when it is already in the circuit. Sometimes these pins connect directly to the USB or serial port in your PC, and sometimes a specialized interfacing device is still needed. When a specialized device is used, it can often allow a debugger running on the PC to debug the program running on the MCU.

ez430The chip that I selected has a cheap and convenient programming mechanism. Texas Instruments sells a $20 programmer called the EZ430 that comes with one chip (an MSP320F2013) on a little adapter board that is easy to integrate into a circuit. The company also sells $10 sets of three MSP320F2012's mounted on the same adapter boards. You can see the setup in the figure. You plug the little adapter board into the 4-pin connector on the programmer, and you plug the programmer into a USB port (or more conveniently, into a USB extension cord). The adapter board comes with 2 rows of connection pads that give you access to all 14 pins of the MCU. I soldered header pins to them, to make it easy for me to connet wires to the chip and to plug the adapter board into a socket.

Texas Instruments also supplies a free programming environment called IAR Kickstart that allows you to develop C and assembler programs for the MSP430, to download them into the chip using the EZ430, and to debug them. This free environment is limited to small programs, but for our purposes it is more than sufficient. There is also a version of GCC, a free C compiler, for the MSP430.

Texas Instruments also supplies a set of simple example programs that shows how to use the peripherals of the chip, and a large set of application notes that shows how to use these chips in various applications.

The MSP320F2012 (and the MSP320F2013, which is similar except for a more sophisicated analog-to-digital converter) also comes in DIP packages that are easy to use on a solderless breadboard and on prototyping boards. You can program these versions with the same USB programmer, but you need to connect the chip to the 4-wire connector. I plan to turn one of my adapter boards into an extension cord for this purpose.

So, what's on the MSP320F2012? It contains 128 bytes of RAM (yes, that's all), 256 bytes of flash for storing data, 2KB of flash for storing programs, a timer, a serial interface that supports I2C, an analog-to-digital converter, and several clocks (internal oscillators). Every processor needs a clock, and most processors require an external crystal to stabilize the clock frequency. The MSP430F2xxx series have clocks that use an external crystal, but also two clocks that don't need any external components: a very slow clock that leads to very low power usage, and a high frequency clock is fairly stable and accurate (to within about 1% or 2%). I used the internal high-frequency clock. Its accuracy is good enough for remote controls. The chip even has pull-up and pull-down resistors that you can connect to any pin under program control, so you don't even need the usual pull-up resistors for the I2C bus.

One somewhat annoying aspect of these MSP430 processors is that their supply voltage is limited to 3.6 volts. They do run on a wide range of voltages, from 1.8 to 3.6 volts. This allows them to run on a pair of 1.5 volt batteries or on a single 3 volts battery and to remain functional when the battery voltage drops as it is drained. But they cannot run directly on the 4.3V supply of the NXT. I therefore used a 3.3V regulator to power the MCU. If you use a different microcontroller that can run on an unregulated supply that can range fro 4 to 5V, you can connect it directly to the NXT's power line without a step-down regulator.

Microcontrollers are fairly complex chips, and there is a huge variety of them, so it can be a challenge to choose one. For small projects, the cost and convenience of the programming mechanism is probably the most important aspect. My choice is certainly not the only reasonable one and perhaps not the best one, but I think that it is reasonable.

Silicon Bugs

The complexity of microcontrollers means that their implementation sometimes contains errors. It costs a lot to fix these errors, so the manufacturer often continues to produce chips with bugs. From the programmer's point of view, these bugs mean that the chip does not always behave as the manual. The user manual often cover many different chips from the same family, some of which and some of which do not have a given bug. So the user manual describes how the chip should behave, even in case of bugs. A different document, called an errata, describes which chip has which bug, and if possible, how to get around the bugs.

You may think that these bugs are rare, but they are not so rare. I bumped into a bug in the I2C hardware in the MSP320F2012. The bug affected even the example program that Texas Instruments supplies to show how to use the chip as an I2C slave, which didn't work! Fortunately, I found a working example program that was posted to the MSP430 group on Yahoo. I had a similar experience with an ARM processor from Philips.

This is one of the drawbacks of working with MCUs as opposed to simpler specialized chips. If your program does not work as you think it should and a bit of analysis and debugging doesn't help, check if a bug in the silicon is affecting your program.

Infrared Remote Control Protocols

There are several communication prototols that infrared remote controls use. Most of them are based on the same principle. The communication channel can be in one of two states that we will call low and high. In the high state, the remote is sending pulses of infrared light at some fixed frequency around 40KHz (each protocol uses a different frequency, but they are all in the same neighborhood). An infrared LED that is switched on and off sends these pulses. The 40KHz pulses modulates the base infrared signal. In the low state, the remote is not sending anything; the LED is off.

The 40KHz modulation is used to distriguish signals sent by the remote control from other infrared radiation that is present in the environment, such as radiation emitted by lights and by the sun.

Infrared remote controls from different manufacturers use slightly different protocols. Philips, JVC, NEC, Sony, and Sharp have their own protocols, and there are more. I programmed the MCU to emit Sony remore control signals, because we have a Sony television. The web site of San Bergmans provides good descriptions of many of these protocols (in the knowledge base).

The Sony protocol, which is called SIRC (Sony InfraRed Control), uses 40KHz pulses. It divides the timeline into 0.6ms periods, which it uses to send 12-bit codes (there are also versions of the protocol that uses longer codes, but I sent 12-bit codes). A single low period follows a sequence of high periods. A transmission starts with high 4 periods. These have no meaning; they just tell the receiver to prepare for a code. These 4 high periods are followed by a low period. Then the 12 bits of the code are sent, starting from the least-significant bit. A 1 bit is represented by two high periods and a 0 bit by one high period. As I explained, every such sequence of high periods is followed by exactly one low period. The code continues to be sent every 75 periods (start to start) for as long as the user holds the remote-control button.

This is pretty similar to Morse code, but a little more logical. In both systems there are two different signals that are represented by short or long periods of signal, separated by short periods of no signal.

The codes themselves contain a 5-bit address, which specifies the type of equipment the code is sent to (such as a television or a DVD player) and a 7-bit command that tells the equipement what to do.

Programming The MCU

As I wrote, I found an example program that showed how to send and receive data through the I2C peripheral with the MCU serving as an I2C slave. So the main challenge was to produce the SIRC signal that corresponds to a 12-bit code that the NXT sends through an I2C command.

Texas Instruments supplies an application note that shows how to send Philips RC5 signals from an MSP430 processor, but I didn't like their method, which required some tuning of parameters to get the timing right. So I used a slightly different method.

I clocked the processor at 16MHz using the internal oscillator. I configured the internal timer to count up to 399. Once it reaches 399, it resets back to 0 and starts counting up again. The timer has registers that allow you to do things when the count reaches a certain value; I configured one of them to 133. This allows the program to configure the timer's output so that one of the pins of the chip is set to a logic high value when the timer resets and set to a logic low when the timer reaches 133. This pin controls the LED (though a switching transistor). When we configure the pin in this way, the LED sends infrared pulses at 40KHz, with the LED on for 1/3 of the perios and off for the rest (this asymmetry helps reduce power consumption in remote controls). At 16MHz, the processor counts from 0 to 399 exactly 40,000 times, which gives us the required 40KHz modulation.

Now that we have the machanism to send a modulated signal, we need to decide when to send it and when not to (when we do not need to send a signal, the program simply disconnectes the pin from the timer and sets explicitly it to a low value). To do this, I used another timer, called the watchdog timer. This timer is primarily designed to reset the chip if the program crashes, but it can be configured as an interval timer to produce an interrupt every fixed number of clock periods. You cannot configure it to generate the interrupt after an arbitrary number of clock ticks, only after 64, 512, 8192, or 32767. It is less flexible than the main timer. I configured the interval timer to generate an interrupt every 64 clocks. Every invocation of the interrupt service routine (the function that the interrupt invokes) increments a counter. When the counter reaches 150, the function knows that a 0.6ms period has ended, and it changes the output of the infrared LED. This works because 150×64=9600 clock cycles, which is exactly 0.6ms when the clock frequency is 16MHz.

The i2c infrared remote

The picture above shows the final working module. You can see the NXT cable at the lower right, the adapter board with the MCU on the upper right, the 8-pin 3.3V regulator near the top of the breadboard, the infrared LED at the end of the yellow-blue wire on the left, and the transistor that turns the LED on and off near the lower-left corner of the breadboard.

Receiving Remote-Control Signals

I have not yet built a circuit that can receive infrared remote-control signals, but it is not too hard to do. The best way to build the circuit is with a specialized infrared receiver module. These modules have an infrared detector and an electronic circuit that detects the modulation. They come in variants that are tuned to specific modulation frequencies, such as 38KHz or 40KHz, but most of them detect nearby frequencies as well, so a 38KHz detector (Radio Shack sells one) usually detects 40KHz modulation and so on. You can see such a module sticking out of the left side of the breadboard in the picture above. I connected its output to a transistor that switches a green LED on and off, to check that the infrared LED is really modulated with a 40KHz signal.

You connect the output module of such a module to a pin of the MCU and configure the MCU to generate an interrupt when the module detects a signal. The interrupt signals the beginning of a transmission. The interrupt service routine configures a timer that generates an interrupt or two in every period of the infrared protocol (0.6ms for SIRC), and you use the high/low sequence that is sampled to decode the transmission. If the sampling detects some unexpected behavior, perhaps from an incompatible remote control, you need to abort the procedure, wait for the incompatible transmission to end, and then start listening again for a signal.

Handling More Protocols

One of the advantages of using a microcontroller to generate infrared signals is that you can extend the program to handle additional protocols, say Philips RC5 or the protocol that the RCX used for infrared communication. Specifications for these protocols are easy to find, so there are good chances that you can build a gadget that can control whatever equipment you have or that can receive commands from remote controls that you have.

In the LEGO worlds, infrared was used for RCX communication and it is used now for the remote-controlled trains. A new line of infrared-controlled Technic motors is supposed to be released in summer 2007. I have not tried to control these with my I2C remote control, but it should be certainly doable. HiTechnic has announced an infrared transmitter/receiver for the NXT that will be able to communicate with the RCX and to control the RC LEGO trains.
A robot that uses the IR remote to turn of a loud TV
Here is the code. I think it works, but I'm not 100% sure. I lost the original but found a copy that I modified into another program. I edited that file to revert to the IR code, but I didn't test it afterwards.

© 2007, Sivan Toledo