I’ve had my ArduinoMega for almost 2 weeks now and until today I had no luck getting it to work as an I2C slave with the NXT. The NXT is a finicky beast when it comes to I2C. It’s really not all that standard and requires very high pull-ups (82K) for the NXT to be able to pull the lines down properly.
After testing the ArduinoMega’s ability to play I2C master to a number of ICs I had lying around, an MCP23008 and a DS1631, I was pretty sure the I2C lines were working properly. I tried in vain to make the ArduinoMega work as a slave with the NXT using the AVRlib I2C library, the one provided by the Atmel AVR311 Appnote (source code) and the Arduino Wire library. Having tested it with 3 libraries, I was pretty sure it was probably not a software issue but some stupid electrical problem. Little did I know how stupid it turned out to be.
Lacking the proper equipment to further diagnose the problem, namely a scope and a logic analyser, I employed the help of my friend Joep. We hooked up the ArduinoMega to his PC based I2C master board and all tests completed successfully. The board responded as it should so that definitely ruled out the software as a source of our problems. So what could it be? We connected the ArduinoMega to the NXT using a small breadboard and two 82K pull-ups. With the scope hooked up to SCL the problem became pretty obvious; the NXT wasn’t pulling down the line enough. That made no sense, since the internal pull-ups of the ATmega1280 were explicitly disabled in our program. Joep re-examined the PDF with the circuit diagram and discovered that the SDA and SCL lines had in fact 10K pull-ups! They were not drawn near the chip itself, but way, way off in the top right corner where you could easily miss them. With the 10K pull-ups in parallel to the 82K ones, the resulting pull-up resistance had been reduced to a mere 8K9. After a little brain surgery, the two evil pull-ups from Hell, were removed and subsequent testing resulted in a successful NXT to ArduinoMega I2C transaction!
Be very careful when removing these two resistor, of course. You don’t want to end up damaging your board. Joep is quite experienced in soldering very small components and has a very fine tipped soldering iron. The end result was very nice. Click on the picture on the right to see a bigger version.
So why had no one else bumped into this problem with Arduino’s before? Well, it turns out that the Arduino Duemilanove, for example, does NOT have these pull-ups. The SCL/SDA lines are shared with the ADC channels. You can’t very well put a pull-up on an ADC channel. I am not sure why they would put the pull-ups on the SDA/SCL lines on the ArduinoMega when they weren’t there on the normal Arduino.
Thank you, Joep, you saved the day!