Color Sensor

Hardware Setup

For this guide, we will be programming a REV Color Sensor V3. This sensor plugs into any of the I2C ports of the REV Expansion Hub, which are labeled 0 to 3. When configuring the device on the phone, select “I2C Bus 0/1/2/3”, click “Add” on the top to add the new device to that I2C port, and finally select the device type as “REV Color/Range Sensor” and give it a meaningful name. In this tutorial, we will name it “colorSensor”. If you are using Java, this is starting hardware configuration code you will need. Replace “MyOpNodeName” with your OpMode’s name:

import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
import com.qualcomm.robotcore.hardware.ColorSensor;
import org.firstinspires.ftc.robotcore.external.JavaUtil;
import android.graphics.Color;

@TeleOp(name="MyOpNodeName")
public class MyOpNodeName extends LinearOpMode {
    ColorSensor colorSensor;
    @Override
    public void runOpMode() {
        // Put initialization blocks here.
        colorSensor = hardwareMap.colorSensor.get("colorSensor");
        waitForStart();
        // Put run blocks here.
        while(opModeIsActive()) {
            //Loop code will go here
        }
    }
}

Concept

The REV Color Sensor V3 senses color by detecting the light that reflects off of a nearby object. All colors are made up of three different primary colors (channels): red, green, and blue; this is known as RGB. The color sensor can sense how much of each of these color channels composes an object’s color. It then returns these values as numbers between 0 and 255. Below is an interactive widget to demonstrate how red, green, and blue color channels make up colors. Move the channel sliders to see the resulting color (in the center) change. Try to see if you can make yellow.

These channels can then be converted to numbers that represent the hue, saturation, and value (HSV) of the color. Hue represents what color it actually is (red, yellow, purple, etc) on a spectrum (similar to a rainbow) and ranges from 0 to 360, saturation represents the strength of the color and ranges from 0.0 to 1.0, and value represents the shade of the color and also ranges from 0.0 to 1.0.

Reading Colors Through Code

Let’s write some code that displays the hue of the color seen onto the phone. In our loop, we want to create a variable (let’s call it “sensedColor”) that stores information about the color that the sensor sees. We can create this variable with a function “Color.rgbToColor” that takes the red, green, and blue values from the sensor and turns it into a color variable.

int sensedColor = Color.rgb(colorSensor.red(), colorSensor.green(), colorSensor.blue());
If you are using Blocks, the color sensor blocks are under Sensors -> REV Color/Range Sensor. The Color.rgbToColor block is under Utilities.

Now that we have this variable, we can pull the HSV information from it. Let’s pull the hue data (recall that this is a whole number between 0 and 255 representing what the color is), store it in a variable (let’s call it “sensedHue”), and display it on the Driver Station through telemetry. Like when we converted the RGB values to the color variable, we can make use of a function of the “Color” utility called “Color.colorToHue”.

int sensedColor = Color.rgb(colorSensor.red(), 
   colorSensor.green(),
   colorSensor.blue());
float sensedHue = JavaUtil.colorToHue(sensedColor);
telemetry.addData("Sensed Hue", sensedHue);
telemetry.update();

If you are using Blocks, the Telemetry blocks are under Utilities.

When I ran this code and placed a yellow object in front of my sensor (don’t place the object too close, or the sensor will not see it) and the “Sensed Hue” number displayed on my Driver Station was about between 50 and 70. To know when the sensor sees yellow, let’s create a boolean (true or false) variable – we’ll call it “yellowIsSensed” – that equals true when the hue value is between 50 and 70. In other words, the hue value must be greater than or equal to 50 and less than or equal to 70. Let’s add this variable to our loop code and display it on the Driver Station.

int sensedColor = Color.rgb(colorSensor.red(), 
   colorSensor.green(),
   colorSensor.blue());
float sensedHue = JavaUtil.colorToHue(sensedColor);
boolean yellowIsSensed = sensedHue >= 50 && sensedHue <= 70;
telemetry.addData("Sensed Hue", sensedHue);
telemetry.addData("Yellow Is Sensed", yellowIsSensed);
telemetry.update();

If you run this code, the value “Yellow Is Sensed” on the Driver Station should change from “false” to “true” when it sees a yellow object! You can expand this code for a lot of different uses in the game. For example, if the robot sees a yellow stone (meaning “yellowIsSensed” equals true), you can have the robot’s claw automatically grab the stone. You could also figure out the hue range for other colors (such as red and blue) and have the robot stop moving when it goes over the red or blue colored line on the field.

The Full Code

import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
import com.qualcomm.robotcore.hardware.ColorSensor;
import org.firstinspires.ftc.robotcore.external.JavaUtil;
import android.graphics.Color;

@TeleOp(name="MyOpNodeName")
public class MyOpNodeName extends LinearOpMode {
  ColorSensor colorSensor;

  @Override
  public void runOpMode() {
    // Put initialization blocks here.
    colorSensor = hardwareMap.colorSensor.get("colorSensor");
    waitForStart();
    if (opModeIsActive()) {
      // Put run blocks here.
      while (opModeIsActive()) {
        // Put loop blocks here.
        int sensedColor = Color.rgb(colorSensor.red(),
          colorSensor.green(),
          colorSensor.blue());
        float sensedHue = JavaUtil.colorToHue(sensedColor);
        boolean yellowIsSensed = sensedHue >= 50 && sensedHue <= 70;
        telemetry.addData("Sensed Hue", sensedHue);
        telemetry.addData("Yellow Is Sensed", yellowIsSensed);
        telemetry.update();
      }
    }
  }
}