C.S.B Color Sensor Test Robot Above: Updated 9/12/16 Key Search Words: ROBOT, ROBOTICS, ROBOTIC VISION, ARTIFICIAL INTELLIGENCE, AI

The color sensor for this project was developed with some spare parts I had lying around, using three cadmium sulfide photocells, three gel filters, and a white LED with a color temperature of around 4000k. You can read about the sensor itself here. This was then mounted on the robot on the underside front to sense oncoming color panels in the arena. When a panel was encountered, the appropriate action was taken, and with that information conveyed to action - the robot moves on to the next encounter.

In practice, the arena is a pretty sterile enviornments as far as lack of interfering colors. In the real world, the robot would have to not only take into account the thousands of color possibilities, but also the surface reflections from a shiny surface - which look like the light source more than anything else and can confuse it. And really, what exactly is white? I set the white detection for when all three photocells are within a certain percentage of the same value. Then its pretty neutral in color. Black is when all three are below a specific value at the same time.

 The setup in the robot arena. The arena is all white, but a bit shiny because it is white painted semigloss panels. The colored squares are construction paper, and it was able to see the difference pretty clearly between colors because the paper is matte finish.

 Underneath the front of the robot is the sensor. You can see the central white LED, and three CdS photocells with filters. I used a Wratten 25 for the Red, Wratten 58 for the Green and a Wratten 47 for the blue. It is important to use a white LED that is not too blue - this one is in the "soft white" category and appears slightly yellowish.

The front view of the robot on the arena floor, with the sensor enclosed in a black housing to exclude ambient light, suspended about 1/8 inch off the floor.

Readings are taken automatically by the sensors processor every 300ms, and are conveyed to the main robot processor by three data lines for each color.

So for RGB data, where each color is sorted out by the sensor processor you get a digital series like this:

Red = 100

Green = 010

Blue = 001

white = 111 and so on.

 Finite State Machine for the programming of the robots processor for this test. (click to enlarge, its tiny here)

The robot jumps from state to state after a trigger is detected. After it gets to the blue state, it stops and beeps. Each state is represented in the program itself as a block of code using the "Switch" function. Each state is a case in the code block, and to jump from one state to the next we simply change the state number upon completion of each task. This is a very powerful method of programming! I have used this for our robots for many years now and is truly the best way to program artificial intelligence into your robot project.

Here is a You Tube movie link to show the robot in action. The program starts by driving forward to the red panel. It then turns right, then escapes the panel. Next it encounters the green panel. Turns left. Then escapes that panel. Finally when it finds the blue panel, its home then stops and plays a beep. :)

Movie1

Conclusion.

It will take a more sophisticated sensor to work in the real house hold environment. The detection of color is not so straightforward as you may think - for example light blue may read higher on the green sensor than dark green. Reds are far from blue and green so usually there are far fewer issues with that color. In future robots, I can envision a small camera like device that can simply be pointed at a color from several feet and give a reliable reading. This could be used to provide the robot with navigation information, or watering instructions for a plant. Think of how we use colors in everyday use, and you can easily come up with dozens of uses for this capability in a home robot!

CCS-C code for project:

//****************************************************************************
//Chris Schur
//(Color Bot 1 16F887)
//Date: 9/11/16
//****************************************************************************

/*Description of this Program:

This version 1 - This is a test of the TDR robot with new color sensor.
stops on all three colors and performs action.

*/

 

//I/O Designations ---------------------------------------------------
// RA0: (AN0)
// RA1: (AN1)
// RA2: (AN2)
// RA3: (AN3)
// RA4: (Open Collector output)
// RA5: (AN4)
// RA6: OSC OUT
// RA7: OSC IN

// RB0: (AN12,EXT INT) Status LED output
// RB1: (AN10) LCD output
// RB2: to piezzo spker
// RB3: (AN9)
// RB4: serial output to M1
// RB5: serial output to M2
// RB6:
// RB7:

// RC0: Left Whisker 1 input (Frontal)
// RC1: Right Whisker 1 input (Frontal)
// RC2: Left Whisker 2 input
// RC3: Right Whisker 2 input
// RC4: Left Whisker 3 input
// RC5: Right Whisker 3 input
// RC6:
// RC7:

// RD0:
// RD1:
// RD2:
// RD3:
// RD4: RED input
// RD5: GREEN input
// RD6: BLUE input
// RD7:

// RE0: (AN5)
// RE1: (AN6)
// RE2: (AN7)
// RE3: (MCLR INPUT - Pull High)

//--------------------------------------------------------------------

//Include Files:
#include <16F887.h> //Normally chip, math, etc. used is here.

//Directives and Defines:
#device ADC=8 //Set ADC when used to 8 bit = 0 - 255
#fuses NOPROTECT,HS,NOWDT //xtal is used
#use delay(crystal=10MHz) //xtal speed
#use fast_io(ALL) //must define tris below in main when using this

//for drive motors:
#use rs232(baud=9600, xmit=Pin_B5, bits=8, parity=N,STREAM=SERVO2)
#use rs232(baud=9600, xmit=Pin_B4, bits=8, parity=N,STREAM=SERVO1)

//for LCD:
#use rs232(baud=9600, xmit=Pin_B1, bits=8, parity=N,stream=SERIALNH)

#define LED Pin_B0
#define RED input(Pin_D4)
#define GREEN input(Pin_D5)
#define BLUE input(Pin_D6)

 

 

//NO_ANALOGS is default in device file...(All I/Os are digital)

//Interrupts:

 

//***Global Variables:********************************************************
//int8 result; //raw reading of a/d 8 bits.
int8 n;
int8 S2 = 0; //servo2 byte select number to be sent - L SIDE
int8 S1 = 0; //servo1 byte select number to be sent - R SIDE
int8 STATE; //FSM state number

 

 

//***Functions/Subroutines, Prototypes:***************************************
void CSEND(void);
void IDLE(void);
void STOP(void);
void HFWD(void);
void FFWD(void);
void HREV(void);
void FREV(void);
void RROT(void);
void LROT(void);
void RPAN(void);
void LPAN(void);
void RBANK(void);
void LBANK(void);
void R90(void);
void L90(void);
void R180(void);

//Clears LCD Display:
void LCDCLR() {
fputc(0xFE,SERIALNH); //Command Prefix
fputc(0x51,SERIALNH); //Clear screen
}

//Sets LCD to line 2 start point
void LCDLN2() {
fputc(0xFE,SERIALNH); //Command Prefix
fputc(0x45,SERIALNH); //set cursor command
fputc(0x40,SERIALNH); //Set cursor to next line, pos 40 = start line 2
}

//Beep 1: //Short single beep
void beep1(void) {
for(n=1; n<=50; n=n+1) {
output_high(Pin_B2);
delay_ms(1);
output_low(Pin_B2);
delay_ms(1);
}
return; }

//****************************************************************************
//***-- Main Program*********************************************************

void main(void) {

// Set TRIS I/O directions, define analog inputs, compartors:
set_tris_A(0b10111111);
set_tris_B(0b11001000);
set_tris_C(0b11111111);
set_tris_D(0b11111111);
set_tris_E(0b1111);

//Initialize variables and Outputs: --------------------------------------

setup_adc(ADC_CLOCK_DIV_32);
setup_adc_ports (sAN1);
set_adc_channel(1);

output_high(Pin_B5); //serial out
output_high(Pin_B4); //serial out


//Setup for timers, PWM, and other peripherals:

//----------------------------------------------------------------

//Main Program

IDLE(); //DONT MOVE ON POWER UP
delay_ms(500); //wait for motors to stop

STATE = 0; //POWER ON

while (true) {

switch (STATE) {

case 0: //WHITE STATE - Drive FWD, look for colors

HFWD();

if ((RED == 1) && (GREEN == 0) && (BLUE == 0)) {
STATE = 1;
break; }

if ((RED == 0) && (GREEN == 1) && (BLUE == 0)) {
STATE = 2;
break; }

if ((RED == 0) && (GREEN == 0) && (BLUE == 1)) {
STATE = 3;
break; }

//Otherwise, were white so drive forward

break;

case 1: //RED DETECT STATE

IDLE(); //STOP
delay_ms(1000);
R90();
IDLE();
STATE = 4;

break;

case 2: //GREEN DETECT STATE

IDLE(); //STOP
delay_ms(1000);
L90();
IDLE();
STATE = 4;

break;

case 3: //BLUE DETECT STATE

IDLE(); //STOP
delay_ms(1000);
beep1();
while (true);

break;

case 4: //DELAY STATE

HFWD();
delay_ms(1000);
STATE = 0;

break;

} //switch

} //while

} //main

//********* Functions which have prototypes at top of program ****************
//Drive Motor Control:
void IDLE(void) {
S2=6;
S1=6;
CSEND();
}

void STOP(void) {
S2=1;
S1=1;
CSEND();
}

void HFWD(void) {
S2=2;
S1=4;
CSEND();
}

void FFWD(void) {
S2=3;
S1=5;
CSEND();
}

void HREV(void) {
S2=4;
S1=2;
CSEND();
}

void FREV(void) {
S2=5;
S1=3;
CSEND();
}

void RROT(void) {
S2=2;
S1=2;
CSEND();
}

void LROT(void) {
S2=4;
S1=4;
CSEND();
}

void RPAN(void) { //RIGHT WHEEL STILL
S2=2;
S1=1;
CSEND();
}

void LPAN(void) { //LEFT WHEEL STILL
S2=1;
S1=4;
CSEND();
}

void RBANK(void) { //RIGHT WHEEL SLOWER
S2=3;
S1=4;
CSEND();
}

void LBANK(void) { //LEFT WHEEL SLOWER
S2=2;
S1=5;
CSEND();
}

void R90(void) {
S2=2;
S1=2;
CSEND();
delay_ms(1400);
IDLE();
delay_ms(1000);

}

void L90(void) {
S2=4;
S1=4;
CSEND();
delay_ms(1500);
STOP();
delay_ms(1000);

}

void R180(void) {
S2=2;
S1=2;
CSEND();
delay_ms(2800);
STOP();
delay_ms(1000);
}

void CSEND(void) { //This sends data out serially to the motor chip.
fputc(S1,SERVO1);
fputc(S2,SERVO2);
delay_ms(10);
fputc(S1,SERVO1);
fputc(S2,SERVO2);
}

Previous Uploads on this robot:

NONE.

  HOME