TCS230 RGB color sensor operation and Code
Here is the image and the block diagram of the TCS230 color sensor,
The first block that comes into picture is the Photodiode array. The photodiode array consists of three sets of diodes each for sensing Red, Green and Blue color respectively. So, when you are measuring the intensity of Red light you need to enable only the Red photodiode array and disable the other two photo diode arrays.
The output enable pin is generic output enable pin which turns the square wave output ON/OFF.
Detecting the color: The TCS230 color sensor is having only one output pin on which a 50% duty cycle square wave is output continuously.
First we need to make the OE pin low to enable the sensor output, and then make the S0 = 1, S1 = 0 to select a 20% scaled squarewave output.
When we are measuring the color of any object in front of the sensor, we need to perform the measurement in three steps,
- Measure the Red color: To enable only the Red photo diode array by making S2=0, S3=0. Wait for sometime and measure the time period of the square wave on the output pin by enabling only Red photodiode array.
- Measure the Blue color: To enable only the Blue photo diode array by making S2=0, S3=1. Wait for sometime and measure the time period of the square wave on the output pin by enabling only Blue photodiode array.
- Measure the Green color: To enable only the Green photo diode array by making S2=1, S3=1. Wait for sometime and measure the time period of the square wave on the output pin by enabling only Green photodiode array.
After you get the values of the Red, Green and Blue components, you can get the name of the color from any RGB color table. You can also measure the light intensity on the sensor by disabling color filters. To measure the light iintensity disbale the color filters by making S2=1, S3=0. Wait for sometime and measure the time period of the square wave on the output pin.
Code for Color sensor TCS230 using PIC16F877A:
Here i have configured the PIC’s timer module in capture mode where i measure the square waves time period. The color sensors output is connected to the timers capture input pin. To measure RED color, i enable only the Red color receptors and measure the count in the timer registers after a delay which gives me the pulse width.
Here is the piece of code i wrote for PIC16F877A microcontroller. If you want i can share the libraries code.
Download the code for TCS230 color sensor with PIC16F877A microcontroller
{code lang:c title:"TCS 230 PIC16F877A code" lines:false hidden:false}
#include "LCD.h"
#include "UART.h"
#include "I2C.h"
#include "Timer.h"
unsigned short Data[20];
unsigned short Red,Green,Blue,Brightness;
unsigned short Count = 0;
unsigned char over = 0;
unsigned char Colour;
unsigned char Level, PrevLevel;
void InitInterrupts(void)
{
//TRISB0 = 1;
//INTEDG = 0;
//INTE = 1;
PEIE = 1;
//ADIE = 1;
CCP1IE = 1;
GIE = 1;
}
unsigned short i;
unsigned char Temp;
void SendPacket(void)
{
//GIE = 0;
Print("$");
if(10000/Brightness < 200)
{
if(Red < Blue && Red < Green)
{
Print("Red");
}
else if(Green < Red && Green < Blue)
{
Print("Green");
}
else if(Blue < Red && Blue < Green)
{
Print("Blue");
}
}
else
{
Print("Too Bright");
}
PrintNumber3(10000/Red);
Print(",");
PrintNumber3(10000/Green);
Print(",");
PrintNumber3(10000/Blue);
Print(",");
PrintNumber3(10000/Brightness);
Print("rn");
if(over==1)
Print("Overflowrn");
//Delay(120000);
//GIE = 1;
//Delay(120000);
}
// rgbb 443 573 427 189
void main()
{
TRISB4 = 0;
// colour s2 s3
TRISDbits.TRISD1 = 0;
TRISDbits.TRISD0 = 0;
// led
TRISCbits.TRISC3 = 0;
// out
TRISCbits.TRISC2 = 1;
// s0 s1 = frequency
TRISDbits.TRISD2 = 0;
TRISDbits.TRISD3 = 0;
//leds
RC3 = 1;
InitUART();
i = 0;
InitInterrupts();
InitTimer1();
StartTimer1();
RD2 = 1;
RD3 = 0;
Colour =1;
while(1)
{
switch(Colour)
{
case 0:
RD1 = 0;//RED
RD0 = 0;
Delay(5000);
Red = Count;
Colour++;
break;
case 1:
RD1 = 0;//Blue
RD0 = 1;
Delay(5000);
Blue = Count;
Colour++;
break;
case 2:
RD1 = 1;//No color
RD0 = 0;
Delay(5000);
Brightness = Count;
Colour++;
break;
case 3:
RD1 = 1;//Green
RD0 = 1;
Delay(50000);
Green = Count;
Colour = 0;
break;
}
GIE = 0;
SendPacket();
GIE = 1;
}
}
unsigned long Sum;
static void interrupt isroutine(void)
{
if(INTF == 1)
{
}
if(CCP1IF == 1)
{
Count = CCPR1;
TMR1H = 0x00;
TMR1L = 0x00;
CCP1IF = 0;
}
if(TMR1IF == 1)
{
TMR1H = 0x00;
TMR1L = 0x00;
TMR1IF = 0;
over = 1;
}
}{/code}
Circuit diagram for interfacing TCS230 RGB color sensor with PIC16F877A microcontroller :
Code for Color sensor TCS230 using 8051/89S52/89C51 microcontroller:
The output of the color sensor is connected to INT0 of 8051 microcontroller. The microcontroller uses the timer module to measure the time period of the square wave pulses. The objective of the code is to detect the color as RED,BLUE,GREEN and move a stepper motor to a particular position.
Here is a piece of code i wrote for interfacing TCS230 color sensor with 89s52/8051 microcontroller.
Download the code for TCS230 color sensor with 89s52/8051 microcontroller
{code lang:c title:"TCS 230 8051 code" lines:false hidden:false}
#include <reg52.h>
#include"SCI.h"
#include"LCD.h"
#include "Controller.h"
#define STEPS 30
#define NO_COLOUR 0
#define RED 1
#define GREEN 2
#define BLUE 3
/*code const BiforcatorPositionStructType BiforcatorPosition[8] =
{
{RED ,GREEN ,STEPS},
{RED ,BLUE ,STEPS*2},
{GREEN ,RED ,-STEPS},
{GREEN ,BLUE ,STEPS},
{BLUE ,RED ,-STEPS*2},
{BLUE ,GREEN ,-STEPS},
{NO_COLOUR ,RED ,-STEPS},
{NO_COLOUR ,GREEN ,0},
{NO_COLOUR ,BLUE ,STEPS}
}; */
code const int BiforcatorPosition[4][4] =
{
//NO_COLOUR, RED, GREEN, BLUE
0,-STEPS,0,STEPS,// NO_COLOUR
0,0,STEPS,STEPS*2,// RED
0,-STEPS,0,STEPS,// GREEN
0,-STEPS*2,-STEPS,0// BLUE
};
sbit PORT20 = 0xA0;
sbit PORT21 = 0xA1;
sbit PORT22 = 0xA2;
sbit PORT23 = 0xA3;
sbit PORT24 = 0xA4;
sbit PORT25 = 0xA5;
sbit PORT26 = 0xA6;
sbit PORT27 = 0xA7;
sfr PORT3 = 0xB0;
sbit DC_MOTOR = 0xA4;
sbit SERVO_MOTOR = 0xA3;
unsigned short TotalBags = 0,RedBags = 0, BlueBags = 0, GreenBags = 0;
unsigned char Colour, PrevColour = NO_COLOUR,Prev = NO_COLOUR;
unsigned short Red,Green,Blue,Brightness;
unsigned short Count = 0;
unsigned char over = 0;
unsigned short GapDuration = 0;
sbit mot1= 0x93;
sbit mot2= 0x94;
sbit mot3= 0x95;
sbit mot4= 0x96;
void RotateClockWise(unsigned char Steps)
{
while(Steps>0)
{
mot1 = 1;mot2 = 1; mot3 = 1; mot4 = 0;
//while(1);
Delay(500);
mot1 = 1;mot2 = 1; mot3 = 0; mot4 = 1;
Delay(500);
mot1 = 1;mot2 = 0; mot3 = 1; mot4 = 1;
Delay(500);
mot1 = 0;mot2 = 1; mot3 = 1; mot4 = 1;
Delay(500);
Steps--;
}
}
void RotateAntiClockWise(unsigned char Steps)
{
while(Steps>0)
{
mot1 = 0;mot2 = 1; mot3 = 1; mot4 = 1;
//while(1);
Delay(500);
mot1 = 1;mot2 = 0; mot3 = 1; mot4 = 1;
Delay(500);
mot1 = 1;mot2 = 1; mot3 = 0; mot4 = 1;
Delay(500);
mot1 = 1;mot2 = 1; mot3 = 1; mot4 = 0;
Delay(500);
Steps--;
}
}
void MoveMotor(unsigned char Prev,unsigned char Curr)
{
int Steps;
Steps = BiforcatorPosition[Prev][Curr];
//DisplayString(LINE1,"prev=",Prev,DATA_WRITE);
//DisplayString(LINE4,"curr=",Curr,DATA_WRITE);
//PrintNumber3(Curr);
if(Steps < 0)
{
RotateAntiClockWise(Steps*-1);
//DisplayString(LINE3,"stps=",Steps,DATA_WRITE);
}
else
{
//DisplayString(LINE3,"stps=",Steps,DATA_WRITE);
RotateClockWise(Steps);
}
}
void Delay(unsigned long Count)
{
while(Count > 0)
{
Count--;
};
}
void UpdateDisplay(void)
{
//InitLCD();
DisplayString(LINE1,"Total Bags = ",TotalBags,DATA_WRITE);
DisplayString(LINE2,"50 KG = ",RedBags,DATA_WRITE);
DisplayString(LINE3,"100 KG = ",GreenBags,DATA_WRITE);
DisplayString(LINE4,"250 KG = ",BlueBags,DATA_WRITE);
}
void SendPacket(void)
{
//GIE = 0;
Print("$");
if
(
(10000/Red > 200) || (10000/Green > 200) || (10000/Red > 200 )
)
{
if(Red < Blue && Red < Green)
{
Print("Red");
if(PrevColour != RED)
{
RedBags++;
//DisplayString(LINE2,"Red",DUMMY_DATA,MESSAGE_WRITE);
MoveMotor(Prev,RED);
PrevColour = RED;
Prev = RED;
}
//DisplayString(LINE2,"Red",DUMMY_DATA,MESSAGE_WRITE);
}
else if(Green < Red && Green < Blue)
{
Print("Green");
if(PrevColour != GREEN)
{
GreenBags++;
//DisplayString(LINE2,"Green",DUMMY_DATA,MESSAGE_WRITE);
MoveMotor(Prev,GREEN);
PrevColour = GREEN;
Prev = GREEN;
}
//DisplayString(LINE2,"Green",DUMMY_DATA,MESSAGE_WRITE);
}
else if(Blue < Red && Blue < Green)
{
Print("Blue");
if(PrevColour != BLUE)
{
BlueBags++;
//DisplayString(LINE2,"Blue",DUMMY_DATA,MESSAGE_WRITE);
MoveMotor(Prev,BLUE);
PrevColour = BLUE;
Prev = BLUE;
}
//DisplayString(LINE2,"Blue",DUMMY_DATA,MESSAGE_WRITE);
}
}
else
{
Print("Too Bright");
if(PrevColour != NO_COLOUR)
{
PrevColour = NO_COLOUR;
}
//DisplayString(LINE2,"Too Bright",DUMMY_DATA,MESSAGE_WRITE);
}
PrintNumber3(10000/Red);
Print(",");
PrintNumber3(10000/Green);
Print(",");
PrintNumber3(10000/Blue);
Print(",");
PrintNumber3(10000/Brightness);
Print("rn");
TotalBags = RedBags + GreenBags + BlueBags;
UpdateDisplay();
//Delay(120000);
//GIE = 1;
//Delay(120000);
}
unsigned short Pulses = 0;
void ReadColour(void)
{
Colour = 0;
while(1)
{
switch(Colour)
{
case 0:
PORT20 = 0; //Red
PORT21 = 0;
Pulses = 0;
while(Pulses < 50);
EA = 0;
Red = GapDuration;
EA = 1;
Colour++;
break;
case 1:
PORT20 = 0;
PORT21 = 1;
Pulses = 0;
while(Pulses < 50);
EA = 0;
Blue = GapDuration;
EA = 1;
Colour++;
break;
case 2:
PORT20 = 1;//No colour
PORT21 = 0;
Pulses = 0;
while(Pulses < 50);
EA = 0;
Brightness = GapDuration;
EA = 1;
Colour++;
break;
case 3:
PORT20 = 1;//Green
PORT21 = 1;
Pulses = 0;
while(Pulses < 50);
EA = 0;
Green = GapDuration;
EA = 1;
EA = 0;
SendPacket();
EA = 1;
Colour = 0;
return;
break;
}
}
}
void interrupt0_ISR (void) interrupt 0
{
TR0 = 0;
GapDuration = (TH0 << 8) | TL0;
TH0 = 0x00;
TL0 = 0x00;
TR0 = 1;
Pulses++;
//Print("Duration = ");
//PrintNumber(GapDuration);
//Print("nr ");
}
sbit SERV_MOTOR1 = 0xA2;
sbit SERV_MOTOR2 = 0xA3;
unsigned char ex1_isr_counter=0;
void ex1_isr(void) interrupt 2
{
unsigned short i;
EA=0;
DC_MOTOR = 0;
SERV_MOTOR1 = 1;
SERV_MOTOR2 = 0;
Delay(11000);
//Delay(42000);
SERV_MOTOR1 = 0;
SERV_MOTOR2 = 0;
Delay(40000);
SERV_MOTOR1 = 0;
SERV_MOTOR2 = 1;
Delay(11000);
//Delay(42000);
SERV_MOTOR1 = 0 ;
SERV_MOTOR2 = 0;
//ex1_isr_counter++;
//DisplayString(LINE1, "Count = ", Binary2Decimal(ex1_isr_counter),DATA_WRITE);
Delay(10000);
DC_MOTOR = 1;
EA=1;
}
void timer0_ISR (void) interrupt 1
{
TH0 = 0x00;
TL0 = 0x00;
Print("Overflow");
TF0 = 0;
}
void InitSystemRegisters(void)
{
TMOD = 0x29;
ET0 = 1;
IT0 = 1;
EX0 = 1;
EX1 = 1;
TR0 = 1;
SCON = 0x50;
//
// Timer 1 loaded for baud rate of 9.6k
//
//
// Load timer counter register with 0xFD for auto reload
//
TH1 = 0xFD;
TL1 = 0xFD;
TR1 = 1;
//ES = 1;
//EA = 1;
EA = 1;
DC_MOTOR = 1;
}
{/code}