Initial commit

Dependencies:   FastPWM Lamp_Intensity_Lock_withTempCo mbed

Fork of Lamp_Intensity_Lock_withTempCo by Medic

main.cpp

Committer:
laserdad
Date:
2017-01-13
Revision:
2:1b142e2aa23e
Parent:
1:2d9d931c8484
Child:
3:a8ec3c6aeb08

File content as of revision 2:1b142e2aa23e:

#include "mbed.h"
#include "FastPWM.h"

#define TMD2772_Addr 0x72 //this is the 8-bit address
#define MAX31725_Addr 0x92 //this is the 8-bit address

const uint8_t ALSDataRegister = 0x14;
const uint8_t waitIntervals = 100; //number of 2.73 ms waits
const int measPeriod_ms = 699;
const float tempRef = 29.5;  //C temperature at which all optical powers are calculated to
const float Ch0tempCo = 0.0025; // % per degree C
const float warmUp = 15; //number of measurements with a higher than usual pGain (to get to target faster);

I2C i2c(I2C_SDA,I2C_SCL);
Serial pc(USBTX,USBRX); //open serial port (optionally add baud rate after specifying TX and RX pins)
Timer t;
FastPWM mypwm(PA_1);



//**********************************
//declare subroutines
void writeRegister(uint8_t addr, uint8_t reg, uint8_t val)
{
    /*writes 1 byte to a single register*/
    char writeData[2];
    writeData[0] = reg ;
    writeData[1] = val;
    i2c.write(addr,writeData, 2);
}

void writeBlock(uint8_t addr, uint8_t startReg, uint8_t *data, uint8_t numBytes)
{
    /*writes data from an array beginning at the startReg*/
    char writeData[numBytes+1];
    writeData[0]=startReg;
    for(int n=1; n<numBytes; n++) {
        writeData[n]=data[n-1];
    }
    i2c.write(addr,writeData,numBytes+1);
}

void readRegisters(uint8_t addr, uint8_t startReg, char *regData, int numBytes)
{
    char writeData = startReg;
    i2c.write(addr,&writeData,1,true); //true is for repeated start
    i2c.read(addr,regData,numBytes);
}

uint16_t LSB_MSB_2uint16(char *data) {
/*returns an unsinged 16 bit integer from a 2 data bytes, where the second byte is the MSB*/
    return ((uint16_t)data[1] << 8) + (uint16_t)data[0];
}

uint16_t MSB_LSB_2uint16(char *data) {
/*returns an unsinged 16 bit integer from a 2 data bytes, where the second byte is the MSB*/
    return ((uint16_t)data[0] << 8) + (uint16_t)data[1];
}

void regDump(uint8_t Addr, uint8_t startByte, uint8_t endByte)
{
    /*print the values of up to 20 registers*/
    char regData[20];
    int numBytes;
    if (endByte>=startByte) {
        numBytes =  (endByte-startByte+1) < 20 ? (endByte-startByte+1) : 20;
    } else {
        numBytes=1;
    }

    regData[0] = startByte;
    i2c.write(Addr,regData,1,true);
    i2c.read(Addr, regData, numBytes);
    for(int n=0; n<numBytes; n++) {
        pc.printf("%X, %X \r\n", startByte+n, regData[n]);
    }
}


bool bitRead(uint16_t data, uint8_t bitNum)
{
    uint16_t mask = 1<<bitNum;
    uint16_t masked_bit = data & mask;
    return masked_bit >> bitNum;
}

float getTemp( int address) {
    char tempData[2];
    uint16_t tempBits; 
    const float LSB =0.00390625;
  // read temperature
    readRegisters(MAX31725_Addr,0x00,tempData,2);
    tempBits = MSB_LSB_2uint16(tempData);
    if(bitRead(tempBits,15) == 1 )
    {
        return( (32768-tempBits)*LSB ); //negative temp
    }
    else {
        return ( tempBits*LSB ); //positive temp
    }
} 


void initTMD2772(void) {
    writeRegister(TMD2772_Addr,(0x00 | 0x80),0x0B);// Set power on, ALS enabled, Wait enabled, Interrupts enabled (register 0)
    writeRegister(TMD2772_Addr,(0x01 | 0x80),0x00);//ALS time register - 0x00 is max integration time of 699ms (register 1) 
    writeRegister(TMD2772_Addr,(0x03 | 0x80),0xFF-waitIntervals); // Wtime = 2.73 ms * delay peroids (subtract from 0xFF to enter into register)
//    writeRegister(TMD2772_Addr,(0x0D | 0x80),0x04); //optionally scale ALS gain by 0.16 by seleting 0x04;
    writeRegister(TMD2772_Addr,(0x0D | 0x80),0x00); //optionally scale ALS gain by 0.16 by seleting 0x04;

    writeRegister(TMD2772_Addr,(0x0F | 0x80),0x00); //ALS gain is 1x
}

float tempCorrectTMDCh0(float counts, float tempC) 
{
    float tDiff = tempC-tempRef;
    float delta = Ch0tempCo*tDiff; //the % difference observed vs. reference temperature
   return counts *(1-delta); //the count value equivalent if measured at reference temperature (less counts if temp is higher)
    
}


int main() {
    float ratio;
    char data[4];
    uint16_t ch0Data;
    uint16_t ch1Data;
    float setpoint = 37250; //ch0/ch1 color setpoint ~0.88 duty cycle
    static float step; //duty cycle change per sample
    float dutyCycle=0.9275;
    float dutyCycleMin =0.8;
    float dutyCycleMax =0.98;
    float stepMax=0.0025;
    float stepMin=-0.0025;
//    float iGain = 0.05; //integral gain --adding this because when I blew on it, it couldn't recover
    float err;
    float tol=1; //tolerance within which to ignore changes in signal intensity
    float pGain = 0.25; //proportional gain
//    float quadGain = 0;*/
    static float temperature = 0;
    //float ch0Avg; //integral error
//    float filterLength = 15;
    float tempFilterLength = 8;
    //setup everything
    mypwm.period_us(400);
    mypwm.write(dutyCycle);
    i2c.frequency(400000); //set I2C frequency to 400kHz
    wait_ms(1000);
    initTMD2772();
    regDump(TMD2772_Addr,(0x00 | 0x80),0x0F);
    pc.printf("Done initializing\r\n");
    wait_ms(700);
    static int loopCount =0;
    
    //get initial filter value
//    reg2write=ALSDataRegister | 0x80;
    readRegisters(TMD2772_Addr, (ALSDataRegister | 0x80), data ,4);
//    
//    i2c.write(TMD2772_Addr,&reg2write,1,true); //1 byte of data, repeated start for read
//    i2c.read(TMD2772_Addr,data,4);
    ch0Data = LSB_MSB_2uint16(data);
    ch1Data = LSB_MSB_2uint16(data+2);
    ratio = (float)ch0Data/(float)ch1Data;
    wait_ms(699);
    
    
    while(1) {
        loopCount++;
        if (loopCount<warmUp) 
        {
            pGain =0.25;
        }
        else 
        {
            pGain =0.2;
        }
        t.start();
        readRegisters(TMD2772_Addr, (ALSDataRegister | 0x80), data ,4);
        //reg2write=ALSDataRegister | 0x80;
////        pc.printf("%X\r\n",reg2write);
//        i2c.write(TMD2772_Addr,&reg2write,1,true); //1 byte of data, repeated start for read
//        i2c.read(TMD2772_Addr,data,4);
        ch0Data = LSB_MSB_2uint16(data);
        if (temperature ==0) 
        {
            temperature = getTemp(MAX31725_Addr);
        }
        else 
        {
            temperature += (getTemp(MAX31725_Addr)-temperature)/tempFilterLength  ;  
        }
        ch0Data = tempCorrectTMDCh0(ch0Data,temperature);
        ch1Data = LSB_MSB_2uint16(data+2);
        ratio = (float)ch0Data/(float)ch1Data;
        err = ch0Data - setpoint;
        pc.printf( "%U,%U, %f, %f, %f, %f\r\n",ch0Data,ch1Data,ratio,mypwm.read(),temperature, step);
        if (abs(err)>tol) {
            step = err/setpoint * pGain ;
            step = (step > stepMax) ? stepMax : step;
            step = (step < stepMin) ? stepMin : step;
            dutyCycle -= step;
            dutyCycle = (dutyCycle < dutyCycleMin) ? dutyCycleMin : dutyCycle;
            dutyCycle = (dutyCycle > dutyCycleMax) ? dutyCycleMax : dutyCycle;
            //update with new settings
            mypwm.write(dutyCycle);
        }
        while(t.read_ms() < measPeriod_ms) {
         //pc.printf("%U \r\n",t.read_ms());   
        }
        t.reset();
    }
    
    
}