Using I2C with NI NXT-toolkit
updated: 11/08/07 (see bottom of page)
For a new sensor that we are developing on the base of a Microchip PIC16F88, it was necessary to use the I2C-connection to NXT. Mike Gasperi already successfully run a PIC with NXT (http://www.extremenxt.com/picnxt.html). So, we went into his code and saw that he had inspired from AN734 Microchip document. He altered the code to have a transaction based communication. The difference to our project however is the fact that we want to have NXT read more bytes. This was not that easy !
1. Changing Gasperi's code:
Like the original code from Microchip, Mike uses 5 different valid states in the interrupt service routine. We follow this way, but in state 4 we simply increment the buffer index, so the next reading will be at the higher address. AN734 engages the PIC watchdog timer to react on bad states. This solution was not sufficient to guarantee a stable communication with NXT. So, we added several timeout loops instead of uncontrolled loops. We also added a variable called I2C_channel_state to monitor the ISR-states. (Our code has been realized in ULTIMATE_PIC. This experimental software doesn't configure the SSP.module for I2C, so we had to do this in Assembly language.)
2. Connecting the sensor to NXT:
We follow the recommendations of the LEGO NXT SDK and use 82k pull-up resistors for both the clock and the data line. We are using an altered toolkit sub.vi from Mindsensors.
3. Surprise: status -35
The sensor immediately worked on one NXT, but not on the other. After long and boring tests... and a few emails around, we found out that the bad one still had firmware 1.01, which definitely does not support the PIC I2C. Switching to firmware 1.03 and later 1.04 solved this problem. However, after a while status -35 reappeared. The NI toolkit documentation and the LEGO SDK tell us that the sensor must be configured wrongly, without explaining what this means.
After many tests, we were finally able to establish a stable communication:
As I write these lines, NXT has received 60000 packages with 800 invalid ones. We have had 17 times status (-35). The first tests were made with the excellent NI toolkit debugging mode. This test revealed that the NXT firmware changes a timing parameter, every time it encounters status (-35). If it happens for the first time, and we don't reset the sensor, the first byte in the package will be badly read every second package. If the status (-35) happens again, the first 2 bytes are received wrongly at 50%. Then 3, 4, 5, 6 ,7, and from the 8th time all the packages are received well again.
We interpret the status (-35) as follows: (not sure about the interpretations though !!)
We could improve the whole communication, by adding a long power-up time to the sensor PIC microcontroller, before activating the I2C module. If the NXT program with I2C exchange starts before the PIC has configured the module, then the line is held LOW and the protocol starts without fail.
Another improvement is the fact that we disobey to the NI toolkit user guide recommendation to send several write cycles from NXT. We ommit this and immediately reconfigure the sensor, if status (-35) appears. We reduced the pauses between two packets to 50ms and between the reconfigurations to 25ms.
Now we can have 100000 packets with only 100 lost and about 30 stati (-35).
==> Multi-byte reading is now working without any fail.