Good Afternoon.
I'm using a classic Nano with an MCP23017 port expander. This uses an I2C interface..
I am setting the clock speed with the Wire.setClock( ) instruction. This is after the Wire.begin() instruction.
I expected the value in "( )" to set the clock speed in Hertz as suggested in the Command Reference Section.
There are obviously limits as the SCK speed is derived from an 8 bit register and a 2 bit prescaler, so there will only be a limited number of values that would work.
However I thought that the IDE would calculate the nearest value to what had been entered and set the two registers to the closest match.
This is not what appears to happen.
Using an Oscilloscope on the SCK line of a Classic Nano I get the following results;-
Value entered into "( )" in Wire.setClock() Measured SCK Frequency
400000 400kHz
100000 100kHz
This is what I would expect, however, with other values I get;-
10000 250kHz
100 61kHz
50 31kHz
10 31kHz
I can't see any logic in this, especially "10000" giving 250KHz.
I know that some of these values are a bit "silly" and a 50Hz I2C bus is well out of spec, but I was simply trying to see how Wire.setClock() actually works.
I'm using I2C with a buffer chip ( P82B96 ) to control a system over a 50m cable. I know that RS485 would be a better physical interface, but I am using existing cabling and the I2C Protocol makes life very simple.
I'm just looking at whether I can slow down the Clock Speed if I need to.
Any information to help me understand what I am seeing would be much appreciated.
What you found is indeed how it is.
The Wire.setClock() for the classic Nano is here, and it calls this function.
The complete code is this single line:
TWBR = ((F_CPU / frequency) - 16) / 2;
No prescaler, no limit check, just some code that works from 50kHz to 400kHz and goes bad with other values.
For very low speeds, you could try a software I2C library.
A low speed does not always make things better. The longer it takes, the more chance that noise will disturb the signal.
50 meters That is a lot.
The P82B96 does not make twisted pair signals. I think that you picked the wrong chip.
However, using the I2C bus over 50 meters is nuts anyway
If you would want to use the P82B98 for 5 meters, then perhaps you could try it (but I still would not like it). 50 meters is far beyond of what makes sense for the I2C bus.
Please use RS-485.
When a project fails, then it is often the I2C bus. Strong currents or peak currents from motors disturb the I2C bus. Sometimes SDA is put next to SCL in a cable. Wrong voltage levels. Wrong pullup. And so on.
The I2C bus makes life not simple, it makes some projects impossible to complete.
Thanks for the feedback, especially the code called when setting the clock speed.
The "setClock()" Reference explanation could be a little clearer as it is a bit ambiguous.
Your explanation helps a lot.
I completely agree that I2C communication over any significant distance is not a great idea and really "doesn't make sense", however this project is a remote input panel for an existing project that uses I2C for the existing MCP23017 and MCP23008 chips, and implementing other serial links on the installed hardware is a significant problem.
The "long distance" part of the I2C bus uses the P82B96 as a buffer and level converter at both ends. The drive voltage is 12V and the buffers can discharge the capacitance of the bus at up to a 100mA (dynamic rating) and 30mA continuously.
Pull up resistors are 1k0 at each end.
If I've read the data sheet correctly the manufacturers (NXP and TI) have been running I2C data at 120KHz down 250m of cable and 185kHz down 100m of cable.
I've been running buffered I2C at 100KHz down 50m for the last six months and had no issues.
On any new project, over any distance, I would go RS485 and put error correction and data checking in the software.