I2c multiple devices not recognized

Hi everyone,

I have a problem with i2c communication from one esp8266-01 to multiple Arduino Nano boards.
Starting point were 6 Arduinos and 1 ESP. 5V to 3,3V bi-directional level shifter is used. The ESP had the internal Pull ups disabled from the beginning, the Arduinos had them enabled.
The i2c communication is always ok until I add a 7th Arduino. I disabled the internal pull ups of the Arduinos and soldered a 10k pull up resistor to the 3,3V side of the SDA line, one 10k on SCL and also a 10k to 5V SDA and one on the 5V SCL.
The connection traces are all in all a few cm long so nothing fancy, a small pcb.
I'm having a hard time calculating the pull ups... Can this problem be related to the pull ups or am I digging in the wrong direction?

That's not a lot. Try something like 3k3 on 3.3V and 4k7 on 5V.

Can you share a schematic and pcb design?

Depends; see question above. The reality is that you're taking us into that direction and in my experience, what you put in is what you get out. So if you make this about pullups, then people will talk about that.

If your concern is that your I2C ceases to work as you add another device to it, then show us what the project is about, how you've implemented, what the working situation is and what changes exactly occur that make it stop working.

I can add to @koraks reply that I would like to see the full sketch of the Master and the Slaves. I assume that the ESP8266 is the Master ?

Can you show a photo or schematic of how the level shifter is used ? It probably has already 10k pullup resistors on both sides. You need to apply 3.3V to the low side and 5V to the high side, or else the level shifting does not work.

Seven Arduino Nano boards with internal pullup resistors is no problem if there is nothing that makes the signal weaker. A level shifter makes the signal weaker, but I think it should be possible to make it work.

I wrote something about pullup resistors at the bottom of this page: How to make a reliable I2C bus.

That's true but I added the question about the direction :slight_smile:

I forgot to mention before that it works 1 out of 10 times when I power it all on with a 7th (or more) Arduino.

It's exactly this project:

With the exception of:

  • it's powered by a Mean Well 5V psu module and a small ams1117 module for the 3,3V.
  • a 1000uF electrolytic cap for the ESP on VCC and GND and a small 100nF ceramic in parallel.

The level shifter has indeed 10k pull ups... so I removed the 10k resistors I added previously.

The issue starts by adding a 7th Arduino. Before that it works everytime I power on the circuit.
After the 7th or 8th is attached I have to powercycle it multiple times to get it working.
Sometimes it works on the first try most of the time not.

Thanks for that link!

Something could be wrong with that 7th Arduino board.

If 6 work all the time, and 7 almost never, that is weird. Maybe a bad wiring or a voltage regulator at its limit.

Do you have a multimeter ? a scope ? logic analyzer ?

Did you know that you can fix a bad link in your post ?
Sometimes I edit my reply and someone is already answering my reply that I'm changing. Try to avoid that :wink:

Well they are working fine when everything is running as all the previous do. I have 10 now and it is running smooth as long as I power on often enough...
The regulator is for ESP only. All the Arduino are connected to the 5V PSU.

Multimeter yes. Scope no. Analyzer yes.

Done.

I'm sorry, I try to avoid that. I guess that's what a preview is for.

This is your Issue ? https://github.com/ricaun/DuinoCoinI2C/issues/49.


I can not find a serious problem in the code for the Slaves at first glance.


However, looking at just a single file for the Master, I see strange things in this file: https://github.com/ricaun/DuinoCoinI2C/blob/main/DuinoCoin_Esp_Async_Master/DuinoCoin_Wire.ino.

It uses Wire.begin() a lot, but that should only be used in setup().

It seems to read one byte per I2C session. That is also weird. The Slave has no "time to breathe", see my notes about Arduino in Slave mode.

It starts looking at I2C address 1.
There is some random delay, in case all the Slaves are powered up at the same time. That random delay uses 9 bytes from the signature data (manufacturer data inside the Nano). Those signature bytes might be the same.

In the last years, the code for the ESP32 and the ESP8266 has been improved a lot. The Wire library is much more compatible with the Arduino Wire library. As a result, it should be used in the same way as the Arduino library. Perhaps those improvements are not compatible with the code for the Master.


Can you explain what is going on ?
What do you mean if you power it on often enough ?
Does it work and then stop working ?
Can the Master print a list of Slaves ? To be sure that the Master sees 10 Slaves.
Was the project on Github only done with 6 Nano boards ? and never more ? Then it could be a in the code, for example an array that is too small.
Is there something else connected to the I2C bus ? For example a OLED ? OLED display have the habit to disturb the I2C bus for others.

Yes it is.

I removed all wire.start(); which contains the .begin. No improvement in behaviour.

I added a random delay to clients_loop(). No improvement in behaviour.

Where do you see that? I only noticed that getTrueRotateRandomByte() reads the input of A1.
I replaced the power-on delay with a regular delay(random(10,500)); No improvement in behaviour.

Do you mean explain the code? I'm fairly new to this stuff, I need to understand it first :slight_smile:

I power it on --> no Slaves in list of Master. I power it on so many times until the Slaves appear in the list.

Yes it can. The List is then numbered from 0 to 9. There is #define CLIENTS in DuinoCoin_Clients.ino and I guess also #define WIRE_MAX 32 in DuinoCoin_Wire.ino (?).
Couldn't find an array that is too small. When it works it works for all devices.

I removed the oled code. No improvement in behaviour.

What helped me today to get it all started without powering on the whole thing many times is to reset the Arduinos one by one. Then everything is fine...
Maybe I should add a random reset :slight_smile:

You have tested a lot !

You are right, a analog input is used for random here.
The manufacturer numbers are read here, but that is not used, or used somewhere else.

These were more or less the same questions:

When you press the reset button one by one, does that work 100% of the time ?
Then the library can deal with 10 Nano boards, and it is the initialization that is going wrong. That means I have to take a look at the Slave code.

Can you do a few tests with this code: https://github.com/ricaun/DuinoCoinI2C/blob/main/DuinoCoin_Arduino_Slave/DuinoCoin_Arduino_Slave.ino

When a Nano is not powered up, then it will keep SDA and SCL low and the I2C bus will not work, and other Nano boards can do nothing with the I2C bus. The Arduino Nano runs the setup() function microseconds after powering up. If I imagine 10 Nano boards acting that way, then I see a big bowl of soup with problems.
The reset button restarts the Arduino while the I2C bus is still valid to be used by others.

Add a delay in setup(). Start with 5 seconds. You could set every Nano board to a different delay. If that works, than you can lower it to 1 second plus some random.

void setup() {
  Serial.begin(115200);

  // If they all powered on together, then don't start using the I2C bus immediate,
  // since some boards are not yet powered up.
  delay( 5000);

  DuinoCoin_setup();
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
}

I have been looking at that library for some time now. There are a few weird things, but to investigate how everything works together is too much work. If you can not find the problem in a easy way, you might have to look for other (simpler, easier) code.

Yes 100%.

I tried it with a few milliseconds before without any luck.
But your suggestion let me raise it up a bit. It turns out that before 6 seconds (until wifi is connected, pool is selceted etc) nothing happens.
I was able to get the connection with more than 8 seconds and not all Arduinos at once.

  randomSeed(analogRead(0));
  delay(8000+random(2000,3000)+random(2000,3000));

I tried delay(random 8000,12000); but for unknown reason they tried to connect all at the same time.... I know that random isn't that random but without randomSeed(); it should work but didn't.

Well now it does and I appreciate your support! THANK you!
I will tinker a bit with the delay times but for now I'm having enough of usb cables that have to be used 10 times for one sketch :slight_smile:

The random() function uses the same sequence and the same seed. That means every Nano has the same sequence of random numbers.
The randomSeed() with one or more analog inputs is required to make different numbers. I use analog input A0 to A7 in my millis_reaction_timer.ino

I'm curious how short the delay can be. If 50ms is enough, then I would use 500ms or more to be sure.