Notifications
Clear all

Arduino and Color Sensors

9 Posts
5 Users
1 Likes
52 Views
SpaghettiCallahan
(@spaghetticallahan)
Active Member
Joined: 1 week ago
Posts: 4
Topic starter  

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


   
Quote
Will
 Will
(@will)
Famed Member
Joined: 2 years ago
Posts: 2219
 

@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.

Experience is what you get when you don't get what you want.


   
ReplyQuote
Ron
 Ron
(@zander)
Famed Member
Joined: 2 years ago
Posts: 3926
 

@spaghetticallahan Where are the sketches?

Arduino says and I agree, in general, the const keyword is preferred for defining constants and should be used instead of #define
"Never wrestle with a pig....the pig loves it and you end up covered in mud..." anon
My experience hours are >75,000 and I stopped counting in 2004.
Major Languages - 360 Macro Assembler, Intel Assembler, PLI/1, Pascal, C plus numerous job control and scripting


   
ReplyQuote
robotBuilder
(@robotbuilder)
Noble Member
Joined: 4 years ago
Posts: 1647
 

@zander 

Probably the first two sketches in this article?

https://dronebotworkshop.com/arduino-color-sense/

 


   
ReplyQuote
Ron
 Ron
(@zander)
Famed Member
Joined: 2 years ago
Posts: 3926
 

@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.

Arduino says and I agree, in general, the const keyword is preferred for defining constants and should be used instead of #define
"Never wrestle with a pig....the pig loves it and you end up covered in mud..." anon
My experience hours are >75,000 and I stopped counting in 2004.
Major Languages - 360 Macro Assembler, Intel Assembler, PLI/1, Pascal, C plus numerous job control and scripting


   
ReplyQuote
SpaghettiCallahan
(@spaghetticallahan)
Active Member
Joined: 1 week ago
Posts: 4
Topic starter  

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;

}

   
ReplyQuote
DaveE
(@davee)
Prominent Member
Joined: 2 years ago
Posts: 788
 

Hi @spaghetticallahan,

  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


   
Inst-Tech reacted
ReplyQuote
SpaghettiCallahan
(@spaghetticallahan)
Active Member
Joined: 1 week ago
Posts: 4
Topic starter  

@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


   
ReplyQuote
Ron
 Ron
(@zander)
Famed Member
Joined: 2 years ago
Posts: 3926
 

@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/

Screenshot 2023 01 25 at 18.38.14

 

Arduino says and I agree, in general, the const keyword is preferred for defining constants and should be used instead of #define
"Never wrestle with a pig....the pig loves it and you end up covered in mud..." anon
My experience hours are >75,000 and I stopped counting in 2004.
Major Languages - 360 Macro Assembler, Intel Assembler, PLI/1, Pascal, C plus numerous job control and scripting


   
ReplyQuote