Plusieurs devices sur plusieurs bus I2C (ESP32)

Bonjour

Mon problème ce soir tient à l'installation de 2 écrans OLED et un accéléromètre en I2C sur un ESP32. Les 2 écrans sont identiques et ont la même adresse 0x3C, donc je ne pouvais pas les mettre sur le même bus. J'utilise donc 2 bus I2C différents, l'un avec {SDA, SCL} sur les pins {19, 23} et l'autre sur les pins {5, 4}. Si j'en reste là, ça fonctionne.

Mais pour corser l'affaire, je veux ajouter un accéléromètre MCU6050, d'adresse 0x68, sur mon premier bus I2C. Je mets des résistances de 13kOhms entre VCC et les deux lignes SDA et SCL (mais le problème persiste si elles ne sont pas là).
Les devices sont bien trouvés par le scanner I2C modifié :

Scanning I2C Addresses Channel 1
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 
.. .. .. .. .. .. .. .. .. .. .. .. 3C .. .. .. 
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 
.. .. .. .. .. .. .. .. 68 .. .. .. .. .. .. .. 
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 
Scan Completed, 2 I2C Devices found.

Scanning I2C Addresses Channel 2
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 
.. .. .. .. .. .. .. .. .. .. .. .. 3C .. .. .. 
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 
Scan Completed, 1 I2C Devices found.

Le problème est le suivant : la présence de l'accéléromètre me fait perdre l'affichage de l'écran avec lequel il partage son bus I2C.

Le code est un peu long, alors je ne vais donner que des extraits (mais je peux fournir le code complet au besoin).

Déclaration des écrans et de l'accéléromètre :

U8G2_SSD1306_128X64_NONAME_1_SW_I2C display1(U8G2_R0, SCL1, SDA1);
U8G2_SSD1306_128X64_NONAME_1_SW_I2C display2(U8G2_R0, SCL2, SDA2);
MPU6050 accelgyro;

Le setup :

void setup() {
  Serial.begin(115200);
  AcceleroSuccess = InitAccelero ();
  display1.begin();
  display2.begin();
  display2.setFont(u8g2_font_helvR08_tr);
  display1.setFont(u8g2_font_helvB18_tr);
}

Et l'initialisation de l'accéléromètre :

bool InitAccelero () {
  Wire.begin(SDA1, SCL1);
  accelgyro.initialize();
  // verify connection
  bool Success  = accelgyro.testConnection();
  if (Success) {
    Serial.println("MPU6050 connection successful");
    // supply your own gyro offsets here, scaled for min sensitivity
    accelgyro.setXGyroOffset(29);
    accelgyro.setYGyroOffset(-30);
    accelgyro.setZGyroOffset(-45);
    accelgyro.setXAccelOffset(-3499);
    accelgyro.setYAccelOffset(-5049);
    accelgyro.setZAccelOffset(887);
  }
  else Serial.println("MPU6050 connection failed");
  return Success;
}

Le problème est-il matériel ou logiciel ? Est-ce dû à la façon d'initialiser l'accéléromètre ?

Merci de vos lumières...

Bonsoir
Peut être un contournement : les afficheurs OLEDà SSD1306 offrent parfois une possibilité de choix entre 2 adresses (court circuit ou résisatnce 0 Ohm à déplacer)
Si c'est le cas avec les tiens il est possible de laissser seul le MPU6050 sur un des bus I2C

Sinon c'est le moment de déballer le petit analyseur logique et d'utiliser l'analyseur de protocole I2C !!

Merci. Je ne pense pas que le problème vienne du fait que le deux écrans ont la même adresse puisque j'arrive à les faire fonctionner indépendamment sans que l'accéléromètre soit connecté. C'est plutôt le fait d'avoir un écran et l'accéléromètre sur le même bus qui fait que l'écran n'affiche plus rien. L'autre écran, seul sur son bus, fonctionne très bien.

je proposais mettre les deux écrans sur le même bus (si tes modèles permettent la modification d'adresse) et le MPU tout seul pour contourner le pb.

Quelle librairie utilises-tu pour le MPU6050 ?
DMP activé ? essayer sans ce mode.

Et pourquoi pas utiliser un multipleur analogique pour aiguiller les signaux I2C sur l'un ou l'autre appareil ?

Quand le chemin est "on" le trajet dans le multipleur est équivalent à une résistance série.
On trouve des produits moodernes qui n'apporte que quelques ohms série.

Oui, je comprends. Dans ce cas, je peux en effet changer l'adresse de l'un des deux écrans, j'ai vu qu'un écran a cette possibilité. Mais n'aurai-je pas le même problème sur l'autre bus ?

La bibli MPU6050 est celle qui est conjointe à I2Cdev.

Je vois qu'elle a une commande
void setIntDMPEnabled(bool enabled);donc il est possible de désactiver le DMP. Je testerai...

Le multiplexeur est aussi une solution, mais je n'en ai pas à disposition (donc un mois d'attente pour une commande en Chine) et j'aimerais limiter le volume du système pour faire en final un packaging compact (j'ai un DHT22 en plus). Alors que l'I2C devrait permettre ce genre de communication de manière native...

Comme c'est la première fois que je mets plusieurs dispositifs sur un même bus, j'aimerais comprendre pourquoi ça ne fonctionne pas. Peut-être devrais-je "initier" la communication à chaque fois que je discute avec l'un des deux devices en rappelant son adresse ? En utilisant

Wire.beginTransmission(address)

j'ai vu qu'un écran a cette possibilité

C'est une chance, il faut en profiter.

Comme c'est la première fois que je mets plusieurs dispositifs sur un même bus

J'ai déjà placé 2 INA226 (en changeant l'adresse de l'un des deux) + un SSD1306 sur le même bus. Aucun problème.
Le MPU6050 serait-il intolérant ?

@+

Comme c'est la première fois que je mets plusieurs dispositifs sur un même bus, j'aimerais comprendre pourquoi ça ne fonctionne pas

La visualisation des signaux I2C décodés permettrait de comprendre ce qui se passe sur le bus I2C, sans cela on est démunis , on ne peut que tatonner, éviter....

Peut être une 'particularité' du MPU6050 qui prendrait quelques libertés.... sans grande conséquence quand il est seul sur son bus mais gênantes en cas de cohabitation.

Je n'ai pas de MPU6050 pour tester avec analyse logique.

MPU6050 avec I2CDdevlib et Wire ? des pb....

bug signalé en mode DMP , issue #252

Il semblerait que le MPU6050 sorte parfois des spécifications du bus I2C (quand DMP est activé) et que cela provoque l'entrée dans une boucle sans fin dans la librairie Wire, le bus I2C serait alors figé.

Si l'explication est bonne le pb serait donc également lié à un manque de robustesse de Wire (risque d'entrée dans une boucle sans fin).

La dernière contribution de l'issue #252 renvoie vers une discussion sur l'ajout d'un 'timeout' dans Wire

Merci de ce lien Al1, j'ai en effet vu la réponse 252. Je vais tester en désactivant le DMP et je verrai ce que ça donne.

A suivre...

J'ai essayé les différentes solutions software, aucun résultat. Demain, je change l'adresse de l'un des deux écrans. C'est une résistance CMS à déplacer ?

Oui , une résistance de 0 Ohm (ou un fil, ou une grosse goutte de soudure bien placée...) pour passer de 0x3C (0x78 / 2 ) à 0x3D (0x7A / 2)
adresse.jpg