i2c dropped txs - 400kHz with level shift

Thread Starter

paulsoulsby

Joined Jan 9, 2013
33
I'm transmitting consecutive messages from a master to slave device on an i2c bus running at 400kHz.
The master is at 3.3V and the slave at 5V. I'm using a MOSFET level shifter as documented here: https://playground.arduino.cc/Main/I2CBi-directionalLevelShifter and numerous other places.

I'm usually sending 4 consecutive 3 byte messages and finding that quite a few are dropped. This problem goes away if I send 1 12 byte message. I can't do this in practice though, as I won't always know how many messages will be sent in a transmission (sometimes 4, sometimes 1 etc).
From doing a little searching I've found threads suggesting that this often due to the pullup resistors being too high. In 3v3 system, 2k2 seems a common value and in a 5v system 4k7 is standard.
So my question is: why are 10k used here? Should I use lower and should I use 2k2 on the 3v3 side and 4k7 on the 5v side? This NXP document suggests that they should all be the same (all labelled Rp) https://www.nxp.com/docs/en/application-note/AN10441.pdf
 

JohnInTX

Joined Jun 26, 2012
4,787
If the communication is always successful with one 12 byte message I would think that the basic I2C levels are OK.
10K is a bit high. What that would do is lengthen the rise time of the SDA/SCL lines and perhaps mess up the timing or pulse widths. If you looked it on a scope, you'd see a slow RC rise times instead of nice squared of tops. I'd look into 2K2 resistors - at least on the 3V3 side but first, I'd scope it out to be sure. Long cable runs can roll off I2C too.

Other than that, I would suspect something in the I2C protocol. Are you generating the stoP condition between messages correctly and giving the slave enough time to recognize that and processing multiple messages?

What is the slave device?
 

Thread Starter

paulsoulsby

Joined Jan 9, 2013
33
It's all using the Arduino compatible microcontrollers and the Wire library at the moment. Master is a Zero and slaves are Unos. Using the Wire library for everything. The buffer is 32 bytes, which I could increase, but it should be enough if the max is 12 bytes and there's processing time inbetween.
I'll give the 2k2 resistors a try and see how it goes. The bus run is currently only about 10cm. Need to allow for maximum run of 50cm though.
 
Is the UNO the master? I thought that the default I2C speed on the UNO using Wire is 100kHz and changing to 400 kHz requires you to change TWBR. Are you doing that?

In addition to the pull-up values as already mentioned, what happens when you drop the speed to 100kHz?
 

BobaMosfet

Joined Jul 1, 2009
2,105
I'm transmitting consecutive messages from a master to slave device on an i2c bus running at 400kHz.
The master is at 3.3V and the slave at 5V. I'm using a MOSFET level shifter as documented here: https://playground.arduino.cc/Main/I2CBi-directionalLevelShifter and numerous other places.

I'm usually sending 4 consecutive 3 byte messages and finding that quite a few are dropped. This problem goes away if I send 1 12 byte message. I can't do this in practice though, as I won't always know how many messages will be sent in a transmission (sometimes 4, sometimes 1 etc).
From doing a little searching I've found threads suggesting that this often due to the pullup resistors being too high. In 3v3 system, 2k2 seems a common value and in a 5v system 4k7 is standard.
So my question is: why are 10k used here? Should I use lower and should I use 2k2 on the 3v3 side and 4k7 on the 5v side? This NXP document suggests that they should all be the same (all labelled Rp) https://www.nxp.com/docs/en/application-note/AN10441.pdf
i2c pull-ups are calculated by rise-time capacitance issues (the below should open a pdf NOTE from TI about it).

https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwjzrLPP1oLZAhUHSK0KHbHlBewQFggpMAA&url=http://www.ti.com/lit/an/slva689/slva689.pdf&usg=AOvVaw1ApZDLO2pYbrZRHLsESHB9
 

Thread Starter

paulsoulsby

Joined Jan 9, 2013
33
Is the UNO the master? I thought that the default I2C speed on the UNO using Wire is 100kHz and changing to 400 kHz requires you to change TWBR. Are you doing that?

In addition to the pull-up values as already mentioned, what happens when you drop the speed to 100kHz?
Zero is the master, Uno slave, both are set to 400kHz. Will try dropping speed to 100kHz. Really need to a find a way to get it up to 400kHz though for this project though.

Thanks for that article! Will try resistors based on those calculations.

Sounds good. Do you have access to an oscilloscope and/or I2C bus analyzer?
Gotta a scope, but not a dedicated I2C analyser. Really need a new scope, so this may be what I need to get one with an I2C analyser!

Moderators note: merged posts, you can do multi quotes and edit posts
 
Last edited by a moderator:

AnalogKid

Joined Aug 1, 2013
10,944
So my question is: why are 10k used here?
From the site you linked to:

A device that pulls a line down has to handle the current through both resistors (on the 3.3V side and on the 5V side). That's why a higher value for the pull-up resistors is chosen, usually 10k.

ak
 

JohnInTX

Joined Jun 26, 2012
4,787
Gotta a scope, but not a dedicated I2C analyser. Really need a new scope, so this may be what I need to get one with an I2C analyser!
You need both! :D
I use a Beagle Analyzer for watching message traffic and find its timing diagrams in the message history very handy. Unlike some others I've used, it's pretty non-intrusive both in circuit loading and data rates. Some others will hold the I2C clock when their buffers get full leading to 'only works when the analyzer is connected' problems.

I also have a 3000T series Keysight MSO with the serial protocol analyzer software. The I2C display on the scope is useful for associating observed data problems with the raw waveforms quickly. My previous scope didn't have the I2C decoding so I got really good at reading I2C data from raw waveforms. That takes a great.deal.of.time. When shopping for a scope, get the biggest memory you can. It's common to post-trigger on an error then wade back through lots of stored traces.

Until then, even a simple scope should let you see the general quality of the waveforms vs. RC risetimes etc.
 
Top