Sensor Warna TCS3200 dengan Arduino: Pengkabelan, Kalibrasi, dan Kode
Cara kerja sensor warna TCS3200: pengaturan S0–S3, membaca R, G, B dengan pulseIn, kalibrasi putih dan hitam, pemilahan warna, serta kode ESP32, Pico, dan TCS34725.
Sensor warna TCS3200 adalah modul pendeteksi warna yang paling banyak dipakai di proyek Arduino: sensor ini mengukur warna permukaan di depannya dengan memecahnya menjadi komponen merah, hijau, dan biru. Cahaya yang ditangkap oleh susunan fotodioda langsung diubah menjadi frekuensi: makin banyak cahaya merah yang dipantulkan sebuah permukaan, makin tinggi frekuensi di kanal merah. Tidak ada pembacaan analog atau protokol komunikasi khusus; kamu bisa membaca nilai R, G, dan B hanya dengan beberapa baris kode memakai perintah pulseIn() dari Arduino. Mesin pemilah permen, robot pengenal warna, kendaraan yang berbelok di tanda berwarna di lantai, dan lampu yang meniru warna benda yang didekatkan ke depannya, semuanya dibuat dengan sensor ini.
Di panduan ini kamu akan melihat langkah demi langkah apa isi sensornya, apa fungsi pin S0–S3, cara menghubungkannya ke Arduino Uno, ESP32, dan Raspberry Pi Pico, cara mengambil pembacaan mentah, cara melakukan kalibrasi putih dan hitam, serta algoritma yang menentukan warna apa yang cocok dengan sebuah pembacaan. Setelah itu kita akan menyusun logika mesin yang memilah benda berdasarkan warna, dan terakhir membandingkannya dengan TCS34725, sensor yang bekerja lewat I2C.

Apa itu sensor warna TCS3200 dan bagaimana cara kerjanya?
Chip TCS3200 yang menjadi jantung modul ini (versi lamanya bernama TCS230) memiliki 64 fotodioda dalam kisi 8×8 di permukaannya. Enam belas di antaranya berada di bawah filter merah, 16 di bawah filter hijau, 16 di bawah filter biru, dan 16 sisanya tanpa filter (clear) sehingga melihat jumlah cahaya total. Ke-16 fotodioda dari setiap warna terhubung paralel, dan pin S2 serta S3 memilih kelompok mana yang diukur. Karena fotodioda dengan warna berbeda disusun berselang-seling di seluruh susunan, cahaya yang jatuh di satu sudut permukaan memengaruhi semua kelompok warna secara merata.
Arus kecil yang dihasilkan kelompok fotodioda terpilih masuk ke konverter arus ke frekuensi di dalam chip. Rangkaian ini menghasilkan gelombang kotak dengan duty cycle 50%, dan frekuensi gelombangnya berbanding lurus dengan intensitas cahaya. Jadi yang kamu ukur bukan tegangan, melainkan jumlah pulsa per detik: beberapa hertz dalam gelap total, puluhan kilohertz ketika didekatkan ke permukaan putih. Kelebihan keluaran frekuensi adalah tahan terhadap derau dan bisa dihubungkan ke pin digital mana pun di Arduino. Kalau kamu hanya ingin mengukur seberapa kuat cahayanya, sensor cahaya LDR adalah pilihan yang lebih sederhana; TCS3200 melakukan pekerjaan yang sama secara terpisah untuk tiga warna.
| Fitur | Nilai |
|---|---|
| Chip | TCS3200 (versi lama TCS230, kompatibel pin) |
| Susunan fotodioda | 8×8 = 64: 16 merah, 16 hijau, 16 biru, 16 clear |
| Keluaran | Gelombang kotak dengan duty cycle 50%, frekuensi sebanding dengan cahaya |
| Frekuensi skala penuh (tipikal) | 600 kHz (100%), 120 kHz (20%), 12 kHz (2%) |
| Tegangan catu daya | 2,7–5,5 V |
| Arus chip | Tipikal 1,4 mA (arus LED modul ditambahkan di atasnya) |
| Pin kontrol | S0, S1 (skala frekuensi), S2, S3 (filter warna), OE (output enable, aktif LOW) |
| Jarak yang disarankan | Sekitar 1–3 cm, sama untuk setiap pembacaan |
| Pencahayaan | 4 LED putih di modul |
Pin S0–S3: skala frekuensi dan pemilihan filter warna
Empat pin kontrol menentukan perilaku TCS3200. S0 dan S1 memperkecil frekuensi keluaran: pada 100%, pulsa menyusut sampai beberapa mikrodetik dan mendekati batas ketelitian pengukuran Arduino Uno, sedangkan pada 2% pulsanya lebih panjang tetapi jumlah pulsa yang datang dalam waktu yang sama lebih sedikit. S2 dan S3 memilih filter warna mana yang dibaca. Kamu menghubungkan pin-pin ini ke output digital Arduino dan mengaturnya dari kode sebelum setiap pembacaan.
| S0 | S1 | Skala frekuensi keluaran | Kapan dipakai |
|---|---|---|---|
| LOW | LOW | Power down (mati daya) | Untuk menidurkan sensor di proyek bertenaga baterai |
| LOW | HIGH | 2% (tipikal sampai 12 kHz) | Prosesor lambat, MicroPython, dan penghitungan dengan interrupt |
| HIGH | LOW | 20% (tipikal sampai 120 kHz) | Pengaturan terbaik untuk Arduino dan pulseIn |
| HIGH | HIGH | 100% (tipikal sampai 600 kHz) | Pengukuran cepat dengan penghitung hardware |
| S2 | S3 | Kelompok fotodioda yang dibaca |
|---|---|---|
| LOW | LOW | Filter merah |
| LOW | HIGH | Filter biru |
| HIGH | LOW | Tanpa filter (clear, cahaya total) |
| HIGH | HIGH | Filter hijau |
Pengkabelan TCS3200: Arduino Uno, ESP32, dan Pico
| Pin modul | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| VCC | 5V | 3V3 | 3V3(OUT), pin 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 |
Empat LED putih di modul menerangi permukaan dengan cara yang sama untuk setiap pembacaan, sehingga hasilnya tetap lebih konsisten meskipun pencahayaan ruangan berubah. Beberapa board punya pin LED terpisah untuk menyalakan dan mematikan LED, sementara di board lain LED langsung menyala begitu daya diberikan; cek label di board-mu sendiri. Untuk hasil terbaik, bungkus sensor dengan tabung hitam atau karton, dekatkan benda pada jarak yang sama setiap kali, dan hindari permukaan yang mengilap dan memantulkan cahaya. Kamu bisa mengecek tata letak pin board-mu di alat Pinout.
Langkah demi langkah: membaca R, G, dan B dengan pulseIn
- Hubungkan modul seperti pada tabel di atas; sambungkan OE ke GND dan VCC ke 5V.
- Pilih skala frekuensi 20% dengan membuat S0 HIGH dan S1 LOW.
- Untuk merah, buat S2 dan S3 LOW, lalu tunggu beberapa milidetik agar output-nya stabil.
- Ukur lama bagian LOW dari pulsa dalam mikrodetik dengan pulseIn(OUT, LOW); ambil rata-rata 10 pembacaan untuk mengurangi derau.
- Ulangi hal yang sama untuk hijau (S2 HIGH, S3 HIGH) dan biru (S2 LOW, S3 HIGH).
- Lihat hasilnya di Serial Monitor pada 9600 baud, lalu dekatkan kertas dengan berbagai warna ke depan sensor.
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}Poin terpenting di kode ini adalah angka yang kamu baca berbanding terbalik dengan cahaya: makin kecil nilainya, makin banyak cahaya dari warna itu. Ketika kamu mendekatkan kertas merah, kamu akan melihat output seperti “R: 24 G: 68 B: 52”; angka terkecil ada di kanal merah. Timeout 50.000 µs yang diberikan ke pulseIn mencegah kode menunggu selama 1 detik (nilai bawaan) ketika tidak ada pulsa yang datang; jika tidak ada pulsa yang tertangkap sama sekali, fungsi ini mengembalikan 50.000, yang berarti “sangat gelap”. Kalau kamu kesulitan membaca output serial, lihat panduan Serial Monitor Arduino.
Kalibrasi putih dan hitam: mengubah nilai mentah menjadi 0–255
Nilai mentah saja bisa menyesatkan, karena ketiga kelompok fotodioda tidak punya sensitivitas yang sama dan LED putih di modul tidak memancarkan setiap warna secara merata. Itu sebabnya kertas yang benar-benar putih pun memberi angka berbeda di tiga kanal. Kalibrasi menghilangkan perbedaan ini dan menempatkan setiap kanal di antara 0 (hitam) dan 255 (putih); idenya sama dengan white balance di kamera. Lakukan kalibrasi di tempat sensor benar-benar akan bekerja, di bawah cahaya yang sama dan pada jarak yang sama; kalibrasi yang dilakukan di mejamu tidak akan berlaku di dalam casing mesin.
- Pasang sensor di dudukan tetap dan atur jarak ukurnya (misalnya 1,5 cm) supaya tidak berubah.
- Letakkan kertas putih polos di depannya, baca nilai R, G, dan B beberapa kali dengan kode di atas, lalu catat rata-ratanya sebagai referensi putih; ini adalah nilai-nilai terkecil.
- Letakkan kertas hitam doff atau kain felt di tempat yang sama dan catat pembacaannya sebagai referensi hitam; ini adalah nilai-nilai terbesar.
- Masukkan keenam angka ini ke konstanta WHITE_ dan BLACK_ di bagian atas kode di bawah, lalu upload kodenya.
- Pastikan ketiga kanal terbaca mendekati 255 pada kertas putih dan mendekati 0 pada kertas hitam; jika tidak, ulangi pengukuran dengan cahaya dan jarak yang sama.
Waspadai kesalahan yang ada di banyak contoh: mengubah lebar pulsa langsung ke 0–255 dengan map() tidak memberi hasil yang benar, karena cahaya sebanding dengan frekuensi, bukan dengan lebar pulsa. Cara yang benar adalah mengubah lebar pulsa ke frekuensi (1/t) terlebih dahulu, lalu menskalakannya: level = (f − f_hitam) / (f_putih − f_hitam) × 255. Mari lihat contohnya: kamu mengukur 20 µs pada putih, 200 µs pada hitam, dan benda memberi 40 µs. map() mengubahnya menjadi 226, sedangkan metode frekuensi memberi 113. Frekuensi benda tepat setengah dari frekuensi putih, dan setelah level hitam dikurangi, itu setara dengan sekitar 44% skala, atau 113; sebaliknya, map() menampilkan warna jauh lebih terang daripada aslinya dan menyulitkan kamu membedakan nuansa gelap.
Algoritma pemilah warna: warna apa pembacaan ini?
Nilai R, G, B yang sudah dikalibrasi masih bergantung pada jumlah cahaya: ketika benda merah yang sama bergeser sedikit lebih dekat ke sensor, ketiga nilai naik bersama-sama. Untuk mengatasinya, kita membagi setiap nilai dengan totalnya: r = R / (R + G + B), begitu juga untuk g dan b. Rasio warna ini hampir tetap meskipun jarak dan kecerahan sedikit berubah. Lalu kamu membandingkannya dengan rasio referensi yang sudah kamu ukur dan simpan sekali untuk setiap warna, dan memilih tetangga terdekat (nearest neighbor). Untuk perbandingannya cukup menjumlahkan kuadrat selisih rasio; makin kecil angka ini, makin mirip warnanya. Jika referensi terdekat pun lebih jauh dari ambang tertentu, hasilnya “tidak dikenal”. Jika cahaya totalnya sangat rendah, benda dianggap hitam, dan jika ketiga kanal sangat tinggi, dianggap putih; dua kasus ini tidak bisa dibedakan lewat rasio, jadi diperiksa lebih dulu.
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}| Bagian kode | Fungsinya |
|---|---|
| WHITE_* dan BLACK_* | Lebar pulsa putih dan hitam yang kamu ukur ketika kalibrasi (µs) |
| toLevel() | Mengubah lebar pulsa ke frekuensi dan menskalakannya ke 0–255 |
| refs[] | Rasio r, g, b referensi untuk setiap warna; ganti dengan hasil pengukuranmu sendiri |
| classify() | Memisahkan hitam dan putih lebih dulu, lalu mencari referensi terdekat |
| MAX_DIST | Pembacaan yang lebih jauh dari jarak ini dihitung sebagai “Unknown” (tidak dikenal) |
Membuat mesin yang memilah benda berdasarkan warna
Proyek TCS3200 yang paling populer adalah mesin yang memilah permen, manik-manik, atau keping LEGO berwarna berdasarkan warnanya. Mekanismenya terdiri dari dua servo. Servo pengumpan di atas memutar piringan berlubang yang pas untuk tepat satu benda: pertama mengambil benda dari bawah tabung corong, lalu membawanya ke depan sensor dan, setelah pembacaan, menjatuhkannya ke saluran di bawahnya. Servo saluran di bawah memutar saluran miring untuk mengirim benda ke wadah sesuai warnanya. Kalau kamu baru pertama kali memakai servo, baca dulu Apa Itu Motor Servo?.
- Pasang corong dan tabung yang sedikit lebih lebar dari bendanya supaya benda jatuh ke piringan pengumpan satu per satu.
- Pasang sensor sehingga bisa melihat benda di piringan dari jarak 1–2 cm, lalu tutup sekelilingnya agar cahaya luar tidak masuk.
- Tentukan tiga sudut untuk servo pengumpan: ambil, sensor, dan jatuhkan. Temukan sudutnya dengan mencoba langsung di mekanismemu sendiri; hubungkan servo pengumpan ke D9 dan servo saluran ke D10.
- Tetapkan satu sudut untuk setiap wadah warna pada servo saluran (misalnya merah 30°, hijau 75°, biru 120°, sisanya 165°).
- Lakukan kalibrasi di dalam mesin, dengan pencahayaan mesin itu sendiri, lalu uji dengan beberapa benda dari setiap warna.
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 dengan ESP32: mengukur frekuensi dengan interrupt
Kode pulseIn yang sama berjalan di ESP32, tetapi ada metode yang lebih stabil: alih-alih mengukur pulsa satu per satu, hitung berapa banyak pulsa yang datang dalam waktu tetap. Sebuah interrupt menaikkan penghitung di setiap tepi naik; kalikan hasil hitungan setelah 50 ms dengan 20 dan kamu mendapat frekuensi dalam hertz. Karena metode ini merata-ratakan ratusan pulsa, satu pulsa yang buruk tidak berpengaruh. Prosesor 240 MHz milik ESP32 dengan mudah menangani puluhan ribu interrupt per detik pada skala 20%; jika hitungannya terlalu besar dalam cahaya yang sangat terang, kamu bisa menurunkan skalanya ke 2%. Kamu juga bisa memakai metode yang sama di Arduino Uno dengan memindahkan OUT ke D2, yang mendukung interrupt. Di ESP32, jangan lupa memberi daya modul dari pin 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 dengan Raspberry Pi Pico dan MicroPython
Di Pico, padanan pulseIn Arduino adalah fungsi machine.time_pulse_us(): fungsi ini mengembalikan panjang pulsa pada level yang diminta dalam mikrodetik, dan angka negatif jika terjadi timeout. Jika dipanggil ketika pin sudah berada di level itu, fungsi ini langsung mulai mengukur dan bisa saja mengukur setengah pulsa; karena itu kode menunggu bagian HIGH selesai lebih dulu, baru mengukur waktu LOW. Karena setiap pemanggilan fungsi di MicroPython memakan beberapa mikrodetik, di sini kita memilih skala 2% (S0=0, S1=1): pulsanya menjadi 10 kali lebih panjang dan efek jeda itu mengecil. Nilai kalibrasinya ditulis dalam Hz; pada skala 2%, wajar melihat beberapa kHz pada kertas putih dan beberapa ratus Hz pada kertas hitam. Beri daya modul dari pin 3V3(OUT) Pico; jika kamu baru mengenal Pico, Apa Itu Raspberry Pi Pico? menjelaskan cara menginstal 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 atau TCS34725?
TCS34725 adalah sensor warna yang lebih baru yang melakukan pekerjaan yang sama lewat I2C. Sensor ini melakukan pengukuran di dalam chip dan mengembalikan hasilnya sebagai angka 16-bit per kanal, jadi Arduino tidak perlu mengukur pulsa apa pun. Perbedaan terpentingnya adalah filter penghalang inframerah (IR) di atas fotodiodanya. TCS3200 tidak punya filter seperti itu; karena fotodioda silikon juga peka terhadap inframerah, pembacaannya bergeser di bawah cahaya yang kaya IR seperti sinar matahari atau lampu pijar. Karena penguatan (1x, 4x, 16x, 60x) dan waktu integrasi (2,4–614 ms) TCS34725 bisa diatur lewat software, sensor ini bekerja di rentang yang lebar, dari cahaya sangat redup sampai terang. Kalau kamu penasaran bagaimana I2C bekerja, lihat artikel Apa Itu I2C?.

| Fitur | TCS3200 | TCS34725 |
|---|---|---|
| Keluaran | Frekuensi (gelombang kotak) | I2C, alamat 0x29 |
| Kabel sinyal | S0–S3, OUT, dan OE | SDA dan SCL (INT dan LED opsional) |
| Resolusi | Bergantung pada metode dan waktu pengukuran | 16 bit per kanal |
| Filter IR | Tidak ada | Ada (di chip) |
| Pengaturan | 3 skala frekuensi dan power down | 4 tingkat penguatan, waktu integrasi 2,4–614 ms |
| Catu daya | 2,7–5,5 V | Chip 3,3 V; modul dengan regulator 3–5 V |
| Pencahayaan | Biasanya 4 LED putih | Biasanya 1 LED putih |
| Beban prosesor | Sibuk selama mengukur pulsa | Chip yang mengukur, Arduino hanya membaca |
| Cocok untuk | Belajar, pemilah warna sederhana | Warna akurat, suhu warna, dan pengukuran 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}Sebelum meng-upload kode, instal library Adafruit TCS34725 dari Library Manager; ketika ditanya soal dependensi, pilih untuk menginstal semuanya. Di Arduino Uno, hubungkan SDA ke A4 dan SCL ke A5; di ESP32, pakai GPIO 21 dan 22. getRawData() menunggu selama waktu integrasi lalu mengembalikan nilai mentah merah, hijau, biru, dan clear (C); calculateColorTemperature_dn40() memberi suhu warna dalam kelvin, dan calculateLux() memberi perkiraan tingkat cahaya. Logika kalibrasi dan warna terdekat berlaku sama persis untuk sensor ini. Kalau kamu ingin sensor yang selain warna juga mendeteksi gerakan tangan dan jarak dekat, APDS-9960 adalah alternatif yang bagus.
Ide proyek dengan TCS3200
- Mesin pemilah warna: Pilah permen, manik-manik, atau keping LEGO ke wadah terpisah berdasarkan warnanya.
- Lampu peniru warna: Tampilkan ulang warna benda yang kamu dekatkan ke sensor dengan LED RGB atau LED strip WS2812B.
- Robot pembaca warna: Ajari robot pengikut garis milikmu untuk berhenti di tanda merah di lantai dan jalan terus di tanda hijau.
- Lengan robot pengenal warna: Gunakan lengan robot untuk mengambil kubus dan menjatuhkan setiap warna ke wadahnya sendiri.
- Pendeteksi warna bersuara: Umumkan warna yang terdeteksi dengan suara rekaman di DFPlayer Mini; alat ini bisa menjadi bantuan praktis bagi penyandang tunanetra.
- Pemantau warna air: Pantau perubahan warna air di wadah bening dari waktu ke waktu dan beri peringatan untuk akuarium atau tangki irigasi.
Kesalahan umum dan cara mengatasinya
| Gejala | Kemungkinan penyebab | Solusi |
|---|---|---|
| pulseIn selalu mengembalikan 0 atau nilai timeout | OE mengambang atau HIGH, S0 dan S1 sama-sama LOW (power down), atau OUT di pin yang salah | Hubungkan OE ke GND, buat S0 HIGH dan S1 LOW, cocokkan pin OUT dengan kode |
| Nilai terus melompat | Cahaya ruangan, lampu yang berkedip, atau jarak yang berubah | Lindungi sensor dengan tabung hitam, tetapkan jaraknya, rata-ratakan beberapa pembacaan |
| Semua benda terbaca sebagai warna yang sama | Belum dikalibrasi; sensitivitas tiap kanal berbeda | Lakukan kalibrasi putih dan hitam, ukur ulang referensinya |
| Warna bergeser di bawah cahaya siang | TCS3200 tidak punya filter IR | Ukur di dalam kotak tertutup atau pakai TCS34725 |
| Level selalu menempel di 0 atau 255 | Jarak benda berbeda dari ketika kalibrasi | Jaga jaraknya tetap sama seperti ketika kalibrasi, kalibrasi ulang jika perlu |
| ESP32 atau Pico berperilaku aneh | Modul diberi daya 5 V, OUT mengeluarkan 5 V | Beri daya modul dari 3V3 atau pakai level shifter |
| Pembacaan kacau ketika servo bergerak | Arus servo menarik turun tegangan catu daya | Pakai catu daya 5 V terpisah untuk servo dan hubungkan GND-nya |
TCS3200 adalah sensor yang bagus untuk belajar bagaimana cahaya berubah menjadi frekuensi, mengapa kalibrasi itu penting, dan cara menyusun algoritma klasifikasi sederhana. Beralih ke TCS34725 ketika kamu butuh akurasi lebih juga mudah, karena logika kalibrasi dan warna terdekat yang sudah kamu pelajari tetap berlaku tanpa perubahan. Di aplikasi BlueGrays kamu akan menemukan proyek pencampuran warna LED RGB, lampu pencampur warna ESP32, pengukuran cahaya dengan LDR, dan motor servo, lengkap dengan skema rangkaian dan kode langkah demi langkah, lalu kamu bisa menggabungkan sensor warna dengan proyek-proyek itu untuk membuat mesinmu sendiri.
Pertanyaan umum
Dari jarak berapa sensor warna TCS3200 bisa mendeteksi warna?
Hasil paling stabil didapat pada jarak sekitar 1–3 cm, karena cahaya dari LED modul cepat melemah seiring jarak. Yang lebih penting daripada jaraknya sendiri adalah menjaganya tetap sama di setiap pembacaan, dan kamu juga sebaiknya melakukan kalibrasi pada jarak itu. Sensor ini tidak cocok untuk membaca warna permukaan besar yang jauh.
Apa perbedaan TCS230 dan TCS3200?
TCS230 adalah sensor warna lama dari produsen yang sama, dan TCS3200 adalah versi perbaikannya. Keduanya memakai susunan fotodioda 8×8, keluaran frekuensi, dan logika kontrol S0–S3 yang sama, jadi pengkabelan dan kodenya bisa dipakai bersama. Sebagian besar modul yang dijual sekarang memakai TCS3200.
Kenapa pulseIn mengembalikan 0 pada TCS3200?
pulseIn mengembalikan 0 ketika tidak melihat pulsa dalam batas timeout yang diberikan. Penyebab paling umum adalah pin OE tidak terhubung ke GND, S0 dan S1 sama-sama dibiarkan LOW (yang membuat sensor masuk ke mode power down), dan OUT tersambung ke pin yang berbeda dari yang ada di kode. Jika area di depan sensor benar-benar gelap, frekuensinya turun sampai beberapa hertz dan tidak ada pulsa yang tertangkap dalam timeout yang singkat.
Apakah TCS3200 bisa dipakai dengan ESP32 dan Raspberry Pi Pico?
Bisa. Karena TCS3200 bekerja pada 2,7–5,5 V, kamu bisa memberi daya modul dari pin 3V3 board, sehingga pin OUT juga menghasilkan pulsa 3,3 V. Jika modul kamu beri daya 5 V, kamu perlu pembagi tegangan atau level shifter di jalur OUT. Ketika mengukur dengan MicroPython di Pico, skala frekuensi 2% memberi hasil yang lebih akurat.
Mana yang lebih baik, TCS3200 atau TCS34725?
Untuk pengukuran warna yang akurat, TCS34725 lebih baik: sensor ini punya filter penghalang IR, resolusi 16-bit per kanal, dan penguatan yang bisa diatur, serta terhubung hanya dengan dua kabel I2C. TCS3200 adalah pilihan yang umum dan sangat memadai untuk belajar pengukuran frekuensi dan kalibrasi, serta untuk membuat pemilah warna sederhana.
Berapa banyak warna yang bisa dibedakan TCS3200?
Dengan pencahayaan terkontrol dan jarak tetap, TCS3200 dapat memisahkan 6–8 warna yang jelas berbeda secara andal, seperti merah, oranye, kuning, hijau, biru, ungu, hitam, dan putih. Membedakan nuansa yang berdekatan, seperti hijau muda dan hijau tua, juga mungkin, tetapi butuh kalibrasi yang lebih teliti, banyak pembacaan referensi untuk setiap nuansa, dan ambang yang ketat.
Proyek untuk dibuat setelah membaca ini
Lihat semua proyek
Mengukur Intensitas Cahaya dengan LDR
Ingin melihat seberapa terang kamarmu dalam bentuk angka? LDR, komponen kecil yang bereaksi terhadap cahaya, mengukur cahaya di sekitarnya, dan Arduino menulis nilainya ke layar komputermu setiap sete

Membaca Intensitas Cahaya dengan Modul LDR ESP32
Memantau secara real-time di Serial Monitor nilai ADC mentah modul LDR dan persentase cahaya relatif yang dihitung dari nilai acuan gelap dan terang. Persentase ini bukan pengukuran lux. Mengajarkan logika kalibrasi modul. Ideal dikerjakan sebelum Proyek 10, karena dipakai untuk menentukan nilai ambang.

Menggunakan LED RGB
Tiga warna tersembunyi di dalam satu LED: LED RGB menyala merah, lalu hijau, lalu biru, setiap warna menyala setengah detik dan mati setengah detik, sebelum siklusnya dimulai lagi. Yang kamu butuhkan

Transisi Warna Halus dengan LED RGB
Satu LED RGB perlahan bergeser dari merah ke hijau, hijau ke biru, lalu kembali ke merah, berputar melewati warna pelangi tanpa pernah berhenti. Setiap peralihan butuh sekitar dua setengah detik, dan

Lampu Pencampur Warna ESP32 (3 Potensiometer + LED RGB + OLED)
Lampu pencampur warna pintar: campur warna apa pun dengan memutar tiga potensiometer di ESP32! Ketika potensiometer merah, hijau, dan biru diputar, LED RGB katoda bersama berubah warna secara real-time. OLED SSD1306 menampilkan nilai setiap warna dalam rentang 0–255, bar pengisi, dan kode warna web HEX (seperti #FF8040). Studio warna mini yang mengajarkan teori warna RGB, pembacaan ADC, pengaturan kecerahan dengan PWM, dan desain layar I2C sekaligus.

Kendali LED RGB ESP32
Menghasilkan warna tanpa batas dengan satu LED RGB alih-alih 3 LED terpisah. Seperti di Arduino, kita membuat transisi pelangi dengan mengatur nilai R/G/B lewat analogWrite(). Teori warna (seperti merah+hijau=kuning) terlihat secara praktis.

Menggunakan Motor Servo
Lengan motor servo kecil berputar ke tiga posisi bergantian: penuh ke awal, tepat ke tengah, dan penuh ke akhir, menunggu dua detik di setiap perhentian. Arduino memberi tahu motor sudut mana yang har

Deteksi Permukaan Hitam dan Putih TCRT5000
Dengan sensor kecil yang menjadi mata robot pengikut garis, kamu bisa tahu apakah lantainya hitam atau putih. TCRT5000 menyinari lantai dengan cahaya tak terlihat dan mengecek berapa banyak yang terpa
Artikel lainnya
Aplikasi BlueGrays
Rakit rangkaian ini langkah demi langkah di ponselmu
Skema pengkabelan, kode, dan daftar komponen dalam satu layar. 200+ proyek Arduino, ESP32, dan Pico siap dibuat.
Pindai dengan ponselmu
Arahkan kamera ke kode ini dan toko aplikasi di ponselmu akan terbuka.
atau buka toko aplikasi

