Arduino Power Functions remote for NXT

Here is a project I did for making an Arduino a Power Functions remote for the NXT. I took advantage of my NXTI2C library, as well as my PFIR library (more info, and download links for both here).

I setup the I2C register of the Arduino system as follows:

0x00-0x07 - version number - "V1.0"      - read only
0x08-0x0F - manuf. name    - "Mt Allen"  - read only
0x10-0x17 - device type    - "PFIR"      - read only

0x41 - Command         - write only
0x42 - Nibble 1        - write/read
0x43 - Nibble 2        - write/read
0x44 - Nibble 3        - write/read
0x45 - ActiveChannel   - write/read

If you write, starting at Nibble 1, and going through at least Nibble 3, the Arduino will load the data into the appropriate (PF channel specific) buffers, and automatically enable sending messages on that channel. You can optionally write to the ActiveChannel buffer, to remote control the permissions bits (either by writing to 0x45, or by writing a 4th byte, starting at 0x42).

There is a fairly extensive list of commands you can issue to the command register. In order to issue a command, you must write it to 0x41 (e.g. you can’t write 2 bytes starting at 0x40, and have the command take effect).

Here are the supported commands, as defined in the program:

#define COMMAND_E_STOP     0x73  // s  Command to float all motors immediately. Applies only to active channels.
#define COMMAND_E_STOP_ALL 0x53  // S  Command to float all motors immediately. Applies to all channels. Takes control of all channels.
#define COMMAND_DIS_ASS    0x64  // d  Disassociate from all IR channels.
#define COMMAND_DIS_ASS_CC 0x44  // D  Disassociate from all IR channels, and completely clear the ActiveChannel byte.
#define COMMAND_DISABLE    0x4E  // N  Disable messages.
#define COMMAND_ENABLE     0x45  // E  Enable messages.
#define COMMAND_LOAD_DATA  0x6C  // l (L) Load data as if it was sent directly to REG_NIBBLE_1.
#define COMMAND_DISABLE_TO 0x4F  // O Disable timeout.
#define COMMAND_ENABLE_TO  0x54  // T Enable timeout. (default when booted).
#define COMMAND_COMP_CON   0x43  // C Enable complete control of IR.
#define COMMAND_COMP_CON_O 0x63  // c Disable complete control of IR.
#define COMMAND_FAST_OFF   0x46  // F Enable really short blank messages.
#define COMMAND_FAST_OFF_O 0x66  // f Disable really short blank messages.

You will need to give the user-program running on the Arduino some time to respond to any messages sent (commands or PF control messages). With the simple loop I made, 10ms between sending messages seems to be more than enough. If I integrated the two libraries into one, specific for this purpose, it would probably eliminate this potential drawback (although 10ms really isn’t much of a wait).

Here’s the schematic of the circuit I’m using:

I used a transistor to increase the current for the IR LED. The IR LED I’m using is rated 1.6v forward drop, up to 100ma continuous current, and 940nm wavelength.

For R3, I used a 47 ohm resistor, but the appropriate value is specific to the LED you use.

For R4, I just used a common value of 330, but 220 to 1k should work just fine.

Download the program from here. You will also need the NXTI2C library and the PFIR library.

This entry was posted in Arduino, Electronics, Mindstorms, NXT and tagged , , , , . Bookmark the permalink.

5 Responses to Arduino Power Functions remote for NXT

  1. guchion says:

    I was just wondering, can this be used to control the power functions with the arduino directly, rather than with the NXT?

    • mattallen37 says:

      Most certainly! The PFIR library is a stand-alone library for the Arduino. This program just combines the NXTI2C library with the PFIR library to create an NXT controllable PF IR remote.

  2. matthias says:

    I was trying ti use the PFIR library on an ASURO board, but the transmit frequency is too low. It seems to be wrong by a factor of 2, so I was tring to adjust the timers in the library. But any time I changed the timer values, the program stopped working completely (hanged somewhere).
    I tried to change the caclulation of the OCR1A values in the SetTimerXX functions and alternatively in the SetTimer function – both didn’t wok.
    Do you have any advise for me which would be the best place in the PFIR library to double the frequency?

    • mattallen37 says:

      The library is designed to run on an AVR running at 16MHz. Most likely your system is running at 8MHz. My only advise would be to go through and manually half all the timer values, but you said it causes the program to hang. This is most likely because the interrupt function doesn’t have enough time to execute before the timer reaches the next interrupt value (and tries to interrupt again). If that is the case, then the library structure is not compatible with an 8MHz system.

      • matthias says:

        Thanks for your reply. You are right that my borad runs at only 8MHz and your point with overlapping interrupts seems to be a good explanation for the issues I observed as I tried to adjust the timers. Meanwhile I have found another library for Lego PF which works on my AVR ( It doesn’t use interrups so that the usage of teh AVR is a bit limited, but currently it’s sufficient for my purposes.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s