I am attempting to interface a Raspberry Pi to an Atmega168 using TWI. The Atmega is the slave. I have a counter-triggered interrupt that sets an update flag at 500 Hz.
The main loop of the Atmega program is structured something like this:
1. Handle TWI data (polling)
2. If update flag is set:
a. Read ADC values from ADC pins 0 and 1, and do some math to convert values to floating point
b. Every 500th iteration, update LCD screen to display floating point values, and do some additional calculations
The TWI frequency is 100 kHz. ADC is running in single-conversion mode.
Originally, the chip was running off of the internal RC oscillator at 8 MHz. I used a scope to confirm that 8 MHz was sufficient to get my update loop to actually run at 500 Hz. In this configuration, I could *sometimes* detect the slave from the RPi using RPi's i2cdetect tool. If I removed the ADC read calls OR the math to do the conversion to floating point, it could successfully be detected every time.
I then tried adding a crystal and increasing the clock frequency to 20 MHz. I also modified the main loop to wait until after the 500 Hz update loop to TWACK or TWNACK, hopefully stretching the TWI clock. This may have made a marginal improvement - tough to tell. Still, to have reliable communication it seems that I need to remove the lines where the ADC is read.
I've tried using i2cset/get, i2cdetect and using open/read/write calls on the RPi. I get the same results each time - rare success with ADC reads in place, consistent success with ADC reads removed.
I have not yet looked at the TWI communication using a scope - I'll have access to one this weekend, but not before.
Also, I'm using the RPi internal pull-ups (1.8kOhm), and I'm not using any level shifting between my 5V AVR and 3.3V RPi. Because the pull-ups are on the RPi (to 3.3V) and the Atmega datasheet says the threshold voltage for I/O pins on a 5V supply is about 2.6V, I think I'm OK here. Just noting it in case anyone has had different experience...
Any ideas? Many variables are shared within the update loop and TWI, so I would like to prevent putting the TWI handler in an interrupt of its own, but if you think that's the solution, I'd give it a try.