Ambient light color sensing

From Mech
Jump to navigationJump to search

Original Assignment

The goal of this project is to build a sensor that can detect the color of light produced by an LCD projector (such as the one in the lab). The sensor will consist of three tightly bundled phototransistors (e.g., the OP506B from digikey), each with its own color filter (see, for example, this description of color filters). Three analog inputs will read the sensed values and the program will print the RGB (or similar) values to an LCD screen (see, e.g., C_Example:_Serial_LCD or C_Example:_Parallel_Interfacing_with_LCDs). The demonstration will show these values changing as you move from one part of the projected image (a simple test pattern consisting of single-color blocks) to another.

Overview

Phototrans.jpg

A phototransistor will alter its emitter current according to the amount of light shone upon its base input. Thus, the current will be at its maximum when the transistor receives the most light, and at a minimum when it receives no light. To translate this current into a voltage measureable by the PIC, the voltage can be probed across a resistor placed in series following the emitter portion of the phototransistor. This means that maximum voltage (at maximum light exposure) should be approximately equal to the input voltage at the collector, minus the voltage drop across the transistor, and the minimum voltage should be approximately zero.

To split the source light into separate colors, color filters must be used to block out other wavelengths of light. A red color filter will only allow red light to pass through (650 nm), a cyan filter will only allow cyan light to pass through, and a green filter will only allow green light to pass through (510 nm). These three filters will split light into Red-Green-Blue (RGB) components, a common quantification of the visible spectrum in PCs. Note that phototransistors may be sensitive to differing wavelengths of light, usually visible light or IR phototransistors- make sure you choose the correct one for your purposes.

Once you have three different phototransistor voltages that are dependent on 3 RGB values, each one can be connected to the PIC via an analog input. While the voltage read may be between 0 and 5, it can be adjusted linearly to a scale from 0 to 255, the range for an RGB value. Each transistor will have a value from 0 to 255, which can then be reconstructed back into a single color on the computer, or can be printed out to an LCD screen.

The LCD screen is a two-line parallel port screen, model MCC162A4-5. The information for displaying content on the lcd screen can be found here: C_Example:_Parallel_Interfacing_with_LCDs.

Phototransistors can be purchased through digikey. Color filters may be ordered here.

Circuit

Photo circuit.jpg

Note that if the positions of the phototransistors are swapped with that of the resistors, the input signs will be reversed.

Code


#include <18f4520.h>

#DEVICE ADC=8;

#fuses HS,NOLVP,NOWDT,NOPROTECT
#use delay(clock=20000000)
#include "flex_lcd.c"

//#use rs232(baud=19200, xmit=PIN_A0, rcv=PIN_A1)    // you can use any pins for software uart...
#use rs232(baud=19200, UART1)       // hardware uart much better; uses  RC6/TX and RC7/RX 
// characters tranmitted faster than the pic eats them will cause UART to hang.

int8 R;
int8 G;
int8 B;
int8 redchan;
int8 bluechan;
int8 greenchan;

void main(){

 setup_adc_ports(AN0_TO_AN3);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11
 setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0
 
lcd_init();  // Always call this first.

lcd_putc("\f(R,G,B)\n");
 
    while (TRUE) {
   
      set_adc_channel(1);     // there's only one ADC so select which input to connect to it; here pin AN0
      delay_us(10);           // wait 10uS for ADC to settle to a newly selected input
      redchan = read_adc();     // now you can read ADC as frequently as you like
      set_adc_channel(2);     // there's only one ADC so select which input to connect to it; here pin AN0
      delay_us(10);           // wait 10uS for ADC to settle to a newly selected input
      greenchan = read_adc();     // now you can read ADC as frequently as you like
      set_adc_channel(3);     // there's only one ADC so select which input to connect to it; here pin AN0
      delay_us(10);           // wait 10uS for ADC to settle to a newly selected input
      bluechan = read_adc();     // now you can read ADC as frequently as you like
      
     R = 255 - redchan  ;
     G = 255 - greenchan;
     B = 255 - bluechan;
   
           
printf(lcd_putc,"(%u, %u, %u) \n", R,G,B);
            
       delay_ms(500);
   }
}