PL9823 programmable RGB led isn't changing colour

Code and schematic at bottom of post. Very low experience with programming. Using an esp32 wroom but I'm not sure the specific model

The design uses TCS34725 colour sensors to detect when an object (in this case, a simple colour filter) is placed in front of it. I built an enclosure for the sensor so that the light input can be controlled. This aspect works perfectly, I can get it to recognise the difference between a red, a blue and no filter, and even serial print "correct" when the red filter is put in (hence solving the puzzle)

The problem however is that when I daisy chain addressable PL9823 LEDs, they all seem to do random things. I want them to show white (255,255,255) when there is no filter (the white light underneath it), red when the red filter is there, blue for the blue filter etc etc, but it just seems to show blue for all the leds no matter what.

I downsized to 1 sensor and 1 LED to debug (the code and schematic example below) but I'm getting the same results. I've triple checked the wiring on the LED and I am getting the correct DIN leg connected to GPIO 15.

Eventually I want to increase the number of detected colours to green, purple, yellow and none (black)

But currently, I just want the LED to be red when the red filter is inserted, repeat for white and blue etc.

The multiplexer is required because there will be 5 colour sensors, the wiring is still in the schematic because I haven't actually disconnected anything yet, I've just changed NUM_SENSORS numSensors to 1 and it is sensing properly. The issue is with the LED

Hope anyone can help!

Edit: When the code checks for 'hasChanged = True' it doesn't seem to be printing (Serial.print(detectedObjects[i]):wink: to the serial monitor the detected object (none, ruby, sapphire etc.), maybe this could be the issue?

Schematic:

Code;

/**
 * "Crown Jewels" Escape Room Puzzle, (c) 2023 Playful Technology
 * Object detection using multiple TCS34725 colour sensors
 * via a TCA9548A I2C multiplexer
 */

// DEFINES
#define ARRAY_SIZE(x) ((sizeof x) / (sizeof *x))

// INCLUDES
// Built-in Arduino library for addressing I2C devices 
#include <Wire.h>
// For addressing PL9823 progammable RGB LEDs. See http://fastled.io/
#include <FastLED.h>
// For interfacing with TCS34725 colour sensor. See https://github.com/playfultechnology/TCS34725
#include "TCS34725.h"

// STRUCTS AND ENUMS
// Enumerate each of the possible objects that we want to detect
enum Object {None, Ruby, Sapphire};
// Define a struct to record colour data about each object: 
// - "input" RGB and lux component values as recorded by the sensor, 
// - "output" RGB values that should be sent to the LED strip
struct Colour {
  TCS34725::Color inRGB; // RGB values as detected by TCS34725 
  float lux; // Input lux as detected by TCS34725
  CRGB outRGB; // RGB values to be emitted by PL9823 LEDs
};

// CONSTANTS
// Array to associate each object with its appropriate colour values
// The .inRGB input values were recorded by holding each item up to the sensor and averaging
// the values printed in the serial monitor
const Colour colours[] = {
  [None] = { .inRGB={14,19,14}, .lux=550, .outRGB={255,255,255}},
  [Ruby] = { .inRGB={141,1,2}, .lux=55, .outRGB={255,0,0} },
  [Sapphire] = { .inRGB={1,24,44}, .lux=140, .outRGB={0,0,255}}
};
// Address of TCA9548A multiplexer set by setting A0-A2 lines HIGH/LOW
// LLL=0x70 (default), HLL=0x71, LHL=0x72, HHL=0x73, LLH=0x74, HLH=0x75, LHH=0x76, HHH=0x77
const byte multiplexAddress = 0x70;
const byte numSensors = 1;
const byte ledDataPin = 15; // GPIO pin connected to DataIn of first LED
const byte relayPin = 14; // GPIO pin connected to signal line of relay module
// The objects that should be placed in front of each sensor to solve the puzzle  
const Object targetObjects[numSensors] = { Ruby};
// Defines how similar detected colour must be to target colour to be matched
const int threshold = 500;

// GLOBALS
// Initialise an array of TCS sensor objects
TCS34725 tcs[numSensors] = {TCS34725()};
// An array to record the detected colours from each sensor
Object detectedObjects[numSensors];
// Define the array of LED RGB values - one per sensor
CRGB leds[numSensors];

// FUNCTIONS
// Select the appropriate channel from the I2C multiplexer
void selectI2CBus(uint8_t channel){
    Wire.beginTransmission(multiplexAddress);
    Wire.write(1 << channel);
    Wire.endTransmission();
}

// Test the similarity between two colours by the difference in their R,G,B, and Lux components
uint32_t getColourDistance(TCS34725::Color Col1, float lux, Colour Col2) {
  return (abs(Col1.r-Col2.inRGB.r) + abs(Col1.g-Col2.inRGB.g) + abs(Col1.b-Col2.inRGB.b) + abs(Col2.lux-lux));
}

void setup(void) {
  // Serial interface used for calibration and debugging
  Serial.begin(115200);
  Serial.println(__FILE__ __DATE__);

  // Start the I2C interface
  Wire.begin();

  // Configure relay to maglock
  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, HIGH);

  // Initialise the array of colour sensors  
  for(int i = 0; i < numSensors; i++) {
    Serial.print(F("Initialising sensor #"));
    Serial.print(i);
    // Set the multiplexer to the appropriate channel
    selectI2CBus(i);
    // Configure sensor
    if (tcs[i].attach(Wire)) {
      tcs[i].integrationTime(500); // ms
      tcs[i].gain(TCS34725::Gain::X01);
      Serial.println(F(" OK!"));
    }
    else {
      Serial.println(F(" Failed to initialise TCS34725"));
    }
    delay(100);
  }

  // Initialise the LEDs
  FastLED.addLeds<PL9823, ledDataPin, RGB>(leds, numSensors).setCorrection(TypicalLEDStrip);
}

void loop(void) {

  // Loop over every sensor to see if a new object has been detected
  bool hasChanged = false;
  for(int i=0; i<numSensors; i++) {
    // Select the appropriate channel on the I2C multiplexer
    selectI2CBus(i);
    // If there is data available to read
    if (tcs[i].available()) {
      // Retrieve the colour and lux values detected by the sensor
      TCS34725::Color colour = tcs[i].color();
      float lux = tcs[i].lux();
      
      // DEBUG/CALIBRATION Print sensor values on the serial monitor
      char buffer[50];
      snprintf(buffer, 50, "Sensor #%d, %.f, %.f, %.f, %.f", i, colour.r, colour.g, colour.b, tcs[i].lux());
      Serial.println(buffer);

      // What was the last known object detected by this sensor?
      Object previousDetectedObject = detectedObjects[i];

      // Compare sensor readings to known colours
      uint32_t currentMinDelta = threshold;
      for(int j=0; j<ARRAY_SIZE(colours); j++){
        // Calculate the difference between the detected colour and the correct target colour
        uint32_t delta = getColourDistance(colour, lux, colours[j]);
        // If this is more similar than the previous best match
        if(delta < currentMinDelta) {
          // Update the best score
          currentMinDelta = delta;
          // Update the array of detected objects
          detectedObjects[i] = (Object)j;
          delay(100);
        }
      }

      // If the detected object is different to the one previously known
      if(detectedObjects[i] != previousDetectedObject){
        hasChanged = true;
        Serial.println("Change detected");
      }
    }
  }

  // If the colour detected by at least one sensor has changed 
  if(hasChanged){
    // Check to see if puzzle is solved
    bool allCorrect = true;
    for(int i=0; i<numSensors; i++) {
      // Debug - print an array of the objects detected by each sensor
      Serial.print(detectedObjects[i]);
      if(i<numSensors-1) { 
        Serial.print(","); 
      }
      else {
        Serial.println("");
      }

      // Set corresponding LED colour for each sensor
      leds[i] = colours[detectedObjects[i]].outRGB;

      // If any sensor detects an object different from that in the targetObjects array, the puzzle is not solved
      if(detectedObjects[i] != targetObjects[i]) {
        allCorrect = false;
      }
    }
    // If we have made it this far and allCorrect is still true, release the maglock
    if(allCorrect) { digitalWrite(relayPin, LOW);
                    Serial.println ("correct"); }
    else { digitalWrite(relayPin, HIGH);
     }

    // Update the LEDs
    FastLED.show();
  }
  delay(500);
  Serial.println("");
}

The PL9823 uses 5V. The ESP32 uses 3v3.

Thanks for your help, if you look at the red wire in the schematic, its connected to 5v which I have tested with my probes... the logic from the pins are 3.3v right? I did some research that said the minimum voltage for a high signal needs to be 0.7v for the logic

However, there is something in what you said as i connected it to my benchtop power supply and the colours were more consistent (not perfect however). Maybe the 5v pin on the esp is inconsistent. Im not sure

I know theyre not the same but ive used neopixels in the past ive always used a 330ohm resistor on the data line and a filter capacitor over the 5v and gnd, ill see if that makes a difference and report back

Maybe I'm misunderstanding something, but, I'm getting 5v between Vin and gnd

Simple google found this post

I've found some people have a better time if they provide 5.5v to the LEDs from a discrete power supply with a ground connection to the esp32

Hi, @milklizard88
Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.

That way we can see what pins of the ESP32 you have connected to what.

Your "diagram" has this vital information missing.

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:
PS. Please no cut and paste images for a circuit diag.