Shayne WierbowskiFebruary 15, 2015

Dr. BiCMPS 358 – Real-Time Systems

EV3 Color Sensor

Hardware

The EV3 Color Sensor contains two main pieces of hardware; 1) the color sensing photo-resistor and 2) an LED floodlight. The color sensor is capable of measuring either the overall ambient light or specifically the reflected red light and can identify 8 color types (including NONE). The LED floodlight can be turned on or off and specific colors of the LED can be controlled independently. A plastic wall is included between the LED floodlight and the color sensor to prevent noise from the floodlight. A depiction of the sensor is provided below.

Additionally, when using the Color Sensor hardware, it is generally important to keep the sensor as close to the object that is being read as possible. The sensor takes an average of the entire field of view that it takes in so for the most precise results it will be desirable to keep this field of view minimized. There may be specific cases where a distant reading is desirable. For example if one wanted to design a EV3 program to identify an approaching black line before encountering it, it may be desirable to take a wider field of view; as the bot transitions from a white surface, towards the black line, and eventually on the black line, the readings would range from high (white only), to middle (white and black averaged), and finally low (black only). Additionally, when reading ambient light, the precise placement of the sensor is less important.

Software

Not entirely sure what to include here. Both the photo-resistor color sensor and LED floodlight hardware components have some specific software to interface with the hardware. For example, the LED floodlight must be able to control which LED colors are on and off at what times. The color sensor must control taking samples and performs some calibration to convert from a raw reading to a normalized reading on a 0-1 scale.

API

The Color Sensor is included in the LeJOS API as an extension of the UARTSensor and is constructed with a Port as its only argument. As such, the sensor makes use of the typical sensor methods used by any other sensor; most notably fetchSample, sampleSize, getCurrentMode, setCurrentMode, and some others[1]. It should be noted that for all modes except for Color ID mode, data must be read using the fetchSample(float[] sample, int offset) method. The new sample data will be placed into the given array starting at offset. Each sample should be a single value normalized to a 0-1 range. In the case of the RGB mode, three values are included for each the red, green, and blue, readings. To verify the size of each sample, the sampleSize() method may be used. For Color ID mode, the sample can be read using the getColorID() method or the fetchSample() method which will return an int representing the color detected.

The usage of the API specific to the Color Sensor[2] itself includes several additional methods for changing modes and monitoring the floodlight usage. Modes can be set using the getAmbientMode, getColorIDMode, getRedMode, and getRGBMode methods. Though it may be possible to pass these methods into the setCurrentMode(s) method in order to change the mode, from a brief sample test attempting to do this produced an error (incorrect parameter type ). Alternatively, you can use setCurrentMode with either the int or String representations of the four modes; 0, “ColorID”, 1, “Red”, 2, “RGB”, 3, “Ambient”. As a final alternative, you can create a SampleProvider object and set it equal to the output of any of the getXMode methods. See an example here (not tested).[3]The status of the floodlight can be checked with the Boolean method isFloodlightOn. The floodlight itself can be toggled on or off using setFloodlight which takes either a Boolean or a Color enumeration constant. A list of these constants is available[4], but from a brief trial, it appears the only valid options are NONE, WHITE, RED, and BLUE.

Based on the fields listed in the API, it also appears that it should be possible to access both the raw color data and potentially a map of the readings coming in from different parts of the sensor, but I have been unable to verify this. Some of the blogs regarding the color sensor seem to be uncertain as to exactly how the value from the color sensor should be interpreted. Some are unsure whether or not the readings are calibrated automatically. Based on my tests I can verify that all of the samples for the Red, RGB, or Ambient modes are returned as a float between 0.0 and 1.0. If raw readings can be obtained they would range from 0-1023. Some users have also stated that the sensor has poor recognition of blue compared to red and green in RGB mode and have claimed to have inconsistencies in reading from the same source among different sensors. As another concern, I have not been able to reliably interpret the results from ColorID mode. It may be the case that I am not looking at the correct reference sheet for the int to color conversion, or that I am not interoperating their enumeration of the color correctly.

Calibration

As I mentioned somewhat towards the end of the API section, the exact interpretation of the readings from the Color Sensor varies. Theoretically, the sensors have been calibrated already during production. Reports from other users have suggested that the best form of “calibration” is simply to play around with different sample input to get a feel for the values you get for each situation. The code should be written based on what values the sensor detects experimentally. For example, if designing a program to distinguish between a white and black surface, one would want to take samples readings over the various surfaces to be used and use these as a guideline. Others have shown that in Red Mode, a black line will give a reading of about 15-20 and a white line will give a reading of about 60. Note these numbers are using a 0-100 scale which may be specific to when the sensor is used separate from the LeJOS API. From my test, the ambient light in the lab gave a value of about 0.25, which drastically decreased upon covering the sensor, and which rose to about 0.6 or higher upon shining a flashlight on it. In the Red color mode, the desk tables gave readings ranging between 0.35 and 0.6 depending on how close the sensor was to the table and significantly lower values (~0.1) on the black keyboard. I would recommend obtaining some experimental values prior to writing any value specific code. It may alternatively be possible to include a calibration phase in the beginning of code execution in which you feed it several samples (eg. for high and low light levels) which become the guideline for the rest of the code.

Modes and Filters

There are four modes associated with the Color Sensor; Color ID, Red, RGB, and Ambient. The Color ID mode identifies the sample as one of 8 possible colors; None, Black, Blue, Green, Yellow, Red, White, or Brown. The sample color is represented as an int and is accessed using the getColorID() method. The colors that can be identified are presented below. Note, the results returned from an experimental trial do not seem to support this numbering scheme. Although that may in part be because of my selection of color samples (Lego pieces which were perhaps more reflective than they should have been), some of the values I was seeing do not even fit into the expected range; I was typically seeing -1, 2, 3, 6, 7, 13.

For the Red mode, the red LED is turned on and the intensity of red light reflected back from a surface is measured. The RGB mode is similar to the Red mode except that a white light is emitted and values are recorded for the intensity of each the red, green, and blue light reflected back from a surface. The RGB mode is also the least reliable and least stable of the modes provided. The Ambient mode simply measures the light intensity from the environment while the LED is off. I am not aware of any specific filters that can be used in conjunction with the Color Sensor.

Sample Code

Below is a samples code that runs through the creation of a EV3ColorSensor, prints out each the int and String representations of each mode, takes 10 samples separated by one second increments for each mode, and runs through a cycle of the available LED floodlight options.

packageedu.scranton.wierbowski;

importjava.util.ArrayList;

importlejos.hardware.lcd.LCD;

importlejos.hardware.port.SensorPort;

import lejos.hardware.sensor.EV3ColorSensor;

importlejos.robotics.Color;

public class Sensor_Test

{

public static void main(String[] args) throws InterruptedException

{

LCD.drawString("Color Sensor Demo", 0, 0);

EV3ColorSensor s = new EV3ColorSensor(SensorPort.S1);

ArrayList<String> a = s.getAvailableModes();

System.out.println("Available Modes for EV3 Color Sensor Are...\n");

for(inti = 0; ia.size(); i ++)

{

s.setCurrentMode(a.get(i));

System.out.println(s.getCurrentMode() + " : " + a.get(i));

}

System.out.println();

float[] sample = new float[3];

System.out.println("TestiongColorID Mode");

s.setCurrentMode("ColorID");

s.setFloodlight(true);

for(inti = 0; i < 10; i ++)

{

s.fetchSample(sample, 0);

System.out.println(sample[0]);

Thread.sleep(1000);

}

System.out.println("Testiong Red Mode");

s.setCurrentMode("Red");

for(inti = 0; i < 10; i ++)

{

s.fetchSample(sample, 0);

System.out.println(sample[0]);

Thread.sleep(1000);

}

System.out.println("Testiong RGB Mode");

s.setCurrentMode("RGB");

for(inti = 0; i < 10; i ++)

{

s.fetchSample(sample, 0);

System.out.println(sample[0] + ", " + sample[1] + ", " + sample[2]);

Thread.sleep(1000);

}

System.out.println("Testiong Ambient Mode");

s.setCurrentMode("Ambient");

for(inti = 0; i < 10; i ++)

{

s.fetchSample(sample, 0);

System.out.println(sample[0]);

Thread.sleep(1000);

}

System.out.println("Testing Floodlight");

s.setFloodlight(false);

System.out.println("NONE");

s.setFloodlight(Color.NONE);

System.out.println("BLUE");

s.setFloodlight(Color.BLUE);

Thread.sleep(1000);

System.out.println("RED");

s.setFloodlight(Color.RED);

Thread.sleep(1000);

System.out.println("WHITE");

s.setFloodlight(Color.WHITE);

Thread.sleep(1000);

System.out.println("NONE");

s.setFloodlight(Color.NONE);

System.out.println("BLUE");

s.setFloodlight(Color.BLUE);

Thread.sleep(1000);

System.out.println("RED");

s.setFloodlight(Color.RED);

Thread.sleep(1000);

System.out.println("WHITE");

s.setFloodlight(Color.WHITE);

Thread.sleep(1000);

}

}

[1]UARTSensor API page,

[2] Color Sensor API page,

[3]StackOverflowColorSensor with a SampleProvider,

[4] Color class API page,