PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Farbsensor Auswertung



Toran
20.03.2018, 14:48
Tag Zusammen,
ich bin gerade dabei einen Farbsensor(TCS3200) in Betrieb zu nehmen und bin auf ein Problem gestoßen. Die Farbe wird gute 5cm von dem Sensor entfernt sein. Wenn ich mir die Werte anschaue, kann ich jedoch keine Muster entdecken. Zu mindest keine, die das Ergebnis nur auf eine Farbe eingrenzen. Ich habe mich mit mehreren If-Abfragen versucht ans Ziel zu kämpfen, aber es gab immer ein zwei Farben, die nicht richtig erkannt wurden. Wenn es mal bei einer Distanz von 1cm gepasst hat, hat es bei einer Distanz von 5cm wieder überhaupt nicht gepasst. Ich drehe mich nun seit gut 3h im Kreis, was die Abfrage angeht . Im wesentlich würde ich gerne rot, grün, blau, weiß und schwarz erkennen.
Habt ihr vielleicht ein paar Tipps, wie ich ans Ziel komme? Gibt es etwas in meinem Code, das grundlegend falsch ist? Ich benutze für die Programmierung einen Arduino Mega.

Sensor-Daten bei keiner Farbe vor dem Sensor:
https://www.pic-upload.de/view-35031812/Sensordaten.png.html

Sonstige Details:
- Wird in einer eher dunkleren Umgebung eingesetzt (der Boden eines Fahrgestells)
- momentan nur schwaches Licht im Zimmer.
- LED des Sensors ist in Betrieb

Mein Code:


const int s0 = 2;
const int s1 = 3;
const int s2 = 4;
const int s3 = 5;
const int out= 6;
const int motor1 = 7;
const int motor2 = 8;
const int motor3 = 9;
const int motor4 = 10;
const int trigger = 11;
const int echo = 12;
const int musicPin = 13;
int red=0;
int green=0;
int blue=0;
void setup()
{
pinMode(motor1,OUTPUT);
pinMode(motor2,OUTPUT);
pinMode(trigger,OUTPUT);
pinMode(echo,INPUT);

pinMode(s0,OUTPUT);
pinMode(s1,OUTPUT);
pinMode(s2,OUTPUT);
pinMode(s3,OUTPUT);
pinMode(out,INPUT);

//Scaling to 20% frequency
digitalWrite(s0,HIGH);
digitalWrite(s1,LOW);
Serial.begin(9600);
}

void loop()
{
//RED

digitalWrite(s2,LOW);
digitalWrite(s3,LOW);
red = pulseIn(out,LOW);
//red = map(red, 120,3000,255,0);
Serial.print("R= ");
Serial.print(red);
Serial.print(" ");
delay(100);

//GREEN
digitalWrite(s2,HIGH);
digitalWrite(s3,HIGH);
green = pulseIn(out,LOW);
//green = map(green, 120,3000,255,0);
Serial.print("G= ");
Serial.print(green);
Serial.print(" ");
delay(100);

//BLUE
digitalWrite(s2,LOW);
digitalWrite(s3,HIGH);
blue = pulseIn(out,LOW);
//blue = map(blue, 120,3000,255,0);
Serial.print("B= ");
Serial.print(blue);
Serial.println(" ");
delay(100);


}

i_make_it
20.03.2018, 17:39
Du hast doch GRB Werte erhalten.
Mach einfach mal 10 Messungen, adiere jeweils für R,B und G die Werte und teile durch 10.
Dann hast Du einen Mittelwert.
Durch Fremdlicht und Schwankungen bekommst Du eh nie ein immer wieder exakt gleiches Signal.
Jede Farbe die Du identifizieren willst wird durch 6 Werte beschrieben Rmax, Rmin, Gmax, Gmin, Bmax, Bmin oder durch 3 Durchnittswerte für R,G und B und eine Range (+,-).

Toran
20.03.2018, 22:31
Perfekt danke! So werde ich es morgen Früh gleich machen

i_make_it
21.03.2018, 05:33
Aus dem Bild ist ja nicht ersichtlich ob die RGB Werte bis 511 oder 1023 gehen, aber was man machen kann ist (bei 1023) eine Schleife in der immer um 29 erhöht wird und verglichen wird ob der variable wert (R,G oder B) kleiner ist.
Wenn ja wird abgebrochen und einer der 36 Werte (0-9,A-Z) zugewiesen.
(Bsp.: xxx < 28 => erg = 0; xxx < 57 => erg = 1;.... xxx < 318 => erg = A)
Die Schleife durchlauft man für R,G, und B und wandelt damit die 1024 * 1024 *1024 möglichen Kombinationen in 36 * 36 * 36 Kominationen die jeweils durch einen 3 Stelligen String repräsentiert werden (000 bis ZZZ).
Jetzt kann man mit Case diesen String mit festgelegten (z.B. 00M für einen Blauton) Farben vergleichen.
Wobei 00M für folgende Messerwerte steht,
R000; G000; B666
bis
R028; G028; B695

Also im Schritt 1 durch Mehrfachmessungen und Mittelwertbildung Rauschen aus der Messung nehmen und stabilere Messwerte bekommen.
Im Schritt 2, die über eine Millionen möglichen Kombinationen reduzieren (im Beispiel auf rund Sechsundvierzigtausen).
Schritt 2, den Umstand nutzen, das man dies mit einem Zeichen Tripplet darstellen kann und Case nutzen um einzelne Farben zu definieren.

Welche Farben man bekommt, kann man zur Not mit wenigen Zeilen HTML und seinem Browser durch probieren.
Dort beträgt der Zahlenraum für die RGB-Werte von <bgcolor> halt 0-255.
Bei 0-1023 müsste man halt den Messwert erst durch 4 teilen und dann in eine Hex Zahl umwandeln bevor man das vergleichen kann.

HaWe
21.03.2018, 09:34
Üblicherweise wird RGB Farbcode mit jeweils 0-255 pro Farbkanal angegeben. Enge also erst einmal alle Einzelwerte auf 1/4 ihres Wertes ein.

weiß wäre dann 255 255 255 in hex: ffffff
Magentarot 255 0 0 in hex: ff0000
Grün 0 255 0 in hex: 00ff00
Blau 0 0 255 in hex: 0000ff
Schwarz 0 0 0 in hex: 000000
usw.

oft verwendet man in Tabellen die Hex-Zahlen (je 2 Stellen, also 255 = (hex)FF ), aber das ist grundsätzlich egal, denn es ist ja nur eine andere Schreibweise derselben Zahlen.

Diese RGB Codes taugen aber nicht viel, wenn man damit detektierte Farben einem Ziel-Farbton zuordnen will und insb. auch wenn das noch für verschiedene Helligkeiten oder Farbsättigungen funktionieren soll,
z.B.: ist das, was ich sehe, jetzt noch rot, oder schon orange oder magenta?
oder: ist RGB 120 20 10 noch der selbe Farbton wie 240 40 20 oder 180 30 15 oder 100 16 8 oder 60 10 5?

dazu ist die Umwandlung in den HSV-Farbraum sinnvoller, damit werden z.B. auch die Farben auf einem Rubik's Cube leichter den Zielfarben zugeordnet, innerhalb bestimmter Toleranzen und Schwankungen. Z.B. Hellrot und Dunkelrot hätten dabei den gleichen, leicht erkennbaren Farbton.

Du nimmst also deine RGB-Farben, wandelst sie in HSV um, und dann geht die Farbzuordnung deutlich einfacher.

openCV (ein Programmpaket u.a. zur Farbrerkennung oder -Separierung) verwendet dazu z.B. auch HSV.

PS, edit:
Übersicht über die Farbraum-Kodierungen: http://start.farben.rehbein.net/