Der sprechende Farbdetektor mit DFPlayer und TCS3200 - Teil 2 - AZ-Delivery

Einführung

Im ersten Teil dieser Blogreihe haben wir den MP3-Player für die Sprachausgabe in Betrieb genommen. Außerdem haben wir mit einem Taster und einem Potentiometer eine Benutzereingabe hinzugefügt. Im zweiten Teil wollen wir nun den Farbsensor anschließen und testen. Ich werde Ihnen zeigen, welche Bibliotheken zur Verfügung stehen und worauf man bei der Bedienung des Sensors achten muss. Los geht's.

Was wir benötigen

Anzahl Bauteil
1 TCS3200 Farbsensor Modul
1 DFPlayer Mini MP3 Player Modul
1 Mikro-SD Karte
1 Arduino Nano V3.0
1 Lautsprecher (Max 3 W)
Verbindungskabel
Widerstand 1 KOhm
Veränderbarer Widerstand (Potentiometer)
1 Taster
Computer mit Arduino IDE und Internetverbindung
Externe Spannungsquelle (empfohlen), 7 – 12 V
Farbreferenzkarten


Vorbereitung 

Ich gehe davon aus, dass Sie die Schaltung aus Teil 1 aufgebaut und die SD-Karte mit den Sprachdateien in den SD-Slot des MP3-Players eingeschoben haben. Wir werden diese Komponenten zwar noch nicht brauchen, es ist aber von Vorteil, wenn die Schaltung schon so aufgebaut ist, wie wir sie am Ende benötigen. Also werden wir sie durch den Farbsensor ergänzen.


DFPlayer Mini Pins Arduino Nano Pins
VCC 5V
GND GND
RX über 1 KOhm an D11 (TX)
TX D10 (RX)
Lautsprecher
SPK_1 Rot (Plus)
SPK_2 Schwarz (Minus)
Potentiometer Arduino Nano Pins
1 GND
2 (Mitte) A0
3 +5V
Taster Arduino Nano Pins
1 D12
2 GND


Für einen Funktionstest laden wir das Programm aus Teil 1 auf den Arduino:

Kompletter Quellcode: 1.2DFPlayerStartsoundPotiTaster.ino

Farbsensor

Der TCS3200 Farbsensor besteht aus einem im Raster angeordneten Photodioden. Es sind immer vier davon im Quadrat angeordnet. Drei davon sind mit einem Farbfilter jeweils in Rot, Grün oder Blau bestückt. Eine Photodiode enthält keinen Farbfilter. Von diesen Quartetts gibt es 16 gleichmäßig auf der Sensorfläche verteilt, also insgesamt 64 Photodioden.

Die Dioden mit den gleichen Farbfiltern sind miteinander verbunden. Dieses Raster aus Dioden ist der eigentliche Farbsensor, der auf das Breakoutboard aufgelötet ist. Zusätzlich befinden sich darauf vier weiße LEDs, die das Objekt beleuchten. Das Licht wird reflektiert und auf die Photodioden zurückgeworfen, die aus dem Licht eine Spannung erzeugen. Die Farbfilter sorgen dann dafür, dass jede Farbgruppe nur eine Farbe aufnimmt. Mit den Anschlüssen S2 und S3 können die Photodioden-Gruppen aktiviert und deaktiviert werden. Es ergeben sich vier Kombinationen, sodass immer eine Gruppe mit der gleichen Farbe eingeschaltet wird.

S2 S3 Farbe
LOW LOW Rot
LOW HIGH Blau
HIGH LOW Klar (ohne Filter)
HIGH HIGH Grün

 


Die erzeugte Spannung jeder Photodiodengruppe wird mit einem Spannungs-Frequenz-Umformer in eine Rechteckschwingung umgewandelt. Je nach Farbe des Objektes ändert sich dessen Frequenz. Man erhält dann aus jeder der Farbgruppen einen Frequenzwert. Dieser muss dann in sinnvolle RGB-Werte umgerechnet werden.

Weitere Anschlüsse sind S0 und S1. Sie dienen einem Frequenzteiler, mit dem die Ausgangsfrequenz skaliert und der Sensor auch deaktiviert werden kann.

S0 S1 Ausgangsfrequenzskalierung
LOW LOW Deaktiviert
LOW HIGH 2%
HIGH LOW 20%
HIGH HIGH 100%


Pin VCC und GND dienen der Spannungsversorgung, die zwischen 2,7 und 5,5 V liegen darf. Am OUT-Pin liegt die gemessene Frequenz an, die wir am Arduino messen können. Der Pin OE (Output Enable) aktiviert oder deaktiviert den Ausgang des Sensors. Er ist low active. Liegt an diesem Eingang nichts an, ist der Sensor standardmäßig aktiv. Man kann also aus dem Programm heraus den Ausgang ausschalten, um z.B. mehrere Sensoren anzuschließen, die sich nicht gegenseitig stören sollen. Ansonsten kann man ihn frei lassen, oder mit GND verbinden.

Technische Details zum Sensor finden Sie im Datenblatt.

Verkabelung

Wir fügen den Farbsensor wie folgt in unsere Schaltung ein:

 

TCS3200 Pins Arduino Nano Pins
VCC 5V
GND GND
OE D3
S0 D4
S1 D8
S2 D6
S3 D7
OUT D5


Wie Sie eventuell erkennen können, sind die Pins nicht komplett chronologisch angeordnet. Das hat auch seinen Grund. Eine der Bibliotheken, die ich später zeigen werde, verlangt den Ausgang an Pin D5. Damit alles einheitlich ist und wir nicht jedes Mal umstecken müssen, lasse ich das auch für die anderen Beispiele so, die ich zeigen werde.

Dinge, die es zu beachten gilt

Der Sensor nimmt auch das Umgebungslicht auf. Das verändert natürlich die Messwerte. Außerdem ist die Entfernung des Sensors zum Messobjekt (empfohlen sind zwischen 1 und 3 cm) ausschlaggebend. Es empfiehlt sich, eine verschlossene Box zu konstruieren, damit die Störfaktoren so konstant wie möglich bleiben. Dann ist es möglich, den Sensor zu kalibrieren und auf seine Umgebung einzustellen. Ich habe mir spontan aus schwarzem Papier etwas gebastelt.

 

Man kann noch einen schmalen Papierstreifen erkennen, den ich um den Sensor gelegt habe. Meiner Meinung nach strahlt zu viel Licht von den LEDs direkt auf den Sensor. Ich habe bei Thingiverse einige Modelle für den 3D-Druck gefunden, die auch dafür gedacht sind (hier und hier).

Natürlich kann man sich auch ein Gehäuse als 3D-Modell designen, in dem gleich noch die restliche Elektronik Platz hat. Wichtig ist, dass so wenig Licht von außen auf den Sensor treffen kann und der Abstand zur gemessenen Fläche gleich bleibt. Es würde sich anbieten, eine ausgediente Taschenlampe zu verwenden. Dort hat dann auch gleiche die Batterie für die mobile Stromversorgung Platz.

Ohne Bibliotheken

Ich habe während meiner Recherchen zum TSC3200 (und auch dem TCS230, dem Vorgängermodell) verschiedene Varianten gefunden, diese Komponente mit dem Arduino zu programmieren. Bevor ich gleich die beiden Bibliotheken zeige, die ich gefunden habe, möchte ich noch einmal darauf eingehen, wie die Kommunikation zwischen dem Mikrocontroller und dem Sensor funktioniert.

Wie bereits oben erwähnt, sind die Pins S2 und S3 für die Beschaltung der Photodioden zuständig. Es sind vier Farbgruppen, deren Dioden (Rot, Grün, Blau und Klar ohne Filter) durch eine der Kombinationen aus S2 und S3 aktiviert werden. Der Sensor erzeugt dann ein gleichmäßiges Rechtecksignal am Ausgang. Dessen Pulsweite (also die Zeit einer "Schwingung") muss dann mit dem Arduino gemessen werden. Dafür ist im Grunde keine zusätzliche Bibliothek notwendig. Probieren wir es zuerst ohne.

Wir definieren unsere Arduino Pins als Konstanten:

#define S0  4
#define S1  8
#define S2  6
#define S3  7
#define OE  3    // LOW = ENABLED
#define TCS_IN  5

Dann benötigen wir einige Variablen für die Farben. Außerdem möchte ich die Ausgabe auf dem Seriellen Monitor formatieren. Das löse ich mit einem Zeichenkettenpuffer:

int rot = 0;
int gruen = 0;
int blau = 0;
int klar = 0;
char serialBuffer[55];

Im setup() initialisieren wir den Seriellen Monitor (auch hier wieder darauf achten, dass dort die gleiche Baudrate eingestellt ist):

void setup()
{
  Serial.begin(115200);
  pinMode(S0, OUTPUT); //S0
  pinMode(S1, OUTPUT); //S1
  pinMode(S2, OUTPUT); //S2
  pinMode(S3, OUTPUT); //S3
  pinMode(OE, OUTPUT); //S3
  pinMode(TCS_IN, INPUT); //OUT

  // Sensor Output aktivieren
  digitalWrite(OE, LOW);
 
  // Frequenzteiler auf 20%
  digitalWrite(S0, HIGH);
  digitalWrite(S1, LOW);
}

Die Eingänge des Farbsensors S0 bis S3, sowie OE sind dort Eingänge. Somit sind sie am Arduino als Ausgänge einzustellen. Des Sensors Ausgang ist am Arduino ein Eingang. Den Pin für OE dann nochmal auf LOW zu setzen, muss man nur machen, wenn er auch angeschlossen ist. Da er active low ist, kann man ihn auch unverbunden lassen und muss ihn dann nicht initialisieren. Es ist wie gesagt auch möglich, ihn mit dem GND-Pin zu verbinden, was aber nicht unbedingt notwendig ist.

Den Frequenzteiler stellen wir (wie in der oben gezeigten Tabelle) auf 20%.

In der loop()-Funktion werden wir nun die einzelnen Farbgruppen nacheinander aktivieren und die Werte am Eingang messen. Damit wir diese Daten besser vergleichen können, habe ich eine Unterbrechung hinzugefügt:

  // Auf Eingabe warten
  while (Serial.available() == 0) {
    if (Serial.available() != 0) {
      break;
    }
  }
  // Serial Puffer loeschen
  while (Serial.read() != -1) {}

Wenn Sie den Seriellen Monitor öffnen, können Sie in dem Eingabefeld einfach die Entertaste betätigen. Dann wird eine Messreihe durchgeführt. Für die nächsten Werte müssen Sie die Taste erneut betätigen. Es folgt die Beschaltung der Photodioden und die Messung am Eingang des Arduinos:

  // LOW / LOW = rote Photodiode
  digitalWrite(S2, LOW);
  digitalWrite(S3, LOW);
  // Frequenz messen
  rot = pulseIn(TCS_IN, digitalRead(TCS_IN) == HIGH ? LOW : HIGH);
  
  // LOW / HIGH = blaue Photodiode
  digitalWrite(S3, HIGH);
  blau = pulseIn(TCS_IN, digitalRead(TCS_IN) == HIGH ? LOW : HIGH);
  
  // HIGH / HIGH = Gruene Photodiode
  digitalWrite(S2, HIGH);
  gruen = pulseIn(TCS_IN, digitalRead(TCS_IN) == HIGH ? LOW : HIGH);
  
  // HIGH / LOW = Photodiode ohne Filter
  digitalWrite(S3, LOW);
  klar = pulseIn(TCS_IN, digitalRead(TCS_IN) == HIGH ?
LOW : HIGH);    
  
  // Ausgabe
  sprintf(serialBuffer, "Rot: %4d Gruen: %4d Blau: %4d Klar: %4d", rot, gruen, blau, klar);
  Serial.println(serialBuffer);

S2 und S3 werden erst auf LOW / LOW gestellt, dann S3 auf HIGH. S2 bleibt LOW, was LOW / HIGH ergibt. Anschließend wird S2 auf HIGH gesetzt, das ergibt HIGH / HIGH, da S3 nicht verändert wird. Zum Schluss wird S3 auf LOW gestellt, ohne S2 zu verändern, was HIGH / LOW ergibt. Vergleichen Sie die Kombinationen mit der oben gezeigten Tabelle für die einzelnen Farben. Ich habe hier lediglich Grün mit Klar vertauscht, damit in der Reihenfolge immer nur ein Digitalpin verändert werden muss, was weniger Zeit für Befehle für den Prozessor bedeutet.

Als Letztes werden die Werte auf dem Seriellen Monitor ausgegeben. Dafür nutze ich die formatierte Ausgabe, die allerdings auf dem Arduino Nano nicht mit Serial.printf() funktioniert. Ein kleiner Umweg geht hier über die formatierte Ausgabe in ein char array, dass dann an den Seriellen Monitor geschickt wird.

Kompletter Quellcode: 2.0TCS3200Test.ino

Laden Sie das Programm auf den Arduino, halten den Sensor an eine Farbfläche Ihrer Wahl und drücken im Eingabefeld des Seriellen Monitors auf Enter. Dann sehen Sie die Farbwerte. Wechseln Sie die Farbfläche und betätigen wieder die Entertaste. Dann ändern sich die Farbwerte.

Ich habe Rot, Grün, Blau, Schwarz und Weiß gescannt und erhalte folgende Ergebnisse:


Jetzt müssen wir die Werte erst einmal interpretieren. Jede Zeile ist ein Farbscan. Betrachten wir die erste Zeile. Diese Werte repräsentieren die rote Farbe meiner Referenzkarte. Ein volles Rot zusammengesetzt, aus den drei Farbwerten in additiver Form in 8 Bit wären 255, 0, 0 (R, G, B). Solch ideale Farben werden wir nur schwer erreichen. Dazu kommt, dass es sich bei diesen ausgegebenen Werten nicht um 8 Bit handelt. Außerdem können wir sehen, dass der Rotanteil niedriger ist, als die Anteile für Grün und Blau. In der nächsten Zeile handelt es sich um die Grüne Referenzkarte. Hier sehen wir, dass die Anteile Grün und Blau gleich sind. Das wäre normalerweise eher ein Türkis. Für die blaue Referenzkarte sehen wir, dass die Werte für den Blauanteil niedriger sind. Messen wir die schwarze Fläche, sind die Werte wesentlich höher. Weiß ergibt sehr niedrige Werte. Daraus lässt sich schließen, dass hellere Farbanteile pro Farbkanal niedrige Werte bedeuten.

Die Funktion pulseIn() misst die Zeit zwischen Zustandswechseln an einem Pin. Also sind die ausgegebenen Werte keine Spannungswerte, die man z.B. mit analogRead() erhält. Es handelt sich um Frequenzen. Je niedriger die Frequenz, desto heller der Farbwert. Für die Farbe Rot bedeutet das, dass der Anteil an rotem reflektiertem Licht am hellsten ist und somit den niedrigsten Wert hat.

Daraus könnte man nun selbst ein Programm schreiben, dass für uns Farben erkennt. Da es sich auch um mehr als nur 8 Bit handelt, kann man die Farbunterschiede wesentlich feiner darstellen. Verändert man die Frequenzskalierung, kann man auf diese Auflösung sogar noch mehr Einfluss nehmen. Für dieses Projekt reichen mir jedoch einfache Farben und das Programm dazu zu schreiben, lasse ich auch mal außen vor.

Mit Bibliotheken

Wir wollen nun unseren sprechenden Farbdetektor dazu bringen, die Farben auszusprechen. Woher weiß er, dass es sich um die Farbe Rot handelt und was ist, wenn sich die Farbwerte ein wenig unterscheiden? Immerhin ist Rot nicht gleich Rot. Dafür müssten wir in das Programm eine Kalibrierung implementieren. Außerdem bräuchten wir eine Gewichtung, falls sich die Farben geringfügig unterscheiden.

Diese Dinge müssen wir nicht mehr selber programmieren. Hier kommen wir nun zu den Bibliotheken. Die Arbeit hat sich nämlich schon jemand gemacht und wir wollen nun deren Beispiele testen. Wir installieren die Bibliotheken MD_TCS230 von majicDesigns und tcs3200 von Panjkrc aus der Bibliotheksverwaltung heraus:

 


Wenn Sie in das Suchfeld "TCS" eingeben, erscheinen die passenden Ergebnisse. Uns stehen nun diese Bibliotheken und deren mitgelieferte Beispiele zur Verfügung. Ein Klick auf "Info" in der Bibliotheksverwaltung auf dem jeweiligen Eintrag führt Sie zu den Beschreibungen und Quelltexten auf Github. In den Link von MajicsDesigns hat sich allerdings ein Fehler eingeschlichen. Sie erreichen die Github-Seite über diesen Link.

Beginnen wir auch gleich mit der MDTCS230 Bibliothek. Sie funktioniert unter anderem mit dem Nachfolgemodell TCS3200, das uns jetzt vorliegt. Es sind vier Beispiele enthalten. Mit den Projekten "SimpleBTCS230" und "SimpleNB_TCS230" wird ein Vergleich zwischen blocking und nonblocking im Zusammenhang mit diesem Sensor gezeigt. Darauf möchte ich nicht weiter eingehen. Probieren Sie es jedoch gern selbst einmal aus. Achten Sie dabei auf die verwendeten Pins.

Öffnen wir das Beispiel "Calibrate_TSC230". Hier wird auffallen, dass eine Bibliothek namens "FreqCount.h" benutzt wird. Diese muss installiert sein:


Wir ändern in dem Beispiel unter "Pin definitions" die Pinnummern wie in unserem Testprojekt. Das sind für S2 Pin 6 und für S3 Pin 7. OE ist Pin 3.

Hinweis: Es handelt sich hierbei um die Bibliothek, die (wie weiter oben bereits erwähnt) den Sensorausgang am Eingang des Arduino-Pins D5 benötigt. Das ist in der Bibliothek "FreqCount.h" so festgelegt. Mehr Informationen finden Sie auf der Webseite von Paul Stoffregen. Dort gibt es auch eine Liste, welche Pins für die jeweiligen Arduino Boards benutzt werden müssen.

Die Baudrate für den Seriellen Monitor ändern wir entweder im Quellcode, oder im Seriellen Monitor. Das können Sie für sich entscheiden, da beides geht. Wichtig ist nur, dass beides den gleichen Wert hat. Nach diesen Änderungen laden wir das Programm auf den Arduino und führen es aus.

Ihnen wird auffallen, dass die Pins S0 und S1 nicht angegeben sind. Diese werden (wie oben beschrieben) für die Frequenzskalierung benutzt, was in diesem Programm nicht eingestellt werden muss. Ohne im Quelltext der Bibliothek nachgesehen zu haben, gehe ich davon aus, dass dort die Einstellung programmiert wurde.

Wenn das Programm gestartet und der Serielle Monitor geöffnet wurde, erscheint ein Hinweis, dass Schwarz gescannt werden soll. Das tun wir und bestätigen mit Enter. Anschließend das Ganze noch einmal mit Weiß. Danach kann man dann die gewünschten Farben scannen. Ich teste das mit Rot, Blau und Grün und erhalte folgende Werte:


Meine Rote Referenzkarte hat die Farbanteile 127, 16, 18 (R, G, B). Blau hat 19, 51, 99 (R, G, B) und Grün hat 53, 78, 39 (R, G, B). In diesem Fall sind das 8 Bit Farbwerte, d.h. jeder Farbkanal kann die Werte 0 bis 255 einnehmen. Je größer der Wert, desto höher der Farbanteil. Daher ist auch der Rotanteil in der aufgezeichneten roten Farbe am höchsten. Das ist der Unterschied zu unserem ersten Test mit diesem Sensor. Die Werte wurden hier bereits umgerechnet. Für unseren sprechenden Farbdetektor fehlt uns noch eine Gewichtung.

Wir öffnen das Beispielprojekt "ColorMatch_TCS230" aus der gleichen Bibliothek. Hier ändern wir ebenfalls wieder die Pinnummern für S2, S3 und OE (6, 7 und 3). Außerdem passen wir die Baudrate für den Seriellen Monitor an und laden das Programm auf den Arduino. In der Bildschirmausgabe werden wir gebeten, zwischen Learn oder Match Mode zu wählen. Im Learn Mode nehmen wir wieder Referenzwerte auf. Diese brauchen wir, um sie in die Datei ColorMatch.h einzutragen. Mit einem Blick in diese Datei (sie erreichen Sie in dem Reiter unter dem Menü in der Arduino IDE), sehen wir ein Array für verschiedene Farben. Dort werden die Werte aus dem Learn Mode später eingetragen.

Wir durchlaufen den Prozess des Learn Modes, in dem wir in die Eingabe des Seriellen Monitors ein großes "L" eintragen. Nun müssen wir wieder Schwarz und Weiß aufzeichnen. Das sind die maximalen Referenzwerte. Weiß hat idealerweise die Werte 255, 255, 255 (RGB) und Schwarz hat 0, 0, 0 (RGB). Da wir diese idealen Werte nicht immer erreichen, brauchen wir die Kalibrierung.

Im nächsten Schritt können wir unsere Referenzen für die Farben in dem Farbarray aufzeichnen. Dabei können wir auch eigene Namen für die Farben eintragen. Schreiben wir keine Namen in die Eingabe, werden die Texte aus der Vorlage übernommen. Nachdem wir alle Farben eingescannt haben, erscheint in der Ausgabe folgende Information:


Wir kopieren den Text ab "//Calibration Data" und fügen ihn in die Datei ColorMatch.h ein, indem wir dort den vorhandenen Text ersetzen.


Hinweis: Im Seriellen Monitor markieren Sie den Text und drücken auf der Tastatur STRG+C. Rechte Maustaste und kopieren funktioniert hier leider nicht.


Wir laden das Programm nun erneut auf den Arduino hoch. Unsere Referenzwerte sind gespeichert. Wir wählen nun mit "M" den Match Mode aus. Scannen wir eine der zuvor gespeicherten Referenzfarben, werden uns diese auch wieder so ausgegeben. Dieses Mal findet eine Gewichtung statt. Auch wenn die Werte nicht exakt gleich sind, bleibt es trotzdem die gleiche Farbe:


35, 14, 8 (RGB) und 27, 9, 5 (RGB) wird bei mir beides als Braun erkannt.

Mit dem Ergebnis können wir bereits zufrieden sein, da wir für unseren sprechenden Farbdetektor genau das brauchen. Das würde aber bedeuten, dass wir jedes Mal die Referenzfarben aufzeichnen und den Arduino danach neu programmieren müssten. Wir behalten das im Hinterkopf und wollen nun noch die zweite Bibliothek testen, die wir installiert haben.

Wir öffnen aus der Bibliothek "tcs3200" das Beispielprojekt "tcs3200_calibration". Der Pin D5 muss hier nicht unbedingt für den Ausgang verwendet werden. Hier könnten wir die Pinreihenfolge wieder so ändern, dass sie chronologisch ist. Allerdings lasse ich sie so gesteckt, falls ich noch einmal etwas vergleichen möchte. Dann brauche ich nicht umstecken, um wieder die andere Bibliothek verwenden zu können. Wir ändern also die Pinnummern in dieser Zeile:

tcs3200 tcs(4, 8, 6, 7, 5); // (S0, S1, S2, S3, output pin)

Der OE-Pin wird hier nicht benötigt. Da wir ihn aber gesteckt haben, initialisieren wir ihn auch, um sicher zu gehen, dass er mit LOW-Pegel eingestellt ist. Außerdem passen wir wieder die Baudrate für den Seriellen Monitor an:

void setup() {
      Serial.begin(115200);
      pinMode(3, OUTPUT);
    digitalWrite(3, LOW);
}

Wenn Sie nun das Programm auf den Arduino laden möchten, werden Sie eine Fehlermeldung erhalten. Zumindest für den Fall, dass in Ihrem Quelltext folgende Zeile im oberen Bereich enthalten ist:

String distinctColors[num_of_colors] = {"white", "black", "red", "yellow", "green", "orange", "blue"};

Das kann so nicht funktionieren. Auf der Github-Seite der Bibliothek finden Sie das gleiche Beispiel, allerdings sieht die Zeile dort so aus:

int distinctColors[num_of_colors] = {0, 1, 2, 3, 4, 5, 6};

In der Bibliothek erwartet die Funktion closestColor() ein int-array und kein String-array. Warum das Beispiel in der Bibliotheksverwaltung anders ist, kann ich nicht sagen. Eventuell gibt es bei Ihnen den Fehler nicht. Nach der Korrektur lässt sich das Programm kompilieren und hochladen. Ich behalte die alte Zeile noch und ändere nur den Namen des Arrays:

String colorNames[num_of_colors] = {"white", "black", "red", "yellow", "green", "orange", "blue"};

Zu diesem Zeitpunkt hatte ich schon vermutet, dass damit die Namen der Farben, statt Nummern ausgegeben werden sollen. Das können wir dann später noch implementieren.

Führen wir das Programm aus, sehen wir die zyklische Ausgabe der Farbwerte.

Im Quellcode finden wir im oberen Bereich folgende Zeile:

int distinctRGB[num_of_colors][3] = {{250, 250, 250}, {0, 0, 0}, {142, 34, 41}, {166, 125, 71}, {35, 55, 38}, {150, 50, 43}, {22, 25, 45}};

Das sind die Referenzwerte für die Farben. Sie halten nun noch einmal alle Referenzkarten vor den Sensor und übernehmen die Farbwerte aus dem Seriellen Monitor in das Array. Die Reihenfolge übernehme ich aus der Zeile der Farbnahmen. Also Weiß, Schwarz, Rot, Gelb, Grün, Orange und Blau. Laden Sie das Programm danach auf den Arduino und Scannen eine der Farben. Es sollte Ihnen die passende Nummer dazu angezeigt werden.

Da wir aber Texte statt Nummern sehen möchten, ändern wir in der loop()-Funktion die Ausgabe. Die Funktion closestColor() gibt einen int-Wert zurück. Dieser wird dort momentan noch ausgegeben. Wir können Ihn als Index für das Array mit unseren Farbnamen verwenden. Also ändern wir einfach die Zeile:

Serial.println(tcs.closestColor(distinctRGB, distinctColors, num_of_colors));

in:

Serial.println(colorNames[tcs.closestColor(distinctRGB, distinctColors, num_of_colors)]);

Voraussetzung ist, dass Sie wie ich die Zeile mit den Namen behalten und lediglich das Array umbenannt haben in colorNames[].

Laden wir das Programm nun auf den Arduino und scannen eine der Referenzfarben, werden uns die dazugehörigen Namen angezeigt. Auch hier findet eine Gewichtung statt, d.h. die Werte dürfen variieren und die Farben werden trotzdem erkannt. Um mehr Farben hinzuzufügen, müssen wir die Konstante numofcolors ändern und tragen weitere Felder in die Arrays distinctRGB, distinctColors und colorNames ein. Darauf gehe ich im dritten Teil weiter ein.

Kompletter Quellcode: 2.1tcs3200calibration_changed.ino

Mit dieser Bibliothek wird noch das Beispiel tcs3200_example mitgeliefert. Allerdings werden dort lediglich gemessene Farbwerte ausgegeben. Dort können die Referenzwerte aus der Kalibrierung nicht eingetragen werden. Außerdem fehlt die Gewichtung und die Ausgabe der aufgezeichneten Farbe. Daher gehe ich auf das Beispiel an dieser Stelle nicht weiter ein.

Ausblick

Im nächsten Blogbeitrag werden wir den Farbsensor in unser Programm integrieren. Wir haben zwei Möglichkeiten, Farben einzuscannen und mit Gewichtung den Namen der aufgezeichneten Farbe auszugeben. Unser Gerät soll die Farbe als Sprache ausgeben. Wir werden einen Weg suchen, die Kalibrierung zu vereinfachen und eventuell den Schritt umgehen, das Programm zweimal auf den Arduino laden zu müssen. Das heißt, wir müssen zwischen Learn Mode und Match Mode im Live-Betrieb umschalten und die Daten direkt auf dem Arduino speichern. Außerdem möchte ich weitere Sprachen hinzufügen, die wir ebenfalls im Live-Betrieb umschalten können. Da wir das Gerät auch mobil nutzen möchten, werde ich es auf Batteriebetrieb umstellen.

Bis dahin,

Andreas Wolter

für AZ-Delivery Blog

Teil 1

Teil 3

Für arduinoProjekte für anfängerSensoren

Lascia un commento

Tutti i commenti vengono moderati prima della pubblicazione