How to drive APA102 FastLED through Pa.HUB (TCA9548A I2C) port extender?

Hello all together,
I’m new with the M5 ecosystem and very inspired from this devices.

Now I’m working on a project to control an APA102 digital LED stripe by two TOF distance sensors by Arduino. The APA102 and the two TOF sensors are connected by a PaHUB to a M5stickC Grove port. I’s no problem to read the distances from this sensors through the port extender.

But how I can tell to the FastLED library to use the two I/O pins of the PaHUB Ch.0 to drive the LED stripe?

Thank you very much for any hints.

Greetings from Berlin in Germany
Vaiolux

TOF: Time-of-Flight Distance Ranging Sensor Unit (VL53L0X) | m5stack-store
Pa.HUB: [EOL] I2C Hub 1 to 6 Expansion Unit (TCA9548A) | m5stack-store
M5stickC: M5StickC ESP32-PICO Mini IoT Development Kit | m5stack-store

My code:

// the setup routine runs once when M5Stack starts up
#include <M5StickC.h>
#include <Wire.h>
#include <FastLED.h>

// Defines for VL53L0X TOF sensor
#define VL53L0X_REG_IDENTIFICATION_MODEL_ID         0xc0
#define VL53L0X_REG_IDENTIFICATION_REVISION_ID      0xc2
#define VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD   0x50
#define VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD 0x70
#define VL53L0X_REG_SYSRANGE_START                  0x00
#define VL53L0X_REG_RESULT_INTERRUPT_STATUS         0x13
#define VL53L0X_REG_RESULT_RANGE_STATUS             0x14
#define address 0x29                                         //the iic address of tof
byte gbuf[16];
uint16_t distance1 = 0;
uint16_t distance2 = 0;

// Defines for Pa.HUB
#define PaHub_I2C_ADDRESS 0X77

// Defines for FastLED
// Use if you want to force the software SPI subsystem to be used for some reason (generally, you don't)
#define FASTLED_FORCE_SOFTWARE_SPI
// Use if you want to force non-accelerated pin access (hint: you really don't, it breaks lots of things)
// #define FASTLED_FORCE_SOFTWARE_SPI
// #define FASTLED_FORCE_SOFTWARE_PINS

// Defines for APA102 LED strip
#define NUM_LEDS 10    // How many leds are in the strip?
#define DATA_PIN 32    // Data pin that led data will be written out over
#define CLOCK_PIN 33   // Clock pin only needed for SPI based chipsets when not using hardware SPI
CRGB leds[NUM_LEDS];   // This is an array of leds.  One item for each led in your strip.

void setup() {

 M5.begin();          // Initialize the M5Stack object
 Wire.begin();        // join i2c bus (address optional for master)    

 // Uncomment one of the following lines for your leds arrangement.
 FastLED.addLeds<APA102, DATA_PIN, CLOCK_PIN, BGR>(leds, NUM_LEDS);
 //FastLED.addLeds<APA102, DATA_PIN, CLOCK_PIN, BGR, DATA_RATE_MHZ(12)>(leds, NUM_LEDS);

 // LCD display
 M5.Lcd.setRotation(1);
 M5.Lcd.setTextSize(2);
 M5.Lcd.setTextColor(BLACK);
}

void portselectall(uint8_t ports) {  
 Wire.beginTransmission(PaHub_I2C_ADDRESS);
 Wire.write(ports&0x3f);
 Wire.endTransmission(); 
}
void portselect(uint8_t i) {
 if (i > 7) return;
 Wire.beginTransmission(PaHub_I2C_ADDRESS);
 Wire.write(1 << i);
 Wire.endTransmission(); 
}

void led_strip() {
  // Move a single  led 
  for(int LedPix = 0; LedPix < NUM_LEDS; LedPix = LedPix + 1) {
 
     leds[LedPix] = CRGB::HotPink;
     FastLED.setBrightness(50);
   
     // Show the leds (only one)
     FastLED.show();
     // Wait a little bit
     delay(50);
     // Turn our current led back to black for the next loop around
     leds[LedPix] = CRGB::Black;
  }
}

void loop() {
 portselect(1);        //Hub range is 0 to 5
 delay(10);
 distance1 = tof_reed();
 portselect(2);        //Hub range is 0 to 5
 delay(10);
 distance2 = tof_reed();
    
 M5.Lcd.fillScreen(0xFF8000);
 M5.Lcd.setCursor(0, 0, 1);
 M5.Lcd.printf("D1:%d ",distance1);
 M5.Lcd.setCursor(0, 15, 1);
 M5.Lcd.printf("D2:%d ",distance2);

 portselect(0);        //Hub range is 0 to 5
 delay(10);  
 led_strip();

}
`

But how I can tell to the FastLED library to use the two I/O pins of the PaHUB Ch.0 to drive the LED stripe?

Sorry but you can’t do this.

I2C is very slow and any refresh of the data will take a comparatively long time. The good news is there is nothing to stop you bit banging the protocol over I2C because it depends on a sequence of signals not the single precise timed data stream of the WS2812 type of LED.
So look at the data sheet and see how you need to send the clock and data line for each bit of data. As one I2C access takes 0.1 mS and I think you need three access per bit transferred and 24 bits per LED that works out at 7.2 mS per LED.

You right, the time issue is a show stopper because I have later around 300 LEDs on this SPI port. This results up to 2 seconds until the last LED is ready. So the smooth dimming of the whole line will be a bit strange. Thanks putting my head straight.

on this SPI port.

I thought it was on the I2C bus.
If you move to doing it on the SPI bus it wii be much faster.

Sorry, it's still the I2C bus, not SPI. I will redesign the hardware so i can connect the APA102 directly to the I/O and move some more low speed sensors to the I2C extender.