Avago colour sensor

jmumby

Senior Member
Spark fun have an RGB colour sensor http://www.sparkfun.com/commerce/product_info.php?products_id=8618. This has proven complicated to implement as the datasheet for this sensor is pretty shocking for a novice. The code below appears to work.

The theory is you calibrate the sensor to a surface or situation where the sensor will meet it's maximum reading so for paper I guess this is a white sheet of paper. This is done by setting 'cap values' and 'integration' times. Cap values is the amount of capacitors you will use to sense colour. The lower the value the higher the initial value. The Value must not exceed 1000. I still haven't found out what integration time is.

---+setting up+---
Code:
WAIT 1
SYMBOL SENSOR_PWR = 2
SYMBOL LED = 1

SYMBOL ADJD = 0x74
 
SYMBOL CAP_RED = 0x06
SYMBOL CAP_GREEN = 0x07
SYMBOL CAP_BLUE = 0x08
SYMBOL CAP_CLEAR = 0x09
 
SYMBOL INT_RED_LO = 0x0A
SYMBOL INT_RED_HI = 0x0B
SYMBOL INT_GREEN_LO = 0x0C
SYMBOL INT_GREEN_HI = 0x0D
SYMBOL INT_BLUE_LO = 0x0E
SYMBOL INT_BLUE_HI = 0x0F
SYMBOL INT_CLEAR_LO = 0x10
SYMBOL INT_CLEAR_HI = 0x11
 
SYMBOL DATA_RED_LO = 0x40
SYMBOL DATA_RED_HI = 0x41
SYMBOL DATA_GREEN_LO = 0x42
SYMBOL DATA_GREEN_HI = 0x43
SYMBOL DATA_BLUE_LO = 0x44
SYMBOL DATA_BLUE_HI = 0x45
SYMBOL DATA_CLEAR_LO = 0x46
SYMBOL DATA_CLEAR_HI = 0x47
 
SYMBOL OFFSET_RED = 0x48
SYMBOL OFFSET_GREEN = 0x49
SYMBOL OFFSET_BLUE = 0x4A
SYMBOL OFFSET_CLEAR = 0x4B

i2cslave %11101001, i2cslow,i2cbyte
The integration values can be upto 4096 so take up two bytes. The cap values are from 0 to 15 so single byte

---+getting optimum value+---
Code:
B10=5
W13=1
START:
W13=W13+1
HIGH SENSOR_PWR

PAUSE 200

writei2c CAP_RED, (B10)
writei2c CAP_GREEN, (B10)
writei2c CAP_BLUE, (B10)
writei2c CAP_CLEAR, (B10)
 
writei2c INT_RED_LO,(B27)
writei2c INT_RED_HI,(B26)
writei2c INT_GREEN_LO,(B27)
writei2c INT_GREEN_HI,(B26)
writei2c INT_BLUE_LO,(B27)
writei2c INT_BLUE_HI,(B26)
writei2c INT_CLEAR_LO,(B27)
writei2c INT_CLEAR_HI,(B26)


HIGH LED

writei2c 0,(0x01) 'write 0x00 to to ctrl
PAUSE 200
readi2c 0,(b8)



readi2c DATA_RED_LO,(b0)
readi2c DATA_RED_HI,(b1)
readi2c DATA_GREEN_LO,(b2)
readi2c DATA_GREEN_HI,(b3)
readi2c DATA_BLUE_LO,(b4)
readi2c DATA_BLUE_HI,(b5)
readi2c DATA_CLEAR_LO,(b6)
readi2c DATA_CLEAR_HI,(b7)

serout 0,T2400,("INT: ",#W13,cr,lf)
serout 0,T2400,("CTRL: ",#B8,cr,lf)
serout 0,T2400,("RED : ",#W0,cr,lf)
serout 0,T2400,("GREEN: ",#W1,cr,lf)
serout 0,T2400,("BLUE: ",#W2,cr,lf)
serout 0,T2400,("B21: ",#B21,cr,lf)
serout 0,T2400,("CLEAR: ",#W3,cr,lf,cr,lf)

if W0 > 900 AND B22 != 1 THEN GOSUB SET_RED
IF W1 > 900 AND B23 != 1 THEN GOSUB SET_GREEN
IF W2 > 900 AND B24 != 1 THEN GOSUB SET_BLUE
IF W3 > 900 AND B25 != 1 THEN GOSUB SET_CLEAR

B21 = B22+B23+B24+B25 

IF B21 = 4 THEN GOSUB FINISH

GOTO START


SET_RED:
serout 0,T2400,("RED SET ",cr,lf)
B22 = 1
WRITE 0,W13
RETURN

SET_GREEN:
serout 0,T2400,("GREEN SET ",cr,lf)
B23 = 1
WRITE 2,W13
RETURN

SET_BLUE:
serout 0,T2400,("BLUE SET ",cr,lf)
B24 = 1
WRITE 4,W13
RETURN

SET_CLEAR:
serout 0,T2400,("CLEAR SET ",cr,lf)
B25 = 1
WRITE 6,W13
RETURN
Once again the aim of the calibration is to get a value of less than 1000 under normal conditions. B10 here is my cap value. Changing this value is to coarse an adjustment so I fix this to a value that gives me small enough changes when looping thru W13. W13 increases by one for each loop in the START: program. This is sent with the cap value to the sensor and the result is read back in. If the value read back in is greater than 900 a byte flag is set and the value is written to EEPROM for later.

The integration value is between 0 and 4095. I have found that a integration value of 256 gives the same sensor value as 0. This is also the case for 512. So I aim to get the optimum value before W13 reaches 256. If this is not the case I lower the CAP value, if the jumps in integration are too high I raise the CAP value.

---+setting up to read+---
Code:
LOW SENSOR_PWR
WAIT 1

HIGH SENSOR_PWR

PAUSE 200

READ 0,W5
READ 2,W6
READ 4,W7
READ 6,W8

serout 0,T2400,(CR,LF,#B10," ",#B11," ",#B12," ",#B13," ",#B14," ",#B15," ",#B16," ",#B17)

writei2c CAP_RED, (0x04)
writei2c CAP_GREEN, (0x04)
writei2c CAP_BLUE, (0x04)
writei2c CAP_CLEAR, (0x04)
 
writei2c INT_RED_LO,(B11)
writei2c INT_RED_HI,(B10)
writei2c INT_GREEN_LO,(B13)
writei2c INT_GREEN_HI,(B12)
writei2c INT_BLUE_LO,(B15)
writei2c INT_BLUE_HI,(B14)
writei2c INT_CLEAR_LO,(B17)
writei2c INT_CLEAR_HI,(B16)

HIGH LED

writei2c 0,(0x01) 'write 0x00 to to ctrl
PAUSE 200
readi2c 0,(b8)

readi2c DATA_RED_LO,(b0)
readi2c DATA_RED_HI,(b1)
readi2c DATA_GREEN_LO,(b2)
readi2c DATA_GREEN_HI,(b3)
readi2c DATA_BLUE_LO,(b4)
readi2c DATA_BLUE_HI,(b5)
readi2c DATA_CLEAR_LO,(b6)
readi2c DATA_CLEAR_HI,(b7)

serout 0,T2400,(cr,lf,"RED : ",#W0,cr,lf)
serout 0,T2400,("GREEN: ",#W1,cr,lf)
serout 0,T2400,("BLUE: ",#W2,cr,lf)
serout 0,T2400,("CLEAR: ",#W3,cr,lf,cr,lf)

low led

writei2c 0x00,(0x02)
readi2c 0x00,(b8)
writei2c 0x01,(0x01)
readi2c 0x00,(b8)

high led

writei2c 0,(0x01) 'write 0x00 to to ctrl
pause 200
readi2c 0x00,(b8)

readi2c DATA_RED_LO,(b8)
readi2c DATA_RED_HI,(b9)
readi2c DATA_GREEN_LO,(b10)
readi2c DATA_GREEN_HI,(b11)
readi2c DATA_BLUE_LO,(b12)
readi2c DATA_BLUE_HI,(b13)
readi2c DATA_CLEAR_LO,(b14)
readi2c DATA_CLEAR_HI,(b15)
This loads the values found in the first code into the sensor. The spec sheet says that the light source must be off when the values are loaded into the register hence the low led and high led. Later I used a more poweful light source which needed to be turned down with PWM.

---+reading the colour+---
Code:
main2:
if pin2 = 1 then gosub read_col:
goto main2:

read_col:

writei2c 0,(0x01) 'write 0x00 to to ctrl
pause 200
readi2c 0x00,(b8)

readi2c DATA_RED_LO,(b0)
readi2c DATA_RED_HI,(b1)
readi2c DATA_GREEN_LO,(b2)
readi2c DATA_GREEN_HI,(b3)
readi2c DATA_BLUE_LO,(b4)
readi2c DATA_BLUE_HI,(b5)
readi2c DATA_CLEAR_LO,(b6)
readi2c DATA_CLEAR_HI,(b7)

serout 0,T2400,(cr,lf,"RED : ,",#W0,",")
serout 0,T2400,(" GREEN: ,",#W1,",")
serout 0,T2400,(" BLUE: ,",#W2,",")
serout 0,T2400,(" CLEAR: ,",#W3,",")

return
This codes initiates a read when a push button is pushed, then writes it to pin 0.

This sensor seems to be able to tell differences between red green and blue. However wanted to measure differences in reflected colours like cyan, magenta and yellow. Cyan and Yellow gives me high values in blue,green and red,green respectivly but Magenta just gives me high values of red.

The results below are of a 12 step gradation from 100% magenta to 0%. The higher the value the higher amount of that colour is sensed. Or not refected depends how you interpret it.

Code:
RED : 	751	 GREEN: 	413	 BLUE: 	376	 CLEAR: 	517
RED : 	792	 GREEN: 	449	 BLUE: 	428	 CLEAR: 	558
RED : 	807	 GREEN: 	481	 BLUE: 	464	 CLEAR: 	588
RED : 	823	 GREEN: 	512	 BLUE: 	509	 CLEAR: 	612
RED : 	836	 GREEN: 	562	 BLUE: 	562	 CLEAR: 	652
RED : 	864	 GREEN: 	616	 BLUE: 	618	 CLEAR: 	700
RED : 	869	 GREEN: 	648	 BLUE: 	655	 CLEAR: 	721
RED : 	894	 GREEN: 	718	 BLUE: 	724	 CLEAR: 	781
RED : 	914	 GREEN: 	788	 BLUE: 	781	 CLEAR: 	842
RED : 	923	 GREEN: 	834	 BLUE: 	820	 CLEAR: 	873
RED : 	940	 GREEN: 	883	 BLUE: 	864	 CLEAR: 	912
RED : 	955	 GREEN: 	937	 BLUE: 	921	 CLEAR: 	952
 
Top