Nhận dạng màu sắc với cảm biến TCS3200 - Atmega32 Color Detector using TCS3200 based on Microcontroller - Atmega32
In this project,
Atmega32 microcontroller will be used to program an application – Color
Detector. The color sensor will collect the data of the color we want to
detect. The microcontroller will use the data to process, analyze the specific
information about the color, it will decide what the color is, and the color
name will be display on a 128x64 graphic screen (Graphic LCD - GLCD). If the
color which is detected, is black, 1 KHz will be created and send this signal
to a buzzer. One button will be program to turn the buzzer off.
In order to
obtain the goal of the project, the extension board of color sensor TCS3200
will be designed and used to collect the data about the color, converts it to
frequency. The microcontroller will count the frequency; determine what color
is, and display information on GLCD.
All code is written in AVRStudio with WinAVR compiler
I) Color Sensor - TCS3200
The TCS3200 is programmable color light-to-frequency converter that combine configurable silicon photodiodes and a current-to-frequency converter on a single monolithic CMOS integrated circuit. The output is a square wave (50% duty cycle) with frequency directly proportional to light intensity [2].
Full-scale output frequency can be scaled by
one of three presets in the table below:
Table 1:
S0
|
S1
|
Output Scaling (f0)
|
0
|
0
|
Power down
|
0
|
1
|
2%
|
1
|
0
|
20%
|
1
|
1
|
100%
|
The Output enable (OE) places the output in the high-impedance state for
multiple-unit sharing of a microcontroller input line. Pin VDD
connects with the power and GND connects with ground.
In the TCS3200, the light-to-frequency converters read an
8x8 array of photodiode. Sixteen photodiodes have blue filters, 16 photodiodes
have green filters, and 16 photodiodes have red filters. All photodiodes of the
same color are connected in parallel. Pin S2 and S3 are used to select which
group of photodiodes (red, blue, green, clear) is active. See the table 2 below
for more details.
Table 2:
S2
|
S3
|
Photodiode Type
|
0
|
0
|
Red
|
0
|
1
|
Blue
|
1
|
0
|
Clear (no
filter)
|
1
|
1
|
Green
|
Module Design:
The
TCS3200 sensor module is designed with SMD TCS3200 IC, four white LEDs, LED
control circuit and a few components. The white LEDs throw light on the object
that is placed in front of the sensor. The complete schematic shows in figure:
You can download complete schematic and layout at the of my post (Orcard)
Four
white LEDs in the module is active with logic 1. To active the output of
TCS3200, the pin !OE needs to be active with logic 0. In this project, 2%
scale-output frequency is chosen because the microcontroller has fast crystal
(8MHz), thus pin S0 is low and S1 is high (see the table 1)
Measurement technique:
The
half period measurement is used to obtain the frequency from output pin of
TCS3200. The frequency of each Green,
Blue and Red will be measured to obtain the RGB value.
Because
the output signal from TCS3200 is 50%-duty cycle square wave, so we only need
to measure the time of half period which means from the falling edge to the first
next rising edge.
For the best measurement result, the process of
measurement for each color (RGB) shows in the figure II.4. Firstly, we need to check
the signal state, if level of signal input frequency is low, we will wait for
the rising edge (1):
if(!(TCS_OUT_PORT & (1<<TCS_OUT_POS)))
{
while(!(TCS_OUT_PORT
& (1<<TCS_OUT_POS))); //Wait
for rising edge
}
Secondly, we will wait from the rising edge to the
next falling edge, until falling edge, timer1 will be initialized and begin the
counter1 to count the time of half pulse (2).
while(TCS_OUT_PORT & (1<<TCS_OUT_POS)); //Wait for falling edge
TCNT1=0x0000; //Reset
Counter
TCCR1B=(1<<CS10); //Prescaller
= F_CPU/1 (Start Counting)
//Stop Timer
TCCR1B=0x00;
return ((float)F_CPU/TCNT1);
Finally, ultil the next rising edge reaches (3), we
will obtain the value of couter1, from this result, we can calculate the time
of pulse or half period time by the equation:
Thus the rate of twice output frequency will be
gathered.
RGB Analyze:
RGB color space or RGB color system, constructs all the
colors from the combination of the Red, Green and Blue
colors.
The red, green and blue use 8 bits each, which have
integer values from 0 to 255. This makes 256*256*256=16777216 possible colors.
Each
pixel in the LCD monitor displays colors this way, by combination of red, green
and blue LEDs (light emitting diodes). When the red pixel is set to 0, the LED
is turned off. When the red pixel is set to 255, the LED is turned fully on.
Any value between them sets the LED to partial light emission.
In
this project, I will determine only seven colors: black, white, green, yellow,
red, blue and purple. The table below is some decimal codes RGB of 7 colors.
Color
|
HTML/CCS Name
|
Decimal Code R,G,B
|
Black
|
0,0,0
|
|
White
|
255,255,255
|
|
Green
|
0,128,0
|
|
Blue
|
0,0,255
|
|
Red
|
255,0,0
|
|
Yellow
|
255,255,0
|
|
Purple
|
128,0,128
|
The
color sensor TCS3200 converts the color into frequency. We will use TCS3200 module to collect the
frequency obtained with Green, Red and Blue filter of the object by enabling
corresponding filter actives. Three function to get RGB value in my program
unsigned
int Measure_R(); //measure
frequency with red filter
unsigned
int Measure_G(); //measure
frequency with green filter
unsigned
int Measure_B(); //measure
frequency with blue filter
unsigned
int Measure_C(); //measure
frequency without filter
Measure_C()
function is used to detect the object in range of measure or not, if the frequency
obtained is smaller than 2 KHz than “no object” message will be displayed on
the graphic LCD.
c = Measure_C();
if (c>2000){
… //main
process in here
}
else{
…
GLCD_Print78(0,10,"No
Object");
…
}
To
determine what color of object is, we need to scale the value of RGB. The
function to find the smallest value is applied: (_r, _g, _b is the RGB value
which have measured before)
if(_r<_b){
if(_r<_g)
wb=_r;
else
wb=_g;
}
else{
if(_b<_g)
wb=_b;
else
wb=_g;
}
wb=wb/10; //decrease the smallest value with factor of
10
r=_r/wb; //r, g, b are the value which have scaled
g=_g/wb;
b=_b/wb;
From
the RGB has scaled, the decimal code RGB table and real experiment, I have
assigned the range value for 7 color (smallest value of RGB is 10), see the
below summary (wb is smallest value of RGB frequency which has scaled down a
factor of 10)
Color
|
Condition match
|
White
|
Wb>200, r=10
|
Yellow
|
(r>b)&(g>b), b=10
|
Green
|
g>b ,g>r, r=10
|
Blue
|
b>g,b>=15, r=10
|
Red
|
r>b,b=10,g=10
|
Purple
|
b>g,r=10,g=11,wb<150
|
Black
|
Wb<80,r=10
|
The
buzzer in this project is used to indicate that the object’s color is black
(active with low logic level). It will turn off if an assigned button is press,
here is button connected with pin PC0
We
have the formula to compute the pulse of signal to generate the desire
frequency.
Thus, we will use
timer0 with TCNT0 = -100 counts to 0, than we use variable count increase 5
time every 0.1ms, we will obtain 1 KHz frequency and send it to buzzer.
…
TCNT0
= -100; //count value to get 0.1ms
…
TCCR0=0x02; //TIMER0 INTERNAL CLOCK, PRESCALER/8
…
ISR
(TIMER0_OVF_vect){ //timer0
interrupt every 0.1ms
TCNT0=-100;
count++;
if (count==5) //0.1x5 = 0.5ms
Buzzer ^=0x02; //create pulse 1kHz at PC1
}
II) Graphic LCD
In this project, the
Graphic LCD 128x64 driven by KS0108 will be used to display the name of color. The
specification of this LCD is as follows [2]:
·
128 horizontal pixel and 64 vertical pixel
resolution.
·
Controlled based on KS0108B
·
Parallel 8bit interface
·
On board graphic memory.
·
Available in Green backlight with dark
green pixels.
·
Also available in Blue backlight with
light blue pixels.
·
LED backlight.
·
20 PIN linear connection
Diagram for connection
Graphic LCD 128x64 interfaces with Atmega32 through
PORTB (control) and PORTD (data),below is short map of interfacing.
GLCD_DATA_O PORTD
// Ouput Data bus
GLCD_DATA_I PIND
// Input Data bus
GLCD_DATA_DDR DDRD
// Direction
GLCD_CTRL_O PORTB
// Output Control bus
GLCD_CTRL_I PINB // Input Control bus
GLCD_CTRL_DDR DDRB // Direction
GLCD_E PB1 // Enable line
GLCD_RW PB2
// read/write selecting line
GLCD_RS PB3
// Register select: Data/Instruction
(DI)
GLCD_CS1 PB5
// left/right selecting line#1
GLCD_CS2 PB4
// left/right selecting line#2
Simulate circuit:
Some
function is used in graphic LCD 128x64:
void
GLCD_Init(void) //Initialize
GLCD
void
GLCD_Clr(void) //clear
GLCD
void
GLCD_PutChar78(uint8_t Line, uint8_t Col, uint8_t chr) //print character 7x8
void
GLCD_Print78(uint8_t Line, uint8_t Col, char* str) //print string
void
GLCD_PutBMP(char *bmp) //put bitmap
image to GLCD
int
GLCD_PutNum(unsigned char x,unsigned char y, unsigned int num) //print number
For example code:
//Initialize the GLCD Library
GLCD_Init();
GLCD_Clr();
//Put
my bitmap to GLCD
GLCD_PutBMP(hiGLCD);
_delay_ms(2000);
GLCD_Clr();
...
color = 8;
Clear();
GLCD_Print78(0,0,"Oooppp!!!");
GLCD_Print78(2,10,"Unknown
color");
Please take a look in GLCD.c file to know the purpose of each function.
III) Result
The
application has programmed and run successfully. Seven colors is determined
with TCS3200 color sensor module: black, yellow, green, blue, white, red,
purple, display the name of color on graphic LCD 128x64 and send 1 KHz signal
to the buzzer when the object is black, turn off the buzzer if PC0 is pressed.
Because
the time is limited, so the application is determined and tested with only 7
colors by the particular specification of each color: white, black, yellow,
blue, green, purple, red, it’s not the common specification of all colors. With
other colors, if it is not assigned color in 7 color s above, the application
will not analyze and respond correct color of object; sometimes it will give
the name of nearby color for color of object, for example: dark red or light
red are named as red, light blue is unknown color…
Finally, this is just my small research, if it has something wrong. please let me know. I'm glad to see your advise. Thanks you!
Download file:
- Schematic and layout (orcad format). Click here (choose file->download or Ctr+S to save all file)
- All firmware files. Click here (choose file->download or Ctr+S to save all file)
- Schematic of the microcontroller kit. Please contact me, because it's reserved. Email me
Have fun,
Thanh Nguyen
I
First of all, thanks for your sharing.
ReplyDeleteFor the scaling the frequency part, i still have little confusion. Could you mind please explain in details? What's the MAX RGB values you could detected? I've different MAX and MIN values for red, green and blue if it detectes black or white color. For example, MAX for red is 200,000hz, green is 60,000hz and blue is 120,000. This makes me very hard to do the scaling to the range between 0-1.
Hi Violet,
ReplyDeletewhat do you mean MAX RGB value it can detect? As you can see in the main code of firmware, i have some line of code to scale the frequency
[code]
if(_r<_b)
{
if(_r<_g){
wb=_r;
}
else
wb=_g;
}
else
{
if(_b<_g)
wb=_b;
else
wb=_g;
}
[\code]
Above code is use to find out what is the smallest value, R or G or B.
than I save it to wb.
[code]
wb=wb/10;
r=_r/wb;
g=_g/wb;
b=_b/wb;
[\code]
I use this code to scale frequency which I obtained from TCS3200 to scale of 10.
For illustration. _r is smallest vaule -> wb=_r, wb=wb/10, r= _r/wb -> r = r/(r/10) = 10. It's mean that when any value in 3 values is smallest, it mus be equal 10.
If it detects black or white, it doesnt need to compare max or min value of RGB, because white is 255,255,255 -> value of R G B is equal after scale, and the frequency of all there r g b values is largest -> white color, and black is revesed with white, you can see in my code, after compare with a range of r g b, i eliminate the range of black color. I need to hornet that my code is not perfect and it just detects main color only. you can create another better algorithm to solve this problem ^^
Have fun!