Control Code with I/O and ADC working

Dependencies:   MODSERIAL mbed

main.cpp

Committer:
jrodenburg
Date:
2018-02-13
Revision:
4:168a446bd0da
Parent:
3:0c9476da0cad
Child:
5:0f38a0bd4f86

File content as of revision 4:168a446bd0da:

// MBED SCRIPT FOR CONTROLLING THE TEMPERATURE CONTROLLED TEST FIXTURE (TCTF)
// DATE: SEPTEMBER 2017

#include "mbed.h"
#include "MODSERIAL.h"
#include "MCP23008.h"
#include "LTC2487.h"
#include <string>

//DEFINITIVE VARIABLES
#define DEBUG         0
#define DEBUG1        1
#define CHN_COUNT     48
#define MIN_TEMP      15
#define MAX_TEMP      60
#define HYST          0.2
#define SAMPLES       5
#define I2C_Freq      2000
#define VALVE         1
#define HEATER        2
#define STATUS_GOOD   3
#define STATUS_BAD    4
#define sizeLUT       34
#define FRONT_THERM   0
#define BACK_THERM    1
#define HEAT_FET_AMP  2
#define VALV_FET_AMP  3


//TCTF CHANNEL DATA
struct CHNL_DATA{
   bool status;
   float setTemp;
};

CHNL_DATA chnlStatus[] = {
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},
    {0, NULL},  
};


//I2C AADRESS LOOK UP TABLE, CREATED IN EXCEL SHEET (COUNT, TEMP)
struct I2C_ADDR_LUT{
   int adc;
   int io;
};

I2C_ADDR_LUT addrLUT[] = {
    {0x23, 0x10},
    {0x53, 0x60},
    {0x43, 0x70},
    {0x73, 0x40},
    {0x63, 0x50},
    {0x22, 0x11},
    {0x52, 0x61},
    {0x42, 0x71},
    {0x72, 0x41},
    {0x62, 0x51},
    {0x21, 0x12},
    {0x51, 0x62},
    {0x41, 0x72},
    {0x71, 0x42},
    {0x61, 0x52},
    {0x20, 0x13},
    {0x50, 0x63},
    {0x40, 0x73},
    {0x70, 0x43},
    {0x60, 0x53},
    {0x26, 0x14},
    {0x56, 0x64},
    {0x46, 0x74},
    {0x76, 0x44},
    {0x66, 0x54},
    {0x2C, 0x1F},
    {0x5C, 0x6F},
    {0x4C, 0x7F},
    {0x7C, 0x4F},
    {0x6C, 0x5F},
    {0x2D, 0x1E},
    {0x5D, 0x6E},
    {0x4D, 0x7E},
    {0x7D, 0x4E},
    {0x6D, 0x5E},
    {0x2E, 0x1D},
    {0x5E, 0x6D},
    {0x4E, 0x7D},
    {0x7E, 0x4D},
    {0x6E, 0x5D},
    {0x2F, 0x1C},
    {0x5F, 0x6C},
    {0x4F, 0x7C},
    {0x7F, 0x4C},
    {0x6F, 0x5C},
    {0x20, 0x1B},
    {0x50, 0x6B},
    {0x40, 0x7B},  
};

//THERMISTOR LOOK UP TABLE, CREATED IN EXCEL SHEET (COUNT, TEMP)
struct THERM_LUT{
   int adc;
   int temp;
};

THERM_LUT thermLUT[] = {
    {113779,-40},
    {109152,-35},
    {103830,-30},
    {97855,-25},
    {91319,-20},
    {84352,-15},
    {77124,-10},
    {69820,-5},
    {62621,0},
    {55693,5},
    {49169,10},
    {43144,15},
    {37669,20},
    {32768,25},
    {28429,30},
    {24622,35},
    {21309,40},
    {18439,45},
    {15962,50},
    {13831,55},
    {12002,60},
    {10428,65},
    {9080,70},
    {7919,75},
    {6923,80},
    {6063,85},
    {5323,90},
    {4685,95},
    {4130,100},
    {3653,105},
    {3234,110},
    {2876,115},
    {2563,120},
    {2284,125}
};

//SERIAL COMMUNICATION SETUP
MODSERIAL pc(USBTX, USBRX);

//DEFINE PINS
DigitalOut myled(LED2);

//I2C FOR MCP23008 (I/O Control)
MCP23008 io_control(PTC9, PTC8, 0x10, 100000); //sda, scl

//I2C FOR LTC2487 (ADC Control)
LTC2487 ltc2487(PTC11, PTC10, 0x23, 100000); //sda, scl

//GLOBAL VARIABLES
volatile bool dataRecieved = false; //used to check if data has been recieved
char rxBuf[50];
int chnlSel;

/* Function: rxInterrupt
   **************************************************************
   Description: serial rx interupt handler 
   Recieves: N/A
   Returns: N/A     
*/

void rxInterrupt(MODSERIAL_IRQ_INFO *info){
    dataRecieved = true;
    if(DEBUG) pc.printf("DATA RECIEVED \r\n");
}

/* Function: parseRXData
   **************************************************************
   Description: The parse recieved data into 
   Recieves: chn: The channel we want to put into the channel
   Returns: N/A     
*/

void parseRXData(){
    int pCount = 0; //count data collected
    int i = 0;
    int chnl;
    string data = "";

    if(DEBUG) pc.printf("buff1 = <%s> \r\n", rxBuf);
    
    while(pCount < 3){
        if(rxBuf[i] != '.'){
            data += rxBuf[i];
        }
        else{
            pCount++; 
            if(pCount == 1){ //get channel
                if((atoi(data.c_str()) < 0) || (atoi(data.c_str()) > 15)){
                    //check if channel is out of array index
                    if(DEBUG) pc.printf("ERROR: INDEX OUT OF RANGE! \r\n", rxBuf);
                }
                else{
                    chnl = atoi(data.c_str());
                    chnl = chnl-1;  //fix for array indexing
                    chnlSel = chnl; //chnl selected by user in GUI
                }
            }
            else if(pCount == 2){ //get channel temperature
                chnlStatus[chnl].setTemp = atoi(data.c_str());
                if(DEBUG) pc.printf("CHANNEL TEMP: %f \r\n", chnlStatus[chnl].setTemp);
            }
            else if(pCount == 3){ //get channel status
                chnlStatus[chnl].status = atoi(data.c_str());
                if(DEBUG) pc.printf("CHANNEL STATUS: %f \r\n", chnlStatus[chnl].status);
            } 
            data = "";  
        }
        i++;
    }
}

/* Function: get_temp
   **************************************************************
   Description: Retrieve data from thermistor
   Recieves: chn: the channel of the fixture to read temp. from
   Returns: the temperature of the fixture (front or back)
*/

float get_temp(int chn){
    myled = 1;
    ltc2487.setAddress(addrLUT[chn].adc);
    
    float ADC_val = ltc2487.readOutput(chn); //(65536*1.334)/2.5;
    
    int i = 0;
    
    while((i < sizeLUT) && (thermLUT[i].adc > ADC_val)){
        i++;    
    }  //find the temp. above therm temp
    
    //Point slope formula extrapolation: 
    // y1 = m (x1-x0)+ y0 , y = temp. value, x = adc value
    // y1 = thermLUT[i-1].temp   y0 = thermLUT[i].temp
    // x1 = thermLUT[i-1].adc    x0 =thermLUT[i].adc
    float a = float(thermLUT[i-1].temp - thermLUT[i].temp); //slope of temp between points where therm temp is between (Tmax - Tmin)
    float b = float(thermLUT[i-1].adc - thermLUT[i].adc);   //slope of adc between points where therm adc is between (Amax - Amin)
    
    float m = a/b;
    float y = (m*(ADC_val-thermLUT[i].adc))+thermLUT[i].temp;
    
    if(DEBUG) pc.printf("ADC VAL: %f TEMP: %f \r\n", ADC_val, y);
    
    //if(chn == chnlSel) 
    pc.printf("%f \r\n", y);
    
    return y;  
}

/* Function: get_heater_current
   **************************************************************
   Description: Retrieve current into heater control MOSFET
   Recieves: chn: the channel of the fixture to read current from
   Returns: the current into the heater control MOSFET
*/

float get_heater_current(int chn){
    return 0.0;
}

/* Function: get_valve_current
   **************************************************************
   Description: Retrieve current into valve control MOSFET
   Recieves: chn: the channel of the fixture to read current from
   Returns: the current into the valve control MOSFET
*/

float get_valve_current(int chn){
    return 0.0;
}

/* Function: turn_valve_on
   **************************************************************
   Description: Turn valve on and green status LED on
   Recieves: chn: the channel of the fixture 
   Returns: N/A
*/

void turn_valve_on(int chn){
    io_control.setAddress(addrLUT[chn].io);
    io_control.init();
    io_control.writeOutput(1,0,1,0);
}

/* Function: turn_valve_off
   **************************************************************
   Description: Turn valve off and green status LED on
   Recieves: chn: the channel of the fixture 
   Returns: N/A
*/

void turn_valve_off(int chn){
    io_control.setAddress(addrLUT[chn].io);
    io_control.init();
    io_control.writeOutput(0,0,1,0);
}

/* Function: turn_heater_on
   **************************************************************
   Description: Turn heater on and green status LED on
   Recieves: chn: the channel of the fixture 
   Returns: N/A
*/

void turn_heater_on(int chn){
    io_control.setAddress(addrLUT[chn].io);
    io_control.init();
    io_control.writeOutput(0,1,1,0);
}

/* Function: turn_heater_off
   **************************************************************
   Description: Turn heater off and green status LED on
   Recieves: chn: the channel of the fixture 
   Returns: N/A
*/

void turn_heater_off(int chn){
    io_control.setAddress(addrLUT[chn].io);
    io_control.init();
    io_control.writeOutput(0,0,1,0);
}

/* Function: status_led
   **************************************************************
   Description: Turn status LED on (turns on green or red)
   Recieves: chn: the channel of the fixture 
             status: the status of channel (good (1) or bad (0))
   Returns: N/A
*/

void status_led(int chn, int status){
    io_control.setAddress(addrLUT[chn].io);
    if(status){
        io_control.writeOutput(0,0,1,0);
    }
    else{
        io_control.writeOutput(0,0,0,1);
    }
}

/* Function: test_mcp23008
   **************************************************************
   Description: Test each output of the MCP23009
   Recieves: N/A
   Returns: N/A
*/

void test_mcp23008(int chn){
    turn_valve_on(chn);
    wait(1);
    turn_valve_off(chn);
    wait(1);
    turn_heater_on(chn);
    wait(1);
    turn_heater_off(chn);
    wait(1);
    status_led(chn, 0);
    wait(1);
    status_led(chn, 1);
}

/* Function: test_ltc2487
   **************************************************************
   Description: Test the reading from LTC2487
   Recieves: N/A
   Returns: N/A
*/

void test_ltc2487(int chn){
    get_temp(chn);
    //if(DEBUG1) pc.printf("TEMPERATURE READING: %f \r\n", get_temp(chn));
}



int main() {
    
    pc.baud(9600);
    pc.autoDetectChar('E');
    pc.attach(&rxInterrupt, MODSERIAL::RxAutoDetect);
    
    myled = 1;
    /*
    //test_mcp23008(1);
    while(1){
        test_ltc2487(1);
    }*/
    
    while(1) {
        if(DEBUG) pc.printf("THE PROGRAM STARTED \r\n");
        
        //check if we recieved data/need to update TCTF data
        if(dataRecieved){
            dataRecieved = false;
            pc.autoDetectChar('\n');
            pc.move(rxBuf, 50);
            pc.rxBufferFlush();
            parseRXData();
        }
        
        for(int chnl = 0; chnl <= CHN_COUNT; chnl++){
            float currentTemp = get_temp(chnl);
            
            //CONTROL LOOP:
            if(chnlStatus[chnl].status == 1){
                if(currentTemp > ((chnlStatus[chnl].setTemp)+HYST)){
                    //Turn chiller on
                    turn_valve_on(chnl); 
                    //Turn heater off
                    turn_heater_off(chnl);
                }
                else if (currentTemp < ((chnlStatus[chnl].setTemp)-HYST)){
                    //Turn chiller off
                    turn_valve_off(chnl); 
                    //Turn heater on
                    turn_heater_on(chnl);
                }
                else{
                    //turn off chiller
                    turn_valve_off(chnl);
                    //turn off heater 
                    turn_heater_off(chnl);
                    //turn on green LED status light
                    status_led(chnl, 1); 
                }   
            }
        }
    }
}