Library for the ADJD-S371, Avago Colour Sensor

ADJDColourSensor.cpp

Committer:
MichaelW
Date:
2010-10-01
Revision:
0:47465be3223d

File content as of revision 0:47465be3223d:

/**
* @section LICENSE
*Copyright (c) 2010 ARM Ltd.
*
*Permission is hereby granted, free of charge, to any person obtaining a copy
*of this software and associated documentation files (the "Software"), to deal
*in the Software without restriction, including without limitation the rights
*to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
*copies of the Software, and to permit persons to whom the Software is
*furnished to do so, subject to the following conditions:
* 
*The above copyright notice and this permission notice shall be included in
*all copies or substantial portions of the Software.
* 
*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
*AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
*LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
*OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
*THE SOFTWARE.
* 
*
* @section DESCRIPTION
*
*
*/

#include "ADJDColourSensor.h"

ADJDColourSensor::ADJDColourSensor(PinName sda, PinName scl, PinName LED):
        _sensor(sda, scl),
        _LED(LED)
{
    _address = 0x74 << 1;
    char cmd[2];
    cmd[0] = 1;     //Config reg
    cmd[1] = 0x01;     //setup
    _sensor.write(_address, cmd, 2);
    
    setCapacitors(0x0E,0x0E,0x0E,0x0E);
    //Good for 500 under office light
    setIntegrationTimeSlot(900,1000,1800,600);
    //1000, 1000, 1700, 600

    
    setIntegrationTimeSlot(1300,1400,2200,1000);
    
}

void ADJDColourSensor::setCapacitors(int redCap, int greenCap, int blueCap, int clearCap){
    //Values from 00H to 0FH
    char cmd[2];
    //Red
    cmd[0] = 0x06;     //Cap Red
    cmd[1] = redCap;     //
    _sensor.write(_address, cmd, 2);
    
    //Green
    cmd[0] = 0x07;     //Cap Green
    cmd[1] = greenCap;     //
    _sensor.write(_address, cmd, 2);
    
    //Blue
    cmd[0] = 0x08;     //Cap Blue
    cmd[1] = blueCap;     //
    _sensor.write(_address, cmd, 2);
    
    //Clear
    cmd[0] = 0x09;     //Cap clear
    cmd[1] = clearCap;     //
    _sensor.write(_address, cmd, 2);
}   
void ADJDColourSensor::setIntegrationTimeSlot(int redInt, int greenInt, int blueInt, int clearInt){
    //values should be 0 to 4095
    char cmd[2];
    //Red
    cmd[0] = 0x0A;     //int red low
    cmd[1] = redInt & 0xFF;     //redInt low
    _sensor.write(_address, cmd, 2);
    
    cmd[0] = 0x0B;     //int red high
    cmd[1] = (redInt >> 8) & 0x0F;     //redInt high
    _sensor.write(_address, cmd, 2);
    
    //Green
    cmd[0] = 0x0C;     //int green low
    cmd[1] = greenInt & 0xFF;     //greenInt low
    _sensor.write(_address, cmd, 2);
    
    cmd[0] = 0x0D;     //int green high
    cmd[1] = (greenInt >> 8) & 0x0F;     //greenInt high
    _sensor.write(_address, cmd, 2);
    
    //Blue
    cmd[0] = 0x0E;     //int blue low
    cmd[1] = blueInt & 0xFF;     //blueInt low
    _sensor.write(_address, cmd, 2);
    
    cmd[0] = 0x0F;     //int blue high
    cmd[1] = (blueInt >> 8) & 0x0F;     //blueInt high
    _sensor.write(_address, cmd, 2);
    
    //Clear
    cmd[0] = 0x10;     //int clear low
    cmd[1] = clearInt & 0xFF;     //clearInt low
    _sensor.write(_address, cmd, 2);
    
    cmd[0] = 0x11;     //int clear high
    cmd[1] = (clearInt >> 8) & 0x0F;     //clearInt high
    _sensor.write(_address, cmd, 2);
}
float ADJDColourSensor::read(){

    _LED = 1;
    
    char cmd[2];
    char cmd2[2];
    char Result[2];
    cmd[0] = 0x00;     //CTRL reg
    cmd[1] = 0x01;     //Get sensor
    _sensor.write(_address, cmd, 2);
    wait(0.1);
   
    do{
        wait(0.1);
        cmd[0] = 0;
        _sensor.write(_address, cmd, 1);
        _sensor.read(_address, cmd2, 1);
        //printf("sensing %i\n", int(cmd2[0]));    
    }while(cmd2[0] != 0);                       //Wait for CTRl register to be clear
   
    
    //red
    cmd[0] = 0x40;
    _sensor.write(_address, cmd, 1);
    _sensor.read(_address, Result, 1);
    cmd[0] = 0x41;
    _sensor.write(_address, cmd, 1);
    _sensor.read(_address, cmd2, 1);
    _red = Result[0] | ((cmd2[0] & 0x03) << 8);
    
    
    //Green
     cmd[0] = 0x42;
    _sensor.write(_address, cmd, 1);
    _sensor.read(_address, Result, 1);
    cmd[0] = 0x43;
    _sensor.write(_address, cmd, 1);
    _sensor.read(_address, cmd2, 1);
    _green = Result[0] | ((cmd2[0] & 0x03) << 8);
    
     //Blue
     cmd[0] = 0x44;
    _sensor.write(_address, cmd, 1);
    _sensor.read(_address, Result, 1);
    cmd[0] = 0x45;
    _sensor.write(_address, cmd, 1);
    _sensor.read(_address, cmd2, 1);
    _blue = Result[0] | ((cmd2[0] & 0x03) << 8);
    _LED = 0;

     //Clear
     float clear;
     cmd[0] = 0x46;
    _sensor.write(_address, cmd, 1);
    _sensor.read(_address, Result, 1);
    cmd[0] = 0x47;
    _sensor.write(_address, cmd, 1);
    _sensor.read(_address, cmd2, 1);
    _clear = Result[0] | ((cmd2[0] & 0x03) << 8);


    //Convert the private int values into the output float values
    red = (float)_red;
    green = (float)_green;
    blue = (float)_blue;
    clear = (float)_clear;

    return(clear);
}

int ADJDColourSensor::readOffset(){
    _LED = 1;
    char cmd[2];
    cmd[0] = 0;     //CTRL reg
    cmd[1] = 2;     //Get sensor
    _sensor.write(_address, cmd, 2);

    wait(0.1); //Or wait till bit cleared
    
    //Red
    cmd[0] = 0x48;
    _sensor.write(_address, cmd, 1);
    _sensor.read(_address, cmd, 1);
    redOffset = cmd[0];
    
    //Green
    cmd[0] = 0x49;
    _sensor.write(_address, cmd, 1);
    _sensor.read(_address, cmd, 1);
    greenOffset = cmd[0];
    
    //Blue
    cmd[0] = 0x4A;
    _sensor.write(_address, cmd, 1);
    _sensor.read(_address, cmd, 1);
    blueOffset = cmd[0];
    
    //Clear
    cmd[0] = 0x4B;
    _sensor.write(_address, cmd, 1);
    _sensor.read(_address, cmd, 1);
    clearOffset = cmd[0];
    
    _LED = 0;
    
    return(clearOffset);
     
}
void ADJDColourSensor::optimise(){
    optimise(500,500,500,500);
}
void ADJDColourSensor::optimise(int optimum){
    optimise(optimum,optimum,optimum,optimum);
}
void ADJDColourSensor::optimise(int redTarget, int blueTarget, int greenTarget ,int clearTarget){
    //use capacitor as they are to begin with
    
    //Optimise all at once as reading 
    int redInt = 1000;
    int greenInt = 1000;
    int blueInt = 1000;
    int clearInt = 1000;
    int range = 20;
    bool Optimised = false;
    read();
    while(!Optimised){
        
    
        //Optimise red
        if(_red > (redTarget + range)){
            //too big so decreae redInt
            redInt = redInt - 50;
        }else{
            if(_red < (redTarget - range)){
            //too low so increase redInt
                redInt = redInt + 50;
            }
        }
        //optimise blue
        if(_blue > (blueTarget + range)){
            blueInt = blueInt - 50;
        }else{
            if(_blue < (blueTarget - range)){
                blueInt = blueInt + 50;
            }
        }
        
        //optimise green
        if(_green > (greenTarget + range)){
            greenInt = greenInt - 50;
        }else{
            if(_green < (greenTarget - range)){
                greenInt = greenInt + 50;
            }
        }
    
        //Optimise Clear
        if(_clear > (clearTarget + range)){
            clearInt = clearInt - 50;
        }else{
            if(_clear < (clearTarget - range)){
                clearInt = clearInt + 50;
            }
        }
        
        //Check if any of the integration values  have exceeded the max limits (0 to 4095) and if so try changing the capacitors 
        if((redInt > 4095 || greenInt > 4095 || blueInt > 4095 || clearInt > 4095) || (redInt <= 0 || greenInt <= 0 || blueInt <= 0 || clearInt <= 0)){
            printf("Also need to change the capacitor values\n");
        }
        //Send the new optimisation
        setIntegrationTimeSlot(redInt, greenInt, blueInt, clearInt);
        
        //get new values
        _clear = read();
        
        //Check if optimised
        if((_red < (redTarget + range) && (_red > redTarget - range)) && (_green < (greenTarget + range) && (_green > greenTarget - range)) && (_blue < (blueTarget + range) && (_blue > blueTarget - range)) && (_clear < (clearTarget + range) && (_clear > clearTarget - range)))Optimised = true;
        
    }
    
    
    //Should check max condition (Outputs do not exceed 1000) - or is the above optimising for max condition

}