Need help on adding TCS34725 Color sensor on a line tracking robot

Hey guys! I am new to this forum but was hoping on getting a bit of help/feedback on my code. I am currently working on a project for my robotics course, it is a line tracking robot with a ultrasonic sensor for obstacle detection, IR sensors for line tracking, a RGB LED that changes color depending on the movement the robot is performing, and a TCS34725 Color sensor that will be used to detect red tape on the track and stop as if it were a stop sign. I have gotten all of my other sensors to work well together, but have not had a lot of success with getting the color sensor to work. I connected it the interrupt pin #3 on my Arduino UNO, but it is not responding except for when my hand completely covers the sensor. Was hoping to get some feedback or help with getting the color sensor working. I am pretty confused on how to use this sensor, any help would be greatly appreciated. Here is my code for just the color sensor

// Libraries for Color Sensor
#include <Wire.h>               //library for communicating with L2C device
#include <Adafruit_TCS34725.h>  //library of commands for color sensor

// Instance of Color Sensor and interrupt variables
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_2_4MS, TCS34725_GAIN_4X);
#define interruptPin 3
volatile boolean changeDetected = false; 

void getRawData_noDelay(uint16_t *r, uint16_t *g, uint16_t *b, uint16_t *c)
{
  *c = tcs.read16(TCS34725_CDATAL);
  *r = tcs.read16(TCS34725_RDATAL);
  *g = tcs.read16(TCS34725_GDATAL);
  *b = tcs.read16(TCS34725_BDATAL);
}

void redInterrupt()
{
  changeDetected = true;
}


void setup()
{
    pinMode(interruptPin, INPUT);
    if (tcs.begin()) 
    {
    Serial.println("Found sensor");
    } 
    else 
    {
      Serial.println("No TCS34725 found ... check your connections");
      while (1); // halt!
    }
    attachInterrupt(digitalPinToInterrupt(interruptPin), redInterrupt, FALLING);
    tcs.setInterrupt(false);
    tcs.setIntLimits(1900, 2300);
    tcs.clearInterrupt();
}

void loop() 
{
  // Get Color Sensor Values
 // delay(100);
  uint16_t  r, g, b, c;
  getRawData_noDelay(&r, &g, &b, &c);
  if(changeDetected == true)
  {
    if (r > g || r > b )
    {
      Serial.println("Red Detcted");
      color(255, 255, 255);  // White
      stop(0);
    }
      //goForward(100);
      changeDetected = false;
      tcs.clearInterrupt();
  }
  else
  {
    /** movement functions**/
  }
}

I Can also provide the rest of the code with all of the components as well and pictures of the circuit if need be, just let me know. Thank you!

Always provide the full program.

Did you calibrate "red" at the location of the red tape? Lighting changes color parameters.

So I did calibrate it at the red tape but I was getting some pretty high numbers for some reason, so I switched to a different room with better lighting and got more reasonable numbers. Here is my full code:

/***************************************************************
Project: Autonomous Car 
Function: A car that is able to drive by itself within a track and avoid 
hitting obstacles and stopping for stop signs
****************************************************************/

// Library for the Ultrasonic Sensor
#include <NewPing.h>

// UltraSonic Sensor Pins
#define TRIGGER_PIN 12    
#define ECHO_PIN 13       
#define MAX_DISTANCE 200  // Maximum distance we want to ping for (in centimeters)
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);


// Libraries for Color Sensor
#include <Wire.h>               //library for communicating with L2C device
#include <Adafruit_TCS34725.h>  //library of commands for color sensor

// Instance of Color Sensor and interrupt variables
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_2_4MS, TCS34725_GAIN_1X);
#define interruptPin 3
volatile boolean changeDetected = false;

// RGB Light
int redPin = 10;     
int greenPin = 5;
int bluePin = 6;

// Motor Pins
#define PWM_A_Pin 9
#define Dir_A_Pin 8
#define PWM_B_Pin 11
#define Dir_B_Pin 4

// Directions values
const bool forward = HIGH;
const bool backward = LOW;


const int Speed = 140;  
const int FowardTurnSpeed = 75;
const int backwardTurnSpeed = 75;
const int noSpeed = 0;


// Labels for Track and Off Track
#define black HIGH  // The Ir  sensor will get a high Signal if it is over black
#define white LOW   // The Ir  sensor will get a low Signal if it is over white

// Tracking Sensor Pins
const int rightTrackingPin = 2;  
const int leftTrackingPin = 7;   
// Tracking Sensors
bool leftSensor;
bool rightSensor;

void goForward(int delayTime) 
{
  digitalWrite(Dir_A_Pin, forward);  // makes motor A spin forward
  digitalWrite(Dir_B_Pin, forward);  // makes motor B spin forward
  analogWrite(PWM_A_Pin, Speed);     // makes motor A spin at a given speed
  analogWrite(PWM_B_Pin, Speed);     // makes motor B spin at a given speed
  delay(delayTime);
}
void goBackward(int delayTime)  
{
  Serial.println("Vehicle Moving Backward");
  // Channel A and B spin backwards @ full speed
  digitalWrite(Dir_A_Pin, backward);  // makes motor A spin forward
  digitalWrite(Dir_B_Pin, backward);  // makes motor B spin forward
  analogWrite(PWM_A_Pin, Speed);      // makes motor A spin at a given speed
  analogWrite(PWM_B_Pin, Speed);      // makes motor B spin at a given speed
  delay(delayTime);
}
void stop(int delayTime) 
{
  // Channel A and B spin forward but @ at no speed
  digitalWrite(Dir_A_Pin, forward);  // makes motor A spin forward
  digitalWrite(Dir_B_Pin, forward);  // makes motor B spin forward
  digitalWrite(PWM_A_Pin, noSpeed);  // motor A will not spin with a PWM of 0
  digitalWrite(PWM_B_Pin, noSpeed);  // motor B will not spin with a PWM of 0
  delay(delayTime);
  Serial.println("Vehicle STOPPED");
}
void turnLeft(int delayTime) 
{
  Serial.println("Vehicle turning Left");
  digitalWrite(Dir_A_Pin, backward);          // makes motor A spin backward
  digitalWrite(Dir_B_Pin, forward);           // makes motor B spin forward
  analogWrite(PWM_A_Pin, backwardTurnSpeed);  // motor A will spin at half speed
  analogWrite(PWM_B_Pin, FowardTurnSpeed);    // motor B will spin at half speed
  delay(delayTime);
}
void turnRight(int delayTime)
{
  Serial.println("Vehicle turning Right");
  digitalWrite(Dir_A_Pin, forward);           // makes motor A spin forward
  digitalWrite(Dir_B_Pin, backward);          // makes motor B spin forward
  analogWrite(PWM_A_Pin, FowardTurnSpeed);    // motor A will spin at half speed
  analogWrite(PWM_B_Pin, backwardTurnSpeed);  // motor B will spin backward at half speed
  delay(delayTime);
}
// For RGB light
void color(unsigned char red, unsigned char green, unsigned char blue) 
{
  analogWrite(redPin, red);
  analogWrite(greenPin, green);
  analogWrite(bluePin, blue);
}
void getRawData_noDelay(uint16_t *r, uint16_t *g, uint16_t *b, uint16_t *c)
{
  *c = tcs.read16(TCS34725_CDATAL);
  *r = tcs.read16(TCS34725_RDATAL);
  *g = tcs.read16(TCS34725_GDATAL);
  *b = tcs.read16(TCS34725_BDATAL);
}

void Interrupt()
{
  changeDetected = true;
}


void setup()  // In setup() we will set the pin mode for all of the pins that we made and begin the Serial monitor
{

  // Set up motor pin, pin mode
  pinMode(Dir_A_Pin, OUTPUT);
  pinMode(Dir_B_Pin, OUTPUT);
  pinMode(PWM_A_Pin, OUTPUT);
  pinMode(PWM_B_Pin, OUTPUT);

  // RGB Light
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);

  // Set up for the Track Sensor Pin, pin mode
  pinMode(leftTrackingPin, INPUT);  // Should we use INPUT_PULLUP here, for the tracking Pins?
  pinMode(rightTrackingPin, INPUT);

  // Begin Serial monitor
  Serial.begin(9600);

  // Color Sensor
    pinMode(interruptPin, INPUT);
    if (tcs.begin()) 
    {
    //Serial.println("Found sensor");
    } 
    else 
    {
      Serial.println("No TCS34725 found ... check your connections");
      while (1); // halt!
    }
    attachInterrupt(digitalPinToInterrupt(interruptPin), Interrupt, FALLING);
    //tcs.setInterrupt(true);
    tcs.setIntLimits(170, 111);
   //tcs.clearInterrupt();
}


void loop() 
{
  // Get Color Sensor Values
  delay(100);
  uint16_t  r, g, b, c;
  tcs.getRawData(&r, &g, &b, &c);  
  //getRawData_noDelay(&r, &g, &b, &c);
  // Read values from tracking sensors
  leftSensor = digitalRead(leftTrackingPin);    
  rightSensor = digitalRead(rightTrackingPin);  

  // Ultra Sonic ping
  //delay(100);  //delay 100ms
  unsigned int uS = sonar.ping();  // Send ping, get ping time in microseconds (uS).
  // Convert ping time to distance in cm and print result (0 = outside set distance range)
  int distance = uS / US_ROUNDTRIP_CM;  //  US_ROUNDTRIP_CM is not defined by the code anywhere, must be built in function to convert to cm
  Serial.print(distance);               // Print the distance to the serial monitor
  Serial.println("cm");

  // Print Color Sensor Values
  Serial.print("Red: "); Serial.print(r);
  Serial.print(", Green: "); Serial.print(g);
  Serial.print(", Blue: "); Serial.println(b);
  Serial.print(", Clear: "); Serial.println(c);
  if(changeDetected == true)
  {
    if (r > g || r > b )
    {
      Serial.println("Red Detcted");
      color(0, 255, 255);  // Red for RGB light 
      stop(0);
    }
      tcs.clearInterrupt();
      changeDetected = false;
  }
  else
  {
    if (distance == 0 || distance > 15) // checking for 0 because, if there is nothing for the ultrasonic to bounce sound off of, then it will default to 0
    {
      if (leftSensor == black && rightSensor == black)  // Higher signal = lower light reflected back, meaning a darker surface
      {
        color(255, 0, 255);  // green
        goForward(0);        
        Serial.println();
        Serial.println("Going Forward, both sensors on track");
        Serial.println(leftSensor);
        Serial.println(rightSensor);
      } 
      else if (leftSensor == black && rightSensor == white)  // Error where the car is turning the wrong way, unsure how to fix
      {
        color(0, 225, 255);  // Orange
        turnLeft(0);        
        Serial.println();
        Serial.println("turning Left, one sensor off track");
        Serial.println(leftSensor);
        Serial.println(rightSensor);

      }
      // If the left sensor is off the track, turn right
      else if (leftSensor == white && rightSensor == black) 
      {
        color(255, 255, 0);  // blue
        turnRight(0);        
        Serial.println();
        Serial.println("turning right, one sensor off track");
        Serial.println(leftSensor);
        Serial.println(rightSensor);

      }
      else if (leftSensor == white && rightSensor == white) 
      {
        color(220, 255, 0);  // Indigo
        goBackward(0);     
        Serial.print("Off the track");
        Serial.println(leftSensor);
        Serial.println(rightSensor);
      }
    } 
    else if (distance <= 15)
    {
      Serial.println("Object Detected");
      color(0, 255, 255);  // red
      stop(0);
    }
  }
}


Maybe the very large numbers are caused by an overflow of these 16 bit valies. Try uint32_t and use both room lighting to test.

So my group and I were able to figure it out, we ended up deciding not to use an interrupt. I think I was just over complicating the code. This is our working code:

Project: Autonomous Car 
Function: A car that is able to drive by itself within a track and avoid 
hitting obstacles and stopping for stop signs
****************************************************************/

// Library for the Ultrasonic Sensor
#include <NewPing.h>

// UltraSonic Sensor Pins
#define TRIGGER_PIN 12    
#define ECHO_PIN 13       
#define MAX_DISTANCE 200  // Maximum distance we want to ping for (in centimeters)
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);


// Libraries for Color Sensor
#include <Wire.h>               //library for communicating with L2C device
#include <Adafruit_TCS34725.h>  //library of commands for color sensor
// Instance of Color Sensor and interrupt variables
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);


// RGB Light
int redPin = 10;     // Originall set to 3 but switched to make room for the color sensor 
int greenPin = 5;
int bluePin = 6;

// Motor Pins
#define PWM_A_Pin 9
#define Dir_A_Pin 8
#define PWM_B_Pin 11
#define Dir_B_Pin 4

// Directions values
const bool forward = HIGH;
const bool backward = LOW;

const int Speed = 140;  
const int FowardTurnSpeed = 70;
const int backwardTurnSpeed = 70;
const int noSpeed = 0;


// Labels for Track and Off Track
#define black HIGH  // The Ir  sensor will get a high Signal if it is over black
#define white LOW   // The Ir  sensor will get a low Signal if it is over white

// Tracking Sensor Pins
const int rightTrackingPin = 2;  
const int leftTrackingPin = 7;   
// Tracking Sensors
bool leftSensor;
bool rightSensor;

void goForward(int delayTime)  // goForward controls movement going forward
{
  // channel A and B spin forward @ full speed
  digitalWrite(Dir_A_Pin, forward);  // makes motor A spin forward
  digitalWrite(Dir_B_Pin, forward);  // makes motor B spin forward
  analogWrite(PWM_A_Pin, Speed);     // makes motor A spin at a given speed
  analogWrite(PWM_B_Pin, Speed);     // makes motor B spin at a given speed
  delay(delayTime);
}
void goBackward(int delayTime)  // goForward controls movement going backwards
{
  // Channel A and B spin backwards @ full speed
  digitalWrite(Dir_A_Pin, backward);  // makes motor A spin forward
  digitalWrite(Dir_B_Pin, backward);  // makes motor B spin forward
  analogWrite(PWM_A_Pin, Speed);      // makes motor A spin at a given speed
  analogWrite(PWM_B_Pin, Speed);      // makes motor B spin at a given speed
  delay(delayTime);
}
void stop(int delayTime)  // stop() controls the stopping of the motors
{
  // Channel A and B spin forward but @ at no speed
  digitalWrite(Dir_A_Pin, forward);  // makes motor A spin forward
  digitalWrite(Dir_B_Pin, forward);  // makes motor B spin forward
  digitalWrite(PWM_A_Pin, noSpeed);  // motor A will not spin with a PWM of 0
  digitalWrite(PWM_B_Pin, noSpeed);  // motor B will not spin with a PWM of 0
  delay(delayTime);
  Serial.println("Vehicle STOPPED");
}
void turnLeft(int delayTime)  // turnLeft() is in control of making the motors turn left, by making motor B go faster than motor A
{
  // Print to Serial monitor that the vehcile is turning Left
  digitalWrite(Dir_A_Pin, backward);          // makes motor A spin backward
  digitalWrite(Dir_B_Pin, forward);           // makes motor B spin forward
  analogWrite(PWM_A_Pin, backwardTurnSpeed);  // motor A will spin at half speed
  analogWrite(PWM_B_Pin, FowardTurnSpeed);    // motor B will spin at half speed
  delay(delayTime);
}
void turnRight(int delayTime)  // turnRight() is in control of making the motors turn right, by making motor A go faster than motor B
{
  // Print to Serial monitor that the vehcile is turning Right
  digitalWrite(Dir_A_Pin, forward);           // makes motor A spin forward
  digitalWrite(Dir_B_Pin, backward);          // makes motor B spin forward
  analogWrite(PWM_A_Pin, FowardTurnSpeed);    // motor A will spin at half speed
  analogWrite(PWM_B_Pin, backwardTurnSpeed);  // motor B will spin backward at half speed
  delay(delayTime);
}
// For RGB light
void color(unsigned char red, unsigned char green, unsigned char blue) 
{
  analogWrite(redPin, red);
  analogWrite(greenPin, green);
  analogWrite(bluePin, blue);
}

void setup()  // In setup() we will set the pin mode for all of the pins that we made and begin the Serial monitor
{

  // Set up motor pin, pin mode
  pinMode(Dir_A_Pin, OUTPUT);
  pinMode(Dir_B_Pin, OUTPUT);
  pinMode(PWM_A_Pin, OUTPUT);
  pinMode(PWM_B_Pin, OUTPUT);

  // RGB Light
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);

  // Set up for the Track Sensor Pin, pin mode
  pinMode(leftTrackingPin, INPUT);  // Should we use INPUT_PULLUP here, for the tracking Pins?
  pinMode(rightTrackingPin, INPUT);

  // Begin Serial monitor
  Serial.begin(9600);

  // Color Sensor
    if (tcs.begin()) 
    {
    //Serial.println("Found sensor");
    } 
    else 
    {
      Serial.println("No TCS34725 found ... check your connections");
      while (1); // halt!
    }
}


void loop() 
{
  // Get Color Sensor Values
  delay(100);
  uint16_t  r, g, b, c;
  tcs.getRawData(&r, &g, &b, &c);  
  const uint16_t redThreshold = 210;    // Adjust based on your sensor's values for red
  const uint16_t greenThreshold = 230;  // Adjust for green
  const uint16_t blueThreshold = 290;   // Adjust for blue


  // Read values from tracking sensors
  leftSensor = digitalRead(leftTrackingPin);    
  rightSensor = digitalRead(rightTrackingPin);  

  // Ultra Sonic ping
  unsigned int uS = sonar.ping();  // Send ping, get ping time in microseconds (uS).
  // Convert ping time to distance in cm and print result (0 = outside set distance range)
  int distance = uS / US_ROUNDTRIP_CM;  
  Serial.print(distance);               
  Serial.println("cm");

  // Print Color Sensor Values
  Serial.println("");
  Serial.println("");
  Serial.println("");
  Serial.println("");
  Serial.print("Red: "); Serial.print(r);
  Serial.print(", Green: "); Serial.print(g);
  Serial.print(", Blue: "); Serial.println(b);
  Serial.print(", Clear: "); Serial.println(c);

    if (r >= redThreshold && g < greenThreshold && b < blueThreshold)
    {
      Serial.println("Red Detcted");
      color(0, 255, 255);  // Red
      stop(1000);
      goForward(300); 
    }   
    else
    {
      if (distance == 0 || distance > 15) // checking for 0 because, if there is nothing for the ultrasonic to bounce sound off of, then it will default to 0
      {
        if (leftSensor == black && rightSensor == black)  // Higher signal = lower light reflected back, meaning a darker surface
        {
          color(255, 0, 255);  // green
          goForward(0);        
          Serial.println();
          Serial.println("Going Forward, both sensors on track");
          Serial.print("Left Tracking Sensor: ");Serial.println(leftSensor);
          Serial.print("Right Tracking Sensor: ");Serial.println(rightSensor);
        } 
        else if (leftSensor == black && rightSensor == white)  
        {
          color(0, 0, 0);  // White
          turnLeft(0);        
          Serial.println();
          Serial.println("turning Left, one sensor off track");
          Serial.print("Left Tracking Sensor: ");Serial.println(leftSensor);
          Serial.print("Right Tracking Sensor: ");Serial.println(rightSensor);

        }
        // If the left sensor is off the track, turn right
        else if (leftSensor == white && rightSensor == black) 
        {
          color(255, 255, 0);  // blue
          turnRight(0);        
          Serial.println();
          Serial.println("turning right, one sensor off track");
          Serial.print("Left Tracking Sensor: ");Serial.println(leftSensor);
          Serial.print("Right Tracking Sensor: ");Serial.println(rightSensor);

        }
        else if (leftSensor == white && rightSensor == white) 
        {
          color(220, 255, 0);  // Indigo
          goBackward(0);     
          Serial.print("Off the track");
          Serial.print("Left Tracking Sensor: ");Serial.println(leftSensor);
          Serial.print("Right Tracking Sensor: ");Serial.println(rightSensor);
        }
      } 
      else if (distance <= 15)
      {
        Serial.println("Object Detected");
        color(0, 255, 255);  // red
        stop(0);
      }
  }
}

We just used thresholds for the rgb values and compared them, their was a lot of noise so our numbers fluctuated a lot in the color sensor readings so we made our range pretty big but it could be better tuned. Also in the original build/code that I posed I had extended the color sensor further down closer to the track that we were using, and we increased the gain of the color sensor by 4x, and we were grabbing the raw color values from the color sensor which was giving us really large numbers. We fixed our code and brought the color sensor up higher on our build and we were getting much more reasonable numbers. The car does stop for red tape pretty quickly in this new code, because it just breaks out of the else{} if the color sensor detects red

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.