Comments/ Advices for Multimaster I2C / TWI with Busyline using analog input

Hello everybody,

at the Technical University we've got a robot prject where we want several Arduinos (uno and mega) from different teams to talk to each other.
We've thought a lot about different bus Systems. None of them was perfect.

I2C seems to work best. But it has no working Multimaster functionality.
As I can see the Problem of aribiation is not solved in the Arduino library.

Some people say Multimaster will also work with the original I2C library. We've had several communication Problems when we've tried it.

Here is my solution. Can anyone proof my Idea?

We use a Busyline connected to an analog Input of every Master.
The Busyline is also connected to GND with 33k.
If a Master wants to use the Bus, it checks the Busyline. If it is low, It activates it's Pullup (30-40k) resistor on the analog Pin.
Then it checks the Busyline again. If the level is lower than ca. 3V (600/1024), it starts to write Bytes to the Bus. (No one else has activated its pullup) If the value is higher it deactivates its Pullup and waits for a short random time before it tries again.

Best Sebastian

boolean multiMasterWriter (int adress)
{
  while (1) {
    if (analogRead(A0) <= 200) {
      pinMode(A0, INPUT_PULLUP);
      if (analogRead(A0) <= 600)
      {
        Wire.beginTransmission(adress);
        Wire.write(data);
        return (1)
      }
      else
      {
        pinMode(A0, INPUT);
        delayMicroseconds(random(100, 1000));
      }
    }
    else
    {
      pinMode(A0, INPUT);
    }
  }

}

How many Arduino boards needs to be connected ? How long are the wires ? What kind of wires/cable ? How many data do you need to transfer ? What kind of currents are involved ? Are cables with high currents near the bus ?

Using an analog signal to measure the signal before and after claiming the bus is a smart idea :smiley: but there are many other problems with I2C.
The impedance with 33k is too high, you will get a lot of noise. The internal resistor is about 50k, but that is not a fixed number and can be different for other Arduino boards. The onRequest and onReceive in the Slave depends heavily on interrupts, there are many libraries that turn off the interrupts for some time, and that makes the I2C unreliable. The code for onRequest and onReceive has to be very clean (no delay, no use of Serial, and so on).

The normal way is to use a serial connecting, preferably with a RS-485 bus. In software there should be some kind of checksum or handshake and the possibility to resend the data.
The Arduino Mega 2560 has three spare serial ports, but the Uno has none, and the SoftwareSerial uses so much of the Uno, that other things might no longer work. The Arduino Leonardo (or Micro or Pro Micro) has a spare serial port.

Do you want to use a Arduino Due or Zero or M0 in the future ? Those are 3.3V Arduino boards.
Would you consider to replace the Arduino Uno boards with Arduino Leonardo, and use the Serial port ?

Some say goodbye to all these problems and use wireless modules. There are even libraries that can create a wireless mesh network, but those need a lot of memory. If you can fit the RadioHead into the Arduino Uno, then you can use the reliable option that will do the acknowledge and retransmit for you.

You should consider a CAN bus. A huge advantage of CAN is that bus glitches are automatically handled by the hardware, corrupted messages are automatically re-transmitted, you can have very long wires (> 100 m) and tens of nodes. With SPI / I2C / UART, extra error detection and handling is required.

Thank you for your comments.
@ard_newbie
I've also thought about a CAN Bus. If it were integrated in the Arduino, this would be my first choice.
But the mostly used CAN Modules with MCP2515/MCP2551 do not allow request Messages (Remote Transmission Request)? Do they? Furthermore some of our Sensors use the I2C bus.
Error detection is something we are working on.
@Koepel
The number of Arduinos is not defined yet. Something between 3 and 10 is realistic.
Size of the robot is about 30x30x30cm. Maximum cable length is maybe 50 - 70cm.
The transfer rate of the standard Bus speed (100kBit) is ok. The low speed (10kBit) could be too slow.
The final decision for the Cable is not made yet. A shielded cable could be used if necessary.
Yes, cables with currents between 3 to 5A are parallel to the I2C Bus Cables.

For the Value of the pullups I've referred to: Measuring Arduino Internal Pull-up Resistors | Majenko's Hardware Hacking Blog
I haven't measured mine yet.

The main reason, why we don't want to use the serial bus, is the fact that only two MCUs can communicate. We want all MCUs to be able to communicate with everybody (like the CAN Bus)

Sensors as well ? That is not looking good, you might need a lot of trial and error and a lot of code and weeks of work to make that reliable. As far as I can tell, there is only one way to make I2C work: with a single Master. You could even add an extra Arduino board just to do the Master task. The Master can request the data from sensors and data from the Slaves, and the Master can send that information to other Slaves.

Do you know about I2C level shifters ? and the combined pullup resistors that should not exceed 3mA pulldown current ? If you don't know these things yet, you still have a lot to do.

A total length of 70cm for SDA and SCL should be possible, unless you put them next to each other in a flat ribbon cable (crosstalk).

Only 303030cm ? That is small. Using wireless is perhaps over the top.

The I2C bus keeps the signal high with a pullup resistor. That pullup resistor makes the I2C higher impedance and noise can get in. The normal Serial RX/TX communication uses digital signals and is much better.

There are 2 builtin CAN controllers in an Arduino DUE (CAN0 and CAN1) and an awesome Library from Collin80.

You will need CAN transceivers, but if your wires are "short" ( less than 1.5 meter) you can make them work without a transceiver (I tested, it works). See this Application Note from Siemens (CAN without transceivers).

Since a DUE is 3.3V compliant, and the current at one port pin should not exceed 1.6 mA, you will choose a 2.2KOhm resistor connected to 3.3V and an 1N914 or 1N4148 diode.

Just wanted to say that the system is working good: Solution can be found here:

https://forum.arduino.cc/index.php?topic=622493.0