A library for the Avago ADJD-S311-CR999 Color Light Sensor
Dependents: ADJD-S311_HelloWorld
Revision 0:d5bb69f92ea3, committed 2014-03-24
- Comitter:
- CheeseW
- Date:
- Mon Mar 24 04:46:51 2014 +0000
- Child:
- 1:fc17a6ccc6f0
- Commit message:
- Come out for publication
Changed in this revision
ADJDs311.cpp | Show annotated file Show diff for this revision Revisions of this file |
ADJDs311.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ADJDs311.cpp Mon Mar 24 04:46:51 2014 +0000 @@ -0,0 +1,320 @@ +#include "ADJDs311.h" +#include "mbed.h" +#include <algorithm> + +ADJDs311::ADJDs311(PinName sda, PinName scl, PinName led): + _i2c(sda, scl), _led(led) { + // hard coded value for number of capacitors + colorCap.red = 12; + colorCap.green = 9; + colorCap.blue = 2; + colorCap.clear = 9; + + // hard coded value for number of integration time slot + colorInt.red = 16; + colorInt.green = 16; + colorInt.blue = 16; + colorInt.clear = 16; + + colorOffset.red = readRegister(OFFSET_RED); + colorOffset.green = readRegister(OFFSET_GREEN); + colorOffset.blue = readRegister(OFFSET_BLUE); + colorOffset.clear = readRegister(OFFSET_CLEAR); + + // write number of capacitors to registers + writeRegister(colorCap.red & 0xF, CAP_RED); + writeRegister(colorCap.green & 0xF, CAP_GREEN); + writeRegister(colorCap.blue & 0xF, CAP_BLUE); + writeRegister(colorCap.clear & 0xF, CAP_CLEAR); + + // write number of integration time slot to registers + writeInt(colorInt.red & 0xFFF, INT_RED_LO); + writeInt(colorInt.green & 0xFFF, INT_GREEN_LO); + writeInt(colorInt.blue & 0xFFF, INT_BLUE_LO); + writeInt(colorInt.clear & 0xFFF, INT_CLEAR_LO); +} + +// Read data regeisters and return a RGBC var +RGBC ADJDs311::read(){ + RGBC color = RGBC(); + + performMeasurement(); + + color.red = readInt(DATA_RED_LO); + color.green = readInt(DATA_GREEN_LO); + color.blue = readInt(DATA_BLUE_LO); + color.clear = readInt(DATA_CLEAR_LO); + + return color; +} + +// get number of capacitor +RGBC ADJDs311::getColorCap() +{ + return colorCap; +} + +// get number of intetgration time slot +RGBC ADJDs311::getColorInt() +{ + return colorInt; +} + +// set number of capacitor +void ADJDs311::setColorCap(int red, int green, int blue, int clear) { + colorCap.red = red; + colorCap.green = green; + colorCap.blue = blue; + colorCap.clear = clear; + + // write number of capacitors to registers + writeRegister(colorCap.red & 0xF, CAP_RED); + writeRegister(colorCap.green & 0xF, CAP_GREEN); + writeRegister(colorCap.blue & 0xF, CAP_BLUE); + writeRegister(colorCap.clear & 0xF, CAP_CLEAR); +} + +// set number of integration time slot +void ADJDs311::setColorInt(int red, int green, int blue, int clear) { + colorInt.red = red; + colorInt.green = green; + colorInt.blue = blue; + colorInt.clear = clear; + + // write number of integration time slot to registers + writeInt(colorInt.red & 0xFFF, INT_RED_LO); + writeInt(colorInt.green & 0xFFF, INT_GREEN_LO); + writeInt(colorInt.blue & 0xFFF, INT_BLUE_LO); + writeInt(colorInt.clear & 0xFFF, INT_CLEAR_LO); +} + +// Perform measurement and save the result to registers +void ADJDs311::performMeasurement(){ + writeRegister(0x01, 0x00); // start sensing + while(readRegister(0x00) != 0) + ; // waiting for a result +} + +// Write a byte of data to a specific ADJD-S311 address +void ADJDs311::writeRegister(char data, char regAddr){ + char temp[2]; + temp[0] = regAddr; // register addresss + temp[1] = data; + + _i2c.write(WRITE_ADDRESS, temp, 2, false); +} + +// Read a byte of data from ADJD-S311 address +char ADJDs311::readRegister(char regAddr){ + char data; + + _i2c.write(WRITE_ADDRESS, ®Addr, 1, true); + _i2c.read(READ_ADDRESS, &data, 1, false); + return data; +} + +// Read two bytes of data from ADJD-S311 address and addres+1 +int ADJDs311::readInt(char loRegAddr) +{ + return (unsigned char)readRegister(loRegAddr) + (((unsigned char)readRegister(loRegAddr+1))<<8); +} + +// Write two bytes of data to ADJD-S311 address and addres+1 +void ADJDs311::writeInt(int data, char loRegAddr) +{ + char lobyte = data; + char hibyte = data >> 8; + + writeRegister(lobyte, loRegAddr); + writeRegister(hibyte, loRegAddr+1); +} + +/* calibrateClear() - This function calibrates the clear integration registers +of the ADJD-S311. +*/ +void ADJDs311::calibrateClearInt(){ + bool gainFound = false; + int upperBox=4096; + int lowerBox = 0; + int half; + + while (!gainFound){ + half = ((upperBox-lowerBox)/2)+lowerBox; + //no further halfing possbile + + if (half==lowerBox){ + gainFound=true; + }else{ + colorInt.clear = half; + writeInt(colorInt.clear & 0xFFF, INT_CLEAR_LO); + performMeasurement(); + int halfValue = readInt(DATA_CLEAR_LO); + + if (halfValue>800){ + upperBox=half; + }else if (halfValue<800){ + lowerBox=half; + }else{ + gainFound=true; + } + } + } +} + +/* calibrateColor() - This function clalibrates the RG and B +integration registers. +*/ +void ADJDs311::calibrateColorInt(){ + bool gainFound = false; + int upperBox=4096; + int lowerBox = 0; + int half; + int halfValue; + + while (!gainFound) + { + half = ((upperBox-lowerBox)/2)+lowerBox; + //no further halfing possbile + if (half==lowerBox) + { + gainFound=true; + } + else { + colorInt.red = half; + colorInt.green = half; + colorInt.blue = half; + + // write number of integration time slot to registers + writeInt(colorInt.red & 0xFFF, INT_RED_LO); + writeInt(colorInt.green & 0xFFF, INT_GREEN_LO); + writeInt(colorInt.blue & 0xFFF, INT_BLUE_LO); + + performMeasurement(); + halfValue = 0; + + halfValue=std::max(halfValue, readInt(DATA_RED_LO)); + halfValue=std::max(halfValue, readInt(DATA_GREEN_LO)); + halfValue=std::max(halfValue, readInt(DATA_BLUE_LO)); + + if (halfValue>800) { + upperBox=half; + } + else if (halfValue<800) { + lowerBox=half; + } + else { + gainFound=true; + } + } + } +} + + +/* calibrateCapacitors() - This function calibrates each of the RGB and C +capacitor registers. +*/ +void ADJDs311::calibrateCapacitors(){ + + bool calibrated = false; + + //need to store detect better calibration + int diff; + int oldDiff = 1024; + + while (!calibrated){ + // sensor gain setting (Avago app note 5330) + // CAPs are 4bit (higher value will result in lower output) + writeRegister(colorCap.red & 0xF, CAP_RED); + writeRegister(colorCap.green & 0xF, CAP_GREEN); + writeRegister(colorCap.blue & 0xF, CAP_BLUE); + + int maxRead = 0; + int minRead = 1024; + int red = 0; + int green = 0; + int blue = 0; + + for (int i=0; i<4 ;i ++) + { + performMeasurement(); + red += readInt(DATA_RED_LO); + green += readInt(DATA_GREEN_LO); + blue += readInt(DATA_BLUE_LO); + } + red /= 4; + green /= 4; + blue /= 4; + + maxRead = std::max(maxRead, red); + maxRead = std::max(maxRead, green); + maxRead = std::max(maxRead, blue); + + minRead = std::min(minRead, red); + minRead = std::min(minRead, green); + minRead = std::min(minRead, blue); + + diff = maxRead - minRead; + + if (oldDiff != diff) + { + if ((maxRead==red) && (colorCap.red<15)) + colorCap.red++; + else if ((maxRead == green) && (colorCap.green<15)) + colorCap.green++; + else if ((maxRead == blue) && (colorCap.blue<15)) + colorCap.blue++; + } + else + calibrated = true; + + oldDiff=diff; + + } + +} + +void ADJDs311::calibrate(){ + setColorCap(0, 0, 0, 8); + calibrateColorInt(); // This calibrates R, G, and B int registers + calibrateClearInt(); // This calibrates the C int registers + calibrateCapacitors(); // This calibrates the RGB, and C cap registers + calibrateColorInt(); +} + + +void ADJDs311::ledMode(bool ledOn) +{ + _led = ledOn; +} + +void ADJDs311::offsetMode(bool useOffset) +{ + if (useOffset) + { + writeRegister(0x01, CONFIG); + } else + { + writeRegister(0x00, CONFIG); + } +} + +RGBC ADJDs311::getOffset() +{ + return colorOffset; +} + +RGBC ADJDs311::setOffset(bool useOffset) +{ + _led = 0; + + writeRegister(0x02, CTRL); + while(readRegister(CTRL)); + colorOffset.red = readRegister(OFFSET_RED); + colorOffset.green = readRegister(OFFSET_GREEN); + colorOffset.blue = readRegister(OFFSET_BLUE); + colorOffset.clear = readRegister(OFFSET_CLEAR); + + offsetMode(useOffset); + + return colorOffset; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ADJDs311.h Mon Mar 24 04:46:51 2014 +0000 @@ -0,0 +1,218 @@ +#ifndef ADJDs311_h +#define ADJDs311_h + +/** + * Includes + */ +#include "mbed.h" + +// ADJD-S311's I2C address, don't change +#define WRITE_ADDRESS 0xE8 // Address for write +#define READ_ADDRESS 0xE9 // Address for read + + +//#define RED 0 +//#define GREEN 1 +//#define BLUE 2 +//#define CLEAR 3 + +// ADJD-S311's register list +#define CTRL 0x00 +#define CONFIG 0x01 +#define CAP_RED 0x06 +#define CAP_GREEN 0x07 +#define CAP_BLUE 0x08 +#define CAP_CLEAR 0x09 +#define INT_RED_LO 0xA +#define INT_RED_HI 0xB +#define INT_GREEN_LO 0xC +#define INT_GREEN_HI 0xD +#define INT_BLUE_LO 0xE +#define INT_BLUE_HI 0xF +#define INT_CLEAR_LO 0x10 +#define INT_CLEAR_HI 0x11 +#define DATA_RED_LO 0x40 +#define DATA_RED_HI 0x41 +#define DATA_GREEN_LO 0x42 +#define DATA_GREEN_HI 0x43 +#define DATA_BLUE_LO 0x44 +#define DATA_BLUE_HI 0x45 +#define DATA_CLEAR_LO 0x46 +#define DATA_CLEAR_HI 0x47 +#define OFFSET_RED 0x48 +#define OFFSET_GREEN 0x49 +#define OFFSET_BLUE 0x4A +#define OFFSET_CLEAR 0x4B + +struct RGBC{ + int red; + int blue; + int green; + int clear; +}; + + +class ADJDs311{ + public: + +/** + * Create a color sensor interface + * + * @param sda pin connected to sda of color sensor + * @param scl pin connected to scl of color sensor + * @param led pin connected to on board led of the sensor + */ + ADJDs311(PinName sda, PinName scl, PinName led); + + +/** + * Calibrate the capacitance and integration time slot so that the current + * readings are as close to 1000 as possible and the difference between RGB + * readings are as small as possible + */ + void calibrate(); + +/** + * Turn the on board LED on/off. + * + * @param ledOn Whether to turn the LED on. + */ + void ledMode(bool ledOn); + +/** + * Get the current offset stored in offset registers + * + * @return Current offset stored in offset registers + */ + RGBC getOffset(); + +/** + * Use the current light condition to set the offset + * + * @param useOffset Wether to use the offset + * @return The offset set + */ + RGBC setOffset(bool useOffset = true); + + +/** + * Use the offset registers to automatically subtract offset from the readings + * + * @param useOffset Wether to use the offset + */ + void offsetMode(bool useOffset); + +/** + * Read in the color value from the sensor + * + * @return Structure containing the value of red, green, blue and clear + */ + RGBC read(); + +/** + * Get the gain of number of capacitor for each channel, in the range of 0 to + * 15. Less capacitor will give higher sensitivity. + * + * @return Structure containing the gain of number of capacitor for each + * channel. + */ + RGBC getColorCap(); + +/** + * Get the gain of number of integration time slot, in the range of 0 to 4095. + * More integration time slot will give higher sensitivity. + * + * @return Structure containing the gain of number of integration time + * slot for each channel. + */ + RGBC getColorInt(); + +/** + * Set the gain of number of capacitor for each channel, in the range of 0 to + * 15. Less capacitor will give higher sensitivity. + * + * @param red gain value for red + * @param green gain value for green + * @param blue gain value for blue + * @param clear gain value for clear + */ + void setColorCap(int red, int green, int blue, int clear); + +/** + * Set the gain of number of integration time slot, in the range of 0 to 4095. + * More integration time slot will give higher sensitivity. + * + * @param red gain value for red + * @param green gain value for green + * @param blue gain value for blue + * @param clear gain value for clear + */ + void setColorInt(int red, int green, int blue, int clear); + +private: + + // fields + I2C _i2c; + DigitalOut _led; + + RGBC colorCap; + RGBC colorInt; + RGBC colorOffset; + +// private memeber functions + +/** Write a byte of data to ADJD-S311 register + * + * @param data byte data to write to the register + * @param regAddr address of the register to write + */ + void writeRegister(char data, char regAddr); + +/** Read a byte of data from ADJD-S311 register + * + * @param regAddr address of the register to write + * @retrun byte data read from the register + */ + char readRegister(char regAddr); + +/** Read 2 bytes of data from ADJD-S311 registers and return as an integer + * + * @param loRegAddr low register address + * @return value from registers as an int + */ + int readInt(char loRegAddr); + +/** Write an integer data of 2 bytes to ADJD-S311 registers + * + * @param loRegAddr low register address + * @param data integer value to write + */ + void writeInt(int data, char loRegAddr); + +/** + * Tell the color sensor to perform measurement and store data to the color and + * clear registers. Must be called before reading + * color values + */ + void performMeasurement(); + +/** + * Calibrate the clear integration time slot so that current reading of the + * clear channel will be as close to 1000 as possible + */ + void calibrateClearInt(); + +/** + * Calibrate the color integration time slots so that the max current reading + * of the RGB channels will be as close to 1000 as possible + */ + void calibrateColorInt(); + +/** + * Calibrate the color capacitors so the difference of reading of different + * channels are as small as possible + */ + void calibrateCapacitors(); +}; + +#endif \ No newline at end of file