Wednesday, June 25, 2025

TCS34725 Color Sensing Cube with Arduino

-----

Whatever color the TCS34725 sensor "sees" is reproduced on the orb on top of the cube.   The switch in front is hardwired to the LED light on the front of the sensor because we found the LED annoying and most of the times unnecessary.

-----

Bill of Materials....

     TCS34725

     The orb is a plastic cover from a non functioning LED light bulb: 

     An old Arduino Nano: 
    A switch and a 3D Printed Box:  
-----

Wire per the comments in the Arduino sketch below and you should get this:


-----

// Read Color Sensor.  Mimic color on RGB LED sees
// https://www.whiskeytangohotel.com/
// JUNE 2026

// Arduino Nano but, must selected under Tools → Processor:
// ATmega328P (Old Bootloader) or suffer the avrdude error.

#include <Wire.h>
#include "Adafruit_TCS34725.h"

// TCS34725 SDA pin should be connected to A4
// TCS34725 SCL pin should be connected to A5
// TCS34725 GND to GND
// TCS34725 3.3V to 5V (Vin is No Connect)
// TCS34725 LED goes to hardwired switch  

// Define pins for RGB LED
const int RED_PIN = 10;
const int GREEN_PIN = 9;
const int BLUE_PIN = 11;

// Define digital pin for TCS34725 LED control
const int SENSOR_LED_PIN = 6;  // Not used, this LED is controlled with a hardwired switch

// Initialize the sensor
Adafruit_TCS34725 tcs = Adafruit_TCS34725(
  TCS34725_INTEGRATIONTIME_50MS,
  TCS34725_GAIN_4X
);

void setup() {
  Serial.begin(9600);  // We use the serial monitor for debug
  
  // RGB LED pins
  pinMode(RED_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BLUE_PIN, OUTPUT);

  // Sensor LED control pin
  pinMode(SENSOR_LED_PIN, OUTPUT);
  digitalWrite(SENSOR_LED_PIN, LOW); // turn off sensor LED initially

  if (tcs.begin()) {
    Serial.println("TCS34725 sensor found");
    // Self-test only if sensor found: cycle RGB LED through R, G, B 
    for (int i = 7; i > 0; i--) {
      // Red
      Serial.println("RED Self Test");
      analogWrite(RED_PIN, 255);
      analogWrite(GREEN_PIN, 0);
      analogWrite(BLUE_PIN, 0);
      delay(50 * i);

      // Green
      Serial.println("GREEN Self Test");
      analogWrite(RED_PIN, 0);
      analogWrite(GREEN_PIN, 255);
      analogWrite(BLUE_PIN, 0);
      delay(50 * i);

      // Blue
      Serial.println("BLUE Self Test");
      analogWrite(RED_PIN, 0);
      analogWrite(GREEN_PIN, 0);
      analogWrite(BLUE_PIN, 255);
      delay(50 * i);  
    }  
  } else {
    Serial.println("No TCS34725 sensor found ... check wiring?");
    // RED LED to show error
    analogWrite(RED_PIN, 155);
    analogWrite(GREEN_PIN, 0);
    analogWrite(BLUE_PIN, 0);
    while (1);
  }
}

void loop() {
  //Flash the sensor's LED before reading (optional)
  //digitalWrite(SENSOR_LED_PIN, HIGH);
  //delay(100);

  // Read raw data from sensor
  uint16_t r, g, b, c;
  tcs.getRawData(&r, &g, &b, &c);

  // Turn off sensor LED after reading
  //digitalWrite(SENSOR_LED_PIN, LOW);

  // Scale colors so that the highest is 255, others proportionally
  uint16_t maxRaw = max(max(r, g), b);
  if (maxRaw == 0) maxRaw = 1; // avoid divide by zero

  int redVal   = (uint32_t)r * 255 / maxRaw;
  int greenVal = (uint32_t)g * 255 / maxRaw;
  int blueVal  = (uint32_t)b * 255 / maxRaw;

  // Constrain to ensure valid PWM range
  redVal   = constrain(redVal, 0, 255);
  greenVal = constrain(greenVal, 0, 255);
  blueVal  = constrain(blueVal, 0, 255);

  // Output to RGB LED
  analogWrite(RED_PIN,   gammaCorrect(redVal));
  analogWrite(GREEN_PIN, gammaCorrect(greenVal));
  analogWrite(BLUE_PIN,  gammaCorrect(blueVal));

  // Debug print
  Serial.print("Raw R: "); Serial.print(r);
  Serial.print(" G: "); Serial.print(g);
  Serial.print(" B: "); Serial.print(b);
  Serial.print(" -> LED R: "); Serial.print(redVal);
  Serial.print(" G: "); Serial.print(greenVal);
  Serial.print(" B: "); Serial.println(blueVal);

  delay(200); // wait before next read
}

int gammaCorrect(int val) {   // makes it look "better" we think?
  float gamma = 2.2;
  return pow(val / 255.0, gamma) * 255.0;
}

-----