Adafruit color sensor- weak saturation - HSV?

I’m working on a project where kids can hold a piece of paper up to one of Adafruit’s color sensor breakout boards (triggered to take a reading from an IR sensor) which lights up a frosted orb.

It’s all working well enough but I wish the colors were more saturated. For example a red sheet of paper creates a pink orb, a blue piece of paper a pale blue orb, etc.

I think I need to convert my values to HSV but I’m not having any luck adjusting my own code.

Does anyone know if there’s a way to juice up the saturation in the code? Under a bit of a tight deadline here…I might just have to live with it but this would be way better if I could get the LED colors closer to the paper colors :frowning:

int irSensor=14;                      
int Led=11;                     
int senRead=0;                  
int SenseRate=900; // higer numbers are more sensitive ir sensor 


// Include the libraries:
#include <Wire.h>
#include <Adafruit_TCS34725.h>
#include <FastLED.h>

// Define variables:
float r, g, b;
#define NUM_LEDS 24
#define BRIGHTNESS  150
                                                

// Define connections:
#define DATA_PIN 6

CRGB leds[NUM_LEDS];

// Initialise with specific int time and gain values:
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_154MS, TCS34725_GAIN_4X); //  integreation times can be 2_4MS, 24MS, 50MS, 101MS, 154MS, 700MS -gain can be 1X, 4X, 16X, 60X


void setup()
{  
  
  
  pinMode(irSensor,INPUT);  
  pinMode(Led,OUTPUT);
  digitalWrite(irSensor,HIGH);       
  digitalWrite(Led,HIGH);      
  Serial.begin(9600);     


  // Begin Serial communication:
  Serial.begin(9600);

  // Check if the sensor is wired correctly: 
  if (tcs.begin()) {
    Serial.println("Found sensor");
  } else {
    Serial.println("No TCS34725 found ... check your connections");
    while (1);
  }

  FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
}

void loop()
{

  int val=analogRead(senRead);    
  Serial.println(val);            
  if(val <= SenseRate)               
  {

  digitalWrite(Led,HIGH);       //spotlight 
   delay(500);                  // spotlight time on

   
  // Get calculated RGB values:
  tcs.getRGB(&r, &g, &b);

  // Convert to integers:
  int red = (int)r;
  int green = (int)g;
  int blue = (int)b;

  // Print the data to the Serial Monitor:
  Serial.print(red); Serial.print(" "); Serial.print(green); Serial.print(" "); Serial.println(blue);

  CRGB color = CRGB(red, green, blue);

  // Set all the LEDs to the measured color:
  fill_solid(leds, NUM_LEDS, color);
  FastLED.show();

  digitalWrite(Led,LOW); 
  delay(2000);
}

else if(val > SenseRate)            
  {  
   digitalWrite(Led,LOW);       
   delay(20);  
  }  
 }

RGB LED strips don't show the corresponding color value if you simply set an RGB value. That's because the brightness of the three base color LEDs is not equal, so if you set all three to the same level (let's say 120) they won't have the same brightness level if you look at them. The additional problem is that the seen brightness is in a linear relation to the set value. So if you set the red value to 30 and then to 60 you would expect it to be doubled in brightness but you'll probably observe a brightness about 4-5 times as high. In the upper value region the effect is the other way around, bigger values shows only slight changes in brightness.

You'll find complete books about the difficulty to reproduce a specific color value, especially if you change the color system (as in your case from subtractive to additive colors).

Take a few clear colors, read the value from the sensor and then adjust the LED color until you think it matches the input color. Write down the different value pairs and the try to interpolate the values in between.

A frosted orb reflects room light, which would explain the poor saturation. Try the experiment in the dark.

As for matching colors, the sensor has its own color response to take into account. You might try using the color sensor to read the RGB LED output, and adjust the RGB values to match the output from the color sensor when pointed at the colored paper.

To expand slightly on the pylon's point, the human eye is most sensitive to green (see black curve below) and responds approximately logarithmically to changes in light intensity. An LED driven by 0-255 PWM shows roughly log(255)/log(2) = 8 linear steps in intensity value, as perceived by the eye. A camera half-stop lookup table gives 16 steps: 255, 180, 128, 90, 64, 45, 32, 23, 16, 12, 8, 6, 4, 3, 2, 1, 0.