Quad RGB sensor with SPI output drive, I2C display interface & analogue inputs / UI for various LED types

Dependencies:   MCP23S17 PCF8574 TextLCD eeprom mbed-dev

main.cpp

Committer:
jolyon
Date:
2016-08-16
Revision:
3:b8218b61b0e2
Parent:
2:4a8eacbb3657
Child:
4:dce5fc58abe9

File content as of revision 3:b8218b61b0e2:

#include "mbed.h"
#include "TextLCD.h"
#include "MCP23S17.h"

#define FACTOR 1

#define SENSOR_ADDR (41 << 1)
#define SENSOR_WHITE_REG 148
#define SENSOR_RED_REG 150
#define SENSOR_GREEN_REG 152
#define SENSOR_BLUE_REG 154

#define WHITE_THRESHOLD 15

//--------------------------------------
//each LED type is defined here
#define NOTUSED    0
#define STD_RED    1
#define STD_GREEN  2
#define STD_BLUE   3
#define STD_YELLOW 4
#define GREEN_YELLOW 5
#define RGB        6


//--------------------------------------
//Current LED Colour Definitions
#define ERROR   0       //off or wrong
#define RED     1
#define GREEN   2
#define BLUE    3
#define YELLOW  4



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




//-------------------------------------------------------------------------------
//----------- LED's -------------------------------------------------------------
//-------------------------------------------------------------------------------
// Detection LED's use the onboard MBED LED's
// These are all blue on the MBED but on DSE PCB they areas follows
// LED1 = GREEN
// LED2 = BLUE
// LED3 = RED
// LED4 = YELLOW
DigitalOut GreenLed(LED1);
DigitalOut BlueLed(LED2);
DigitalOut RedLed(LED3);
DigitalOut YellowLed(LED4);

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

//-------------------------------------------------------------------------------
//----------- Analogue Inputs ---------------------------------------------------
//-------------------------------------------------------------------------------
//Analogue inputs are used to set thresholds for detector levels
//AnalogIn RedTrimmer(p15);
//AnalogIn GreenTrimmer(p16);
//AnalogIn BlueTrimmer(p17);
//AnalogIn HysTrimmer(p18);
//-------------------------------------------------------------------------------

//-------------------------------------------------------------------------------
//------------ Text display -----------------------------------------------------
//-------------------------------------------------------------------------------
//debug display. Standard display driver set up in 4 bit mode
//final version uses I2C port
TextLCD lcd(p14, p16, p17, p18, p19, p20, TextLCD::LCD16x2); // rs, e, d4-d7

//set up I2C Communication to LCD
//I2C i2c_lcd(p9,p10); // SDA, SCL

//I2C Portexpander PCF8574 for LCD
//TextLCD_I2C lcd(&i2c_lcd, 0x42, TextLCD::LCD16x2); // I2C bus, PCF8574 Slaveaddress, LCD Type ok

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

//-------------------------------------------------------------------------------
//------------ Create SPI bus -----------------------------------------------------
//-------------------------------------------------------------------------------
//set up the SPI port for use as output driver
SPI spi(p5, p6, p7);

char Opcode = 0x40;
 
// Next create a MCP23S17
// mbed p20 is connected to ~chipSelect on the MCP23S17
MCP23S17 chip = MCP23S17(spi, p20, Opcode);

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

//-------------------------------------------------------------------------------
//------------ colour sensor Comms Pins -----------------------------------------
//-------------------------------------------------------------------------------
//TMC Sensor: this is the raw I2C Port, the clock like is muxed
I2C i2c(p28, p27); //pins for I2C communication (SDA, SCL)


typedef struct{
    uint16_t White;
    uint16_t Red;
    uint16_t Green;
    uint16_t Blue;
}Colour;

Colour SensorData;

//-------------------------------------------------------------------------------
//The system looks up the type of LED that is being detected for Each sensor and will fill in the result table & update the associated Output list
//outputs start at 0 torough to 15

char Config[32]={   RGB,    0,  //sensor 0 , uses 3 outputs  - 0,1,2
                    NOTUSED,3,  //sensor 1
                    NOTUSED,4,  //sensor 2
                    NOTUSED,5,  //sensor 3
                    NOTUSED,6,  //sensor 4                    
                    NOTUSED,7,  //sensor 5
                    NOTUSED,8,  //sensor 6
                    NOTUSED,9,  //sensor 7
                    NOTUSED,10,  //sensor 8
                    NOTUSED,11,  //sensor 9
                    NOTUSED,12,  //sensor 10
                    NOTUSED,13,  //sensor 11
                    NOTUSED,14,  //sensor 12
                    NOTUSED,15,  //sensor 13
                    NOTUSED,15,  //sensor 14
                    NOTUSED,15,  //sensor 15
                };

char LEDState[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //current detected LED states

uint16_t OutputData = 0;    //word containing the current output states of the board
 
uint8_t SensorNumber = 0;   //current sensor number
char SensorResult = 0;      //detected colour


//------------TSC Stuff----------------
int sensor_addr = 41 << 1;

char TempReg[1] = {0};
char TempData[2] = {0,0};


//------------TSC Stuff----------------

uint16_t Red = 1;
uint16_t Green = 2;
uint16_t Blue = 3;
uint16_t White = 4;
uint16_t Yellow = 0;

uint32_t AvgRed = 0;
uint32_t AvgGreen = 0;
uint32_t AvgBlue = 0;
uint32_t AvgWhite = 0;
uint32_t Temp = 0;
uint32_t TempR = 0;
uint32_t TempG = 0;
uint32_t TempB = 0;


uint16_t RedProp = 0;
uint16_t GreenProp = 0;
uint16_t BlueProp = 0;

uint16_t myMix = 0;

float MyCCT;
float MyCCTi;
uint8_t DisplayIndex = 0;

uint8_t SensorConfig = 0x30;
// bit  description              setting
//  0   SD,   0 = enabled             0
//  1   AF,   0 = Automode            0
//  2   TRIG, 0 = no trigrer          0
//  3   N/F,  0                       0
//  4   IT0   0                       0
//  5   IT1   1 = 160ms               1
//  6   IT2   0                       0
//  7   N/F   0                       0


uint16_t MyPort = 1;

//working thresholds from pot inputs, scaled 0-100
uint16_t    RedThreshold    = 0;
uint16_t    GreenThreshold  = 0;
uint16_t    BlueThreshold   = 0;
uint16_t    Hysteresis      = 0;


uint16_t Filter(uint32_t *Acc,uint16_t NewData, uint8_t factor)
{
    uint32_t Temp = 0;
    Temp = *Acc >> factor ;
    Temp = *Acc - Temp + NewData;
    *Acc = Temp;
    return  *Acc >> factor;
}


void ConfigureTSC(uint8_t Address)
{
    I2C i2c(p28, p27);          //pins for I2C communication (SDA, SCL)
    i2c.frequency(200000);



    char id_regval[1] = {146};
    char data[1] = {0};
    i2c.write(sensor_addr,id_regval,1, true);
    i2c.read(sensor_addr,data,1,false);

    if (data[0]==68) {
        GreenLed = 0;
        wait (2);
        GreenLed = 1;
    } else {
        GreenLed = 1;
    }

    // Initialize color sensor

    char enable_register[2] = {128,3};          //enable the sensor
    i2c.write(sensor_addr,enable_register,2,false);

    char timing_register[2] = {0x81,0xC0};      //approx 100ms
    i2c.write(sensor_addr,timing_register,2,false);

    char control_register[2] = {0x8F,2};        //gain = x16
    i2c.write(sensor_addr,control_register,2,false);



    // Read data from color sensor (Clear/Red/Green/Blue)
    //led = 1;

}

Colour GetSensorData(char SensorNumber)
{
    Colour NewData;
    char AddrReg[1] = {0};
    char DataReg[5] ={0,0,0,0,0};
        
    NewData.White = 0;
    NewData.Red = 0;
    NewData.Green = 0;
    NewData.Blue = 0;

    AddrReg[0] = SENSOR_WHITE_REG;
    i2c.write(SENSOR_ADDR, AddrReg,1, true);
    i2c.read(SENSOR_ADDR,DataReg,2, false);
    NewData.White = ((int)DataReg[1] << 8) | DataReg[0];
 
    AddrReg[0] = SENSOR_RED_REG;
    i2c.write(SENSOR_ADDR, AddrReg,1, true);
    i2c.read(SENSOR_ADDR,DataReg,2, false);
    NewData.Red = ((int)DataReg[1] << 8) | DataReg[0];
    
    AddrReg[0] = SENSOR_GREEN_REG;
    i2c.write(SENSOR_ADDR, AddrReg,1, true);
    i2c.read(SENSOR_ADDR,DataReg,2, false);
    NewData.Green = ((int)DataReg[1] << 8) | DataReg[0];

    AddrReg[0] = SENSOR_BLUE_REG;
    i2c.write(SENSOR_ADDR, AddrReg,1, true);
    i2c.read(SENSOR_ADDR,DataReg,2, false);
    NewData.Blue = ((int)DataReg[1] << 8) | DataReg[0];
          
    return NewData;
}

void InitOutputs(void)
{
    //  Set all 8 Port A bits to output direction
    chip.direction(PORT_A, 0x00);
    //  Set all 8 Port B bits to output direction
    chip.direction(PORT_B, 0x00); 
}

void SetOutputBit(char bit)
{
    uint16_t OutputWord = 1;
    char BitA, BitB, PortA, PortB;
    
    OutputWord <<= bit;
    BitA = OutputWord & 0xFF;
    BitB = OutputWord >> 8;
    
    PortA = chip.read(PORT_A);
    PortA |=BitA;
    chip.write(PORT_A, PortA);
    
    PortB = chip.read(PORT_B);
    PortB |=BitB;
    chip.write(PORT_B, PortB);   
}

void ClearOutputBit(char bit)
{
    uint16_t OutputWord = 1;
    char BitA, BitB, PortA, PortB;
    
    OutputWord <<= bit;
    OutputWord = ~OutputWord;
        
    BitA = OutputWord & 0xFF;
    BitB = OutputWord >> 8;
    
    PortA = chip.read(PORT_A);
    PortA &=BitA;
    chip.write(PORT_A, PortA);
    
    PortB = chip.read(PORT_B);
    PortB &=BitB;
    chip.write(PORT_B, PortB);   
}

void WriteOutputPort(uint16_t FullPort)
{
    chip.write(PORT_A, FullPort & 0xFF); 
    chip.write(PORT_B, FullPort >> 8);     
}


void GetThresholds(void)
{
    //Load the pot values ant make 0 to 100%  value 
    /*
    RedThreshold    = RedTrimmer.read_u16()   * 100 >> 11;
    GreenThreshold  = GreenTrimmer.read_u16() * 100 >> 11;
    BlueThreshold   = BlueTrimmer.read_u16()  * 100 >> 11;
    Hysteresis      = HysTrimmer.read_u16()   * 100 >> 11;      
    */
    
    RedThreshold    = 45;
    GreenThreshold  = 35;
    BlueThreshold   = 10;
    Hysteresis      = 5;
}


void UpdateDisplay(void)
{
    //make 12 bit only (display)
    Red >>=4;
    Green >>=4;
    Blue >>=4;
    White >>=4;

    lcd.locate(0, 0);
    lcd.printf("R%02i G%02i B%02i W%04i",RedProp,GreenProp,BlueProp,White); 
    lcd.locate(0, 1);       
    lcd.printf("R%02i G%02i B%02i H%02i ",RedThreshold, GreenThreshold, BlueThreshold, Hysteresis);   
}


char GetResults(uint8_t ThisSensor)
{

    char LEDColour = ERROR;
    
    
    if(White > WHITE_THRESHOLD) //looking at intensity somthing is on!
    {  
        switch(Config[(ThisSensor << 1)])
        {
            case STD_RED:
            {
                if((RedProp - GreenProp  > 30) && (RedProp - BlueProp  > 30))
                {
                    LEDColour = RED;
                }          
            }
            break;
            
            case STD_GREEN:
            {
                if((GreenProp - RedProp  > 30) && (GreenProp - BlueProp  > 30))
                {
                    LEDColour = GREEN;
                }             
            }
            break;       
    
            case STD_BLUE:
            {
                if((BlueProp - RedProp  > 30) && (BlueProp - GreenProp   > 30))
                {
                    LEDColour = BLUE;
                }             
            }
            break; 
            
            case STD_YELLOW:
            {
                if( (GreenProp <= (GreenThreshold-Hysteresis)) && (RedProp >=(RedThreshold+Hysteresis)) ) 
                {             
                    LEDColour = YELLOW;
                } 
            }
            break;   
            
            case GREEN_YELLOW:
            {
                if( (GreenProp <= (GreenThreshold-Hysteresis)) && (RedProp >=(RedThreshold+Hysteresis)) ) 
                { //pretty sure it's Yellow
                
                    LEDColour = YELLOW;
                } 
                else 
                {
                    if( (GreenProp > (GreenThreshold+Hysteresis)) && (RedProp <=(RedThreshold-Hysteresis)) ) 
                    { //pretty sure it's green
                        LEDColour = GREEN;
                    } 
                }
            }
            break;
            
            case RGB:
            {
                if((RedProp - GreenProp  > 30) && (RedProp - BlueProp  > 30))
                {
                    LEDColour = RED;
                }
                else
                {       
                    if((GreenProp - RedProp  > 30) && (GreenProp - BlueProp  > 30))
                    {
                        LEDColour = GREEN;
                    }
                    else
                    {           
                        if((BlueProp - RedProp  > 30) && (BlueProp - GreenProp   > 30))
                        {
                            LEDColour = BLUE;
                        }
                    }
                }
            }
            break;       
                       
            case NOTUSED:
            default:
            {
                LEDColour = ERROR;       
            }
            break; 
        }
    }
    return LEDColour;
}



int main()
{
    InitOutputs();
    //----------------------Initialise My TCS3472--------------------
    ConfigureTSC(0);
    //----------------------    My TCS3472       --------------------

    while(1) 
    {
        
        //WriteOutputPort(MyPort);
        ClearOutputBit(MyPort);
        MyPort++;
        if (MyPort == 16)
        {
            MyPort = 0;
        }
        SetOutputBit(MyPort);       
        
        GetThresholds();

        DisplayIndex++;
        if(DisplayIndex >= 20) {
            DisplayIndex = 0;
        }

        wait(0.1);
        
//----------------------My TCS3472--------------------


        for(SensorNumber = 0; SensorNumber < 16; SensorNumber++)
        {
            if(Config[((SensorNumber << 1) + 1)] != NOTUSED) //check to see if the sensor is being used
            {  
                SensorData =  GetSensorData(SensorNumber);

                White = SensorData.White;
                Red   = SensorData.Red;
                Green = SensorData.Green;
                Blue  = SensorData.Blue;

                UpdateDisplay();
                
                // work out % of colour mix
                Temp = (Red+Blue+Green);
                RedProp = (Red* 100) / Temp ;
                GreenProp = (Green* 100) / Temp ;
                BlueProp = (Blue* 100) / Temp ;


                SensorResult = GetResults(SensorNumber);
                
                

                //good LED so turn on Outputs
                switch (Config[(SensorNumber << 1)])
                {
                    case STD_RED:
                    case STD_GREEN:                    
                    case STD_BLUE:                    
                    case STD_YELLOW: 
                    {
                        if (SensorResult == Config[(SensorNumber << 1)])
                        {
                            SetOutputBit(Config[((SensorNumber << 1)+1)]);
                        }
                        else
                        {
                            ClearOutputBit(Config[((SensorNumber << 1)+1)]);
                        }  
                    }
                    break;
                    
                    case GREEN_YELLOW:
                    {
                        if (SensorResult == YELLOW)
                        { 
                            SetOutputBit(Config[((SensorNumber << 1)+1)]); //base output
                            ClearOutputBit(    Config[((SensorNumber << 1)+1)] +1);//next output
                        }
                        else 
                        {   
                            if (SensorResult == GREEN)
                            {
                                ClearOutputBit(Config[((SensorNumber << 1)+1)]); //base output
                                SetOutputBit(    Config[((SensorNumber << 1)+1)] +1);//next output
                            }
                            else
                            {
                                ClearOutputBit(Config[((SensorNumber << 1)+1)]); //base output
                                ClearOutputBit(    Config[((SensorNumber << 1)+1)] +1);//next output
                            }
                        }      
                    }
                    break;
                    
                    case RGB:
                    {
                        if (SensorResult == RED)
                        { 
                            SetOutputBit(Config[((SensorNumber << 1)+1)]);          //base output
                            ClearOutputBit(Config[((SensorNumber << 1)+1)] +1); //next output
                            ClearOutputBit(Config[((SensorNumber << 1)+1)] +2); //next output
                        }
                        else 
                        {   
                            if (SensorResult == GREEN)
                            {
                                ClearOutputBit(Config[((SensorNumber << 1)+1)]);          //base output
                                SetOutputBit(Config[((SensorNumber << 1)+1)] +1); //next output
                                ClearOutputBit(Config[((SensorNumber << 1)+1)] +2); //next output
                            }
                            else
                            {
                                if (SensorResult == BLUE)
                                {
                                    ClearOutputBit(Config[((SensorNumber << 1)+1)]);          //base output
                                    ClearOutputBit(Config[((SensorNumber << 1)+1)] +1); //next output
                                    SetOutputBit(Config[((SensorNumber << 1)+1)] +2); //next output  
                                }
                                else  
                                {
                                    ClearOutputBit(Config[((SensorNumber << 1)+1)]);          //base output
                                    ClearOutputBit(Config[((SensorNumber << 1)+1)] +1); //next output
                                    ClearOutputBit(Config[((SensorNumber << 1)+1)] +2); //next output               
                                }
                                
                            }
                        }          
                    }
                    break;  
                    
                    default:
                    {
                        ClearOutputBit(Config[((SensorNumber << 1)+1)]);          //base output  
                    }
                     break;                       
                 }   //end switch                             
            } //end if
        } //end for 
                   
 




        //guess the colour
        if(White > WHITE_THRESHOLD) //looking at intensity somthing is on!
        { 
        /*
            if((GreenProp <= 30) && (RedProp >=50)) 
            { //pretty sure it's Yellow
                YellowLed = 1;
                GreenLed = 0;
            } 
            else 
            {
                YellowLed = 0;
                if((GreenProp > 40) && (RedProp <=40)) { //pretty sure it's green
                    GreenLed = 1;
                } else {
                    GreenLed = 1;
                    YellowLed = 1;
                }
            }
            */
            
            //------------------------CHECK red-----------------------------------------
            if((RedProp - GreenProp  > 30) && (RedProp - BlueProp  > 30))
            {
                RedLed = 1;
                GreenLed = 0; 
                BlueLed = 0;           
                YellowLed = 0;
            }
            else
            {
                 
                if((GreenProp - RedProp  > 30) && (GreenProp - BlueProp  > 30))
                {
                    RedLed = 0;
                    GreenLed = 1; 
                    BlueLed = 0;           
                    YellowLed = 0;
                }
                else
                {           
                    if((BlueProp - RedProp  > 30) && (BlueProp - GreenProp   > 30))
                    {
                        RedLed = 0;
                        GreenLed = 0; 
                        BlueLed = 1;           
                        YellowLed = 0;
                    }
                    else
                    {     
                        if( (GreenProp <= (GreenThreshold-Hysteresis)) && (RedProp >=(RedThreshold+Hysteresis)) ) 
                        { //pretty sure it's Yellow
                            //YellowLed = 1;
                            //GreenLed = 0;
                            
                            RedLed = 0;
                            GreenLed = 0; 
                            BlueLed = 0;           
                            YellowLed = 1;;
                        }
                        else
                        { 
                            RedLed = 0;
                            GreenLed = 0; 
                            BlueLed = 0;           
                            YellowLed = 0;
                        }
                    }
                }
            }
            
        }
        else
        {
            RedLed = 0;
            GreenLed = 0; 
            BlueLed = 0;           
            YellowLed = 0;
        }    
            
                           
 
 
  /*
  //-------------------------------------------------------------------------------------------------------------------          
            
            if( (GreenProp <= (GreenThreshold-Hysteresis)) && (RedProp >=(RedThreshold+Hysteresis)) ) 
            { //pretty sure it's Yellow
                YellowLed = 1;
                GreenLed = 0;
            } 
            else 
            {
                YellowLed = 0;
                if( (GreenProp > (GreenThreshold+Hysteresis)) && (RedProp <=(RedThreshold-Hysteresis)) ) 
                { //pretty sure it's green
                    GreenLed = 1;
                } 
                else 
                {
                    GreenLed = 1;
                    YellowLed = 1;
                }
            }
        } 
        else 
        {
            //not enough intensity to determine
            GreenLed = 0;
            YellowLed = 0;
        }
    
*/ 
//----------------------------------------------------------------------------------------------------------------       
    } //while(1)
}//main



/*
---------------------------------------------------------------------------------------------
//SPI SampleCode

#include "mbed.h"
#include "MCP23S17.h"
// Create SPI bus
SPI spi(p5, p6, p7);
// 
 
char Opcode = 0x40;
 
// Next create a MCP23S17
// mbed p20 is connected to ~chipSelect on the MCP23S17
MCP23S17 chip = MCP23S17(spi, p20, Opcode);
 
DigitalOut led1(LED1); // mbed LED1 is used for test status display
 
int main() {
//
//  Set all 8 Port A bits to output direction
    chip.direction(PORT_A, 0x00);
//  Set all 8 Port B bits to input direction
    chip.direction(PORT_B, 0xFF);
    led1=0;
//  Start Loopback test sending out and reading back values
//  loopback test uses A0 and B0 pins - so use a wire to jumper those two pins on MCP23S17 together
    while (1) {
        // write 0xAA to MCP23S17 Port A
        chip.write(PORT_A, 0xAA);
        wait(.5);
        // read back value from MCP23S17 Port B and display B0 on mbed led1
        led1 = chip.read(PORT_B)& 0x01;
        // write 0x55 to MCP23S17 Port A
        chip.write(PORT_A, 0x55);
        wait(.5);
        // read back value from MCP23S17 Port B and display B0 on mbed led1
        led1 = chip.read(PORT_B)& 0x01;
        // led1 should blink slowly when it is all working
    }
}
*/

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