{"id":2862,"date":"2020-06-20T16:30:22","date_gmt":"2020-06-20T23:30:22","guid":{"rendered":"http:\/\/firstinmichigan.us\/FTC\/?page_id=2862"},"modified":"2022-10-18T06:33:12","modified_gmt":"2022-10-18T13:33:12","slug":"color-sensor","status":"publish","type":"page","link":"https:\/\/firstinmichigan.us\/FTC\/color-sensor\/","title":{"rendered":"Color Sensor"},"content":{"rendered":"\n<script src=\"https:\/\/cdn.jsdelivr.net\/gh\/google\/code-prettify@master\/loader\/run_prettify.js\"><\/script>\n<script src=\"\/FTC\/ftc-programming-resources-assets\/js\/comps.js?v=1\"><\/script>\n<script src=\"\/FTC\/ftc-programming-resources-assets\/js\/color-sensor.js?v=3\"><\/script>\n<link href=\"https:\/\/fonts.googleapis.com\/icon?family=Material+Icons\" rel=\"stylesheet\">\n<link rel=\"stylesheet\" href=\"\/FTC\/ftc-programming-resources-assets\/css\/style.css\">\n\n\n<h2>Hardware Setup<\/h2>\n<p>For this guide, we will be programming a <a href=\"http:\/\/www.revrobotics.com\/rev-31-1557\/\">REV Color Sensor V3<\/a>. 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 &#8220;I2C Bus 0\/1\/2\/3&#8221;, click &#8220;Add&#8221; on the top to add the new device to that I2C port, and finally select the device type as &#8220;REV Color\/Range Sensor&#8221; and give it a meaningful name. In this tutorial, we will name it &#8220;colorSensor&#8221;. If you are using <strong>Java<\/strong>, this is starting hardware configuration code you will need. Replace &#8220;MyOpNodeName&#8221; with your OpMode&#8217;s name:<\/p>\n\n\n<pre class=\"prettyprint\">import com.qualcomm.robotcore.eventloop.opmode.TeleOp;\nimport com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;\nimport com.qualcomm.robotcore.hardware.ColorSensor;\nimport org.firstinspires.ftc.robotcore.external.JavaUtil;\nimport android.graphics.Color;\n\n@TeleOp(name=\"MyOpNodeName\")\npublic class MyOpNodeName extends LinearOpMode {\n    ColorSensor colorSensor;\n    @Override\n    public void runOpMode() {\n        \/\/ Put initialization blocks here.\n        colorSensor = hardwareMap.colorSensor.get(\"colorSensor\");\n        waitForStart();\n        \/\/ Put run blocks here.\n        while(opModeIsActive()) {\n            \/\/Loop code will go here\n        }\n    }\n}<\/pre>\n\n\n<h2>Concept<\/h2>\n<p>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): <strong>red<\/strong>, <strong>green<\/strong>, and <strong>blue<\/strong>; this is known as <strong>RGB<\/strong>. The color sensor can sense how much of each of these color channels composes an object&#8217;s color. It then returns these values as numbers between <strong>0<\/strong> and <strong>255<\/strong>. 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.<\/p>\n\n\n<canvas id=\"nkCanvas\" width=\"325\" height=\"325\"><\/canvas>\n<div class=\"nkCenter\"><input id=\"red\" class=\"nkSlider\" max=\"255\" min=\"0\" type=\"range\" value=\"255\"><label style=\"padding-left: 10px;\" for=\"red\">Red<\/label><\/div>\n<div class=\"nkCenter\"><input id=\"green\" class=\"nkSlider\" max=\"255\" min=\"0\" type=\"range\" value=\"255\"><label style=\"padding-left: 10px;\" for=\"green\">Green<\/label><\/div>\n<div class=\"nkCenter\"><input id=\"blue\" class=\"nkSlider\" max=\"255\" min=\"0\" type=\"range\" value=\"255\"><label style=\"padding-left: 10px;\" for=\"blue\">Blue<\/label><\/div>\n\n\n<p>These channels can then be converted to numbers that represent the&nbsp;<b>hue<\/b>, <b>saturation<\/b>, and <b>value<\/b> (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 <b>0 to 360<\/b>, saturation represents the strength of the color and ranges from <b>0.0 to 1.0<\/b>, and value represents the shade of the color and also ranges from <b>0.0 to 1.0<\/b>.<\/p>\n<h2>Reading Colors Through Code<\/h2>\n<p>Let&#8217;s write some code that displays the <b>hue<\/b> of the color seen onto the phone. In our <b>loop<\/b>, we want to create a variable (let&#8217;s call it &#8220;sensedColor&#8221;) that stores information about the color that the sensor sees. We can create this variable with a function &#8220;Color.rgbToColor&#8221; that takes the red, green, and blue values from the sensor and turns it into a color variable.<\/p>\n\n\n<div class=\"nk-comp\" data-nk-img=\"\/FTC\/wp-content\/uploads\/2019\/10\/color-sensor1.png\">int sensedColor = Color.rgb(colorSensor.red(),\n   colorSensor.green(),\n   colorSensor.blue());<\/div>\n<div class=\"nk-text-blocks\"><b>If you are using Blocks<\/b>, the color sensor blocks are under <b>Sensors -&gt; REV Color\/Range Sensor<\/b>. The Color.rgbToColor block is under <b>Utilities<\/b>.<\/div>\n\n\n<p>Now that we have this variable, we can pull the <b>HSV<\/b> information from it. Let&#8217;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&#8217;s call it &#8220;sensedHue&#8221;), 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 &#8220;Color&#8221; utility called &#8220;Color.colorToHue&#8221;.<\/p>\n\n\n<div class=\"nk-comp\" data-nk-img=\"\/FTC\/wp-content\/uploads\/2019\/11\/color-sensor2.png\">\n<pre>int sensedColor = Color.rgb(colorSensor.red(), \n   colorSensor.green(),\n   colorSensor.blue());\nfloat sensedHue = JavaUtil.colorToHue(sensedColor);\ntelemetry.addData(\"Sensed Hue\", sensedHue);\ntelemetry.update();<\/pre>\n<\/div>\n<p><span class=\"nk-text-blocks\"><b>If you are using Blocks<\/b>, the Telemetry blocks are under <b>Utilities<\/b>.<\/span><\/p>\n\n\n<p>When I ran this code and placed a <b>yellow<\/b> object in front of my sensor (don&#8217;t place the object too close, or the sensor will not see it) and the &#8220;Sensed Hue&#8221; number displayed on my Driver Station was about <b>between 50 and 70<\/b>. To know when the sensor sees yellow, let&#8217;s create a boolean (true or false) variable &#8211; we&#8217;ll call it &#8220;yellowIsSensed&#8221; &#8211; that equals <b>true<\/b> when the hue value is between 50 and 70. In other words, the hue value must be <b>greater than or equal to 50 and less than or equal to 70<\/b>. Let&#8217;s add this variable to our loop code and display it on the Driver Station.<\/p>\n\n\n<div class=\"nk-comp\" data-nk-img=\"\/FTC\/wp-content\/uploads\/2019\/11\/color-sensor3.png\">\n<pre>int sensedColor = Color.rgb(colorSensor.red(), \n   colorSensor.green(),\n   colorSensor.blue());\nfloat sensedHue = JavaUtil.colorToHue(sensedColor);\nboolean yellowIsSensed = sensedHue &gt;= 50 &amp;&amp; sensedHue &lt;= 70;\ntelemetry.addData(\"Sensed Hue\", sensedHue);\ntelemetry.addData(\"Yellow Is Sensed\", yellowIsSensed);\ntelemetry.update();<\/pre>\n<\/div>\n\n\n<p>If you run this code, the value &#8220;Yellow Is Sensed&#8221; on the Driver Station should change from &#8220;false&#8221; to &#8220;true&#8221; 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 &#8220;yellowIsSensed&#8221; equals true), you can have the robot&#8217;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.<\/p>\n<h2>The Full Code<\/h2>\n\n\n<div class=\"nk-comp\" data-nk-img=\"\/FTC\/wp-content\/uploads\/2019\/11\/color-sensor4.png\">\n<pre>import com.qualcomm.robotcore.eventloop.opmode.TeleOp;\nimport com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;\nimport com.qualcomm.robotcore.hardware.ColorSensor;\nimport org.firstinspires.ftc.robotcore.external.JavaUtil;\nimport android.graphics.Color;\n\n@TeleOp(name=\"MyOpNodeName\")\npublic class MyOpNodeName extends LinearOpMode {\n  ColorSensor colorSensor;\n\n  @Override\n  public void runOpMode() {\n    \/\/ Put initialization blocks here.\n    colorSensor = hardwareMap.colorSensor.get(\"colorSensor\");\n    waitForStart();\n    if (opModeIsActive()) {\n      \/\/ Put run blocks here.\n      while (opModeIsActive()) {\n        \/\/ Put loop blocks here.\n        int sensedColor = Color.rgb(colorSensor.red(),\n          colorSensor.green(),\n          colorSensor.blue());\n        float sensedHue = JavaUtil.colorToHue(sensedColor);\n        boolean yellowIsSensed = sensedHue >= 50 && sensedHue <= 70;\n        telemetry.addData(\"Sensed Hue\", sensedHue);\n        telemetry.addData(\"Yellow Is Sensed\", yellowIsSensed);\n        telemetry.update();\n      }\n    }\n  }\n}<\/pre>\n<\/div>\n\n\n\n<script>\nnkRunComps();\nnkRunWidgets();\n<\/script>\n","protected":false},"excerpt":{"rendered":"<p>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 &#8220;I2C Bus 0\/1\/2\/3&#8221;, click &#8220;Add&#8221; on the top to add the new device to that I2C port, and finally select the device type as &#8220;REV Color\/Range Sensor&#8221; and give it a meaningful name. In this tutorial, we will name it &#8220;colorSensor&#8221;. If you are using Java, this is starting hardware configuration code you will need. Replace &#8220;MyOpNodeName&#8221; with your OpMode&#8217;s name: import com.qualcomm.robotcore.eventloop.opmode.TeleOp;<a class=\"more-link\" href=\"https:\/\/firstinmichigan.us\/FTC\/color-sensor\/\">Read More &rarr;<\/a><\/p>\n","protected":false},"author":7,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"nf_dc_page":"","footnotes":""},"class_list":["entry","page","publish","author-eschnabel","post-2862"],"_links":{"self":[{"href":"https:\/\/firstinmichigan.us\/FTC\/wp-json\/wp\/v2\/pages\/2862","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/firstinmichigan.us\/FTC\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/firstinmichigan.us\/FTC\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/firstinmichigan.us\/FTC\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/firstinmichigan.us\/FTC\/wp-json\/wp\/v2\/comments?post=2862"}],"version-history":[{"count":19,"href":"https:\/\/firstinmichigan.us\/FTC\/wp-json\/wp\/v2\/pages\/2862\/revisions"}],"predecessor-version":[{"id":2889,"href":"https:\/\/firstinmichigan.us\/FTC\/wp-json\/wp\/v2\/pages\/2862\/revisions\/2889"}],"wp:attachment":[{"href":"https:\/\/firstinmichigan.us\/FTC\/wp-json\/wp\/v2\/media?parent=2862"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}