This Page was lost a long time ago, and I found a .doc containing the info recently, hope this is still useful to people out there :-)

I2C Communication using the LEGO NXT

 

My Current Firmware: 1.04

 

LSWRITE is used for both reading registers and writing commands from the NXT.

 

LSGETSTATUS is used basically to wait until the i2c bus is free.

 

LSREAD will read any bytes that the NXT has received from the i2c device.

 

LSWRITE format:

 

Bytes

0

1

2

3

4

5

6

7

0x00

0x0f

port

TxLength

RxLength

Device Address

Command / Register

 

 

 

Byte 0:

0x00 or 0x80 (0x00 = response required, 0x80 = No response)

Personally I’d leave it at 0x00 until you are finished debugging your masterpiece.

 

Byte 1:

0x0f – LSWRITE command

 

Byte 2:

Port     0x00 = port 1

            0x01 = port 2

            0x02 = port 3

            0x03 = port 4

 

Byte 3:

TxLength – This is the length of the message you want the NXT to write to the i2c bus. (It is a count of all the bytes starting with Byte 5).

 

Byte 4:

RxLength – How many bytes do you wish to receive for a command this is usually zero.

 

Byte 5 – N

These bytes are the ONLY ones that will be sent to the i2c device.

Byte 5 is the i2c address of the device, for the NXT it is usually 0x02

 

Byte 6

This is the register you are attempting to write to. It is device dependent, so get your data-sheets out.

For the NXT Distance Sensor 0x41 is used for commands, and the read registers are in 0x42 to 0x49.

 

Putting it all together to read values with the Distance Sensor

1)         Set the port into LOWSPEED_9V mode and RAWDATA mode

Command: {0x00, 0x05, port, 0x0B, 0x00}

2)         The sensor automatically goes into constant measurement mode.

3)         To read Measurement 0:

Send: {0x00, 0x0F, port, 0x02, 0x01, 0x02, 0x42 }

This tells the sensor you want 1 byte from register 0x42 which according to the data sheet is ‘Measurement Byte 0’

4)         Now you need to wait for the NXT to send the command to the i2c device and receive the byte back.

You can either pause for ~500msec (slow but wasy way) or poll the NXT with the LSGETSTATUS command until the status goes to 0x00 (no error) and there is at least 1 byte avalible.

Send: {0x00, 0x0e, port}

You will receive:

{0x02, 0x0e, status, bytesReady}

When the device is ready it will look like this:

{0x02, 0x0e, 0x00, 0x01}

5)         You can now use LSREAD to get the 1 byte which is ready and waiting on the NXT

Your command should look like:

{0x00, 0x0f, port}

The NXT will return a 20-byte block containing up to 16 bytes from the i2c device.

Format:

{0x02, 0x10, statusByte, bytesRead, byte1, byte2, byte3, ……, byte19}

statusByte should be 0x00 to indicate no error, and only byte 1 should contain any data, the rest will be zero-padded.

 

This works for the NXT Distance sensor, and both my Mindsensors Compass and my Mindsensors Acceleration sensor, however When reading multiple bytes from the registers, I have had no luck recieveing more than 2 bytes at a time from the Mindsensors devices.

More specifically, only access 1 measurement each time you query the device.

Eg: Do not ask for both the X-Tilt and the Y-Tilt bytes, it will return garbages results.

You can however, and SHOULD read both the LSB and MSB of the acceleration registers, if you read 1 byte at a time, it’s possible the value will change inbetween reads and your result will get corrupted.

 

Sending Commands

 

To send commands to i2c devices you use LSWRITE

Each device has a register which you write commands to. On the NXT it is usually 0x41, for all the devices I have seen commands are 1 extra byte following the register.

 

Reset command for the NXT distance sensor:

 

{ 0x00, 0x0f, port, 0x03, 0x00, 0x02, 0x41, 0x04 }

This will perform a ‘warm reset’ on the distance sensor.