Capteur de couleur TCS3200 Arduino : câblage et calibrage
Comment fonctionne le capteur de couleur TCS3200 : réglages S0–S3, lecture RVB avec pulseIn, calibrage blanc et noir, tri des couleurs, code ESP32 et Pico.
Le capteur de couleur TCS3200 est le module de détection de couleur le plus utilisé dans les projets Arduino : il mesure la couleur de la surface placée devant lui en la décomposant en rouge, vert et bleu. Il convertit la lumière captée par une matrice de photodiodes directement en fréquence : plus une surface renvoie de lumière rouge, plus la fréquence du canal rouge est élevée. Pas besoin de lecture analogique ni de protocole de communication particulier ; avec la fonction pulseIn() d'Arduino, tu lis les valeurs R, V et B en quelques lignes. Machines qui trient des bonbons colorés, robots qui reconnaissent les couleurs, véhicules qui tournent devant des repères colorés au sol, lampes qui copient la couleur de l'objet qu'on leur présente : tout cela se fait avec ce capteur.
Dans ce guide, tu verras pas à pas ce qu'il y a dans le capteur, à quoi servent les broches S0–S3, comment le câbler sur une Arduino Uno, un ESP32 et une Raspberry Pi Pico, comment faire des lectures brutes, comment réaliser le calibrage blanc et noir, ainsi qu'un algorithme qui détermine à quelle couleur correspond une mesure. Ensuite, nous construirons la logique d'une machine qui trie les objets par couleur et, pour finir, nous le comparerons au TCS34725, un capteur qui fonctionne en I2C.

Qu'est-ce que le capteur de couleur TCS3200 et comment fonctionne-t-il ?
La puce TCS3200, cœur du module (sa version précédente s'appelle TCS230), porte sur sa surface 64 photodiodes disposées en grille 8×8. Seize d'entre elles sont sous un filtre rouge, 16 sous un filtre vert, 16 sous un filtre bleu, et les 16 dernières n'ont pas de filtre (clear) et voient la quantité totale de lumière. Les 16 photodiodes d'une même couleur sont branchées en parallèle, et les broches S2 et S3 choisissent le groupe mesuré. Comme les photodiodes des différentes couleurs sont entrelacées dans la matrice, la lumière qui tombe sur un coin de la surface agit de la même façon sur tous les groupes de couleur.
Le faible courant produit par le groupe de photodiodes choisi arrive à un convertisseur courant-fréquence intégré à la puce. Ce circuit génère un signal carré au rapport cyclique de 50 %, dont la fréquence est directement proportionnelle à l'intensité lumineuse. Ce que tu mesures n'est donc pas une tension mais un nombre d'impulsions par seconde : quelques hertz dans l'obscurité totale, plusieurs dizaines de kilohertz tout près d'une surface blanche. L'avantage d'une sortie en fréquence, c'est qu'elle résiste bien aux parasites et qu'elle se branche sur n'importe quelle broche numérique de l'Arduino. Si tu veux seulement mesurer la quantité de lumière, une photorésistance LDR est plus simple ; le TCS3200 fait le même travail séparément pour trois couleurs.
| Caractéristique | Valeur |
|---|---|
| Puce | TCS3200 (ancienne version TCS230, compatible broche à broche) |
| Matrice de photodiodes | 8×8 = 64 : 16 rouges, 16 vertes, 16 bleues, 16 sans filtre |
| Sortie | Signal carré au rapport cyclique de 50 %, fréquence proportionnelle à la lumière |
| Fréquence pleine échelle (typique) | 600 kHz (100 %), 120 kHz (20 %), 12 kHz (2 %) |
| Tension d'alimentation | 2,7–5,5 V |
| Consommation de la puce | 1,4 mA typique (le courant des LED du module s'y ajoute) |
| Broches de commande | S0, S1 (échelle de fréquence), S2, S3 (filtre de couleur), OE (validation de sortie, active à LOW) |
| Distance conseillée | Environ 1–3 cm, identique à chaque mesure |
| Éclairage | 4 LED blanches sur le module |
Broches S0–S3 : échelle de fréquence et choix du filtre de couleur
Quatre broches de commande déterminent le comportement du TCS3200. S0 et S1 divisent la fréquence de sortie : à 100 %, les impulsions descendent à quelques microsecondes et mettent à rude épreuve la précision de mesure de l'Arduino Uno, tandis qu'à 2 % elles s'allongent mais arrivent moins nombreuses dans le même temps. S2 et S3 choisissent le filtre de couleur lu. Tu relies ces broches à des sorties numériques de l'Arduino et tu les règles dans le code avant chaque mesure.
| S0 | S1 | Échelle de la fréquence de sortie | Quand l'utiliser ? |
|---|---|---|---|
| LOW | LOW | Hors tension (power-down) | Pour mettre le capteur en veille dans un projet sur batterie |
| LOW | HIGH | 2 % (typiquement jusqu'à 12 kHz) | Processeurs lents, MicroPython et comptage par interruption |
| HIGH | LOW | 20 % (typiquement jusqu'à 120 kHz) | Le meilleur réglage pour Arduino et pulseIn |
| HIGH | HIGH | 100 % (typiquement jusqu'à 600 kHz) | Mesures rapides avec un compteur matériel |
| S2 | S3 | Groupe de photodiodes lu |
|---|---|---|
| LOW | LOW | Filtre rouge |
| LOW | HIGH | Filtre bleu |
| HIGH | LOW | Sans filtre (clear, lumière totale) |
| HIGH | HIGH | Filtre vert |
Câblage du TCS3200 : Arduino Uno, ESP32 et Pico
| Broche du module | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| VCC | 5V | 3V3 | 3V3(OUT), broche 36 |
| GND | GND | GND | GND |
| S0 | D4 | GPIO 32 | GP2 |
| S1 | D5 | GPIO 33 | GP3 |
| S2 | D6 | GPIO 25 | GP4 |
| S3 | D7 | GPIO 26 | GP5 |
| OUT | D8 | GPIO 27 | GP6 |
| OE | GND | GND | GND |
Les quatre LED blanches du module éclairent la surface de la même manière à chaque mesure, ce qui rend les résultats plus cohérents même si l'éclairage de la pièce change. Certaines cartes ont une broche LED séparée pour allumer et éteindre les LED, sur d'autres elles s'allument dès la mise sous tension ; regarde la sérigraphie de ta carte. Pour de meilleurs résultats, entoure le capteur d'un tube ou d'un carton noir, place l'objet toujours à la même distance et évite les surfaces brillantes et réfléchissantes. Tu peux vérifier le brochage de ta carte avec l'outil Pinout.
Pas à pas : lire R, V et B avec pulseIn
- Câble le module comme dans le tableau ci-dessus ; OE sur GND et VCC sur 5V.
- Choisis l'échelle de fréquence 20 % en mettant S0 à HIGH et S1 à LOW.
- Pour le rouge, mets S2 et S3 à LOW et attends quelques millisecondes que la sortie se stabilise.
- Mesure en microsecondes la durée de la partie LOW de l'impulsion avec pulseIn(OUT, LOW) ; fais la moyenne de 10 mesures pour réduire le bruit.
- Recommence pour le vert (S2 HIGH, S3 HIGH) et le bleu (S2 LOW, S3 HIGH).
- Suis les résultats dans le moniteur série à 9600 bauds et place des feuilles de différentes couleurs devant le capteur.
1// TCS3200 ile ham R, G, B okuma / Raw R, G, B reading with the TCS3200
2const int S0 = 4;
3const int S1 = 5;
4const int S2 = 6;
5const int S3 = 7;
6const int OUT_PIN = 8;
7
8// Filtreyi seçer, 10 darbenin ortalama LOW süresini döndürür (µs) / Selects a filter, returns the average LOW time of 10 pulses (µs)
9unsigned long readPulse(bool s2, bool s3) {
10 digitalWrite(S2, s2 ? HIGH : LOW);
11 digitalWrite(S3, s3 ? HIGH : LOW);
12 delay(5); // çıkışın oturmasını bekle / let the output settle
13 unsigned long total = 0;
14 int count = 0;
15 for (int i = 0; i < 10; i++) {
16 unsigned long t = pulseIn(OUT_PIN, LOW, 50000UL); // 50 ms zaman aşımı / 50 ms timeout
17 if (t > 0) {
18 total += t;
19 count++;
20 }
21 }
22 return count > 0 ? total / count : 50000UL; // darbe yoksa çok karanlık / no pulse means very dark
23}
24
25void setup() {
26 pinMode(S0, OUTPUT);
27 pinMode(S1, OUTPUT);
28 pinMode(S2, OUTPUT);
29 pinMode(S3, OUTPUT);
30 pinMode(OUT_PIN, INPUT);
31 digitalWrite(S0, HIGH); // S0=HIGH, S1=LOW: %20 ölçek / 20% scaling
32 digitalWrite(S1, LOW);
33 Serial.begin(9600);
34}
35
36void loop() {
37 unsigned long r = readPulse(false, false); // kırmızı filtre / red filter
38 unsigned long g = readPulse(true, true); // yeşil filtre / green filter
39 unsigned long b = readPulse(false, true); // mavi filtre / blue filter
40 Serial.print("R: ");
41 Serial.print(r);
42 Serial.print(" G: ");
43 Serial.print(g);
44 Serial.print(" B: ");
45 Serial.println(b);
46 delay(500);
47}Le point le plus important de ce code : le nombre lu est inversement proportionnel à la lumière. Plus la valeur est petite, plus cette couleur renvoie de lumière. Avec une feuille rouge devant le capteur, tu verras par exemple "R: 24 G: 68 B: 52" ; le plus petit nombre se trouve sur le canal rouge. Le délai maximal de 50 000 µs passé à pulseIn évite au code d'attendre la seconde complète prévue par défaut quand aucune impulsion n'arrive ; si aucune impulsion n'est captée, la fonction renvoie 50 000, ce qui signifie "très sombre". Si tu as du mal à lire la sortie série, jette un œil au guide du moniteur série Arduino.
Calibrage blanc et noir : convertir les valeurs brutes en 0–255
Les valeurs brutes seules sont trompeuses, car les trois groupes de photodiodes n'ont pas la même sensibilité et les LED blanches du module n'émettent pas toutes les couleurs de façon égale. C'est pourquoi même une feuille d'un blanc éclatant donne des nombres différents sur les trois canaux. Le calibrage gomme ces écarts et place chaque canal entre 0 (noir) et 255 (blanc) ; c'est la même idée que la balance des blancs d'un appareil photo. Calibre à l'endroit où le capteur travaillera vraiment, avec la même lumière et à la même distance ; un calibrage fait sur ton bureau ne vaut pas dans le boîtier de la machine.
- Fixe le capteur sur un support et règle la distance de mesure (par exemple 1,5 cm) pour qu'elle ne change pas.
- Place une feuille blanche unie devant, lis plusieurs fois les valeurs R, V et B avec le code ci-dessus et note leurs moyennes comme référence blanche ; ce sont les plus petites valeurs.
- Mets au même endroit une feuille noire mate ou de la feutrine et note les valeurs comme référence noire ; ce sont les plus grandes valeurs.
- Saisis ces six nombres dans les constantes WHITE_ et BLACK_ au début du code suivant, puis téléverse-le.
- Vérifie que les trois canaux sont proches de 255 sur la feuille blanche et de 0 sur la noire ; sinon, refais la mesure avec la même lumière et la même distance.
Attention à une erreur présente dans beaucoup d'exemples : convertir directement la durée d'impulsion en 0–255 avec map() ne donne pas le bon résultat, car la lumière est proportionnelle à la fréquence et non à la durée de l'impulsion. La bonne méthode consiste à convertir d'abord la durée en fréquence (1/t), puis à mettre à l'échelle : niveau = (f − f_noir) / (f_blanc − f_noir) × 255. Prenons un exemple : tu as mesuré 20 µs sur le blanc, 200 µs sur le noir, et l'objet donne 40 µs. map() le transforme en 226, alors que la méthode par la fréquence donne 113. La fréquence de l'objet vaut exactement la moitié de celle du blanc et, une fois le niveau du noir retranché, cela correspond à environ 44 % de l'échelle, soit 113 ; map(), lui, affiche les couleurs bien plus claires qu'elles ne le sont et complique la distinction des teintes sombres.
Algorithme de tri des couleurs : de quelle couleur s'agit-il ?
Les valeurs R, V, B calibrées dépendent encore de la quantité de lumière : si le même objet rouge se rapproche un peu du capteur, les trois valeurs augmentent ensemble. Pour corriger cela, on divise chaque valeur par la somme : r = R / (R + G + B), et de même pour g et b. Ces proportions de couleur restent presque constantes même si la distance et la luminosité varient un peu. Tu les compares ensuite à des proportions de référence mesurées et enregistrées une fois pour chaque couleur, et tu choisis le plus proche voisin. Pour comparer, il suffit d'additionner les carrés des écarts ; plus ce nombre est petit, plus les couleurs se ressemblent. Si même la référence la plus proche dépasse un certain seuil, le résultat est "inconnu". Si la lumière totale est très faible, l'objet est considéré comme noir, et si les trois canaux sont très élevés, comme blanc ; ces deux cas ne se distinguent pas par les proportions, ils sont donc testés en premier.
1// TCS3200 ile kalibrasyonlu renk tanıma / Calibrated color recognition with the TCS3200
2const int S0 = 4, S1 = 5, S2 = 6, S3 = 7, OUT_PIN = 8;
3
4// Kalibrasyonda ölçtüğün süreler (µs), kendi değerlerinle değiştir / Pulse widths from your calibration (µs), use your own
5const float WHITE_R = 16, WHITE_G = 20, WHITE_B = 18; // beyaz kağıt / white paper
6const float BLACK_R = 140, BLACK_G = 170, BLACK_B = 150; // siyah kağıt / black paper
7
8struct ColorRef {
9 const char *name;
10 float r, g, b; // renk oranları, toplamı 1 / color ratios, sum is 1
11};
12
13// Örnek referanslar, kendi ölçümlerinle değiştir / Sample references, replace with your own measurements
14ColorRef refs[] = {
15 {"Kirmizi / Red", 0.58, 0.20, 0.22},
16 {"Turuncu / Orange", 0.55, 0.30, 0.15},
17 {"Sari / Yellow", 0.42, 0.40, 0.18},
18 {"Yesil / Green", 0.24, 0.46, 0.30},
19 {"Mavi / Blue", 0.18, 0.30, 0.52},
20 {"Mor / Purple", 0.40, 0.20, 0.40}
21};
22const int REF_COUNT = sizeof(refs) / sizeof(refs[0]);
23const float MAX_DIST = 0.02; // bundan uzaksa bilinmiyor / farther than this is unknown
24
25unsigned long readPulse(bool s2, bool s3) {
26 digitalWrite(S2, s2 ? HIGH : LOW);
27 digitalWrite(S3, s3 ? HIGH : LOW);
28 delay(5);
29 unsigned long total = 0;
30 int count = 0;
31 for (int i = 0; i < 10; i++) {
32 unsigned long t = pulseIn(OUT_PIN, LOW, 50000UL);
33 if (t > 0) {
34 total += t;
35 count++;
36 }
37 }
38 return count > 0 ? total / count : 50000UL;
39}
40
41// Süreyi frekansa çevirip 0-255 arasına ölçekler / Converts the pulse width to frequency and scales it to 0-255
42float toLevel(unsigned long t, float tWhite, float tBlack) {
43 float f = 1.0 / t; // ışık frekansla orantılı / light is proportional to frequency
44 float fWhite = 1.0 / tWhite;
45 float fBlack = 1.0 / tBlack;
46 float level = (f - fBlack) / (fWhite - fBlack) * 255.0;
47 return constrain(level, 0.0, 255.0);
48}
49
50// En yakın referans rengi bulur / Finds the nearest reference color
51const char *classify(float R, float G, float B) {
52 float sum = R + G + B;
53 if (sum < 90) return "Siyah / Black"; // çok az ışık / very little light
54 if (R > 200 && G > 200 && B > 200) return "Beyaz / White";
55 float r = R / sum, g = G / sum, b = B / sum; // parlaklıktan bağımsız oranlar / brightness-independent ratios
56 int best = 0;
57 float bestDist = 1e9;
58 for (int i = 0; i < REF_COUNT; i++) {
59 float d = sq(r - refs[i].r) + sq(g - refs[i].g) + sq(b - refs[i].b); // uzaklığın karesi / squared distance
60 if (d < bestDist) {
61 bestDist = d;
62 best = i;
63 }
64 }
65 if (bestDist > MAX_DIST) return "Bilinmiyor / Unknown";
66 return refs[best].name;
67}
68
69void setup() {
70 pinMode(S0, OUTPUT);
71 pinMode(S1, OUTPUT);
72 pinMode(S2, OUTPUT);
73 pinMode(S3, OUTPUT);
74 pinMode(OUT_PIN, INPUT);
75 digitalWrite(S0, HIGH); // %20 ölçek / 20% scaling
76 digitalWrite(S1, LOW);
77 Serial.begin(9600);
78}
79
80void loop() {
81 float R = toLevel(readPulse(false, false), WHITE_R, BLACK_R);
82 float G = toLevel(readPulse(true, true), WHITE_G, BLACK_G);
83 float B = toLevel(readPulse(false, true), WHITE_B, BLACK_B);
84 float sum = R + G + B;
85 Serial.print("R=");
86 Serial.print(R, 0);
87 Serial.print(" G=");
88 Serial.print(G, 0);
89 Serial.print(" B=");
90 Serial.print(B, 0);
91 if (sum > 0) { // referans için oranlar / ratios for your references
92 Serial.print(" r=");
93 Serial.print(R / sum, 2);
94 Serial.print(" g=");
95 Serial.print(G / sum, 2);
96 Serial.print(" b=");
97 Serial.print(B / sum, 2);
98 }
99 Serial.print(" -> ");
100 Serial.println(classify(R, G, B));
101 delay(500);
102}| Partie du code | Rôle |
|---|---|
| WHITE_* et BLACK_* | Les durées d'impulsion du blanc et du noir mesurées au calibrage (µs) |
| toLevel() | Convertit la durée d'impulsion en fréquence et la ramène entre 0 et 255 |
| refs[] | Proportions r, g, b de référence de chaque couleur ; remplace-les par tes propres mesures |
| classify() | Sépare d'abord le noir et le blanc, puis cherche la référence la plus proche |
| MAX_DIST | Les mesures au-delà de cette distance sont classées "Inconnu" |
Construire une machine qui trie les objets par couleur
Le projet TCS3200 le plus apprécié est une machine qui trie des bonbons colorés, des perles ou des pièces LEGO par couleur. Le mécanisme compte deux servos. Le servo d'alimentation, en haut, fait tourner un disque percé d'un trou où tient un seul objet : il prend d'abord un objet sous le tube de la trémie, l'amène devant le capteur puis, après la mesure, le lâche dans la goulotte du dessous. Le servo de la goulotte, en bas, oriente une goulotte inclinée et envoie l'objet dans le bac de sa couleur. Si tu utilises des servos pour la première fois, lis d'abord Qu'est-ce qu'un servomoteur ?.
- Installe la trémie et un tube un peu plus large que les objets, pour qu'ils tombent un par un sur le disque d'alimentation.
- Fixe le capteur pour qu'il voie l'objet posé sur le disque à 1–2 cm, et ferme l'ensemble pour bloquer la lumière extérieure.
- Définis trois angles pour le servo d'alimentation : chargement, capteur et largage. Trouve-les par essais sur ton propre mécanisme ; branche le servo d'alimentation sur D9 et celui de la goulotte sur D10.
- Attribue un angle du servo de goulotte à chaque bac de couleur (par exemple rouge 30°, vert 75°, bleu 120°, tout le reste 165°).
- Calibre à l'intérieur de la machine, avec son propre éclairage, et teste avec plusieurs objets de chaque couleur.
1// TCS3200 ve iki servoyla renk ayırıcı / Color sorter with a TCS3200 and two servos
2#include <Servo.h>
3
4const int S0 = 4, S1 = 5, S2 = 6, S3 = 7, OUT_PIN = 8;
5const int FEEDER_PIN = 9; // besleme servosu / feeder servo
6const int CHUTE_PIN = 10; // yönlendirme servosu / chute servo
7
8const int LOAD_ANGLE = 160; // huninin altı / under the hopper
9const int SENSOR_ANGLE = 95; // sensörün önü / in front of the sensor
10const int DROP_ANGLE = 30; // bırakma deliği / drop hole
11
12// Kalibrasyon süreleri (µs) / Calibration pulse widths (µs)
13const float WHITE_R = 16, WHITE_G = 20, WHITE_B = 18;
14const float BLACK_R = 140, BLACK_G = 170, BLACK_B = 150;
15
16Servo feeder;
17Servo chute;
18
19unsigned long readPulse(bool s2, bool s3) {
20 digitalWrite(S2, s2 ? HIGH : LOW);
21 digitalWrite(S3, s3 ? HIGH : LOW);
22 delay(5);
23 unsigned long total = 0;
24 int count = 0;
25 for (int i = 0; i < 10; i++) {
26 unsigned long t = pulseIn(OUT_PIN, LOW, 50000UL);
27 if (t > 0) {
28 total += t;
29 count++;
30 }
31 }
32 return count > 0 ? total / count : 50000UL;
33}
34
35float toLevel(unsigned long t, float tWhite, float tBlack) {
36 float f = 1.0 / t;
37 float level = (f - 1.0 / tBlack) / (1.0 / tWhite - 1.0 / tBlack) * 255.0;
38 return constrain(level, 0.0, 255.0);
39}
40
41// Baskın kanala göre kutu açısını seçer / Picks the bin angle from the dominant channel
42int binAngle(float R, float G, float B) {
43 if (R + G + B < 90) return 165; // çok koyu: diğer kutusu / too dark: "other" bin
44 if (R > G * 1.3 && R > B * 1.3) return 30; // kırmızı kutusu / red bin
45 if (G > R * 1.3 && G > B * 1.3) return 75; // yeşil kutusu / green bin
46 if (B > R * 1.3 && B > G * 1.3) return 120; // mavi kutusu / blue bin
47 return 165; // karar verilemedi / undecided
48}
49
50void setup() {
51 pinMode(S0, OUTPUT);
52 pinMode(S1, OUTPUT);
53 pinMode(S2, OUTPUT);
54 pinMode(S3, OUTPUT);
55 pinMode(OUT_PIN, INPUT);
56 digitalWrite(S0, HIGH); // %20 ölçek / 20% scaling
57 digitalWrite(S1, LOW);
58 feeder.attach(FEEDER_PIN);
59 chute.attach(CHUTE_PIN);
60 feeder.write(LOAD_ANGLE);
61 delay(500);
62}
63
64void loop() {
65 feeder.write(LOAD_ANGLE); // huniden bir nesne al / take one object from the hopper
66 delay(600);
67 feeder.write(SENSOR_ANGLE); // sensörün önüne getir / bring it to the sensor
68 delay(600); // servo dursun, titreşim geçsin / let the servo settle
69 float R = toLevel(readPulse(false, false), WHITE_R, BLACK_R);
70 float G = toLevel(readPulse(true, true), WHITE_G, BLACK_G);
71 float B = toLevel(readPulse(false, true), WHITE_B, BLACK_B);
72 chute.write(binAngle(R, G, B)); // kanalı doğru kutuya çevir / aim the chute at the right bin
73 delay(400);
74 feeder.write(DROP_ANGLE); // nesneyi kanala bırak / drop the object into the chute
75 delay(600);
76}TCS3200 avec ESP32 : mesurer la fréquence par interruption
Le même code avec pulseIn fonctionne sur l'ESP32, mais il existe une méthode plus stable : au lieu de chronométrer les impulsions une par une, compter combien arrivent pendant une durée fixe. Une interruption incrémente un compteur à chaque front montant ; en multipliant par 20 le compte obtenu après 50 ms, tu obtiens la fréquence en hertz. Comme cette méthode fait la moyenne de centaines d'impulsions, une seule impulsion perturbée ne la dérange pas. Le processeur à 240 MHz de l'ESP32 encaisse sans peine des dizaines de milliers d'interruptions par seconde à l'échelle 20 % ; si le compte devient trop grand sous une lumière très forte, tu peux passer à 2 %. Tu peux aussi utiliser cette méthode sur l'Arduino Uno en déplaçant OUT sur la broche D2, qui gère les interruptions. Sur l'ESP32, n'oublie pas d'alimenter le module par la broche 3V3.
1// ESP32: kesmeyle TCS3200 frekans ölçümü / ESP32: TCS3200 frequency measurement with an interrupt
2const int S0 = 32, S1 = 33, S2 = 25, S3 = 26, OUT_PIN = 27;
3
4volatile uint32_t pulseCount = 0;
5
6void IRAM_ATTR onPulse() {
7 pulseCount++; // her yükselen kenarda say / count every rising edge
8}
9
10// Seçilen filtrenin frekansını Hz olarak döndürür / Returns the frequency of the selected filter in Hz
11uint32_t readHz(bool s2, bool s3) {
12 digitalWrite(S2, s2 ? HIGH : LOW);
13 digitalWrite(S3, s3 ? HIGH : LOW);
14 delay(5); // çıkış otursun / let the output settle
15 pulseCount = 0;
16 delay(50); // 50 ms boyunca say / count for 50 ms
17 return pulseCount * 20; // 50 ms x 20 = 1 saniye / 1 second
18}
19
20void setup() {
21 Serial.begin(115200);
22 pinMode(S0, OUTPUT);
23 pinMode(S1, OUTPUT);
24 pinMode(S2, OUTPUT);
25 pinMode(S3, OUTPUT);
26 pinMode(OUT_PIN, INPUT);
27 digitalWrite(S0, HIGH); // %20 ölçek / 20% scaling
28 digitalWrite(S1, LOW);
29 attachInterrupt(digitalPinToInterrupt(OUT_PIN), onPulse, RISING);
30}
31
32void loop() {
33 uint32_t r = readHz(false, false); // kırmızı / red
34 uint32_t g = readHz(true, true); // yeşil / green
35 uint32_t b = readHz(false, true); // mavi / blue
36 Serial.print("R: ");
37 Serial.print(r);
38 Serial.print(" Hz G: ");
39 Serial.print(g);
40 Serial.print(" Hz B: ");
41 Serial.print(b);
42 Serial.println(" Hz");
43 delay(300);
44}TCS3200 avec la Raspberry Pi Pico et MicroPython
Sur la Pico, l'équivalent du pulseIn d'Arduino est la fonction machine.time_pulse_us() : elle renvoie en microsecondes la durée d'une impulsion au niveau demandé, et un nombre négatif en cas de délai dépassé. Si on l'appelle alors que la broche est déjà à ce niveau, elle commence à mesurer immédiatement et peut ne mesurer qu'une demi-impulsion ; c'est pourquoi le code attend d'abord la fin de la partie HIGH, puis mesure la durée LOW. Comme chaque appel de fonction en MicroPython prend quelques microsecondes, nous avons choisi ici l'échelle 2 % (S0=0, S1=1) : les impulsions sont 10 fois plus longues et l'effet de ce retard diminue. Les valeurs de calibrage s'écrivent en Hz ; à l'échelle 2 %, il est normal de voir quelques kHz sur une feuille blanche et quelques centaines de Hz sur une noire. Alimente le module par la broche 3V3(OUT) de la Pico ; si tu découvres la Pico, Qu'est-ce que la Raspberry Pi Pico ? explique comment installer MicroPython.
1# Pico + TCS3200: süreden frekansa ve 0-255 seviyesine / Pico + TCS3200: from pulse width to frequency and a 0-255 level
2from machine import Pin, time_pulse_us
3import time
4
5s0 = Pin(2, Pin.OUT)
6s1 = Pin(3, Pin.OUT)
7s2 = Pin(4, Pin.OUT)
8s3 = Pin(5, Pin.OUT)
9out = Pin(6, Pin.IN)
10
11s0.value(0) # S0=0, S1=1: %2 ölçek / 2% scaling
12s1.value(1)
13
14FILTERS = {"R": (0, 0), "G": (1, 1), "B": (0, 1)} # S2, S3 değerleri / S2, S3 values
15WHITE_HZ = {"R": 3125, "G": 2500, "B": 2778} # beyaz kağıtta Hz / Hz on white paper
16BLACK_HZ = {"R": 357, "G": 294, "B": 333} # siyah kağıtta Hz / Hz on black paper
17
18def read_hz(channel, samples=10):
19 s2.value(FILTERS[channel][0])
20 s3.value(FILTERS[channel][1])
21 time.sleep_ms(5) # çıkış otursun / let the output settle
22 total = 0
23 count = 0
24 for _ in range(samples):
25 time_pulse_us(out, 1, 50000) # HIGH bitsin, LOW başında ol / wait for HIGH to end
26 t = time_pulse_us(out, 0, 50000) # LOW süresi, µs / LOW time, µs
27 if t > 0: # negatif = zaman aşımı / negative = timeout
28 total += t
29 count += 1
30 if count == 0:
31 return 0
32 return 1000000 / (2 * total / count) # f = 1 / (2t)
33
34def level(channel, hz):
35 v = (hz - BLACK_HZ[channel]) / (WHITE_HZ[channel] - BLACK_HZ[channel]) * 255
36 return max(0, min(255, int(v)))
37
38while True:
39 r = level("R", read_hz("R"))
40 g = level("G", read_hz("G"))
41 b = level("B", read_hz("B"))
42 print("R:", r, "G:", g, "B:", b)
43 time.sleep(0.5)TCS3200 ou TCS34725 ?
Le TCS34725 est un capteur de couleur plus récent qui fait le même travail en I2C. Il effectue la mesure dans la puce elle-même et fournit les résultats sous forme de nombres de 16 bits par canal ; l'Arduino n'a aucune impulsion à mesurer. Sa différence la plus importante est le filtre bloquant l'infrarouge (IR) placé sur ses photodiodes. Le TCS3200 n'en a pas ; comme les photodiodes en silicium sont aussi sensibles à l'infrarouge, les mesures dérivent sous une lumière riche en IR comme le soleil ou les ampoules à incandescence. Comme le gain (1x, 4x, 16x, 60x) et le temps d'intégration (2,4–614 ms) du TCS34725 se règlent par logiciel, il fonctionne sur une large plage, de la lumière très faible à la lumière vive. Si tu veux savoir comment fonctionne l'I2C, consulte l'article Qu'est-ce que l'I2C ?.

| Caractéristique | TCS3200 | TCS34725 |
|---|---|---|
| Sortie | Fréquence (signal carré) | I2C, adresse 0x29 |
| Fils de signal | S0–S3, OUT et OE | SDA et SCL (INT et LED en option) |
| Résolution | Dépend de la méthode et de la durée de mesure | 16 bits par canal |
| Filtre IR | Non | Oui (sur la puce) |
| Réglages | 3 échelles de fréquence et mise hors tension | 4 gains, temps d'intégration de 2,4 à 614 ms |
| Alimentation | 2,7–5,5 V | Puce en 3,3 V ; modules avec régulateur en 3–5 V |
| Éclairage | Généralement 4 LED blanches | Généralement 1 LED blanche |
| Charge du processeur | Occupé pendant la mesure des impulsions | La puce mesure, l'Arduino se contente de lire |
| Idéal pour | Apprendre, trieurs de couleurs simples | Couleur précise, température de couleur et mesure en lux |
1// TCS34725 ile ham RGBC, renk sıcaklığı ve lüks / Raw RGBC, color temperature and lux with the TCS34725
2#include <Wire.h>
3#include <Adafruit_TCS34725.h>
4
5// 50 ms entegrasyon süresi, 4x kazanç / 50 ms integration time, 4x gain
6Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);
7
8void setup() {
9 Serial.begin(9600);
10 if (!tcs.begin()) { // 0x29 adresinde ara / look for it at 0x29
11 Serial.println("TCS34725 bulunamadi / not found");
12 while (true) {
13 delay(1000);
14 }
15 }
16}
17
18void loop() {
19 uint16_t r, g, b, c;
20 tcs.getRawData(&r, &g, &b, &c); // 16 bit ham değerler / 16-bit raw values
21 uint16_t kelvin = tcs.calculateColorTemperature_dn40(r, g, b, c);
22 uint16_t lux = tcs.calculateLux(r, g, b);
23 Serial.print("R: ");
24 Serial.print(r);
25 Serial.print(" G: ");
26 Serial.print(g);
27 Serial.print(" B: ");
28 Serial.print(b);
29 Serial.print(" C: ");
30 Serial.print(c);
31 Serial.print(" K: ");
32 Serial.print(kelvin);
33 Serial.print(" Lux: ");
34 Serial.println(lux);
35 delay(500);
36}Avant de téléverser le code, installe la bibliothèque Adafruit TCS34725 depuis le gestionnaire de bibliothèques ; quand il te propose les dépendances, choisis de toutes les installer. Sur l'Arduino Uno, relie SDA à A4 et SCL à A5 ; sur l'ESP32, aux GPIO 21 et 22. getRawData() attend la fin du temps d'intégration et renvoie les valeurs brutes rouge, verte, bleue et sans filtre (C) ; calculateColorTemperature_dn40() donne la température de couleur en kelvins et calculateLux() le niveau d'éclairement approximatif. Le calibrage et la logique de la couleur la plus proche s'appliquent de la même façon à ce capteur. Si tu cherches un capteur qui détecte aussi les gestes de la main et la proximité en plus de la couleur, l'APDS-9960 est une bonne alternative.
Idées de projets avec le TCS3200
- Machine de tri par couleur : Trie des bonbons, des perles ou des pièces LEGO dans des bacs séparés selon leur couleur.
- Lampe caméléon : Reproduis la couleur de l'objet placé devant le capteur avec une LED RVB ou un ruban WS2812B.
- Robot qui lit les couleurs : Apprends à ton robot suiveur de ligne à s'arrêter sur un repère rouge au sol et à repartir sur un vert.
- Bras robotique qui reconnaît les couleurs : Utilise un bras robotique pour saisir des cubes et déposer chaque couleur dans son propre bac.
- Détecteur de couleur parlant : Annonce la couleur détectée avec un message préenregistré sur un DFPlayer Mini ; une aide pratique pour les personnes malvoyantes.
- Suivi de la couleur de l'eau : Observe dans le temps les changements de couleur de l'eau d'un récipient transparent et déclenche une alerte pour un aquarium ou une cuve d'arrosage.
Erreurs fréquentes et solutions
| Symptôme | Cause probable | Solution |
|---|---|---|
| pulseIn renvoie toujours 0 ou la valeur de délai | OE en l'air ou à HIGH, S0 et S1 tous deux à LOW (hors tension) ou OUT sur la mauvaise broche | Relie OE à GND, mets S0 à HIGH et S1 à LOW, compare la broche OUT avec le code |
| Les valeurs sautent sans arrêt | Lumière ambiante, lampe qui scintille ou distance qui varie | Protège le capteur avec un tube noir, fixe la distance, fais la moyenne de plusieurs mesures |
| Tous les objets sortent de la même couleur | Pas de calibrage ; les canaux n'ont pas la même sensibilité | Fais le calibrage blanc et noir, mesure à nouveau les références |
| Les couleurs dérivent à la lumière du jour | Le TCS3200 n'a pas de filtre IR | Mesure dans une boîte fermée ou utilise un TCS34725 |
| Les niveaux restent bloqués à 0 ou 255 | L'objet n'est pas à la même distance qu'au calibrage | Garde la même distance qu'au calibrage, recalibre si besoin |
| L'ESP32 ou la Pico se comporte bizarrement | Module alimenté en 5 V, OUT sort du 5 V | Alimente le module en 3V3 ou utilise un convertisseur de niveau |
| Les mesures se faussent quand le servo tourne | Le courant du servo fait chuter la tension d'alimentation | Source 5 V séparée pour les servos, masses reliées |
Le TCS3200 est un excellent capteur pour comprendre comment la lumière devient une fréquence, pourquoi le calibrage est indispensable et comment bâtir un algorithme de classification simple. Passer au TCS34725 quand tu as besoin de plus de précision est facile, car le calibrage et la logique de la couleur la plus proche que tu as appris restent valables tels quels. Dans l'application BlueGrays, tu trouveras des projets de mélange de couleurs avec une LED RVB, une lampe mélangeuse de couleurs à ESP32, la mesure de lumière avec une LDR et des projets à servomoteur, avec schémas de câblage et code pas à pas ; combine-les avec le capteur de couleur pour construire ta propre machine.
Questions fréquentes
À quelle distance le capteur TCS3200 détecte-t-il les couleurs ?
Les résultats les plus stables s'obtiennent vers 1–3 cm, car la lumière des LED du module faiblit vite avec la distance. Plus que la distance elle-même, l'essentiel est de la garder identique à chaque mesure ; fais aussi le calibrage à cette distance. Ce capteur ne convient pas pour lire la couleur de grandes surfaces éloignées.
Quelle est la différence entre le TCS230 et le TCS3200 ?
Le TCS230 est l'ancien capteur de couleur du même fabricant, et le TCS3200 sa version améliorée. Tous deux utilisent une matrice de photodiodes 8×8, une sortie en fréquence et la même logique de commande S0–S3 ; le câblage et le code sont donc identiques. La plupart des modules vendus aujourd'hui sont équipés d'un TCS3200.
Pourquoi pulseIn renvoie 0 avec le TCS3200 ?
pulseIn renvoie 0 lorsqu'il ne voit aucune impulsion dans le délai indiqué. Les causes les plus courantes sont une broche OE non reliée à GND, S0 et S1 tous deux à LOW (le capteur passe alors hors tension) et une sortie OUT branchée sur une autre broche que celle du code. Si tout est noir devant le capteur, la fréquence tombe à quelques hertz et aucune impulsion n'est captée avec un délai court.
Le TCS3200 fonctionne-t-il avec l'ESP32 et la Raspberry Pi Pico ?
Oui. Comme le TCS3200 fonctionne entre 2,7 et 5,5 V, tu peux alimenter le module par la broche 3V3 de la carte ; la broche OUT délivre alors aussi des impulsions de 3,3 V. Si tu l'alimentes en 5 V, il te faut un pont diviseur ou un convertisseur de niveau sur la ligne OUT. Pour mesurer en MicroPython sur la Pico, l'échelle de fréquence 2 % donne des résultats plus précis.
Lequel choisir : TCS3200 ou TCS34725 ?
Pour une mesure de couleur précise, le TCS34725 est meilleur : il possède un filtre anti-IR, une résolution de 16 bits par canal et un gain réglable, et se branche avec seulement deux fils I2C. Le TCS3200 reste un choix courant et tout à fait suffisant pour apprendre la mesure de fréquence et le calibrage, et pour construire des trieurs de couleurs simples.
Combien de couleurs le TCS3200 peut-il distinguer ?
Sous un éclairage maîtrisé et à distance fixe, le TCS3200 sépare de façon fiable 6 à 8 couleurs nettement différentes, comme le rouge, l'orange, le jaune, le vert, le bleu, le violet, le noir et le blanc. Distinguer des teintes proches, comme le vert clair et le vert foncé, est possible aussi, mais demande un calibrage plus soigné, de nombreuses mesures de référence par teinte et un seuil serré.
Projets à réaliser après cet article
Voir tous les projets
Mesurer l'intensité lumineuse avec une LDR
Envie de voir en chiffres à quel point ta chambre est lumineuse ? Le LDR, une petite pièce sensible à la lumière, mesure la lumière ambiante, et l'Arduino écrit la valeur sur l'écran de ton ordinateur

Mesure de l'intensité lumineuse avec le module LDR ESP32
Suivi en temps réel sur le moniteur série de la valeur brute de l'ADC du module LDR et du pourcentage relatif de luminosité calculé à partir de références dans l'obscurité et à la lumière. Ce pourcentage n'est pas une mesure en lux. Permet de comprendre le principe de calibrage du module. Il est préférable de réaliser cet exercice avant le projet 10, car il sert à déterminer la valeur seuil.

Utilisation d'une LED RVB
Trois couleurs se cachent dans une seule LED : la LED RGB s'allume en rouge, puis en vert, puis en bleu, chaque couleur allumée une demi-seconde puis éteinte une demi-seconde, avant que tout recommenc

Transition douce des couleurs avec une LED RVB
Une seule LED RGB glisse doucement du rouge au vert, du vert au bleu, puis revient au rouge, dans une boucle arc-en-ciel qui ne s'arrête jamais. Chaque transition dure environ deux secondes et demie,

Lampe à mélangeur de couleurs ESP32 (3 potentiomètres + LED RVB + écran OLED)
Une lampe mélangeuse de couleurs intelligente qui vous permet de créer la couleur de votre choix en tournant 3 potentiomètres grâce à l'ESP32 ! À mesure que vous tournez les potentiomètres rouge, vert et bleu, la LED RVB à cathode commune change de couleur en temps réel. L'écran OLED SSD1306 affiche en temps réel la valeur de chaque couleur sur une plage de 0 à 255, des barres de remplissage visuelles et le code couleur HEX (#FF8040, par exemple). Un mini-studio de couleur professionnel — il per

Contrôle d'une LED RVB avec ESP32
Génération illimitée de couleurs avec une seule LED RVB au lieu de 3 LED séparées. Comme dans Arduino, nous réalisons une transition arc-en-ciel en réglant les valeurs R/G/B avec analogWrite(). La théorie des couleurs (telle que rouge+vert=jaune) est mise en pratique.

Utilisation du servomoteur
Le bras d'un petit servomoteur tourne tour à tour vers trois positions : tout au début, pile au milieu et tout au bout, en attendant deux secondes à chaque arrêt. L'Arduino indique au moteur l'angle à

TCRT5000 Détection de surface noire et blanche
Avec le petit capteur qui sert d'œil aux robots suiveurs de ligne, tu sais si le sol est noir ou blanc. Le TCRT5000 envoie une lumière invisible vers le sol et regarde combien revient ; sur du blanc l
Autres articles
Application BlueGrays
Réalise ce montage pas à pas sur ton téléphone
Schéma, code et liste des composants sur un seul écran. Plus de 200 projets Arduino, ESP32 et Pico à réaliser.
Scanne avec ton téléphone
Pointe l’appareil photo vers le code : la boutique d’applications de ton téléphone s’ouvre.
ou ouvre la boutique

