تشخیص رنگ با سنسور TCS230 و آردوینو [شامل کد کالیبراسیون]

فهرست مطالب

مقدمه

در این آموزش با سنسور رنگ TSC320 آشنا شده و یاد می گیرید که چگونه این سنسور  را به آردوینو متصل کرده و از آن در تشخیص رنگ استفاده کنید.

در انتهای این آموزش یک ایده ی جذاب برای ساخت قلم اسکن رنگ، مطرح شده است. با این قلم می توانید رنگ اجسام محیط را اسکن کرده و با آن رنگ، شروع به نقاشی روی یک نمایشگر کنید.

آنچه در این آموزش یاد می گیرید

سنسور TSC230 چیست؟

تراشه ی  TSC230 دارای یک آرایه ی 8×8 از فوتو دیود های سیلیکونی است که از آن ها برای تشخیص رنگ استفاده می کند. از این 64 فتو دیود، 16 عدد دارای فیلتر رنگ قرمز، 16 عدد دارای فیلتر رنگ سبز، 16 عدد دارای فیلتر  رنگ آبی و 16 عدد بدون فیلتر هستند.

ماژول TCS230 دارای 4 ال ای دی سفید رنگ است. فوتو دیود ها، بازتاب نور این الی ای دی ها را از سطح جسم دریافت می کنند و بسته به رنگی که دریافت کرده اند، یک جریان الکتریکی تولید می کنند.

در داخل این سنسور علاوه بر فوتو دیودها، یک مبدل جریان به فرکانس نیز وجود دارد. این مبدل، جریان تولید شده توسط فوتو دیود ها را به فرکانس تبدیل می کند.

خروجی این ماژول به صورت فرکانس با پالس های مربعی با duty cycle 50 درصد است.

بهترین بازه ی اندازه گیری این سنسور حدود 2 تا 4 سانتی متر است.

پایه های سنسور

این سنسور 4 پایه ی کنترلی دارد. پایه های S0 و S1 برای کنترل مقیاس فرکانس خروجی (OUTPUT FREQUENCY SCALING) و پایه های S2 و S3 برای انتخاب نوع فوتو دیود (قرمز، سبز، آبی و بدون فیلتر) است.

مدار مبدل جریان به فرکانس، دارای مقسم های فرکانس (frequency dividers)  است. با پایه های کنترلی S0 و S1 می توانید این مقسم فرکانسی را کنترل کنید.

S0 S1 OUTPUT FREQUENCY SCALING (f0) S2 S3 PHOTODIODE TYPE
L L Power down L L Red
L H 2% L H Blue
H L 20% H L Clear (no filter)
H H 100% H H green

برای مثال، اگر بخواهید مقدار رنگ آبی یک جسم را اندازه گیری کنید، باید همزمان پایه ی S2 را LOW و S3 را HIGH کنید.

لوازمی که به آن احتیاج دارید

قطعات مورد نیاز

برد آردوینو UNO × 1
سنسور تشخیص رنگ TCS230 × 1
Breadboard × 1
RGB LED × 1
نمایشگر 2.4” TFT × 1
سیم جامپر نری به مادگی × 1
مقاومت 220 اهم × 3

نرم افزارهای مورد نیاز

Arduino IDE

راه اندازی سنسور تشخیص رنگ TCS230 با آردوینو

برای راه اندازی این ماژول کافیست طبق مدار زیر آن را به آردوینو وصل کرده و با مقداردهی به پایه های S0 تا S4، خروجی رنگ های مختلف را تحلیل کنید.

سیم بندی

طبق مدار زیر، سنسور را به آردینو متصل کنید.

کد

کد زیر، سیگنال خروجی برای هر سه رنگ قرمز، سبز و آبی را اندازه گیری می کند و نتیجه را روی پورت سریال نمایش می دهد.


/* 

  TCS230 color recognition sensor 

  modified on 7 May 2019 

  by Mohammadreza Akbari @ Electropeak 

  
Home
Color Sensor Arduino ----------- -------- VCC 5V GND GND s0 8 s1 9 s2 10 s3 11 OUT 12 OE GND */ const int s0 = 8; const int s1 = 9; const int s2 = 10; const int s3 = 11; const int out = 12; // LED pins connected to Arduino int redLed = 2; int greenLed = 3; int blueLed = 4; // Variables int red = 0; int green = 0; int blue = 0; void color() { digitalWrite(s2, LOW); digitalWrite(s3, LOW); //count OUT, pRed, RED red = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH); digitalWrite(s3, HIGH); //count OUT, pBLUE, BLUE blue = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH); digitalWrite(s2, HIGH); //count OUT, pGreen, GREEN green = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH); } void setup() { Serial.begin(9600); pinMode(s0, OUTPUT); pinMode(s1, OUTPUT); pinMode(s2, OUTPUT); pinMode(s3, OUTPUT); pinMode(out, INPUT); pinMode(redLed, OUTPUT); pinMode(greenLed, OUTPUT); pinMode(blueLed, OUTPUT); digitalWrite(s0, HIGH); digitalWrite(s1, HIGH); } void loop() { color(); Serial.print("R Intensity:"); Serial.print(red, DEC); Serial.print(" G Intensity: "); Serial.print(green, DEC); Serial.print(" B Intensity : "); Serial.print(blue, DEC); //Serial.println(); if (red < blue && red < green && red < 20) { Serial.println(" - (Red Color)"); digitalWrite(redLed, HIGH); // Turn RED LED ON digitalWrite(greenLed, LOW); digitalWrite(blueLed, LOW); } else if (blue < red && blue < green) { Serial.println(" - (Blue Color)"); digitalWrite(redLed, LOW); digitalWrite(greenLed, LOW); digitalWrite(blueLed, HIGH); // Turn BLUE LED ON } else if (green < red && green < blue) { Serial.println(" - (Green Color)"); digitalWrite(redLed, LOW); digitalWrite(greenLed, HIGH); // Turn GREEN LED ON digitalWrite(blueLed, LOW); } else{ Serial.println(); } delay(300); digitalWrite(redLed, LOW); digitalWrite(greenLed, LOW); digitalWrite(blueLed, LOW); }
تابع color پایه های S2 و S3 را کنترل می کند تا همه ی رنگ های جسم خوانده شود. در این تابع از دستور pulseIn برای دریافت پالس های ورودی از ماژول رنگ استفاده شده است. توضیحات بیشتر راجع به این دستور را می توانید در اینجا مشاهده کنید.
دستور شرطی
عملکرد این دستور مشابه دستور if و else است. اگر شرط درست باشد، exp1 و در غیر این صورت exp2 به عنوان خروجی این دستور خواهد بود.

کالیبره کردن سنسور تشخیص رنگ TCS230

برای کالیبره کردن سنسور نیاز به یک جسم با رنگ سفید دارید.

تابع  calibrate عملیات کالیبره کردن سنسور را انجام می دهد. برای کالیبره کردن سنسور کافیست در پنجره سریال، کاراکتر “c” را وارد کنید. سپس باید اجسام رنگی را از سنسور دور کرده و مجددا “c” را وارد کنید. حالا جسم سفید رنگ را نزدیک سنسور بگیرید و مجددا “c” را وارد کنید.

در پایان کالیبره کردن، اگر جسم سفید رنگ را مقابل سنسور نگه دارید، برای هر سه رنگ قرمز و سبز و آبی باید مقدار 255 (یا نزدیک به 255) را در پنجره ی سریال مشاهده کنید.

نحوه ی کار این تابع بسیار ساده است. این تابع حداقل و حداکثر تغییرات فرکانس خروجی سنسور را در محیط بدون رنگ و  رنگ سفید محاسبه و ذخیره می کند.

سپس در بخش loop با دستور map بازه ی حداقل و حداکثر تغییرات را روی بازه ی 0 تا 255 (یا هر بازه ای که شما تعریف کنید) مقیاس (map) می کند.

اگر با دستور map آشنا نیستید به اینجا مراجعه کنید.

کد

/* 

  // TCS230 color recognition with calibration 

  modified on 7 May 2019 

  by Mohammadreza Akbari @ Electropeak 

  
Home
Color Sensor Arduino ----------- -------- VCC 5V GND GND s0 8 s1 9 s2 10 s3 11 OUT 12 OE GND */ const int s0 = 8; const int s1 = 9; const int s2 = 10; const int s3 = 11; const int out = 12; // LED pins connected to Arduino int redLed = 5; int greenLed = 6; int blueLed = 3; // Variables int red = 0; int green = 0; int blue = 0; // Calibrated value int cal_min = 5; int cal_max_r = 50; int cal_max_g = 50; int cal_max_b = 50; void calibrate() { Serial.println("Clear sensor area. Then enter c again"); while (Serial.read() != 'c') { //do nothing ; } color(); cal_max_r = red; cal_max_g = green; cal_max_b = blue; Serial.println("Put white color infront of sensor, Then enter c again"); while (Serial.read() != 'c') { //do nothing ; } color(); cal_min = (red + green + blue) / 3; Serial.println("calibrated successfully."); delay(300); } void color() { digitalWrite(s2, LOW); digitalWrite(s3, LOW); //count OUT, pRed, RED red = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH); digitalWrite(s3, HIGH); //count OUT, pBLUE, BLUE blue = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH); digitalWrite(s2, HIGH); //count OUT, pGreen, GREEN green = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH); } void setup() { Serial.begin(9600); pinMode(s0, OUTPUT); pinMode(s1, OUTPUT); pinMode(s2, OUTPUT); pinMode(s3, OUTPUT); pinMode(out, INPUT); pinMode(redLed, OUTPUT); pinMode(greenLed, OUTPUT); pinMode(blueLed, OUTPUT); digitalWrite(s0, HIGH); digitalWrite(s1, HIGH); } void loop() { color(); if (Serial.read() == 'c') { calibrate(); } red = map(red, cal_min, cal_max_r, 255, 0); green = map(green, cal_min, cal_max_g, 255, 0); blue = map(blue, cal_min, cal_max_b, 255, 0); Serial.print("R Intensity:"); Serial.print(red); Serial.print(" G Intensity: "); Serial.print(green); Serial.print(" B Intensity : "); Serial.println(blue); delay(200); }

ساخت قلم اسکن رنگ با سنسور TCS230 و آردوینو

اگر از آردوینو UNO استفاده می کنید، باید سنسور رنگ را با سیم به پایه های آردوینو لحیم کنید. ولی اگر از آردوینو MEGA استفاده می کنید، می توانید از پایه های انتهای برد برای اتصال سنسور رنگ استفاده کنید

اگر برای اولین بار است که با نمایشگر کار می کنید، می توانید آموزش راه اندازی نمایشگر را در اینجا مشاهده کنید.

کد زیر یک صفحه ی نقاشی را روی نمایشگر ایجاد می کند. رنگ اولیه ی قلم قرمز است. با نگه داشتن کلید و نزدیک کردن سنسور تشخیص رنگ به جسم مورد نظر، رنگ آن انتخاب می شود و رنگ قلم شما به رنگ جسم مورد نظر تغییر می کند.

سیم بندی

کد

/* 

  TCS230 color picker + paint 

  Modified on 8 May 2019 

  By Mohammadreza Akbari @ Electropeak 

  
Home
Color Sensor Arduino ----------- -------- VCC 5V GND GND s0 5V s1 5V s2 10 s3 11 OUT 12 OE GND */ #include <Adafruit_GFX.h>    // Core graphics library #include <Adafruit_TFTLCD.h> // Hardware-specific library #include <TouchScreen.h> #if defined(__SAM3X8E__) #undef __FlashStringHelper::F(string_literal) #define F(string_literal) string_literal #endif //LCD #define YP A3 // must be an analog pin, use "An" notation! #define XM A2 // must be an analog pin, use "An" notation! #define YM 9 // can be a digital pin #define XP 8 // can be a digital pin #define TS_MINX 150 #define TS_MINY 120 #define TS_MAXX 920 #define TS_MAXY 940 // For better pressure precision, we need to know the resistance // between X+ and X- Use any multimeter to read it // For the one we're using, its 300 ohms across the X plate TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300); #define LCD_CS A3 #define LCD_CD A2 #define LCD_WR A1 #define LCD_RD A0 // optional #define LCD_RESET A4 // Assign human-readable names to some common 16-bit color values: #define BLACK 0x0000 #define BLUE 0x001F #define RED 0xF800 #define GREEN 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define WHITE 0xFFFF Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET); #define BOXSIZE 40 #define PENRADIUS 3 int oldcolor, ccolor; #define MINPRESSURE 10 #define MAXPRESSURE 1000 //Color sensor const int s2 = 10; const int s3 = 11; const int out = 12; const int button = 13; // Color variables int red = 0; int green = 0; int blue = 0; // Calibrated value int cal_min = 5; int cal_max_r = 50; int cal_max_g = 50; int cal_max_b = 50; uint16_t my_color; void calibrate() { Serial.println("Clear sensor area. Then enter c again"); while (Serial.read() != 'c') { //do nothing ; } color(); cal_max_r = red; cal_max_g = green; cal_max_b = blue; Serial.println("Put white color infront of sensor, Then enter c again"); while (Serial.read() != 'c') { //do nothing ; } color(); cal_min = (red + green + blue) / 3; Serial.println("calibrated successfully."); delay(300); } void color() { digitalWrite(s2, LOW); digitalWrite(s3, LOW); //count OUT, pRed, RED red = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH); digitalWrite(s3, HIGH); //count OUT, pBLUE, BLUE blue = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH); digitalWrite(s2, HIGH); //count OUT, pGreen, GREEN green = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH); } void pick_color() { color(); red = map(red, cal_min, cal_max_r, 255, 0); green = map(green, cal_min, cal_max_g, 255, 0); blue = map(blue, cal_min, cal_max_b, 255, 0); Serial.print("R Intensity:"); Serial.print(red); Serial.print(" G Intensity: "); Serial.print(green); Serial.print(" B Intensity : "); Serial.println(blue); //my_color = tft.color565(abs(255 - red), abs(255 - green), abs(255 - blue)); my_color = tft.color565(red, green, blue); tft.fillRect(0, 0, 6*BOXSIZE, BOXSIZE, my_color); delay(100); } void setup() { Serial.begin(9600); tft.reset(); delay(1000); uint16_t identifier = tft.readID(); if (identifier == 0x9325) { Serial.println(F("Found ILI9325 LCD driver")); } else if (identifier == 0x9328) { Serial.println(F("Found ILI9328 LCD driver")); } else if (identifier == 0x7575) { Serial.println(F("Found HX8347G LCD driver")); } else if (identifier == 0x9341) { Serial.println(F("Found ILI9341 LCD driver")); } else if (identifier == 0x8357) { Serial.println(F("Found HX8357D LCD driver")); } else { Serial.print(F("Unknown LCD driver chip: ")); Serial.println(identifier, HEX); Serial.println(F("If using the Adafruit 2.8\" TFT Arduino shield, the line:")); Serial.println(F("#define USE_ADAFRUIT_SHIELD_PINOUT")); Serial.println(F("should appear in the library header (Adafruit_TFT.h).")); Serial.println(F("If using the breakout board, it should NOT be #defined!")); Serial.println(F("Also if using the breakout, double-check that all wiring")); Serial.println(F("matches the tutorial.")); return; } tft.begin(identifier); tft.fillScreen(BLACK); tft.fillRect(0, 0, 6*BOXSIZE, BOXSIZE, RED); my_color = RED; pinMode(s2, OUTPUT); pinMode(s3, OUTPUT); pinMode(out, INPUT); pinMode(button, INPUT_PULLUP); } void loop() { if (Serial.read() == 'c') { calibrate(); } while (digitalRead(button) == LOW) { pick_color(); } TSPoint p = ts.getPoint(); // if sharing pins, you'll need to fix the directions of the touchscreen pins //pinMode(XP, OUTPUT); pinMode(XM, OUTPUT); pinMode(YP, OUTPUT); //pinMode(YM, OUTPUT); // we have some minimum pressure we consider 'valid' // pressure of 0 means no pressing! if (p.z > MINPRESSURE && p.z < MAXPRESSURE) { /* Serial.print("X = "); Serial.print(p.x); Serial.print("\tY = "); Serial.print(p.y); Serial.print("\tPressure = "); Serial.println(p.z); */ if (p.y < (TS_MINY-5)) { Serial.println("erase"); // press the bottom of the screen to erase tft.fillRect(0, BOXSIZE, tft.width(), tft.height()-BOXSIZE, BLACK); } // scale from 0->1023 to tft.width p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0); p.y = map(p.y, TS_MINY, TS_MAXY, tft.height(), 0); /* Serial.print("("); Serial.print(p.x); Serial.print(", "); Serial.print(p.y); Serial.println(")"); */ if (((p.y-PENRADIUS) > BOXSIZE) && ((p.y+PENRADIUS) < tft.height())) { tft.fillCircle(p.x, p.y, PENRADIUS, my_color); } } }

تابع pick_color، در زمان فشردن کلید فراخوانی می شود و رنگ جسمی که در نزدیکی سنسور قرار دارد را می خواند. سپس رنگ قلم را به رنگ جسم تغییر می دهد.

یک گام جلوتر

  • یک دستگاه انبارداری کوچک بسازید که قطعات لگو را با توجه به رنگ آن ها از یکدیگر جدا کند.

آموزش‌های مشابه

از این مطلب خوشتان آمد؟

آخرین مطالت و آموزش ها را در ایمیلتان دریافت کنید:

مطالب بیشتر

Comments (2)

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد.