Using the PCA9546 I2C multiplexer with Arduino involves wiring up the I2C multiplexer to your Arduino-compatible microcontroller and running the provided example code.

If you're curious why you'd need an I2C multiplexer, be sure to check out this guide that goes in depth on working with multiple copies of the same I2C device, which most likely have the same I2C address.

Wiring

Wire as shown for a 5V board like an Uno. If you are using a 3V board, like an Adafruit Feather, wire the board's 3V pin to the PCA9546 VIN.

Here is an Adafruit Metro wired up to the PCA9546 using a solderless breadboard, along with two VL53L4CD STEMMA boards attached to pins SD0/SC1 and SD2/SC2:

Power

  • Metro 5V to multiplexer VIN (red wire)
  • Metro 5V to VL53L4CD 1 VIN (red wire)
  • Metro 5V to VL53L4CD 2 VIN (red wire)

Ground

  • Metro GND to multiplexer GND (black wire)
  • Metro GND to VL53L4CD 1 GND (black wire)
  • Metro GND to VL53L4CD 2 GND (black wire)

Metro I2C

  • Metro SCL to multiplexer SCL (yellow wire)
  • Metro SDA to multiplexer SDA (blue wire)

VL53L4CD I2C

  • VL53L4CD 1 SCL to multiplexer SC1
  • VL53L4CD 1 SDA to multiplexer SD0
  • VL53L4CD 2 SCL to multiplexer SC2
  • VL53L4CD 2 SDA to multiplexer SD2

Library Installation

The Multi-Sensor example uses two VL53L4CD time of flight sensors. You can install the VL53L4CD library for Arduino using the Library Manager in the Arduino IDE.

Click the Manage Libraries ... menu item, search for VL53L4CD, and select the STM32duino VL53L4CD library:

I2C Scanner Example Code

// SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries
//
// SPDX-License-Identifier: MIT
/**
 * PCA9546 I2CScanner.ino -- I2C bus scanner for Arduino
 *
 * Based on https://playground.arduino.cc/Main/I2cScanner/
 *
 */

#include "Wire.h"

#define PCAADDR 0x70

void pcaselect(uint8_t i) {
  if (i > 3) return;
 
  Wire.beginTransmission(PCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission();  
}


// standard Arduino setup()
void setup()
{
    while (!Serial);
    delay(1000);

    Wire.begin();
    
    Serial.begin(115200);
    Serial.println("\nPCAScanner ready!");
    
    for (uint8_t t=0; t<4; t++) {
      pcaselect(t);
      Serial.print("PCA Port #"); Serial.println(t);

      for (uint8_t addr = 0; addr<=127; addr++) {
        if (addr == PCAADDR) continue;

        Wire.beginTransmission(addr);
        if (!Wire.endTransmission()) {
          Serial.print("Found I2C 0x");  Serial.println(addr,HEX);
        }
      }
    }
    Serial.println("\ndone");
}

void loop() 
{
}

Upload the sketch to your board and open up the Serial Monitor (Tools -> Serial Monitor) at 115200 baud. You should see the 4 ports print to the Serial Monitor. If an I2C device is plugged into one of the ports, its address will be printed below the port number.

Multi-Sensor Example Code

// SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries
//
// SPDX-License-Identifier: MIT
/**
 * PCA9546 I2C Multi Sensor Example
 *
 * Using two VL53L4CD sensors on ports 0 and 1
 *
 */

#include <Arduino.h>
#include <Wire.h>
#include <vl53l4cd_class.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <assert.h>

#define PCAADDR 0x70
#define DEV_I2C Wire

#define SerialPort Serial

// create two instances of the sensor
VL53L4CD tof1(&DEV_I2C, A1);
VL53L4CD tof2(&DEV_I2C, A1);

void pcaselect(uint8_t i) {
  if (i > 3) return;
 
  Wire.beginTransmission(PCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission();  
}

// standard Arduino setup()
void setup()
{
    while (!Serial);
    delay(1000);

    Wire.begin();
    
    Serial.begin(115200);
    Serial.println("\nMultiSensor PCA9546");
    
    // define the port on the PCA9546 for the first sensor
    pcaselect(0);
    // setup the first sensor
    tof1.begin();
    tof1.VL53L4CD_Off();
    tof1.InitSensor();
    tof1.VL53L4CD_SetRangeTiming(200, 0);
    tof1.VL53L4CD_StartRanging();
  
    // define the port on the PCA9546 for the 2nd sensor
    pcaselect(1);
    
    // setup the 2nd sensor
    tof2.begin();
    tof2.VL53L4CD_Off();
    tof2.InitSensor();
    tof2.VL53L4CD_SetRangeTiming(200, 0);
    tof2.VL53L4CD_StartRanging();
      
}

void loop() 
{
  uint8_t NewDataReady = 0;
  VL53L4CD_Result_t results;
  uint8_t status;
  char report[64];
  
  // define port on the PCA9546
  pcaselect(0);

  // loop for time of flight sensor 1
  do {
    status = tof1.VL53L4CD_CheckForDataReady(&NewDataReady);
  } while (!NewDataReady);

  if ((!status) && (NewDataReady != 0)) {
    // (Mandatory) Clear HW interrupt to restart measurements
    tof1.VL53L4CD_ClearInterrupt();

    // Read measured distance. RangeStatus = 0 means valid data
    tof1.VL53L4CD_GetResult(&results);
    snprintf(report, sizeof(report), "ToF 1 - Status = %3u, Distance = %5u mm, Signal = %6u kcps/spad\r\n",
             results.range_status,
             results.distance_mm,
             results.signal_per_spad_kcps);
    SerialPort.println(report);
  }

  // define port on PCA9546
  pcaselect(1);

  // loop for time of flight sensor 2
  do {
    status = tof2.VL53L4CD_CheckForDataReady(&NewDataReady);
  } while (!NewDataReady);

  if ((!status) && (NewDataReady != 0)) {
    // (Mandatory) Clear HW interrupt to restart measurements
    tof2.VL53L4CD_ClearInterrupt();

    // Read measured distance. RangeStatus = 0 means valid data
    tof2.VL53L4CD_GetResult(&results);
    snprintf(report, sizeof(report), "ToF 2 - Status = %3u, Distance = %5u mm, Signal = %6u kcps/spad\r\n",
             results.range_status,
             results.distance_mm,
             results.signal_per_spad_kcps);
    SerialPort.println(report);
  }
}

Upload the sketch to your board and open up the Serial Monitor (Tools -> Serial Monitor) at 115200 baud. You should see readings from the two VL53L4CD time of flight sensors print to the Serial Monitor.

This guide was first published on Jan 11, 2023. It was last updated on May 13, 2024.

This page (Arduino) was last updated on May 13, 2024.

Text editor powered by tinymce.