[아두이노] Color Sensor 제어

IOT/아두이노|2019. 8. 1. 09:00

[아두이노] Color Sensor 제어



Color Sensor(TCS3200)은 색을 감지할 수 있는 센서입니다. 빛에서 색을 주파수값으로 읽는 센서인데 이 주파수 값을 가지고 RGB색을 만들어 내게 됩니다. 참고로 주파수 값을 읽을 수 있다고 해서 색값으로 바로 만들어 지지 않습니다. 각 RGB색의 값에 대한 주파수 영역을 잡아 색값 0~255사이의 값으로 변환 시켜야 합니다. 그 색 주파수 영역을 통해서 진짜 RGB색을 만들어 내는데 최근에 구매한 부품이여서 정확히 RGB 주파수 영역을 직접 만들어 내지 못했네요. 색종이로 RGB색을 측정하여 주파수 영역을 잡고 조정 작업을 해야 하는데 이미 만들놓은 분의 RGB 주파수 영역을 인용하여 간단히 실험을 하였습니다. 시간적 여유가 되시는 분들은 꼭 직접 RGB 주파수 영역을 본인이 가지고 있는 Color Sensor의 값을 측정하면서 원시값을 토대로 직접 그 영역을 만들어 보세요. 영유가 안된다면 저처럼 인용을 통해 간단히 실험하시면 됩니다.


1. Color Sensor




위 그림처럼 해당 핀에 대해서 살펴봅시다.

S0, S1 핀을 통해서 출력되는 주파수 크기값을 지정 합니다.


퍼센트 수치가 클수록 출력되는 숫자의 값은 작아 집니다. (L, H)은 숫자의 크기가 너무 큰 수가 나오고 (H,H)은 너무 작은 숫자값이 나오기 때문에 RGB색을 추출하기에는 좀 불편합니다. 그나마 색(0~255)을 만들기 위해서는 적당한 출력 수치값으로 (H,L)로 출력하면 적당한 주파수 크기로 출력됩니다. 실험에서는 (H,L)로 20% 크기로 출력됩니다.

RGB 각 색의 주파수 값을 얻기 위해서는 S2, S3의 상태로 해당 색상의 주파수 값을 얻을 수 있습니다.


위 표를 통해 RGB 색의 주파수 값을 얻게 됩니다.

결론은 S0, S1은 출력되는 주파수 크기를 지정하고 S2,S3은 해당 색을 지정해 줍니다.

2. Color Sensor 회로도




Color 센서에서 측정된 RGB 값을 3색 LED로 출력하는 회로도 입니다.

3. 코딩


위 데이터시트에의 나온 표를 기반으로 Color Sensor의 색을 읽기

Red 색 읽기

digitalWrite(s0_pin,HIGH); //출력 크기
digitalWrite(s1_pin,LOW);

digitalWrite(s2_pin,LOW); //Red 색
digitalWrite(s3_pin,LOW);
int Red = pulseIn(out_pin, LOW); //Red 주파수 값

Green 색 읽기

digitalWrite(s0_pin,HIGH);
digitalWrite(s1_pin,LOW);
digitalWrite(s2_pin,HIGH); //Green 색
digitalWrite(s3_pin,HIGH);
int Green = pulseIn(out_pin, LOW);

Blue 색 읽기

digitalWrite(s0_pin,HIGH);
digitalWrite(s1_pin,LOW);
digitalWrite(s2_pin,LOW); //Blue 색
digitalWrite(s3_pin,HIGH);
int Blue = pulseIn(out_pin, LOW);

3가지 색을 이렇게 읽게 됩니다.

스케일 20%로 고정이니깐 출력 크기는 setup()함수로 빼내고 나머지 각 색은 Loop함수에서 지정해 주면 되겠죠.

R,G,B 색값을 읽으면 그 색값이 색으로 보여지지 않습니다. 데이터시트에 가시면 주파수 챠트가 있는데 그걸 보고 색의 추출 범위를 지정해야 합니다.

색종이 같은 걸로 Red, Green, Blue 색의 주파수 최소 최대 범위를 지정하면 좋은데 색종이가 없어서 색의 범위 지정하기 어려워서 색의 범위를 만든 post를 겨우 찾아서 색의 범위를 지정할 수 있게 되었네요.



위 post 출처에서 Red, green, blue의 범위를 인용하여 실험했네요.

red_color = map(red_color, 25,72,255,0);
green_color = map(green_color, 30,90,255,0);
blue_color = map(blue_color, 25,70,255,0);

제가 보유한 Color Sensor는 깔금하게 색을 만들어 내지 못하더군요. 그리고 색 값이 0~255 범위를 벗어나는 값이 나오기 때문에 constrain()함수로 0~255사이로 묶어 두었습니다. 0보다 작은 값은 0에 고정되게 하고 255값을 벗어나면 255에 고정되게 만들었네요.

Red을 기준으로 표현하면

int Red = pulseIn(out_pin, LOW);
red_color = map(red_color, 25,72,255,0);
red_color = constrain(red_color, 0, 255);

나머지 색도 위 코딩과 같이 코딩하시면 됩니다.

Color 값을 만들었다면 그 값을 3색 LED로 핀은 PWM 핀으로 아날로그값을 출력하기 때문에 아래와 같이 코딩하면 됩니다.

RGB LED 출력

analogWrite(r_pin, red_color);
analogWrite(g_pin, green_color);
analogWrite(b_pin, blue_color);

종합해 보면,

const byte s0_pin = 3;
const byte s1_pin = 4;
const byte s2_pin = 5;
const byte s3_pin = 6;
const byte out_pin = 7;

const byte r_pin = 9;
const byte g_pin = 10;
const byte b_pin = 11;


void setup() {
  Serial.begin(9600);
  
  pinMode(r_pin, OUTPUT);
  pinMode(g_pin, OUTPUT);
  pinMode(b_pin, OUTPUT);
  
  pinMode(s0_pin, OUTPUT);
  pinMode(s1_pin, OUTPUT);
  pinMode(s2_pin, OUTPUT);
  pinMode(s3_pin, OUTPUT);
  
  pinMode(out_pin, INPUT);
  
  digitalWrite(s0_pin,HIGH);
  digitalWrite(s1_pin,LOW);
}

void loop() {

  //Red Color Read
  digitalWrite(s2_pin,LOW);
  digitalWrite(s3_pin,LOW);
  int red_color = pulseIn(out_pin, LOW);
  red_color = map(red_color, 25,72,255,0);
  red_color = constrain(red_color, 0, 255);
  delay(50);
  
  //Green Color Read
  digitalWrite(s2_pin,HIGH);
  digitalWrite(s3_pin,HIGH);
  int green_color = pulseIn(out_pin, LOW);
  green_color = map(green_color, 30,90,255,0);
  green_color = constrain(green_color, 0, 255);
  delay(50);
  
  //Blue Color Read
  digitalWrite(s2_pin,LOW);
  digitalWrite(s3_pin,HIGH);
  int blue_color = pulseIn(out_pin, LOW);
  blue_color = map(blue_color, 25,70,255,0);
  blue_color = constrain(blue_color, 0, 255);
  delay(50);

  //3색 LED에 RGB 출력
  analogWrite(r_pin, red_color);
  analogWrite(g_pin, green_color);
  analogWrite(b_pin, blue_color);
  
  Serial.print("RED: ");
  Serial.print(red_color);
  Serial.print("  ");
  
  Serial.print("GREEN: ");
  Serial.print(green_color);
  Serial.print("  ");

  Serial.print("BLUE: ");
  Serial.print(blue_color);
  Serial.println("  ");
  
  delay(1000);
}

4. 결과


시리얼 모니터에 색값을 출력해 보았습니다.


스케일을 2%로 지정했다면 위 값은 천단위로 출력되고 스케일을 100% 했다면 일단위로 값이 출력됩니다. 위 결과처럼 20%가 가장 적당합니다. 참고로 위 결과는 20% 스케일의 map()함수를 이용하여 주파수 값을 색값으로 변환하고 다시 constrain()함수로 0~255사이로 고정시켜 나온 결과입니다.

아래 3색 LED에 Color Sensor로 측정한 값이 출력한 영상인데 깔끔하게 출력되지 않네요. Color Sensor를 딱 붙이지 않고 좀 높이를 어느정도 띄워서 측정하면 색이 좀 더 측정하는 색에 가깝게 출력되더군요. 한손으로 측정하고 한손으로 스마트폰 촬영을 하다 보니깐 높이를 제대로 맞추지 못해서 결과는 마음에 들지 않게 나왔네요.


마무리


Color Sensor부품은 처음에는 좀 쉽게 생각했는데 다루기가 좀 까다로운 부품이네요. 동작 코딩은 어렵지 않지만 정확하게 색의 값을 만들어 내는게 쉽지 않네요. 센서의 연결 부분에 노이즈가 발생하면 값의 변화가 크고 정확하게 RGB값으로 분리해 내기도 어렵습니다. 직접 사용하는 센서의 측정되는 RGB값의 범위를 일일히 잡아야 하는게 쉬운 부품이 아니네요. RGB 색값의 범위를 지정 할 수 있다면 나머지 부분은 간단하기 때문에 컨트롤 하기는 어렵지는 않는데 색 주파수 영역이 문제네요.


댓글()