Mise en oeuvre TCA9548A

Bonjour à tous,
Ces dernier jours, je tente de faire fonctionner 2 module oled (type ssd1306 I2C) avec un module RTC DS1307, tout ceci avec un module multiplexeur tca9548a. J'utilise la librairie Greiman pour les afficheur (elle suffit amplement à mes besoins), la librairie RTClib.h et la librairie Wire.h.

Lorsque je fais tourner le programme avec seulement le module rtc, cela fonctionne magnifiquement, lorsque je fais tourner le programme avec seulement les afficheurs, cela fonctionne aussi très bien. Lorsque je fais tourner le programme avec tout, je ne sais plus lire l'heure du module rtc, de plus, à certain moments, il affiche n'importe quoi. Pensez-vous qu'il y aurait un problème de compatibilé de librairie, ou es-ce le programmeur qui fait n'importe quoi ?
Voici mes exemples:

[code]
#include <SSD1306Ascii.h>
#include <SSD1306AsciiAvrI2c.h>
#include "RTClib.h"

//SSD1306AsciiAvrI2c ecran;
RTC_DS1307 rtc;

//#include <Wire.h>



// Define address for TCA
//#define TCAADDR 0x70


char textDisplayOne[] = "Ecran 1";
char textDisplayTwo[] = "Ecran 2";
int cpti;
int cptj;

// Pour affichage du jour de la semaine
char *JOUR[7] = {"Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"};
//





void setup() {
  Serial.begin(115200);
  Serial.println(("Start"));

  // start wire library for I2C
//  Wire.begin();

  // Lance le communication I2C avec le module RTC et
  // attend que la connection soit operationelle

  while (! rtc.begin()) {
    Serial.println("Attente du module RTC...");
    delay(1000);
  }
  // Mise a jour de l'horloge du module RTC si elle n'a pas
  // ete reglee au prealable
  if (! rtc.isrunning()) {
    // La date et l'heure de la compilation de ce croquis
    // est utilisee pour mettre a jour l'horloge
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

    // When time needs to be re-set on a previously configured device, the
    // following line sets the RTC to the date & time this sketch was compiled
    // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));


    Serial.println("Horloge du module RTC mise a jour");
  }


}







void loop() {
  lecture_heure();
//  oled1();
//  oled2();


}

// Lecture de date et heure depuis le module RTC

void lecture_heure (void) {

  DateTime now = rtc.now();

  // Affiche l'heure courante retournee par le module RTC
  Serial.print("Il est ");
  if (now.hour() <= 9) Serial.print("0");
  Serial.print(now.hour());
  Serial.print(":");
  if (now.minute() <= 9) Serial.print("0");
  Serial.print(now.minute());
  Serial.print(":");
  if (now.second() <= 9) Serial.print("0");
  Serial.print(now.second());
  Serial.print(" ");
  Serial.print(JOUR[now.dayOfTheWeek()]);
  Serial.print(" ");
  if (now.day() <= 9) Serial.print("0");
  Serial.print(now.day());
  Serial.print("/");
  if (now.month() <= 9) Serial.print("0");
  Serial.print(now.month());
  Serial.print("/");
  Serial.print(now.year());
  Serial.println(" ");
  delay(1000);

}
/*
void TCA9548A(uint8_t bus)
{
  ecran.begin(&Adafruit128x32, 0x3c);
  ecran.clear();
  ecran.setFont(System5x7);
  Serial.println(("Initialize 1"));
  Wire.beginTransmission(TCAADDR); //TCA9548A address is 0x70
  Wire.write(1 << bus);         // send byte to select bus
  Serial.println("TCA Loop "); Serial.println(bus);
  Wire.endTransmission();
}

void oled1() {

  TCA9548A(0);
  ecran.clear();
  ecran.set2X();
  //set the cursor coordinates

  for (cpti = 0; cpti <= 400; cpti++)
  {
    ecran.setCursor(30, 0);
    ecran.print(cpti);
  }
  ecran.setCursor(20, 2);
  ecran.print(textDisplayOne);
  delay(2000);
  ecran.clear();
}


void oled2() {

  TCA9548A(1);
  ecran.clear();
  //set color (always white)
  ecran.set2X();
  //set the cursor coordinates
  ecran.setCursor(20, 0);
  ecran.print(textDisplayTwo);
  delay(2000);
  ecran.clear();
}
*/
[/code]

Ci-dessus, il y n'y a que la version avec module rtc, pour les afficheurs il faut dé-commenter les lignes 5-8-13-34-72-73 et de 107 à 151.
D'avance merci à tous pour prendre le temps de me lire.
Jean Antonio

Voici le cablage:

Je pense que vous avez un conflit d'adresse I2c. Savez-vous dans quel sens fonctionne le rtc ?Vous devriez faire un scan du bus I2C pour voir ce qu'il sort, en chargeant évidemment les bibliothèques rtc et en l'initialisant. Une autre façon pourrait être de le connecter à un autre port du tca9548 et de le traiter comme des écrans.

Il pourrait y avoir un problème lié à la fréquence de l'horloge sur le bus I²C.
Les SSD1306 peuvent fonctionner avec une horloge SCL à 400kHz alors que le DS1307 est lui limité à 100kHz. Je ne sais pas si les librairies savent gérer cette problématique.

Bonsoir jeanantonio

Essayes de connecter la RTC sur TCA9548A(2).
Ou, est ce qu'un affichage et la RTC, sans le TCA, ça fonctionne?
Regardes aussi du côté des pull-up des bus secondaires, page 18 du data sheet.

Cordialement
jpbbricole

Bonjour à tous,

Je viens de vous lire et je vais vérifier tout ce dont vous m'avez parlé ce soir, hier j'ai été rappelé au boulot (j'y suis encore) et après avoir dormi quelques heures, je m'y attellerai.

Pour gonpezzi, je penses aussi avoir un problème d'adresse sur le bus, j'ai déjà essayé de mettre le rtc sur le canal 07 du tca, j'ai exactement le même phénomène, le isruning passe bien, mais je reçois des infos complètements farfelues du style date: 165:165:2001 et pour time, idem.

Merci, Jean Antonio.

Je ne sais pas si vos écrans sont comme les miens, ou si cela fonctionnera pour votre projet.
Regardez au dos de vos écrans et regardez la puce du régulateur de tension marquée Q1. A gauche il a un condensateur et à droite des plots libres ou avec une résistance soudée, (s'il en a c'est 0 ohms). Le retirer s'il le porte ou le contourner s'il ne le porte pas, on change son adresse I2c. Vous pourriez avoir les 2 oleds sans le TCA9548A.

Bonjour jeanantonio

J'ai fait l'essai avec la même configuration que toi, ce type d'affichage
image
et ces bibliothèques:

#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiAvrI2c.h"
#include "RTClib.h"

J'ai mis 10kOhms de pull-up sur les SDL et SDA des bus secondaires et ça fonctionne sans problème.

Cordialement
jpbbricole

Bonjour, merci de ta réponse, avant d'aller dormir un peu, j'ai voulu essayer ce que tu me conseille, mais apparemment je dois louper quelque chose, car en mettant les résistances pullup, je n'ai aucuns changements. Les afficheurs fonctionnent bien, mais le rtc me renvoie des valeurs anormales non évolutives. voici le résultat d'un scanner tca:

RTC Connecté sur le tca canal 07
16:04:39.210 -> TCAScanner ready!
16:04:39.210 -> TCA Port #0
16:04:39.210 -> Found I2C 0x3C
16:04:39.210 -> TCA Port #1
16:04:39.257 -> Found I2C 0x3C
16:04:39.257 -> TCA Port #2
16:04:39.257 -> TCA Port #3
16:04:39.304 -> TCA Port #4
16:04:39.304 -> TCA Port #5
16:04:39.304 -> TCA Port #6
16:04:39.350 -> TCA Port #7
16:04:39.350 -> Found I2C 0x50
16:04:39.350 -> Found I2C 0x68
16:04:39.350 -> 
16:04:39.350 -> done
RTC Connecté sur le bus i2c
16:00:27.985 -> TCAScanner ready!
16:00:27.985 -> TCA Port #0
16:00:28.032 -> Found I2C 0x3C
16:00:28.032 -> Found I2C 0x50
16:00:28.032 -> Found I2C 0x68
16:00:28.032 -> TCA Port #1
16:00:28.032 -> Found I2C 0x3C
16:00:28.032 -> Found I2C 0x50
16:00:28.032 -> Found I2C 0x68
16:00:28.032 -> TCA Port #2
16:00:28.032 -> Found I2C 0x50
16:00:28.032 -> Found I2C 0x68
16:00:28.032 -> TCA Port #3
16:00:28.079 -> Found I2C 0x50
16:00:28.079 -> Found I2C 0x68
16:00:28.079 -> TCA Port #4
16:00:28.079 -> Found I2C 0x50
16:00:28.079 -> Found I2C 0x68
16:00:28.079 -> TCA Port #5
16:00:28.079 -> Found I2C 0x50
16:00:28.126 -> Found I2C 0x68
16:00:28.126 -> TCA Port #6
16:00:28.126 -> Found I2C 0x50
16:00:28.126 -> Found I2C 0x68
16:00:28.126 -> TCA Port #7
16:00:28.126 -> Found I2C 0x50
16:00:28.126 -> Found I2C 0x68
16:00:28.126 -> 
16:00:28.126 -> done

Je dois absolument aller dormir. Merci encore, Jean Antonio

Bonjour Jean Antonio

D'après ton schéma et ton programme, ta RTC est branchée directement sur le bus i2C, d'après ton TCAScanner, ta RTC est connectée sur le bus secondaire #7!

A+
Cordialement
jpbbricole

Bonsoir jpbbricole

Tu as raison, sur le schéma, j'ai mis la rtc sur le bus i2c, mais j'ai fais deux scanner, un avec rtc sur i2c

l'autre avec rtc sur tca canal 07.

Bonsoir jeanantonio

Si ta RTC est connectée sur le canal 07, dans ton programme, il ne faut pas oublier de commuter le tca sur ce canal, avant chaque accès à la RTC.

Cordialement
jpbbricole

Re bonsoir,
J'ai dormi un peu, mais pas suffisamment que pour avoir l'esprit suffisamment vif. Voici le programme que j'ai écris jusqu'à présent, sur base de la rtc sur le canal 7 du tca.

[code]
#include <EEPROM.h> // Pour extension à venir
#include "RTClib.h"
#include <OneWire.h>
#include <DallasTemperature.h>

RTC_DS1307 rtc;

#include <SSD1306Ascii.h>
#include <SSD1306AsciiAvrI2c.h>
#include <Wire.h>

// Attachement écran0 avec la librairie
SSD1306AsciiAvrI2c ecran0;
// Attachement écran1 avec la librairie
SSD1306AsciiAvrI2c ecran1;
// Création d'un objet pour l'adresse du module TCA9548A
#define TCAADDR 0x70


char textDisplayOne[] = "Afficheur 1";
char textDisplayTwo[] = "Afficheur 2";


int pot = A1;               // Acquisition d'une valeur de potentiomètre sur A1
int valeur_pot;
int consigne;               // Pour test avec pot en guise de consigne
float newtemp = 0.0;
float tempC;
bool chauffe;
int memo_temp[144];
int cpt_memo_temp = 0;
byte cpti;
byte cptj;
byte cptk;
byte cptl;
bool premier_cycle = true;


// Pour affichage du jour de la semaine
char *JOUR[7] = {"Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"};
//
int HH[7][4];
int MM[7][4];

bool mode_marche = true ; // Auto = true, Manu = False
bool prog_spec = true;  // 1 prog par jour = true, le même programme tous les jours = false
int jour_derogation = 0; // Si > 0 dérogation pendant x jours, sinon programme normal

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

void setup() {

  Wire.begin();
  Serial.begin(115200);
  // Lance le communication I2C avec le module RTC et
  // attend que la connection soit operationelle
  TCA9548A(7);
  while (! rtc.begin()) {
    Serial.println("Attente du module RTC...");
    delay(1000);
  }
  sensors.begin();

  // Mise a jour de l'horloge du module RTC si elle n'a pas
  // ete reglee au prealable
  if (! rtc.isrunning()) {
    // La date et l'heure de la compilation de ce croquis
    // est utilisee pour mettre a jour l'horloge
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // Pour ajuster en manu, ex: 01 Janvier 2021 00h00
    // rtc.adjust(DateTime(2021, 1, 1, 0, 0));
    Serial.println("Horloge du module RTC mise a jour");
  }

  acquisition_temperature();  // appel fonction

  Serial.print(tempC);
  Serial.println(" Celsius");

  /* Ecriture par défaut du contenu mémoires pour les programmes sur 7 jours
      A remplacer par la lecture EEPROM
                                                HH[0..7][0] = 06     MM[0..7][0] = 30
                                                HH[0..7][1] = 12     MM[0..7][1] = 00
                                                HH[0..7][2] = 15     MM[0..7][2] = 00
                                                HH[0..7][3] = 22     MM[0..7][3] = 30
  */
  for (cpti = 0; cpti <= 6; cpti ++)
  {
    HH[cpti][0] = 06;
    MM[cpti][0] = 30;
    HH[cpti][1] = 12;
    MM[cpti][1] = 00;
    HH[cpti][2] = 15;
    MM[cpti][2] = 00;
    HH[cpti][3] = 22;
    MM[cpti][3] = 30;
  }
  // Initialisation canal 0 TCA pour écran 0
  TCA9548A(0);
  ecran0.begin(&Adafruit128x32, 0x3C);
  ecran0.clear();
  ecran0.setFont(System5x7);
  Serial.println(("Initialize 0"));

  // Initialisation canal 1 TCA pour écran 1
  TCA9548A(1);
  ecran1.begin(&Adafruit128x32, 0x3C);
  ecran1.clear();
  ecran1.setFont(System5x7);
  Serial.println(("Initialize 1"));


}

void loop() {
  oled0();
  oled1();


  /* Vérification du contenu mémoires pour les programmes sur 7 jours
      ex:
          Contrôle température pour Dimanche de 06:30 à 12:00 et de 15:00 à 22:30
                                                HH[0..7][0] = 06     MM[0..7][0] = 30
                                                HH[0..7][1] = 12     MM[0..7][1] = 00
                                                HH[0..7][2] = 15     MM[0..7][2] = 00
                                                HH[0..7][3] = 22     MM[0..7][3] = 30
  */
  if (premier_cycle == true)
  {
    for (cpti = 0; cpti <= 6; cpti ++)
    {
      Serial.println();
      Serial.print(JOUR[cpti]);
      for (cptj = 0; cptj <= 3; cptj ++)
      {
        Serial.print(" ");
        if (HH[cpti][cptj] <= 10) Serial.print("0");
        Serial.print(HH[cpti][cptj]);
        Serial.print(":");
        if (MM[cpti][cptj] <= 10) Serial.print("0");
        Serial.print(MM[cpti][cptj]);
        Serial.print(" ");
      }
    }
    Serial.println("");
  }

  chauffage();
  lecture_heure();
  delay(5000);

  valeur_pot = analogRead(pot);
  consigne = map(valeur_pot, 0, 1023, 15, 45);
  Serial.print("Consigne: ");
  Serial.print(consigne);
  Serial.print(" C");
  Serial.print(",Mesure: ");
  Serial.print(tempC);
  Serial.print(",Demande de chauffage: ");
  Serial.println(chauffe);

  acquisition_temperature();  // appel fonction

  // Mémorisation temp toutes les 10 minutes

  if (abs(newtemp - millis()) >= 600000)
  {
    memo_temp[cpt_memo_temp] = tempC;
    newtemp = millis();
    acquisition_temperature();

    cpt_memo_temp ++;

    if (cpt_memo_temp >= 144)
    {
      cpt_memo_temp = 0;
    }
  }

  premier_cycle = false;
}

// Lecture de date et heure depuis le module RTC

void lecture_heure (void) {
  TCA9548A(7);
  Serial.print("Lire l'heure\n");
  // Lecture de l'heure depuis le module RTC
  DateTime now = rtc.now();
  // Affiche l'heure courante retournee par le module RTC
  Serial.print("Il est ");
  if (now.hour() <= 9) Serial.print("0");
  Serial.print(now.hour());
  Serial.print(":");
  if (now.minute() <= 9) Serial.print("0");
  Serial.print(now.minute());
  Serial.print(":");
  if (now.second() <= 9) Serial.print("0");
  Serial.print(now.second());
  Serial.print(" ");
  Serial.print(JOUR[now.dayOfTheWeek()]);
  Serial.print(" ");
  if (now.day() <= 9) Serial.print("0");
  Serial.print(now.day());
  Serial.print("/");
  if (now.month() <= 9) Serial.print("0");
  Serial.print(now.month());
  Serial.print("/");
  Serial.print(now.year());
  Serial.println(" ");

}

void acquisition_temperature(void) {
  sensors.requestTemperatures(); // Send the command to get temperatures
  tempC = sensors.getTempCByIndex(0);
}

void chauffage(void) {

  // Comparaison consigne / mesure
  // Si comparaison +, pas de chauffe
  // Si comparaison - de 2 degrés, chauffe

  if (int(tempC) >= consigne)
  {
    chauffe = false;
  } else {
    if (int(tempC) <= (consigne - 2))
    {
      chauffe = true;
    }
  }

}

void TCA9548A(uint8_t bus)
{
  Wire.beginTransmission(TCAADDR); //TCA9548A address is 0x70
  Wire.write(1 << bus);           // send byte to select bus
  Serial.print("Boucle TCA, Bus: "); 
  Serial.println(bus);
  Wire.endTransmission();
}

void oled0() {

  TCA9548A(0);
  ecran0.clear();
  ecran0.set1X();
  ecran0.setCursor(15, 0);
  ecran0.print(tempC);
  ecran0.print(" C");
  ecran0.setCursor(0, 2);
  ecran0.print(textDisplayOne);
  Serial.println(("Ecrire sur écran 1"));
  delay(1000);
  ecran0.clear();
}


void oled1() {

  TCA9548A(1);
  ecran1.clear();
  ecran1.set1X();
  ecran1.setCursor(0, 0);
  ecran1.print(textDisplayTwo);
  Serial.println(("Ecrire sur écran 2"));
  delay(1000);
  ecran1.clear();
}
[/code]

Et, la sortie du moniteur série (les premières secondes).

22:37:22.837 -> Boucle TCA, Bus: 7
22:37:23.540 -> 23.81 Celsius
22:37:23.540 -> Boucle TCA, Bus: 0
22:37:23.587 -> Initialize 0
22:37:23.587 -> Boucle TCA, Bus: 1
22:37:23.634 -> Initialize 1
22:37:23.634 -> Boucle TCA, Bus: 0
22:37:23.634 -> Ecrire sur écran 1
22:37:24.665 -> Boucle TCA, Bus: 1
22:37:24.712 -> Ecrire sur écran 2
22:37:25.696 -> 
22:37:25.696 -> Dimanche 06:30  12:00  15:00  22:30 
22:37:25.696 -> Lundi 06:30  12:00  15:00  22:30 
22:37:25.696 -> Mardi 06:30  12:00  15:00  22:30 
22:37:25.696 -> Mercredi 06:30  12:00  15:00  22:30 
22:37:25.743 -> Jeudi 06:30  12:00  15:00  22:30 
22:37:25.743 -> Vendredi 06:30  12:00  15:00  22:30 
22:37:25.743 -> Samedi 06:30  12:00  15:00  22:30 
22:37:25.743 -> Boucle TCA, Bus: 7
22:37:25.743 -> Lire l'heure
22:37:25.743 -> Il est 165:165:45 Dimanche 165/165/2165 
22:37:30.710 -> Consigne: 24 C,Mesure: 23.81,Demande de chauffage: 0
22:37:31.366 -> Boucle TCA, Bus: 0
22:37:31.413 -> Ecrire sur écran 1
22:37:32.444 -> Boucle TCA, Bus: 1
22:37:32.444 -> Ecrire sur écran 2
22:37:33.475 -> Boucle TCA, Bus: 7
22:37:33.475 -> Lire l'heure
22:37:33.475 -> Il est 165:165:45 Dimanche 165/165/2165 
22:37:38.490 -> Consigne: 24 C,Mesure: 23.81,Demande de chauffage: 0
22:37:39.146 -> Boucle TCA, Bus: 0
22:37:39.146 -> Ecrire sur écran 1
22:37:40.158 -> Boucle TCA, Bus: 1
22:37:40.204 -> Ecrire sur écran 2
22:37:41.235 -> Boucle TCA, Bus: 7
22:37:41.235 -> Lire l'heure
22:37:41.235 -> Il est 165:165:45 Dimanche 165/165/2165 

Je suis certain de mal faire quelques chose, ou d'avoir mal compris le fonctionnement du tca (??)

Bonne soirée.

Bonsoir jeanantonio

Je ne vois rien de flagrant!

Je peux essayer ton programme demain.

Bonne nuit
jpbbricole

Bonjour jeanantonio

J'ai essayé ton programme, sans problème d'horloge RTC.

Consigne: 24 C,Mesure: -127.00,Demande de chauffage: 1
Boucle TCA, Bus: 0
Ecrire sur ?cran 1
Boucle TCA, Bus: 1
Ecrire sur ?cran 2
Boucle TCA, Bus: 7
Lire l'heure
Il est 08:35:08 Samedi 18/12/2021 

Avec cette configuration:

TCAScanner ready!
TCA Port #0	Found I2C 0x3C
TCA Port #1	Found I2C 0x3C
TCA Port #2
TCA Port #3
TCA Port #4
TCA Port #5
TCA Port #6
TCA Port #7	Found I2C 0x50	Found I2C 0x68

Avec des PULL-UP de 10k.

Cordialement
jpbbricole

Bonjour jpbbricole,
un grand merci pour le temps passé à essayer de m'aider, j'en arrive donc à la conclusion que j'ai une erreur dans mon circuit, je vais revérifier cela dès maintenant.
Les résistances de PULL-UP se mettent bien à chaque canal tca utilisés, entre le signal et le +Vcc ou j'ai mal compris ? Ou défaillance matérielle, c'est du chinois mais bon ....

Cordialement, Jean Antonio

Bonjour jeanantonio

Oui, regardes la doc page 18.

A+
Bonne journée
Cordialement
jpbbricole

J'ai téléchargé la doc la première fois que tu en à parlé, et c'est bien ce que j'ai fais, mais là j'y perd un peu mon latin, car tu as essayé mon programme, tu obtiens des résultats correctes, mais moi pas.

Bonjour jeanantonio

Essaies de remplacer void TCA9548A(uint8_t bus) par ça:

void TCA9548A(uint8_t bus)
{
  Wire.beginTransmission(TCAADDR); //TCA9548A address is 0x70
  Wire.write(1 << bus);           // send byte to select bus
  Wire.endTransmission();
  
  Serial.print("Boucle TCA, Bus: ");
  Serial.println(bus);
  delay(100);
}

A+
Cordialement
jpbbricole

Éventuellement :

Normalement les écrans OLED et le module TCA9548 possèdent leurs propres pullups I2C.