zwei oder mehr TCA9548A Multiplexer an einen I2C?

Hallo,

ich möchte 48 Sensoren (Luftdruck, BMP180) auslesen (per i2c), das wollte ich mit 6 TCA9548A realisieren. Die TCA9548A kann man ja auch adressieren, also müsste das gehen.

Ich suche nun ein Code-Beispiel mit mehr als einem TCA9548A, kann da jemand helfen?

MfG.

Ungetestet: Tutorial – Using the TCA9548A 1-to-8 I2C Multiplexer Breakout with Arduino

Generell ist diese Quelle aber ganz gut.

Und eine weitere Quelle: I2C-Multipl. TCA9548A :: Meine Arduino-Projekte

a)
eigentlich muss du dem Umschalter nur noch die jeweilige Adresse mitgeben

also die eigentliche Funktion mit einem zweiten Parameter ausstatten

uint8_t TCA9548A(uint8_t addr, uint8_t bus)       // switch bus
{
  uint8_t result = 0; // 0 = success
  Wire.beginTransmission(addr);  // TCA9548A address is 0x70 .. 0x77
  Wire.write(1 << bus);          // send byte to select bus
  return Wire.endTransmission();
}

dann kannst du einfach mit

TCA9548A(0x71, 3);

auf den zweiten (0x71) TCA, Bus 3 aktivieren und danach deinen Sensor auslesen

aber
b)
48 Sensoren. Das ist massiv. Machst du da eine eigene Platine mit den 48 Sensoren oder wie sorgst du dafür dass die Leitungen so kurz wie möglich sind? Du kommst da eh nicht auf die Idee nun i2c quer durchs Haus mit Klingeldraht zu verlegen?

(deleted)

ja, die Quellen habe ich natürlich als ersten gefunden.

bin dann selbst auf die Lösung gekommen, siehe auch noiasca.

void TCA9548A(uint8_t i2cadd, uint8_t bus)
{
  Wire.beginTransmission(i2cadd);  // TCA9548A address is 0x70
  Wire.write(1 << bus);          // send byte to select bus
  Wire.endTransmission();
}


void loop()
{
  for (addr = 0x70; addr < 0x76; addr++) {
    for (tcanr = 0; tcanr < 8; tcanr++) {
      TCA9548A(addr, tcanr);   
      pressure = int(BMP180.readPressure());
      Serial.print(tcanr);
      Serial.print(":");
      Serial.print(pressure);
      Serial.println();
    }
  }
}

ich will den Luftdruck in 48 Schläuchen überwachen, in denen leichtes Schüttgut transportiert wird. Erhöht sich der Druck, liegt eine Blockierung nach dem Sensor vor, verringert sich der Druck, gibt es eine Blockierung vor dem Sensor (so die Theorie). Die Leitungen der Sensoren sind max. 1-2m lang.
"Normal" mit optischen Sensoren würde sowas ca. 7.000 - 8.000 € kosten, das will ich mir aber sparen.

spunky1a:
ja, die Quellen habe ich natürlich als ersten gefunden.

bin dann selbst auf die Lösung gekommen, siehe auch noiasca.

Ok, aber das muss ich jetzt nicht verstehen ?

spunky1a:
Die Leitungen der Sensoren sind max. 1-2m lang.

Je nach Umgebung und Busgeschwindigkeit kann das für I2C schon problematisch werden. Mit 48 Sensoren baust Du eine Antenne. Daher ergänzend zu #4: Eine Tüte Nanos und eine Tüte CAN-Bus.

Hmm- ich hol mir mal eine Tüte Popcorn.

Je nachdem wie weit jeweils die 48 Schläuche auseinander liegen, würde ich - verzeiht bitte - dann statt Arduino doch 48 Controller mit eingebautem CAN verwenden :slight_smile:

Da lohnt sich ein eigenes HW-Design schon.

Gruß Walter

die Schläuche kommen aus einem Verteiler und liegen max. 50 cm auseinander. Ich wollte einen ESP32 verwenden, da kann ich die Daten per Web, Bluetooth oder seriell auslesen.

Hatte auch schon an einen Controller pro Sensor gedacht und dann per CAN die Daten zusammenzufassen. Welchen Controller könnte man da nehmen?

wno158:
Hmm- ich hol mir mal eine Tüte Popcorn.

Bring' bitte eine für mich mit :smiley:

spunky1a:
Welchen Controller könnte man da nehmen?

Bin gerade über CANBed - Arduino CAN-BUS Development Kit (ATmega32U4 with MCP2515 and MCP2551) gestolpert. Nicht gerade ein Schnäppchen, spart aber vermutlich Entwicklungszeit.

@spunky: Oh je - die Frage habe ich befürchtet.
Da es gefühlt Tausende davon gibt, mag ich keine dedizierte Empfehlung geben.
Der muss ja nicht viel können:
I2C für den Sensor und CAN zum weiterverteilen z.B. an den ESP, der hat auch CAN.
Bei 50cm kommst Du vielleicht auch mit weniger als 48 Controllern aus, wenn Du von einem aus sternförmig ein paar von den Schläuchen erreichen kannst.

Eine Liste von CAN-fähigen Chips gibt es bei den Kollegen mikrocontroller:

Der erste Atmel AVR dort ist der AT90CAN32. Im Datenblatt (PDF) findet sich auch ein "Byte-oriented Two-wire Serial Interface" (Kapitel 18) - weil I2C ein Philips-Ding ist.

Noch - aus (physikalischer) Neugier - eine Verständnisfrage:
Wie genau soll der BMP180 in den Schläuchen angebracht werden? Musst Du da ein Löchlein reinschneiden?
Es gibt ja für den Arduino auch IR-LEDs und -Sensoren; dann sollte das Schüttgut aber nicht allzu durchsichtig sein :slight_smile:

Gruß Walter

@agmue: Mach' ich!

wno158:
@agmue: Mach' ich!

Ich freu' mich :smiley:

wno158:
Eine Liste von CAN-fähigen Chips gibt es bei den Kollegen mikrocontroller:

Da sticht mir der STM32 ins Auge, der soll auch günstig sein. Kenne ich aber nicht aus eigener Erfahrung und wichtig ist, welche Bibliotheken darauf laufen. ATmega328P ist Standard und daher kommst Du damit möglicherweise schneller zu einem Ergebnis.

ESP32 und UNO am CAN-Bus habe ich schon probiert, das funktioniert.

ich habe mal 5 BMP180 an den TCA angeschlossen, bekomme aber keine vernünftigen Werte ausgelesen (siehe Bild, 3. Zeile Druck, 4. Zeile Temp), woran kann das liegen?

5xbmp180.jpg

ich benutze den folgenden Code:

#include <Adafruit_BMP085.h>
#include <Wire.h>

Adafruit_BMP085 bmp180;
int tcanr;

void setup()
{

  Wire.begin();
  Serial.begin(115200);

  for (tcanr = 0; tcanr < 8; tcanr++) {
    TCA9548A(0, tcanr);
    bmp180.begin();
  }

}


void loop()
{

  for (tcanr = 0; tcanr < 8; tcanr++) {

    TCA9548A(0, tcanr);

    Serial.println(tcanr);

    Serial.print("Temperature = ");
    Serial.print(bmp180.readTemperature());
    Serial.println(" °C");

    Serial.print("Pressure = ");
    Serial.print(bmp180.readPressure());
    Serial.println(" Pa");

    Serial.println();
    delay(1000);
  }

}

uint8_t TCA9548A(uint8_t addr, uint8_t bus)       // switch bus
{
  uint8_t result = 0; // 0 = success
  Wire.beginTransmission(0x70 + addr);  // TCA9548A address is 0x70 .. 0x77
  Wire.write(1 << bus);          // send byte to select bus
  return Wire.endTransmission();
}

Teste ich jeden Sensor einzeln, werden korrekte Werde ausgelesen:

#include <Wire.h>
#include <Adafruit_BMP085.h>

Adafruit_BMP085 bmp180;

long druck1, temp1;

void setup()
{
Serial.begin(115200);
Wire.begin ();
if (!bmp180.begin(0x77))
{
Serial.println("Could not find BMP180 or BMP085 sensor at 0x77");
while (1) {}
}
}

void loop()
{
temp1 = bmp180.readTemperature();
Serial.print("Temperatur = ");
Serial.print(temp1);
Serial.println("°C");

druck1 = bmp180.readPressure() - 0;
Serial.print("Luftdruck = ");
Serial.print(druck1);
Serial.println("Pa");

Serial.println();
delay(1000);
}

5xbmp180.jpg

(deleted)

ok, habe verstanden, ich muss nach jeder Adressänderung den Sensor neu initialisieren, jetzt geht es, danke. :slight_smile:

    TCA9548A(0, tcanr);
    bmp180.begin();

die Abfrage aller 48 Sensoren dauert 1,65 Sekunden, das ist doch ziemlich unpraktisch, lässt sich das irgendwie beschleunigen? Vermutlich nicht... :confused:

spunky1a:
... lässt sich das irgendwie beschleunigen?

Welche Datenrate auf dem I2C-Bus verwendest Du?

Abhängig vom Modus ändert sich auch die Bereitstellungszeit für die Daten. Mittels begin(BMP085_STANDARD) oder so kann man das einstellen.

Zur Berechnung des Drucks wird auch immer die Temperatur gemessen, was zusätzliche Zeit benötigt. Die Temperatur kann man seltener lesen, was aber wohl von der Bibliothek nicht unterstützt wird.

Ob es merklich was bringt, kann ich nicht versprechen, aber Möglichkeiten zum Probieren gibt es :smiley: