Intermittent TWI Communication

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello all,

 

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.

 

Thanks,

Kerry

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually I believe the TWI threshold is ~3.5 volts for a 5 volt AVR. See section 28.7 of the data sheet, table 28.6 row 2 .

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I must have a different version of the datasheet than you do - table 28.6 is a breakdown of the fuse high byte.

 

I'm using this one:  http://www.atmel.com/images/doc2545.pdf

 

But I do see where you're looking - Table 29.5 on pg 315.

 

So maybe 3.3V is borderline, and for some reason the combination of ADC + low TWI voltage makes it fail?

 

I'll look into a level shifter.

 

Thanks,

 

Kerry

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My experience with I2C  with one being +5 and the other being +3.3v is that when the +3.3v system asserts  (pulls line to 0 v) SDA or SCL, the voltage on the +5 system's lines goes to +1.5V.  The +5V system misses most of the other unit's assertions because they aren't in the the logic low region.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK - so I've added level shifting, and I've confirmed with a scope that nothing funky is going on with the TWI signals.  On both sides of the level shifter the transitions are nice and crisp.

 

Reads seem less reliable than writes, although writes are not 100%, either.  Generally my reads are longer than my writes, so it's possible that this observation doesn't really mean anything.

 

I'm trying to put together a MWE, but it's proving difficult to remove any big chunks of code without solving the communication problems.  Maybe I'll stumble upon the cause as I'm going through the process.  In the meantime, though, any other suggestions are welcome :-)

 

Thanks,

 

Kerry

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It turns out that there is a known Raspberry Pi (actually Broadcom 2708) bug related to clock stretching.  More info here:  https://www.raspberrypi.org/forums/viewtopic.php?p=146272

 

Dropping the Raspberry Pi i2c clock frequency to 10 kHz prevents my slave from ever attempting to stretch the clock, and fortunately I don't require faster communication.  Everything seems to be working well now.

 

Thanks for your responses.

 

-Kerry