Мультиплексирование Arduino I2C с использованием TCA9548A

Я использую 5 датчиков, два из которых имеют одинаковый адрес I2C и подключены через мультиплексор TCA9548. Остальные 3 датчика подключены к основной шине arduino I2C. В примерах скетчей онлайн я вижу следующую функцию для выбора конкретного порта/канала на мультиплексоре:

#define MPLXADR 0x70 // Адрес мультиплексора I2C TCA9548A
void multiplexer (uint8_t ch) {
  if (ch > 7) return;
  Wire.beginTransmission(MPLXADR);
  Wire.write(1 << ch);
  Wire.endTransmission();
}

Я понимаю, что эту функцию следует вызывать перед выполнением инструкций для датчиков с общим адресом, но как она все равно отправит данные на нужный датчик, когда последняя строка "Wire.endTransmission();" просто закрывает соединение?

Поскольку в моей схеме есть датчики, которые подключены непосредственно к шине I2C Arduino, мне интересно, если код, относящийся к этим датчикам, идет после кода для датчиков с общим адресом, не будут ли эти инструкции также отправлены датчикам. с общим адресом I2C? На мой взгляд, имеет больше смысла, если инструкции для датчиков общего адреса заключены в вышеупомянутую функцию следующим образом:

выбор канала -> выполнить инструкцию -> завершить передачу

Но использование, которое я вижу в учебниках, ставит меня в тупик. Может ли кто-нибудь прояснить эти моменты? Спасибо

Вот полный скетч, который я использую:

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <AHT10.h>
#include <HDC2080.h>

Adafruit_BME280 bme1; // на шине Arduino I2C
Adafruit_BME280 bme2; // на шине I2C мультиплексора
Adafruit_BME280 bme3; // на шине I2C мультиплексора
AHT10 AHT(AHT10_ADDRESS_0X38); // на шине Arduino I2C
HDC2080 HDC2080(0x41);// на шине Arduino I2C


#define MPLXADR 0x70 // Адрес мультиплексора I2C TCA9548A
void multiplexer (uint8_t ch) {
  if (ch > 7) return;
  Wire.beginTransmission(MPLXADR);
  Wire.write(1 << ch);
  Wire.endTransmission();
}

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

  while (AHT.begin() != true)
  {
    Serial.println(F("AHT10 not connected or fail to load calibration coefficient"));
    delay(5000);
  }
  Serial.println(F("AHT10 OK"));

  HDC2080.begin();

  // Начнем со сброса устройства
  HDC2080.reset();

  // Настраиваем зону комфорта
  HDC2080.setHighTemp(28);         // Высокая температура 28С
  HDC2080.setLowTemp(22);          // Низкая температура 22C
  HDC2080.setHighHumidity(55);     // Высокая влажность 55%
  HDC2080.setLowHumidity(40);      // Низкая влажность 40%

  // Настройка измерений
  HDC2080.setMeasurementMode(TEMP_AND_HUMID);  // Установить измерения температуры и влажности
  HDC2080.setRate(ONE_HZ);                     // Установите частоту измерения на 1 Гц
  HDC2080.setTempRes(FOURTEEN_BIT);
  HDC2080.setHumidRes(FOURTEEN_BIT);

  // начинаем измерение
  HDC2080.triggerMeasurement();
  Serial.println();

  Serial.println(F("BME280 test"));

  //датчик BME280 1
  multiplexer(0);
  if (! bme1.begin(0x77, &Wire)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

  // мониторинг погоды
  Serial.println("-- Weather Station Scenario --");
  Serial.println("forced mode, 1x temperature / 1x humidity / 1x pressure oversampling,");
  Serial.println("filter off");
  bme1.setSampling(Adafruit_BME280::MODE_FORCED,
                   Adafruit_BME280::SAMPLING_X1, // температура
                   Adafruit_BME280::SAMPLING_X1, // давление
                   Adafruit_BME280::SAMPLING_X1, // влажность
                   Adafruit_BME280::FILTER_OFF   );

  //датчик BME280 2
  multiplexer(1);
  if (! bme2.begin(0x77, &Wire)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

  // мониторинг погоды
  Serial.println("-- Weather Station Scenario --");
  Serial.println("forced mode, 1x temperature / 1x humidity / 1x pressure oversampling,");
  Serial.println("filter off");
  bme2.setSampling(Adafruit_BME280::MODE_FORCED,
                   Adafruit_BME280::SAMPLING_X1, // температура
                   Adafruit_BME280::SAMPLING_X1, // давление
                   Adafruit_BME280::SAMPLING_X1, // влажность
                   Adafruit_BME280::FILTER_OFF   );

  //датчик BME280 3
  if (! bme3.begin(0x76, &Wire)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

  // мониторинг погоды
  Serial.println("-- Weather Station Scenario --");
  Serial.println("forced mode, 1x temperature / 1x humidity / 1x pressure oversampling,");
  Serial.println("filter off");
  bme3.setSampling(Adafruit_BME280::MODE_FORCED,
                   Adafruit_BME280::SAMPLING_X1, // температура
                   Adafruit_BME280::SAMPLING_X1, // давление
                   Adafruit_BME280::SAMPLING_X1, // влажность
                   Adafruit_BME280::FILTER_OFF   );

  // рекомендуемая частота 1/60 Гц (1 м)
 }

void loop() {
  bme3.takeForcedMeasurement(); // не действует в обычном режиме
  printValuesBME3();
  delay(5000);

  printValuesAHT();
  delay(5000);

  printValuesHDC2080();
  delay(5000);

  multiplexer(0);
  bme1.takeForcedMeasurement(); // не действует в обычном режиме
  printValuesBME1();
  delay(5000);

  multiplexer(1);
  bme2.takeForcedMeasurement(); // не действует в обычном режиме
  printValuesBME2();
  delay(10000);
}

void printValuesBME1() {

  Serial.println();
  Serial.print("BME1 Readings");

  Serial.print("Temperature = ");
  Serial.print(bme1.readTemperature());
  Serial.println(" *C");

  Serial.print("Humidity = ");
  Serial.print(bme1.readHumidity());
  Serial.println(" %");

  Serial.println();
}

void printValuesBME2() {

  Serial.println();
  Serial.print("BME2 Readings");

  Serial.print("Temperature = ");
  Serial.print(bme2.readTemperature());
  Serial.println(" *C");

  Serial.print("Humidity = ");
  Serial.print(bme2.readHumidity());
  Serial.println(" %");

  Serial.println();
}

void printValuesBME3() {

  Serial.println();
  Serial.print("BME3 Readings");

  Serial.print("Temperature = ");
  Serial.print(bme3.readTemperature());
  Serial.println(" *C");

  Serial.print("Humidity = ");
  Serial.print(bme3.readHumidity());
  Serial.println(" %");

  Serial.println();
}

void printValuesHDC2080() {
  Serial.println("HDC2080 Values");
  Serial.print("Temperature (C): "); Serial.print(HDC2080.readTemp());
  Serial.print("\t\tHumidity (%): "); Serial.println(HDC2080.readHumidity());
}

void printValuesAHT() {
  
  Serial.println(F("AHT10: read 12-bytes, show 255 if communication error is occurred"));
  Serial.print(F("Temperature: ")); Serial.print(AHT.readTemperature()); Serial.println(F(" +-0.3C")); //по умолчанию "AHT10_FORCE_READ_DATA"
  Serial.print(F("Humidity...: ")); Serial.print(AHT.readHumidity());    Serial.println(F(" +-2%"));   //по умолчанию "AHT10_FORCE_READ_DATA"
}

, 👍0


1 ответ


Лучший ответ:

2

TCA9548 — это коммутатор.

Вы начинаете с ним транзакцию, меняете канал, через который он проходит, а затем завершаете эту конкретную транзакцию.

С этого момента к вашему автобусу подключен один и только один из двух других датчиков - другого не существует. Когда вы сообщаете адрес этого датчика, он проходит через TCA9548, как будто его не существует.

Вы можете думать о TCA9548 как о контроллере, который находится рядом с коммутатором:

схема

Отправьте канал 0, и он переключит переключатель в одну сторону. Отправьте канал 1, и он переключит переключатель в другую сторону. Когда переключатель щелкнут, он останется включенным, пока вы не скажете иначе.

С точки зрения скетчей, два HDC2080 на MUX — это всего лишь один HDC2080. Просто переведите переключатель в нужное положение, чтобы получить доступ к конкретному физическому устройству, которое вам нужно в данный момент.

,