Hello everyone! My first post here so please let me know if this topic belongs in a different section. My project is as follows. To build a golf ball sorter that is capable of distinguishing 10 different color balls (mostly primary colors). This will be done using 2 analog servos to progressively queue the ball in front of the sensor, and one to rotate and distribute the balls to different hoppers. I am taking the project in bites so I decided to get the color sensor up and returning consistent values using 6 different color balls. I have gone with the standard TCS3200 color sensing module and an Arduino Uno. I was fortunate enough to find the DroneBot video on youtube which was extremely helpful getting things wired up and returning values but I am experiencing some anomalies. They are as follows:
1) While running the 2nd provided script for returning RGB values between 0 and 255 I am getting numbers that exceed 255
2) I also get negative numbers returned when the sensor is removed from the test jig.
ANY help on these issues would be greatly appreciated. My guess, is that the setup I was using was not maintaining the position of the sensor in a totally repeatable manner.
Judging by the level of expertise on here and what I have read in some of the topics, this is likely old hat for many of you here but nonetheless, any help would be greatly appreciated.
Thanks in advance,
-Keith
@spaghetticallahan
It's hard to tell what's wrong from the information you've given us.
However, since the colour values are calculated by using the map function to translate the range from the observed high and low values observed from the first (calibration) sketch Tinto the range 255-0, it seems that the problem is most likely that your calibration results (from sketch 1) are incorrect.
You should probably rerun that sketch and regenerate the max and min values. Errors in the min value may cause calculations exceeding 255 and errors in the max value may cause negative values.
Anything seems possible when you don't know what you're talking about.
@spaghetticallahan Where are the sketches?
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
@robotbuilder Possibly, but is it more likely that Bill made a mistake or the OP? If he copies and pastes the code he is executing, we can check, but as it is now, I assume, as is the case 99% of the time, USER ERROR.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
Thanks for all the replies!
I have included the code I am using below; note it is directly taken from the DroneBot tutorial on the color sensors with the calibration numbers amended to match my own results. Please take a look and let me know if you see any issues. Again, thank you very much for your help
/* RGB Color Sensor Demonstration rgb-color-sensor-demo.ino Read RGB values from Color Sensor Must use calibration values from Color Sensor Calibration Sketch DroneBot Workshop 2020 https://dronebotworkshop.com */ // Define color sensor pins #define S0 4 #define S1 5 #define S2 6 #define S3 7 #define sensorOut 8 // Calibration Values // Get these from Calibration Sketch int redMin = 25; // Red minimum value int redMax = 286; // Red maximum value int greenMin = 26; // Green minimum value int greenMax = 303; // Green maximum value int blueMin = 24; // Blue minimum value int blueMax = 278; // Blue maximum value // Variables for Color Pulse Width Measurements int redPW = 0; int greenPW = 0; int bluePW = 0; // Variables for final Color values int redValue; int greenValue; int blueValue; void setup() { // Set S0 - S3 as outputs pinMode(S0, OUTPUT); pinMode(S1, OUTPUT); pinMode(S2, OUTPUT); pinMode(S3, OUTPUT); // Set Sensor output as input pinMode(sensorOut, INPUT); // Set Frequency scaling to 20% digitalWrite(S0,HIGH); digitalWrite(S1,LOW); // Setup Serial Monitor Serial.begin(9600); } void loop() { // Read Red value redPW = getRedPW(); // Map to value from 0-255 redValue = map(redPW, redMin,redMax,255,0); // Delay to stabilize sensor delay(200); // Read Green value greenPW = getGreenPW(); // Map to value from 0-255 greenValue = map(greenPW, greenMin,greenMax,255,0); // Delay to stabilize sensor delay(200); // Read Blue value bluePW = getBluePW(); // Map to value from 0-255 blueValue = map(bluePW, blueMin,blueMax,255,0); // Delay to stabilize sensor delay(200); // Print output to Serial Monitor Serial.print("Red = "); Serial.print(redValue); Serial.print(" - Green = "); Serial.print(greenValue); Serial.print(" - Blue = "); Serial.println(blueValue); } // Function to read Red Pulse Widths int getRedPW() { // Set sensor to read Red only digitalWrite(S2,LOW); digitalWrite(S3,LOW); // Define integer to represent Pulse Width int PW; // Read the output Pulse Width PW = pulseIn(sensorOut, LOW); // Return the value return PW; } // Function to read Green Pulse Widths int getGreenPW() { // Set sensor to read Green only digitalWrite(S2,HIGH); digitalWrite(S3,HIGH); // Define integer to represent Pulse Width int PW; // Read the output Pulse Width PW = pulseIn(sensorOut, LOW); // Return the value return PW; } // Function to read Blue Pulse Widths int getBluePW() { // Set sensor to read Blue only digitalWrite(S2,LOW); digitalWrite(S3,HIGH); // Define integer to represent Pulse Width int PW; // Read the output Pulse Width PW = pulseIn(sensorOut, LOW); // Return the value return PW; }
I am not familiar with this product, but I just had a quick glance at the code, etc.
This product is unusual (compared to most RGB) 'camera' sensors, in that the raw data is not a fixed number of bits .. e.g. 8-bit with a range of 0-255. Instead it produces somewhat arbitrary values that need to be mapped to a convenient range ... which in the second program is chosen to be 0..255.
---------------
Just considering Red for a moment (green and blue have similar story, but different numbers)
Looking at the values you have inserted in the second progaram, your calibration found that for Red (say), the sensor returns 25 for 'no' red, and 286 for 'maximum' red.
Then the second program uses the map function, to convert raw sensor numbers in the range 25...286 into numbers 0..255 .... so incoming 25 would convert to 0, 286 to 255, and so on. The implication being, the sensor will only every produce numbers in the range 25 to 286.
However, this means that if you read a raw value below 25, say 23, then the mapping will give a negative value (about -2), and if you read a raw value above 286, say 288, then the mapping output be above 255 (about 257).
Now assuming the sensor is working completely 'perfectly', which may or may not be realistic, then it could simply be the light hitting the sensor during the calibration run was not 'ideal'. That is some red light hit the sensor when determing the minimum value, and the amount of red light hitting the sensor when determing the maximum value, was not a true maximum.
That is , if a little red light hit the sensor during the calibration, then the minimum value of 25, might not be a true 'minimum' ... the 'true minimum' calibration might be 15 (say)...
So that if you see a negative red value with the second program, it might simply be the conditions sent less red light to the sensor, than happened during the 'min' calibration.
The same argument, albeit reversed, could produce values higher than 255 for the second program, if for some reason, the sensor got more red light in the second program than it got during the 'maximum' part of the calibration run.
-----------
So it may simply be your calibration experiment was slightly flawed, and should be repeated.
Of course, there may be other 'experimental' variations which caused the sensitivity of the sensor to vary between the calibration and 'demo' runs, but my gut feeling suggests it has more to do with the optical reflectivity changing. Also, remember any room illumination could add more red light.
It may be that for your purposes, it doesn't matter very much ... recognition of ball colours could be simply a case of comparing the raw RGB values and deciding the most likely ball colour. Depending upon your analysis software, you may not need to convert it to a fixed range like 0..255.
Hope this helps ... obviously, I can't see your experiment, so I might be totally mistaken, in which case, apologies.
Best wishes, Dave
@davee Wow, thank you for the thorough looking through. My instincts tell me you are correct. My initial calibration setup was pretty hacked together. I believe movement of the sensor and varying ambient light exposure due to said movement are causing the readings coming in outside of the range, and therefore as values greater than 255 and below 0. The bit about how exactly the integers end up above and below is very helpful. I also agree and had considered in my fussing about that the code section converting values to those which lie between 0-255 may be unnecessary. With that being said I am currently 3D printing a 'real' fixture where the light pollution should be minimized. In the actual mechanism, I intend to use the servos as 'gates' to queue the balls and simultaneously close out exterior light during the sensing process. In short, garbage in garbage out on the calibration front on my part.
This forum is awesome.
-Keith
@spaghetticallahan FYI @davee You need to add a constrain statement after the map statements. See pic, further doc'n at https://www.arduino.cc/reference/en/language/functions/math/constrain/
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.