Sensor Warna TCS230 dengan Arduino: Cara Kesan dan Asing Warna

Cartoon of a deep-blue TCS230 colour sensor board with a matte-black lens holder and four clear white LEDs shining a cone of light down onto bright red, green and blue plastic bricks

TCS230 tidak pernah melaporkan sesuatu warna. Ia melaporkan satu nombor pada satu masa β€” satu frekuensi, melalui penapis mana yang anda pilih dengan dua pin β€” jadi satu bacaan warna ialah tiga pengukuran berturut-turut, dan sketch anda, bukan cip itu, yang menentukan apa maknanya. Set S0 HIGH, S1 LOW, ukur setiap channel dengan pulseIn(), dan kalibrasi dengan kad putih dahulu.

Apa sebenarnya yang diukur oleh sensor warna TCS230?

TCS230 membawa satu array fotodiod 8Γ—8, dan 64 fotodiod itu tidak serupa: enam belas duduk di belakang penapis merah, enam belas di belakang hijau, enam belas di belakang biru dan enam belas lagi tanpa sebarang penapis. Hanya satu kumpulan disambung kepada penukar pada satu-satu masa, dan S2 serta S3 yang memilih kumpulan mana. Jadi tiada panggilan “baca warna” di sini β€” yang ada hanyalah pilih merah, ukur; pilih hijau, ukur; pilih biru, ukur.

Apa yang sampai di OUT pun bukan voltan. Penukar itu menukarkan arus foto kumpulan yang dipilih menjadi gelombang segi empat duti 50% yang frekuensinya berkadar dengan jumlah cahaya yang mendarat padanya, pada bekalan 2.7–5.5 V, menurut datasheet TAOS TCS230. Terang bermakna laju, gelap bermakna perlahan.

S2 S3 Kumpulan fotodiod yang disambung
LOW LOW Merah
LOW HIGH Biru
HIGH LOW Clear β€” tiada penapis
HIGH HIGH Hijau

S0 dan S1 pula membahagikan frekuensi itu ke bawah sebelum ia keluar daripada cip, dan tetapan inilah yang menentukan sama ada Arduino mampu mengukur gelombang itu langsung atau tidak.

S0 S1 Penskalaan output Frekuensi skala penuh Separuh tempoh pada skala penuh
LOW LOW power down β€” β€”
LOW HIGH 2% 10–12 kHz 42–50 Β΅s
HIGH LOW 20% 100–120 kHz 4–5 Β΅s
HIGH HIGH 100% 500–600 kHz 0.8–1 Β΅s

Rujukan pulseIn() Arduino mendokumenkan fungsi itu sebagai berfungsi pada denyut dari 10 Β΅s ke atas, dan nombor itulah yang memilih baris mana untuk anda. Pada 100%, bacaan terang hanyalah sepersekian daripada 10 Β΅s, jadi objek cerah semuanya runtuh menjadi satu nilai yang sama dan tidak bermakna. Pada 2% pula tiada apa yang terlalu laju, tetapi objek gelap meregangkan satu pengukuran sehingga milisaat, dan tiga daripadanya bagi setiap bacaan menjadi lag yang nampak. 20% meletakkan bacaan dalam bilik biasa pada julat puluhan mikrosaat; 4–5 Β΅s pada baris itu ialah skala penuh, satu tahap kecerahan yang empat LED modul ini sendiri tidak pernah capai daripada objek harian.

Parts list

ItemPriceQty
Soldering Service for Circuit Boards & Electronics - 10 Pins Soldering ServiceSoldering Service for Circuit Boards & Electronics - 10 Pins Soldering ServiceSOLSE10RM1.40

Modul TCS230 perlukan tepat 10 pin header disolder. Kalau anda lebih suka tidak menyolder sendiri, tambah servis solder 10 pin dan kami pasangkan jalur itu untuk anda.

Bagaimana cara menyambung TCS230 kepada Arduino Uno?

Modul TCS230 menampilkan dua baris 5-pinnya sebagai lubang tembus bersalut yang masih bogel, jadi kerja pertama ialah menyolder. Patahkan dua kepingan 5-hala daripada jalur male 40-pin 2.54 mm dalam senarai komponen dan tolak masuk dari sebelah kanta, supaya pinnya keluar di belakang dan tiada shell jumper duduk dalam laluan cahaya; panduan solder header kami menerangkan tekniknya, atau servis solder 10 pin menguruskannya kalau anda tiada besi solder.

Dua baris itu membawa pin yang berbeza dan berjalan dalam arah bertentangan, jadi baca silkscreen dan jangan mengagak ikut kedudukan: satu tepi berbunyi GND OUT S2 S3 VCC, satu lagi berbunyi VCC S1 S0 LED GND, masing-masing dengan pad segi empat pada pin 1. Baris-baris itu duduk pada tepi yang bertentangan pada board segi empat sama 33.2 mm, kira-kira 30 mm jaraknya β€” lebih lebar daripada rentang 28 mm merentasi dua bank breadboard mini, jadi modul ini tidak boleh mencangkung di atasnya. Guna Sensor Shield V5.0 pada Uno sebaliknya: ia menerbitkan semula setiap pin digital sebagai blok male tiga pin berlabel G, V dan S, berserta satu port IIC empat pin untuk OLED. Dengan pin male di kedua-dua hujung, kesemua dua belas sambungan menggunakan jumper female-to-female, dan wayar 20 cm membolehkan sensor itu tergantung ke mana sahaja anda halakan.

Pin bertanda LED bukan pin logik. Ia menghidupkan empat LED putih onboard modul itu, yang manualnya letakkan pada lebih kurang 25 mA kesemuanya, dan board itu sendiri mengesahkannya: perintang di sebelah setiap LED bertanda 331, bermakna 330 Ξ©, dan LED putih menjatuhkan kira-kira 3.1 V, jadi setiap cabang menarik (5 βˆ’ 3.1) / 330 = 5.8 mA dan empat cabang β‰ˆ 23 mA. Datasheet ATmega328P membenarkan 40 mA bagi setiap pin I/O sebagai maksimum mutlak dan hanya menyatakan voltan output pin itu sehingga 20 mA sahaja. Ikat LED terus ke 5V dan biarkan lampu itu menyala β€” dan itulah juga yang dikehendaki oleh pengukuran warna.

Jumper SEL kuning pada shield, di sebelah terminal skru biru, menyalurkan kuasa kepada pin V blok digital daripada 5V Uno sendiri. Biarkan ia di tempat asalnya β€” cabut ia dan setiap pin V pada blok D0–D13 mati, dan itu nampak sungguh-sungguh macam sensor rosak, sedangkan yang hilang hanyalah satu jumper. Jangan sambung apa-apa pada terminal skru itu: bekalan luar dengan SEL masih terpasang akan mendarat terus pada rel 5V Uno.

Pin modul (silkscreen) Ke mana pada shield Pin Uno di sebaliknya
TCS230 OUT blok D8, S D8
TCS230 S0 blok D4, S D4
TCS230 S1 blok D5, S D5
TCS230 S2 blok D6, S D6
TCS230 S3 blok D7, S D7
TCS230 VCC pin V mana-mana blok 5V
TCS230 GND pin G mana-mana blok GND
TCS230 LED pin V mana-mana blok yang kosong 5V β€” jangan sekali pin digital
OLED GND header IIC, βˆ’ GND
OLED VCC header IIC, + 5V
OLED SCL header IIC, SCL A5
OLED SDA header IIC, SDA A4

Header OLED itu berjalan GND, VCC, SCL, SDA β€” ground dahulu, terbalik daripada susunan VCC-dahulu yang biasa β€” sementara port IIC shield pula berjalan SCL, SDA, βˆ’, +. Pasang empat sambungan itu satu demi satu, bukan sebagai riben lurus merentas. Headernya sampai sudah tersolder; panel yang sama inilah yang memacu menu OLED rotary encoder kami.

Lukisan kartun board TCS230 biru gelap dengan pemegang kanta hitam matt dan empat LED jernih, satu baris lubang masih bogel dan satu baris lagi sudah dipasang jalur header male hitam yang sedang disolder oleh hujung besi solder berbara oren
Modul ini sampai dengan sepuluh lubang bersalut yang bogel. Patahkan dua kepingan 5-hala daripada jalur 40-pin, solder masuk, dan selepas itu setiap jumper hanya perlu ditolak masuk.

Kenapa objek merah memberi bacaan merah yang PALING RENDAH?

Sebabnya pin OUT TCS230 itu diukur masanya, bukan dibaca nilainya. pulseIn(OUT, LOW) tidak mengukur cahaya β€” ia mengukur panjang separuh LOW gelombang segi empat itu dalam mikrosaat, iaitu separuh tempoh. Tempoh ialah 1 / frekuensi, jadi nombor yang anda dapat balik ialah 500000 / f: 25 pada 20 kHz, 100 pada 5 kHz.

Letakkan blok merah di bawah penapis merah dan ia memantulkan merah dengan kuat, jadi frekuensi memanjat, separuh tempoh mengecut, dan nombornya jadi lebih kecil. Channel yang paling sepadan ialah channel dengan kiraan mentah paling rendah: kiraan mentah daripada TCS230 mengukur kegelapan.

Perbandingan kartun menunjukkan sensor TCS230 biru gelap di atas kad putih menghasilkan gelombang segi empat navy yang padat rapat dengan denyut low terukur yang pendek, dan di atas kad hitam menghasilkan gelombang yang teregang dengan denyut low terukur yang panjang
Kad putih memantulkan banyak cahaya, jadi gelombangnya laju dan separuh LOWnya pendek. Kad hitam hampir tidak memantulkan apa-apa, jadi pengukuran yang sama memulangkan nombor yang jauh lebih besar.

Bagaimana cara kalibrasi TCS230, dan kenapa kalibrasi itu keseluruhan projek ini?

Kiraan mentah TCS230 hanyut mengikut jarak, pencahayaan bilik dan kecerahan asal objek itu sendiri, jadi anda kunci dua hujungnya. Tetapkan ketinggian dahulu dan jangan sekali-kali ubah lagi β€” sekitar 10–30 mm daripada kanta sesuai untuk kebanyakan objek, cukup dekat untuk kon cahaya keempat-empat LED bertindih pada sasaran. Pada ketinggian itu, pegang kad putih dan catat tiga nombor mentahnya β€” yang terkecil anda akan lihat. Kemudian pegang sesuatu yang hitam matt dan catat nombor itu pula β€” yang terbesar.

map(raw, white, black, 255, 0) kemudian menukarkan kiraan mentah kepada 0–255. Perhatikan julat output ditulis terbalik: putih ialah nilai mentah yang kecil dan mesti mendarat pada 255. Satu argumen terbalik itulah yang meleraikan penyongsangan tadi.

Itu pun masih belum cukup, dan inilah langkah yang paling kerap dilangkau panduan lain. Alihkan objek 5 mm lebih jauh dan ketiga-tiga nilai ternormal mengecut serentak, sebab kurang cahaya yang kembali secara keseluruhan. Jadi bahagikan setiap satu dengan jumlah ketiga-tiganya: r = R / (R+G+B). Kecerahan terbatal dan hanya perkadaran yang tinggal. Sebuah blok merah yang tiga nilai 0–255nya berbunyi 210/70/60 pada jarak dekat memberi nisbah 617/205/176 per seribu; undurkan sampai bacaannya jadi 120/40/34 dan nisbahnya 618/206/175 β€” keputusan yang sama daripada nombor yang jauh berbeza, dan itulah sebabnya sebuah mesin pengasing kekal boleh diulang. Pembahagian integer memotong baki, jadi ketiga-tiganya tidak pernah betul-betul berjumlah 1000.

Empat LED putih yang mengelilingi kanta itu wujud atas sebab yang sama: sensor ini mengukur cahaya pantulan, jadi sumber cahaya yang berubah bermakna bacaan yang berubah. Biarkan ia menyala dan lindungi celah itu daripada cahaya bilik. Melihat nombor bergerak sambil objek lalu di bawah sensor berbaloi diluangkan beberapa minit di sini:

Perbandingan kartun sebuah blok merah dekat dengan dan jauh daripada sensor TCS230 biru gelap, dengan kumpulan bar merah hijau biru yang tinggi dan yang rendah di bawahnya berkongsi perkadaran yang serupa
Alihkan objek lebih jauh dan ketiga-tiga bacaan mengecut serentak. Bahagikan setiap satu dengan jumlahnya dan perkadaran itu tidak berubah β€” dan itulah sebabnya pengelas ini membandingkan nisbah, bukan aras.

Macam mana rupa sketch Arduino untuk TCS230?

Sketch TCS230 ialah tiga bacaan, satu normalisasi, satu nisbah, kemudian padanan terdekat dengan rujukan anda sendiri. Pasang Adafruit SSD1306 dan Adafruit GFX Library daripada Library Manager dahulu. Setiap nombor dalam dua blok kalibrasi itu hanyalah nilai sementara β€” jalankannya, baca baris raw dalam Serial Monitor pada 9600, tampal nombor anda sendiri.

// Sensor warna TCS230 + OLED SSD1306 0.96" pada Arduino Uno.
// Pendawaian: OUT -> D8, S0 -> D4, S1 -> D5, S2 -> D6, S3 -> D7,
//             VCC -> 5V, GND -> GND, LED -> 5V (jangan sekali pin digital: ~25 mA).
//             OLED SCL -> A5, SDA -> A4, VCC -> 5V, GND -> GND.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define OLED_ADDR 0x3C   // silkscreen tulis 0x78; itu bentuk 8-bit, 0x78 >> 1 = 0x3C

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const uint8_t PIN_S0  = 4;
const uint8_t PIN_S1  = 5;
const uint8_t PIN_S2  = 6;
const uint8_t PIN_S3  = 7;
const uint8_t PIN_OUT = 8;

// ---- LANGKAH 1: kalibrasi anda sendiri, dalam mikrosaat mentah (R, G, B) --
// Pegang kad PUTIH pada jarak kerja anda, baca baris "raw" dalam Serial
// Monitor, tampal tiga nombor itu di sini. Ulang dengan bahan HITAM matt.
const uint16_t WHITE_RAW[3] = {  26,  30,  25 };
const uint16_t BLACK_RAW[3] = { 240, 265, 230 };

// ---- LANGKAH 2: nisbah rujukan x1000, diukur pada objek ANDA SENDIRI ------
// Cetak baris ratio sambil memegang setiap objek, kemudian tampal triplet di sini.
const int16_t REF[4][3] = {
  { 560, 235, 205 },   // merah
  { 235, 520, 245 },   // hijau
  { 205, 270, 525 },   // biru
  { 333, 333, 334 }    // putih / kelabu
};
const char *const NAME[4] = { "RED", "GREEN", "BLUE", "WHITE" };

// Satu pengukuran. S2/S3 memilih kumpulan fotodiod mana yang disambung kepada
// penukar; pulseIn mengukur separuh LOW gelombang segi empat duti 50%, jadi
// nombor yang dipulangkan ialah separuh tempoh - LAGI banyak cahaya, LAGI kecil nombornya.
uint16_t readRaw(uint8_t s2, uint8_t s3) {
  digitalWrite(PIN_S2, s2);
  digitalWrite(PIN_S3, s3);
  delay(10);                                        // beri penapis baharu masa untuk stabil
  unsigned long us = pulseIn(PIN_OUT, LOW, 50000UL);
  if (us == 0 || us > 50000UL) return 50000;        // tamat masa: pada praktiknya hitam
  return (uint16_t)us;
}

// Tukar separuh tempoh mentah menjadi 0-255 "berapa banyak warna ini kembali".
// Julat output ditulis terbalik dengan sengaja: putih ialah nilai mentah yang
// KECIL dan mesti mendarat pada 255.
uint8_t normalise(uint16_t raw, uint16_t white, uint16_t black) {
  long v = map((long)raw, (long)white, (long)black, 255L, 0L);
  return (uint8_t)constrain(v, 0L, 255L);
}

void setup() {
  pinMode(PIN_S0, OUTPUT);
  pinMode(PIN_S1, OUTPUT);
  pinMode(PIN_S2, OUTPUT);
  pinMode(PIN_S3, OUTPUT);
  pinMode(PIN_OUT, INPUT);

  digitalWrite(PIN_S0, HIGH);   // S0 HIGH, S1 LOW = penskalaan output 20%,
  digitalWrite(PIN_S1, LOW);    // skala penuh 100-120 kHz - yang pulseIn mampu ukur

  Serial.begin(9600);
  if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
    Serial.println(F("No SSD1306 at 0x3C - check SDA/SCL and 5V"));
    for (;;) { }
  }
  display.setTextColor(SSD1306_WHITE);
}

void loop() {
  uint16_t raw[3];
  raw[0] = readRaw(LOW,  LOW);    // kumpulan penapis merah
  raw[1] = readRaw(HIGH, HIGH);   // kumpulan penapis hijau
  raw[2] = readRaw(LOW,  HIGH);   // kumpulan penapis biru

  uint8_t rgb[3];
  for (uint8_t i = 0; i < 3; i++) {
    rgb[i] = normalise(raw[i], WHITE_RAW[i], BLACK_RAW[i]);
  }

  // Nisbah, bukan aras. Membahagi dengan jumlahnya membuang "berapa terang" dan
  // mengekalkan hanya "warna apa", dan itulah yang kekal bila objek beralih.
  uint16_t sum = (uint16_t)rgb[0] + rgb[1] + rgb[2];
  if (sum == 0) sum = 1;
  int16_t ratio[3];
  for (uint8_t i = 0; i < 3; i++) {
    ratio[i] = (int16_t)((1000L * rgb[i]) / sum);
  }

  // Rujukan terdekat dalam ruang nisbah: jarak kuasa dua, yang terkecil menang.
  uint8_t best = 0;
  int32_t bestDist = 2147483647L;
  for (uint8_t k = 0; k < 4; k++) {
    int32_t d = 0;
    for (uint8_t i = 0; i < 3; i++) {
      int32_t e = (int32_t)ratio[i] - REF[k][i];
      d += e * e;
    }
    if (d < bestDist) { bestDist = d; best = k; }
  }

  Serial.print(F("raw "));
  for (uint8_t i = 0; i < 3; i++) { Serial.print(raw[i]); Serial.print(' '); }
  Serial.print(F(" rgb "));
  for (uint8_t i = 0; i < 3; i++) { Serial.print(rgb[i]); Serial.print(' '); }
  Serial.print(F(" ratio "));
  for (uint8_t i = 0; i < 3; i++) { Serial.print(ratio[i]); Serial.print(' '); }
  Serial.print(F(" -> "));
  Serial.println(NAME[best]);

  display.clearDisplay();
  display.setTextSize(2);
  display.setCursor(0, 0);
  display.println(NAME[best]);
  display.setTextSize(1);
  display.setCursor(0, 24);
  display.print(F("R ")); display.print(rgb[0]);
  display.print(F("  G ")); display.print(rgb[1]);
  display.print(F("  B ")); display.println(rgb[2]);
  display.setCursor(0, 40);
  display.print(ratio[0]); display.print(F(" / "));
  display.print(ratio[1]); display.print(F(" / "));
  display.println(ratio[2]);
  display.setCursor(0, 54);
  display.print(F("fit ")); display.print(bestDist);
  display.display();

  delay(200);
}

Ia dikompil menjadi 16,160 bait flash dan 587 bait pemboleh ubah global β€” tetapi display.begin() menuntut 1024 bait lagi untuk frame buffer semasa ia berjalan, dan angka itu tidak pernah ditunjukkan oleh IDE, jadi kos SRAM yang sebenar ialah kira-kira 1611 daripada 2048 bait Uno. Angka fit pada paparan itu ialah jarak kuasa dua rujukan yang menang: kecil bermakna padanan yang yakin, besar bermakna padanan yang meragukan. Satu pemeriksaan waras semasa kalibrasi: kalau kad putih memulangkan nilai mentah di bawah lebih kurang 10, anda sudah sampai ke lantai pulseIn() β€” angkat sensor sedikit, atau turun ke penskalaan 2%. Itu bermakna S0 LOW dan S1 HIGH β€” menaikkan S1 sahaja meninggalkan S0 pada HIGH, iaitu baris 100%, dan itu memendekkan lagi denyutnya.

Kesilapan biasa yang kami nampak daripada pelanggan sebenar

Objek merah memberi nombor merah paling rendah, jadi sensor itu nampak macam tersalah wayar. Wayarnya betul. pulseIn() memulangkan separuh tempoh, jadi lebih banyak cahaya memberi denyut yang lebih pendek. Normalkan dahulu sebelum membandingkan apa-apa.

Bacaan melompat setiap kali ada tangan lalu di atasnya. Cahaya bilik sedang sampai kepada objek itu bersama-sama LED modul sendiri. Pengelas ini hanya sestabil pencahayaannya: tetapkan ketinggian, lindungi celahnya.

Semua warna dikelaskan sama, atau semuanya terbaca hitam. Selalunya salah satu daripada tiga: jalur header itu tidak pernah disolder dan jumper hanya tersandar dalam lubang, jumper SEL shield sudah tercabut jadi pin V sensor mati, atau pin LED dibiarkan tidak bersambung dan tiada apa yang menyuluh objek itu.

Objek yang asing pun tetap dinamakan, dengan penuh yakin. Padanan terdekat tiada kes tolak: ia memulangkan rujukan yang paling hampir daripada empat rujukan anda, apa sahaja yang anda angkat, jadi blok kuning pun tetap mendarat pada salah satu daripadanya. Catat di mana fit duduk untuk objek yang anda tahu, dan tolak apa-apa yang lebih teruk daripada itu β€” satu salur UNKNOWN lebih baik daripada salur yang salah.

Ia menjadi di atas meja tetapi gagal pada rig. Kalibrasi terikat pada jarak. Rakam semula putih, hitam dan setiap nisbah rujukan pada ketinggian yang benar-benar digunakan oleh mesin siap itu.

Soalan Lazim

Adakah TCS230 sama dengan TCS3200?

Untuk sketch anda, ya. Kedua-duanya berkongsi model pengaturcaraan dan susunan pin yang sama β€” penskalaan S0/S1, pemilihan penapis S2/S3, frekuensi pada OUT β€” jadi kod untuk mana-mana satu berjalan tanpa diubah di sini. Board ini ialah yang biasa disenaraikan sebagai GY-31, dengan silkscreen Color Sensor merentasi belakangnya.

Perlukah saya solder modul TCS230?

Ya β€” dua baris 5-pinnya ialah lubang tembus bersalut yang menerima header male 2.54 mm. Senarai komponen sudah memasukkan jalur 40-pin untuk dipatahkan dua kepingan 5-hala, atau tambah servis solder 10 pin dan kami pasangkan.

Kenapa pin LED mesti ke 5V dan bukan ke pin digital?

Ia memacu empat LED putih melalui perintang 330 Ξ©, lebih kurang 23–25 mA kesemuanya β€” melebihi 20 mA yang masih dinyatakan oleh datasheet ATmega328P untuk voltan output sesuatu pin, dan hampir dengan maksimum mutlaknya 40 mA. Pencahayaan yang berterusan pun lebih sesuai untuk pengukuran.

Kenapa sensor ini perlukan kad putih sebelum ia berfungsi?

TCS230 mengukur cahaya pantulan, jadi kiraan mentahnya bergantung pada jarak dan pencahayaan bilik sama banyak seperti pada warna. Satu bacaan putih dan satu bacaan hitam pada jarak kerja anda memberi map() dua hujung skalanya.

Boleh tak ia bezakan biru cair daripada biru tua?

Boleh, tapi hanya kalau anda kekalkan kecerahan dalam kiraan. Nisbah memang sengaja membuang kecerahan, jadi biru pucat dan biru pekat pada rona yang sama mendarat pada triplet yang serupa. Simpan jumlah pra-nisbah 0–255 di sebelah setiap rujukan sebagai ujian kedua.

Pengelas warna ialah mata sebuah mesin pengasing, bukan keseluruhan mesin itu. Panduan motor stepper 28BYJ-48 kami merangkumi lengannya, dan projek robot line follower pula menunjukkan jenis penderiaan optik yang satu lagi β€” pantulan, cerah lawan gelap.

Kemas kini terakhir Ogos 2026. Tersangkut? Chat dengan kami di WhatsApp.

Leave a Reply

Your email address will not be published. Required fields are marked *