Under what circumstances, and with what protections? I find this surprising. Have you dialed down the data rate, added some form of driver, or in other ways gone beyond the standard implementation? I've got a network of Nanos in my basement, and would love to extend beyond the 2m boundaries I set long ago.
Happy to take this off-topic, if you'd rather.
C
Context:
Perry posted elsewhere about a long I2C data run; I've not found much evidence of long I2C implementations, and would love to know what compromises were required to make it work.
C
Why not use ESP32s (WIFI) ?
Sure. You fund it. I've got an existing network running in my basement, but when I built it a year ago I limited the I2C part to 2m reaches; now I'm at a point where I want to add a few IO to a few nodes, a few feet further away, and I can either drop in more Nano nodes(RS485 network, have them and the rest of the hardware needed), or stretch the I2C(minimum cost), or go down the ESP32 rabbit hole; the latter requires more money, and I'm retired and prefer to spend it on my wife, and the rest of my life. I have the I2C hardware, I was just leery of introducing Murphy to my world.
C
Interesting read. So it can be done, but with caution. I think I'll go for it, most of my out-of-reach stuff is at most 2m further. My base 2m run is actually a 'T' configuration (1m in each direction from the Nano). Capacitance would be the same, though so that may not matter. Have to check my pullups, they may be too large.
Thank you, everyone who responded.
As this is only partly related to the original question and as the answer has more general utility I've moved this to a new topic.
When I first tried to use I2C it was on a Z80 and I had to write a software implementation for it. No one told me I2C only worked over short distances, so I didn't let such concerns bother me. It worked slowly, I can't remember how slowly but probably hundreds of Hz clock, not thousands, and worked perfectly well. Later I re-designed my project to run on a PIC with a hardware I2C implementation, again no problems. The current version is running at 10kHz, but I'm sure I've had it a lot faster without problems. So far as I remember I have never had it fail because of excess cable length. I use it to read DS1624 temperature sensors around the house. On one occasion one of them started giving errors some of the time, I traced the fault to a loose power connection meaning it was getting power from SDA and SCL, but, even under these conditions it worked, sort of. Pull up resistors are low value, 1k I think. Cable is 2 pair telephone cable, cat 5 should be just as good. Total length is abut 25 to 30m, don't know exactly. Take one pair and put 0V and one of the signals on it, the other pair put 5V and the other signal.
I did start to experiment with I2C between 2 Nano Everys a Uno and a Mega with a view to writing a tutorial on here, but never finished due to other commitments. I think I got to something like 20m cat 5 with no problems. I don't know what the maximum usable length of cable is because I've never pushed the cable length in an experiment far enough to make I2C unreliable.
Why did you set a boundary? This saddens me, electronics is a wonderful hobby for experimentation, what have you go to lose by getting 20m or whatever of cable and trying it? Even if you destroy 2 microcontrollers in the process (not very likely I don't think) I'd say that's worth it for the knowledge gained. Whatever cable length you want your project to work over add 50%, get two Arduinos of some kind plus some cable and test it. Do let us know the outcome.
Test code on a Uno as master
#include <Wire.h>
uint8_t TxData = 0;
uint8_t SlaveAddress = 44;
void setup() {
Serial.begin(115200);
Serial.println(__FILE__);
Wire.begin();
}
void loop() {
sendToSlave();
}
void sendToSlave() {
uint32_t currentMillis = millis();
static uint32_t lastMillis = 0;
const uint32_t TxInterval = 1000;
if (currentMillis - lastMillis >= TxInterval) {
lastMillis += TxInterval;
Wire.beginTransmission(SlaveAddress);
Wire.write(TxData);
++TxData;
Wire.endTransmission();
}
}
Test code on a Mega as slave
#include <Wire.h>
uint8_t SlaveAddress = 44;
void setup() {
Serial.begin(115200);
Serial.println(__FILE__);
Wire.begin(SlaveAddress);
Wire.onReceive(receiveEvent);
}
void loop() {
}
void receiveEvent(int howMany){
uint8_t x = Wire.read();
Serial.println(x);
}
Bad answer - advice from another, plus I was in a hurry to get that first implementation (6 nodes, 400 i/o) up and running.
One of the things I overlooked was that article(i.e. do my own research, don't trust people we respect...); another was that I could dial down the I2C speed, because my nodes are running far faster than they "need to" - allthough if I add more I/O, that will be less easy. And, yes, I have 4.7k pullups, which can be reduced significantly (but I have to board hack to do it, they're part of a SIP network). So I have things to try. The good news is, I have nodes that are functional and stable, so I can expand them one at a time and hopefully spot if any become problematic.
Thanks! I'll look at the test code, and get back on this thread if I have questions!
C
If you have a scope, you can try tuning the resistors to get the best results.
See:
Eh? Just add more resistors in parallel on the wires, not need to hack anything. As for SIP, to me that means Session Initiated Protocol, which is used for messaging including VoIP telephony. If it means something else to you do please explain.
Ideally don't use a T but a bus with the resistors at each end, so for example to get 1k pull up put 2k resistors at each end of the bus so they are in parallel. However, this is extreme and not really necessary, my network is a mess of Ts and works perfectly well.
I now use ESP8266s (super cheap if you buy D1 minis) for collection of weather and other data, I use the methods explained here: Link to a very basic tutorial about TCP (evolved to: TCP-socket democode to send / receive data / characters similar to serial
I wish. I live far enough into the boondocks, the only "scope" I know of around here is owned by the guy who does my C-scope every 5 years!
But seriously, I should ask around, see if any of my former co-workers has a hobby on the side.
C
SIP
Single In-line Package
Sorry, forgot you're a software guy.
SIP:
But yes, I can solder a discrete leaded resistor from pin 1 to whichever pin is the resistor I need to parallel. It's still a hack.
I'm not! Electronics is my thing, software I learned from hard graft, swearing, and putting two of my friends, who are very definitely software guys, to a lot of grief with all my questions!
I'd forgotten that meaning of SIP, thank you both.
I appreciate the advice, I really do, but I'm not redoing my network to spread a new generation around just yet. With 16 or more nodes in the plan (8 up and running), and a whole lot of other stuff to keep me busy, it's just not happening. Give us another 1-year COVID lockdown, with enough warning to order them, and maybe, but I'm neither hoping for, nor betting on that.
Besides, I figure I'll probably decide to upgrade the network at some point, but it will be because I'm expanding beyond the designed "feature set", not upgrading for upgrading sake. When I do that, I'll also refactor the nodes and create a new node carrier, all at once. Not yet.
There's a much longer, and hoarier(?) story behind all of this, but I've got a work session tonight to prepare for, and right now the shop power circuit is dissected, so I've got to get back to wiring.
Thanks
C
Texas Instruments has a I2C-Range-extender-chip
best regards Stefan
You might also consider an Adafruit LTC4311. Here is a link to a post that shows the SCL signal before and after.
Thanks.
Somewhat unusual ...