[매드정] 아두이노 강좌 - 23. 칼라 검출 센서 모듈 동작




안녕하세요~ 매드 입니다.
지난 영상강좌로 칼라센서를 했었는데 블로깅 하기도 전에 시간이 벌써 이렇게 지나버렸네요. ㅎㅎ

지난 시간에 말씀드린데로 이번 칼라센서는 2부로 진행하면서 ... 블로깅은 한번에 진행하겠습니다. 하하;; (게으름)

1부 영상에서 말씀드린데로 칼라센서 동작을 시키고 그걸로 RGB LED의 색깔을 나타내고자 합니다. 1부 에서는 정신 없이 진행하느라 동작에 대해서 잘 알 수 없었는데 제가 알아본 칼라센서의 특징에 대해서 알아보도록 하죠.


23-1. 칼라센서란?
< 출처 : 구글 사진 >
칼라센서는 위와 같이 생겼습니다~ ㅎㅎ 렌즈 홀더가 없는 것들도 있는데요. 제가 사용하는건 렌즈 홀더가 없는 버젼이 되겠네요. 렌즈홀더가 있는게 아무래도 칼라 측정할 때 외부의 색을 차단해주기 때문에 좀 더 정확한 칼라를 측정할 수 있지 않을까 생각해 봅니다.

칼라센서로 측정할 수 있는 데이터는 RGB로 출력되는데요. 이 데이터는 저희가 기존에 알고 있던 RGB 888 과 같은 데이터는 아니고 센서가 칼라에 따라서 출력되는 펄스값을 출력하는 것입니다. 그럼 이걸로 어떻게 칼라를 구별하냐구요?

이 칼라센서 같은경우 8가지? 정로는 판별할 수 있을 것 같지만 그 이상이되면 오류가 많아 질 것 같네요. 기준이 되는 색깔을 미리 준비해두고 하나하나 측정하면서 값의 범위를 기록하여 오차범위를 계산해서 그 안에 들어오면 칼라를 구별 할 수 있도록 프로그램을 코딩하면 될 것 같습니다. ㅠ

아 .. 먼가 복잡하네요 ㅎㅎ 이 칼라센서 같은 경우는 한두가지의 색 구별 또는 판단용으로만 사용하는게 맞을 것 같네요! ㅎㅎ

그럼 연결해서 사용해보도록 할까요?~


23-2. 칼라센서 회로

< 출처 : http://www.dfrobot.com/wiki/index.php/TCS3200_Color_Sensor_(SKU:SEN0101) >

구글에 검색해보니 위와 같이 연결 방법을 정리 둔 것이 있네요! ㅎㅎ 간단하죠~?

기능에 비해서 사용법은 대략 까다로운 편인 것 같습니다.

가격대비 성능을 본다면 생각에는 그냥 OV7670 CMOS의 RGB 출력을 이용하여 칼라를 판별하는 것이 좀 더 정확하고 확실할 것 같네요 ㅎㅎ

특별한 연결은 없지만 OE 핀이 있으신분은 GND에 연결하여 사용하시면 될것 같습니다. OUT ENABLE 핀인데 ㅎㅎ 이 핀을 활성화 시켜주셔야 출력이 나가기 때문이죠

센서의 OUT을 아두이노의 D2에 연결하는 이유는 아두이노가 가지고 있는 외부인터럽트 핀이 2개(D2,D3)가 있는데 이를 이용하여 센서로부터 출력되는 신호를 모드 잡아내기 위해서 이렇게 연결한 것 같네요. ㅎㅎ

저희는 여기에 좀 더 화려하게 보이기 위해서 센서로 측정한 데이터를 RGB LED를 통해 칼라를 포현하도록 해보겠습니다. RGB LED는 이전에 했었던 WS2812b 를 가지고 해보겠습니다~~



23-3. 펌웨어 코드

- RGB 칼라 비교 검출 코드
int s0=3,s1=4,s2=5,s3=6;
int flag=0;
int counter=0;
int countR=0,countG=0,countB=0;
void setup()
 {
 Serial.begin(9600);
 pinMode(s0,OUTPUT);
 pinMode(s1,OUTPUT);
 pinMode(s2,OUTPUT);
 pinMode(s3,OUTPUT);
 }
void TCS()
 {
   digitalWrite(s1,HIGH);
   digitalWrite(s0,LOW);
   flag=0;
   attachInterrupt(0, ISR_INTO, CHANGE);
   timer2_init();
 }
void ISR_INTO()
 {
   counter++;
 }
 void timer2_init(void)
 {
   TCCR2A=0x00;
   TCCR2B=0x07; //the clock frequency source 1024 points
   TCNT2= 100;    //10 ms overflow again
   TIMSK2 = 0x01; //allow interrupt
 }
 int i=0;
 ISR(TIMER2_OVF_vect)//the timer 2, 10ms interrupt overflow again. Internal overflow interrupt executive function
{
 TCNT2=100;
 flag++;
 if(flag==1)
  {
    counter=0;
  }
 else if(flag==2)
   {
    digitalWrite(s2,LOW);
    digitalWrite(s3,LOW);
    countR=counter/1.051;
    Serial.print("red=");
    Serial.println(countR,DEC);
    digitalWrite(s2,HIGH);
    digitalWrite(s3,HIGH);
   }
 else if(flag==3)
    {
     countG=counter/1.0157;
    Serial.print("green=");
    Serial.println(countG,DEC);
     digitalWrite(s2,LOW);
     digitalWrite(s3,HIGH);
 
    }
 else if(flag==4)
    {
     countB=counter/1.114;
    Serial.print("blue=");
    Serial.println(countB,DEC);
     digitalWrite(s2,LOW);
     digitalWrite(s3,LOW);
     }
 else
     {
     flag=0;
      TIMSK2 = 0x00;
     }
     counter=0;
     delay(2);
}
void loop()
 {
  delay(10);
  TCS();
  if((countR>10)||(countG>10)||(countB>10))
   {
      if((countR>countG)&&(countR>countB))
       {
            Serial.print("red");
            Serial.print("\n");
            delay(1000);
       }
      else if((countG>=countR)&&(countG>countB))
       {
            Serial.print("green");
            Serial.print("\n");
            delay(1000);
       }
     else if((countB>countG)&&(countB>countR))
      {
            Serial.print("blue");
            Serial.print("\n");
           delay(1000);
      }
    }
  else
  {
     delay(1000);    
  }
 }


- WS2812b 를 이용해서 검출한 칼라를 출력하는 코드!
#include <Adafruit_NeoPixel.h>

#define PIN            7
#define NUMPIXELS      1

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int s0 = 3, s1 = 4, s2 = 5, s3 = 6;
int flag = 0;
int counter = 0;
int countR = 0, countG = 0, countB = 0;
void setup()
{
  Serial.begin(9600);
  pinMode(s0, OUTPUT);
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  pinMode(s3, OUTPUT);
  pixels.begin(); // This initializes the NeoPixel library.
  pixels.setPixelColor(0, pixels.Color(0, 0, 0)); // Moderately bright green color.
  pixels.show(); // This sends the updated pixel color to the hardware.
}
void TCS()
{
  digitalWrite(s1, HIGH);
  digitalWrite(s0, LOW);
  flag = 0;
  attachInterrupt(0, ISR_INTO, CHANGE);
  timer2_init();
}
void ISR_INTO()
{
  counter++;
}
void timer2_init(void)
{
  TCCR2A = 0x00;
  TCCR2B = 0x07; //the clock frequency source 1024 points
  TCNT2 = 100;   //10 ms overflow again
  TIMSK2 = 0x01; //allow interrupt
}
int i = 0;
ISR(TIMER2_OVF_vect)//the timer 2, 10ms interrupt overflow again. Internal overflow interrupt executive function
{
  TCNT2 = 100;
  flag++;
  if (flag == 1)
  {
    counter = 0;
  }
  else if (flag == 2)
  {
    digitalWrite(s2, LOW);
    digitalWrite(s3, LOW);
    countR = counter / 1.051;
    Serial.print("red=");
    Serial.println(countR, DEC);
    digitalWrite(s2, HIGH);
    digitalWrite(s3, HIGH);
  }
  else if (flag == 3)
  {
    countG = counter / 1.0157;
    Serial.print("green=");
    Serial.println(countG, DEC);
    digitalWrite(s2, LOW);
    digitalWrite(s3, HIGH);

  }
  else if (flag == 4)
  {
    countB = counter / 1.114;
    Serial.print("blue=");
    Serial.println(countB, DEC);
    digitalWrite(s2, LOW);
    digitalWrite(s3, LOW);
  }
  else
  {
    flag = 0;
    TIMSK2 = 0x00;
  }
  counter = 0;
  delay(2);
}
void loop()
{
  delay(10);
  TCS();
  if ((countR > 10) || (countG > 10) || (countB > 10))
  {
    if ((countR > countG) && (countR > countB))
    {
      Serial.print("===== red =====");
      Serial.print("\n");
      pixels.setPixelColor(0, pixels.Color(255, 0, 0)); // Moderately bright green color.
      pixels.show(); // This sends the updated pixel color to the hardware.
      delay(1000);
    }
    else if ((countG >= countR) && (countG > countB))
    {
      Serial.print("===== green =====");
      Serial.print("\n");
      pixels.setPixelColor(0, pixels.Color(0, 255, 0)); // Moderately bright green color.
      pixels.show(); // This sends the updated pixel color to the hardware.
      delay(1000);
    }
    else if ((countB > countG) && (countB > countR))
    {
      Serial.print("===== blue =====");
      Serial.print("\n");
      pixels.setPixelColor(0, pixels.Color(0, 0, 255)); // Moderately bright green color.
      pixels.show(); // This sends the updated pixel color to the hardware.
      delay(1000);
    }
  }
  else
  {
    pixels.setPixelColor(0, pixels.Color(0, 0, 0)); // Moderately bright green color.
    pixels.show(); // This sends the updated pixel color to the hardware.
    delay(1000);
  }
}


1부


2부


오늘도 다들 수고 하셨구요~~~ ㅎㅎ 다음에는 아두이노에서 그 유명한 ESP8266 WiFi 모듈을 다뤄보도록 하겠습니다!! ㅎㅎ

그럼 다음주에 뵐께요~~!

댓글 쓰기

2 댓글

  1. 저기 이대로 했는데 값이 10000넘게 출력되는경우에 어디를 건드려야 될까요??ㅠㅠ

    답글삭제
    답글
    1. 안녕하세요~ ㅎㅎ
      칼라 데이터 출력되는건 어느정도 차이가 생길 수도 있습니다.
      좀 더 상세한 정보를 알려주셔야 답변이 가능할 것 같네요~~ >,.<

      삭제