Justin Rodenburg / Mbed 2 deprecated TCTF_Control_Main

Dependencies:   MODSERIAL mbed

Fork of TCTF_Control_Main by Rivian Irvine Team

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 // MBED SCRIPT FOR CONTROLLING THE TEMPERATURE CONTROLLED TEST FIXTURE (TCTF)
00002 // DATE: SEPTEMBER 2017
00003 
00004 #define FW_VERSION      "V.010"
00005 #include "mbed.h"
00006 #include "MODSERIAL.h"
00007 #include "MCP23008.h"
00008 #include "LTC2487.h"
00009 #include <string>
00010 
00011 //DEFINITIVE VARIABLES
00012 #define DEBUG                0
00013 #define DEBUG1               0
00014 #define DEBUG2               0
00015 #define DEBUG3               0
00016 #define DEBUG5               0
00017 #define UID_PRINT            1
00018 #define TEMP_PRINT           0
00019 #define LOOP_TIME            0  
00020 #define CHN_COUNT            8
00021 #define MIN_TEMP             10
00022 #define MAX_TEMP             65
00023 #define TEMP_MARGIN          20
00024 #define HYST_LOW             0.3
00025 #define HYST_HIGH            1
00026 #define SAMPLES              5
00027 #define I2C_Freq             2000
00028 #define VALVE                1
00029 #define HEATER               2
00030 #define STATUS_GOOD          3
00031 #define STATUS_BAD           0
00032 #define sizeLUT              34
00033 #define BACK_THERM           0
00034 #define FRONT_THERM          1
00035 #define HEAT_FET_AMP         2
00036 #define VALVE_FET_AMP        3
00037 #define FET_ON_CURRENT       1.12
00038 #define ROOM_TEMP            22
00039 #define MAX_HEATER_ON_TIME   25
00040 #define MAX_CHILL_TIME       10 //10sec
00041 
00042 // Defines for use with Serial communication
00043 #pragma pack (1)
00044 #define RX_SOF                  0x7B
00045 #define RX_EOF                  0x7D
00046 #define TX_SOF                  0x7B
00047 #define TX_EOF                  0x7D
00048 #define DELIMETER               0x2E
00049 #define SET_TEMPERATURE         0xB0
00050 #define SELECT_CHANNEL          0xB1
00051 #define READ_UID                0xB2
00052 #define RESPONSE_DATA           0xD0
00053 #define TEMP_DATA               0xD1
00054 #define UID_DATA                0xD2
00055 #define ERROR_DATA              0xDF
00056 
00057 
00058 unsigned int chanSel_SendTemp = 0;
00059 unsigned int chanSel_SetTemp = 0;
00060 // Default to chan 0
00061 int currChan = 0;
00062 bool newTempSet = false;
00063 
00064 
00065 //***********************************************
00066 // Serial Rx Packet Format
00067 //***********************************************
00068 typedef struct {
00069     unsigned char SOF_flag;
00070     unsigned char cmd_type;
00071     unsigned char len;
00072     unsigned char Delim;
00073 } HOST_CMD_HEADER;
00074 
00075 typedef struct {
00076     HOST_CMD_HEADER cmd_header;
00077     unsigned char chanID;
00078     unsigned char tempDelim;
00079     float setTemp;
00080     unsigned char chanStatDelim;
00081     unsigned char chanStat;
00082 } SET_TEMPERATURE_CMD;
00083 
00084 typedef struct {
00085     HOST_CMD_HEADER cmd_header;
00086     unsigned char chanIDSel;
00087     unsigned char chanDelim;
00088     unsigned char chanStat;
00089 } SELECT_CHANNEL_CMD;
00090 
00091 typedef struct {
00092     unsigned char SOF_flag;
00093     unsigned char cmd_type;
00094     unsigned char len;
00095     unsigned char Delim;
00096     float data;
00097     unsigned char EOF_flag;
00098 } RESPONSE_CMD;
00099 
00100 typedef struct {
00101     unsigned char SOF_flag;
00102     unsigned char cmd_type;
00103     unsigned char len;
00104     unsigned char Delim;
00105     float chTemp[CHN_COUNT];
00106     unsigned char EOF_flag;
00107 } RESPONSE_TEMP_CMD;
00108 
00109 typedef struct {
00110     HOST_CMD_HEADER cmd_header;
00111     unsigned char chanIDSel;
00112     unsigned char chanDelim;
00113     unsigned char chanStat;
00114 } READ_UID_CMD;
00115 
00116 typedef struct {
00117     unsigned char SOF_flag;
00118     unsigned char cmd_type;
00119     unsigned char len;
00120     unsigned char Delim;
00121     uint32_t UIDMH;
00122     uint32_t UIDML;
00123     uint32_t UIDL;
00124     unsigned char EOF_flag;
00125 } UID_RESPONSE;
00126 
00127 //TCTF CHANNEL DATA
00128 struct CHNL_DATA{
00129    bool status;
00130    float setTemp;
00131    bool error;
00132    int heater_init_time;
00133 };
00134 
00135 CHNL_DATA chnlStatus[] = {
00136     {0, NULL, 0, 0},
00137     {0, NULL, 0, 0},
00138     {0, NULL, 0, 0},
00139     {0, NULL, 0, 0},
00140     {0, NULL, 0, 0},
00141     {0, NULL, 0, 0},
00142     {0, NULL, 0, 0},
00143     {0, NULL, 0, 0},
00144     {0, NULL, 0, 0},
00145     {0, NULL, 0, 0},
00146     {0, NULL, 0, 0},
00147     {0, NULL, 0, 0},
00148     {0, NULL, 0, 0},
00149     {0, NULL, 0, 0},
00150     {0, NULL, 0, 0},
00151     {0, NULL, 0, 0},
00152     {0, NULL, 0, 0},
00153     {0, NULL, 0, 0},
00154     {0, NULL, 0, 0},
00155     {0, NULL, 0, 0},
00156     {0, NULL, 0, 0},
00157     {0, NULL, 0, 0},
00158     {0, NULL, 0, 0},
00159     {0, NULL, 0, 0},
00160     {0, NULL, 0, 0},
00161     {0, NULL, 0, 0},
00162     {0, NULL, 0, 0},
00163     {0, NULL, 0, 0},
00164     {0, NULL, 0, 0},
00165     {0, NULL, 0, 0},
00166     {0, NULL, 0, 0},
00167     {0, NULL, 0, 0},
00168     {0, NULL, 0, 0},
00169     {0, NULL, 0, 0},
00170     {0, NULL, 0, 0},
00171     {0, NULL, 0, 0},
00172     {0, NULL, 0, 0},
00173     {0, NULL, 0, 0},
00174     {0, NULL, 0, 0},
00175     {0, NULL, 0, 0},
00176     {0, NULL, 0, 0},
00177     {0, NULL, 0, 0},
00178     {0, NULL, 0, 0},
00179     {0, NULL, 0, 0},
00180     {0, NULL, 0, 0},
00181     {0, NULL, 0, 0},
00182     {0, NULL, 0, 0},
00183     {0, NULL, 0, 0},
00184 };
00185 
00186 
00187 //I2C AADRESS LOOK UP TABLE, CREATED IN EXCEL SHEET (COUNT, TEMP)
00188 struct I2C_ADDR_LUT{
00189    int adc;
00190    int io;
00191 };
00192 
00193 I2C_ADDR_LUT addrLUT[] = {
00194     {0x23, 0x10},
00195     {0x53, 0x60},
00196     {0x43, 0x70},
00197     {0x73, 0x40},
00198     {0x63, 0x50},
00199     {0x22, 0x11},
00200     {0x52, 0x61},
00201     {0x42, 0x71},
00202     {0x72, 0x41},
00203     {0x62, 0x51},
00204     {0x21, 0x12},
00205     {0x51, 0x62},
00206     {0x41, 0x72},
00207     {0x71, 0x42},
00208     {0x61, 0x52},
00209     {0x20, 0x13},
00210     {0x50, 0x63},
00211     {0x40, 0x73},
00212     {0x70, 0x43},
00213     {0x60, 0x53},
00214     {0x26, 0x14},
00215     {0x56, 0x64},
00216     {0x46, 0x74},
00217     {0x76, 0x44},
00218     {0x66, 0x54},
00219     {0x2C, 0x1F},
00220     {0x5C, 0x6F},
00221     {0x4C, 0x7F},
00222     {0x7C, 0x4F},
00223     {0x6C, 0x5F},
00224     {0x2D, 0x1E},
00225     {0x5D, 0x6E},
00226     {0x4D, 0x7E},
00227     {0x7D, 0x4E},
00228     {0x6D, 0x5E},
00229     {0x2E, 0x1D},
00230     {0x5E, 0x6D},
00231     {0x4E, 0x7D},
00232     {0x7E, 0x4D},
00233     {0x6E, 0x5D},
00234     {0x2F, 0x1C},
00235     {0x5F, 0x6C},
00236     {0x4F, 0x7C},
00237     {0x7F, 0x4C},
00238     {0x6F, 0x5C},
00239     {0x20, 0x1B},
00240     {0x50, 0x6B},
00241     {0x40, 0x7B},
00242 };
00243 
00244 //THERMISTOR LOOK UP TABLE, CREATED IN EXCEL SHEET (COUNT, TEMP)
00245 struct THERM_LUT{
00246    int adc;
00247    int temp;
00248 };
00249 
00250 THERM_LUT thermLUT[] = {
00251     {113779,-40},
00252     {109152,-35},
00253     {103830,-30},
00254     {97855,-25},
00255     {91319,-20},
00256     {84352,-15},
00257     {77124,-10},
00258     {69820,-5},
00259     {62621,0},
00260     {55693,5},
00261     {49169,10},
00262     {43144,15},
00263     {37669,20},
00264     {32768,25},
00265     {28429,30},
00266     {24622,35},
00267     {21309,40},
00268     {18439,45},
00269     {15962,50},
00270     {13831,55},
00271     {12002,60},
00272     {10428,65},
00273     {9080,70},
00274     {7919,75},
00275     {6923,80},
00276     {6063,85},
00277     {5323,90},
00278     {4685,95},
00279     {4130,100},
00280     {3653,105},
00281     {3234,110},
00282     {2876,115},
00283     {2563,120},
00284     {2284,125}
00285 };
00286 
00287 //TCTF CHANNEL TEMPERATURE
00288 typedef struct{
00289    float currTempFront;
00290    float currTempBack;
00291 }CHNL_TEMP;
00292 
00293 CHNL_TEMP channelTempData[CHN_COUNT];
00294 
00295 //SERIAL COMMUNICATION SETUP
00296 MODSERIAL pc(USBTX, USBRX);
00297 
00298 //DEFINE PINS
00299 DigitalOut myled(LED2);
00300 
00301 //I2C FOR MCP23008 (I/O Control)
00302 MCP23008 io_control(PTC9, PTC8, 0x10, 100000); //sda, scl
00303 
00304 //I2C FOR LTC2487 (ADC Control)
00305 LTC2487 ltc2487(PTC11, PTC10, 0x23, 100000); //sda, scl
00306 
00307 //GLOBAL VARIABLES
00308 volatile bool dataReceived = false; //used to check if data has been received
00309 volatile bool dataTxReady = false;
00310 char rxBuf[50];
00311 int chnlSel;
00312 
00313 
00314 /* Function: turnOffChannel
00315    **************************************************************
00316    Description: Turns off a channel
00317    Recieves: chnl: channel to turn off
00318    Returns: N/A
00319 */
00320 
00321 void turnOffChannel(int chnl){
00322     io_control.setAddress(addrLUT[chnl].io);
00323     io_control.init();
00324     io_control.writeOutput(0,0,0,0);
00325 }
00326 
00327 
00328 /* Function: rxInterrupt
00329    **************************************************************
00330    Description: serial rx interupt handler
00331    Receives: N/A
00332    Returns: N/A
00333 */
00334 
00335 DigitalOut rLed(LED1);
00336 DigitalOut gLed(LED2);
00337 
00338 void sendUID ();
00339 
00340 //***********************************************
00341 // Rx Interrupt from serial Host interface
00342 //***********************************************
00343 void rxInterrupt(MODSERIAL_IRQ_INFO *info)
00344 {
00345     gLed = 0;
00346     dataReceived = true;
00347     gLed = 1;
00348 }
00349 
00350 
00351 //***************************************************************
00352 // Tx Interrupt from serial Host interface
00353 //***************************************************************
00354 void txInterrupt(MODSERIAL_IRQ_INFO *info)
00355 {
00356     dataTxReady = true;
00357 }
00358 
00359 
00360 /* Function: parseRXData
00361    **************************************************************
00362    Description: The parse received data into
00363    Receives: chn: The channel we want to put into the channel
00364    Returns: N/A
00365 */
00366 
00367 void parseRXData()
00368 {
00369     HOST_CMD_HEADER *pRxPktHdr;
00370     string data = "";
00371     unsigned char *ptemp;
00372     int i;
00373 
00374     pRxPktHdr = (HOST_CMD_HEADER *)rxBuf;
00375 
00376 #ifdef DEBUG
00377     pc.printf("DBG: fl=%02x, len=%02x\n", pRxPktHdr->SOF_flag, pRxPktHdr->len);
00378 #endif
00379 
00380     // Exit if the packet does not contain correct header
00381     // Maybe send NAK?
00382     if ((pRxPktHdr->SOF_flag != RX_SOF) || (pRxPktHdr->Delim != DELIMETER))
00383         return;
00384 
00385     switch (pRxPktHdr->cmd_type)
00386     {
00387         case SET_TEMPERATURE:
00388             // Process set temp for specified channel
00389             {
00390                 SET_TEMPERATURE_CMD *pRxPkt = (SET_TEMPERATURE_CMD *)(rxBuf);
00391 #ifdef DEBUG
00392                 pc.printf("DBG: SETTEMP: ch = %02x, tempSet = %f, chanStat = %02x\n",
00393                             pRxPkt->chanID, pRxPkt->setTemp, pRxPkt->chanStat);
00394 #endif
00395                 if ((pRxPkt->tempDelim != DELIMETER) || (pRxPkt->chanStatDelim != DELIMETER)) {
00396                     // Send NAK back
00397                     pc.printf("DBG: Error\n");
00398                 }
00399                 else {
00400                     chanSel_SetTemp = pRxPkt->chanID;
00401                     chnlStatus[pRxPkt->chanID].status = pRxPkt->chanStat;
00402                     chnlStatus[pRxPkt->chanID].setTemp = pRxPkt->setTemp;
00403                     chnlStatus[pRxPkt->chanID].error = 0;
00404                     chnlStatus[pRxPkt->chanID].heater_init_time = 0;
00405                     newTempSet = true;
00406                 }
00407             }
00408             break;
00409 
00410         case SELECT_CHANNEL:
00411             // Select channel to send temp data to
00412             {
00413                 SELECT_CHANNEL_CMD *pRxPkt = (SELECT_CHANNEL_CMD *)(rxBuf);
00414 
00415                 chanSel_SendTemp = pRxPkt->chanIDSel;
00416 #ifdef DEBUG
00417                 pc.printf("DBG: CHAN_SEL: chan=%02x, chanStat = %02x\n", pRxPkt->chanIDSel, pRxPkt->chanStat);
00418 #endif
00419             }
00420             break;
00421 
00422         case READ_UID:
00423             {
00424                 READ_UID_CMD *pRxPkt = (READ_UID_CMD *)(rxBuf);
00425 #ifdef DEBUG
00426                 pc.printf("DBG: Read UID: chan%02x\n", pRxPkt->chanIDSel);
00427 #endif
00428                 sendUID();
00429             }
00430             break;
00431 
00432         default:
00433             // Error
00434             break;
00435     }
00436 }
00437 
00438 /* Function: get_temp
00439    **************************************************************
00440    Description: Convert A/D count to temperature value
00441    Receives: ADC_val: the count from the A/D reading
00442    Returns: the temp. of the A/D reading 
00443 */
00444 
00445 float get_temp(float ADC_val){
00446     myled = 1;
00447     //ltc2487.setAddress(addrLUT[chn].adc);
00448 
00449     //float ADC_val = ltc2487.readOutput(port); //(65536*1.334)/2.5
00450 
00451     int i = 0;
00452 
00453     while((i < sizeLUT) && (thermLUT[i].adc > ADC_val)){
00454         i++;
00455     }  //find the temp. above therm temp
00456 
00457     //Point slope formula extrapolation:
00458     // m = (y1-y0)/(x1-x0)+ y0 , y = temp. value, x = adc value
00459     // y1 = thermLUT[i-1].temp   y0 = thermLUT[i].temp
00460     // x1 = thermLUT[i-1].adc    x0 =thermLUT[i].adc
00461     float a = float(thermLUT[i-1].temp - thermLUT[i].temp); //slope of temp between points where therm temp is between (Tmax - Tmin)
00462     float b = float(thermLUT[i-1].adc - thermLUT[i].adc);   //slope of adc between points where therm adc is between (Amax - Amin)
00463 
00464     float m = a/b;
00465     float y = (m*(ADC_val-thermLUT[i].adc))+thermLUT[i].temp;
00466 
00467     if(DEBUG3) pc.printf("DBG: ADC VAL: %f TEMP: %f \r\n", ADC_val, y);
00468 
00469     return y;
00470 }
00471 
00472 /* Function: get_temp_DATA
00473    **************************************************************
00474    Description: Read A/D data from LTC2487 and set array with front and back temp.
00475    Receives: N/A
00476    Returns: N/A
00477 */
00478 
00479 void get_temp_data(){
00480     //Write to all 8 channels selecting the front port to read
00481     for(int chnl = 0; chnl < CHN_COUNT; chnl++){
00482         ltc2487.setAddress(addrLUT[chnl].adc);
00483         ltc2487.writePort(FRONT_THERM);
00484     }
00485     //wait until next clock cycle on LTC
00486     wait(0.08);
00487     for(int chnl = 0; chnl < CHN_COUNT; chnl++){
00488         ltc2487.setAddress(addrLUT[chnl].adc);
00489         channelTempData[chnl].currTempFront = get_temp(ltc2487.read());
00490     }
00491     //wait until next clock cycle on LTC
00492     wait(0.08);
00493     for(int chnl = 0; chnl < CHN_COUNT; chnl++){
00494         ltc2487.setAddress(addrLUT[chnl].adc);
00495         ltc2487.writePort(BACK_THERM);
00496     }
00497     //wait until next clock cycle on LTC
00498     wait(0.08);
00499     for(int chnl = 0; chnl < CHN_COUNT; chnl++){
00500         ltc2487.setAddress(addrLUT[chnl].adc);
00501         channelTempData[chnl].currTempBack = get_temp(ltc2487.read());
00502     }
00503 }
00504 
00505 /* Function: get_heater_current
00506    **************************************************************
00507    Description: Retrieve current into heater control MOSFET
00508    Receives: chn: the channel of the fixture to read current from
00509    Returns: the current into the heater control MOSFET
00510 */
00511 
00512 float get_heater_current(int chn, int port){
00513     ltc2487.setAddress(addrLUT[chn].adc);
00514     ltc2487.writePort(HEAT_FET_AMP);
00515     wait(0.08);
00516     ltc2487.read();
00517     wait(0.08);
00518 }
00519 
00520 /* Function: get_valve_current
00521    **************************************************************
00522    Description: Retrieve current into valve control MOSFET
00523    Receives: chn: the channel of the fixture to read current from
00524    Returns: the current into the valve control MOSFET
00525 */
00526 
00527 float get_valve_current(int chn, int port){
00528     ltc2487.setAddress(addrLUT[chn].adc);
00529     ltc2487.writePort(VALVE_FET_AMP);
00530     wait(0.08);
00531     ltc2487.read();
00532     wait(0.08);
00533 }
00534 
00535 /* Function: turn_valve_on
00536    **************************************************************
00537    Description: Turn valve on and green status LED on
00538    Receives: chn: the channel of the fixture
00539    Returns: N/A
00540 */
00541 
00542 void turn_valve_on(int chn){
00543     io_control.setAddress(addrLUT[chn].io);
00544     io_control.init();
00545     io_control.writeOutput(1,0,1,0);
00546 }
00547 
00548 /* Function: turn_valve_off
00549    **************************************************************
00550    Description: Turn valve off and green status LED on
00551    Receives: chn: the channel of the fixture
00552    Returns: N/A
00553 */
00554 
00555 void turn_valve_off(int chn){
00556     io_control.setAddress(addrLUT[chn].io);
00557     io_control.init();
00558     io_control.writeOutput(0,0,1,0);
00559 }
00560 
00561 /* Function: turn_heater_on
00562    **************************************************************
00563    Description: Turn heater on and green status LED on
00564    Receives: chn: the channel of the fixture
00565    Returns: N/A
00566 */
00567 
00568 void turn_heater_on(int chn){
00569     io_control.setAddress(addrLUT[chn].io);
00570     io_control.init();
00571     io_control.writeOutput(0,1,1,0);
00572 }
00573 
00574 /* Function: turn_heater_off
00575    **************************************************************
00576    Description: Turn heater off and green status LED on
00577    Receives: chn: the channel of the fixture
00578    Returns: N/A
00579 */
00580 
00581 void turn_heater_off(int chn){
00582     io_control.setAddress(addrLUT[chn].io);
00583     io_control.init();
00584     io_control.writeOutput(0,0,1,0);
00585 }
00586 
00587 /* Function: status_led
00588    **************************************************************
00589    Description: Turn status LED on (turns on green or red)
00590    Receives: chn: the channel of the fixture
00591              status: the status of channel (good (1) or bad (0))
00592    Returns: N/A
00593 */
00594 
00595 void status_led(int chn, int status){
00596     io_control.setAddress(addrLUT[chn].io);
00597     if(status){
00598         io_control.writeOutput(0,0,1,0);
00599     }
00600     else{
00601         //turn valve on too
00602         io_control.writeOutput(1,0,0,1);
00603     }
00604 }
00605 
00606 /* Function: test_mcp23008
00607    **************************************************************
00608    Description: Test each output of the MCP23009
00609    Receives: N/A
00610    Returns: N/A
00611 */
00612 
00613 void test_mcp23008(int chn){
00614     turn_valve_on(chn);
00615     wait(0.5);
00616     turn_valve_off(chn);
00617     wait(0.5);
00618     turn_heater_on(chn);
00619     wait(0.5);
00620     turn_heater_off(chn);
00621     wait(0.5);
00622     status_led(chn, 0);
00623     wait(0.5);
00624     status_led(chn, 1);
00625 }
00626 
00627 /* Function: test_ltc2487
00628    **************************************************************
00629    Description: Test the reading from LTC2487
00630    Receives: N/A
00631    Returns: N/A
00632 */
00633 
00634 void test_ltc2487(){
00635     for(int chnl = 0; chnl < CHN_COUNT; chnl++){
00636         float frontTemp = channelTempData[chnl].currTempFront;
00637         float backTemp = channelTempData[chnl].currTempBack;
00638         pc.printf("TEMPERATURE READING [%i]:: BACK: %f FRONT: %f \r\n", chnl, backTemp, frontTemp);
00639     }
00640 }
00641 
00642 //***************************************************************
00643 // Build packet with temperature readings to send to GUI
00644 //***************************************************************
00645 void sendTempReadings(){
00646     RESPONSE_TEMP_CMD response;
00647     unsigned char *ptr = (unsigned char *)&response;
00648     int i;
00649 
00650     response.SOF_flag = TX_SOF;
00651     response.cmd_type = TEMP_DATA;
00652     response.len = 5+(sizeof(response.chTemp));
00653     response.Delim = DELIMETER;
00654     response.chTemp[0] = channelTempData[0].currTempBack;
00655     response.chTemp[1] = channelTempData[1].currTempBack;
00656     response.chTemp[2] = channelTempData[2].currTempBack;
00657     response.chTemp[3] = channelTempData[3].currTempBack;
00658     response.chTemp[4] = channelTempData[4].currTempBack;
00659     response.chTemp[5] = channelTempData[5].currTempBack;
00660     response.chTemp[6] = channelTempData[6].currTempBack;
00661     response.chTemp[7] = channelTempData[7].currTempBack;
00662     /*float *dst = (float *)&response.chTemp[0];
00663     float *src = (float *)&channelTempData[0];
00664     memcpy(dst, src, sizeof(channelTempData));*/
00665     response.EOF_flag = TX_EOF;
00666 
00667     // Send response to GUI
00668     for (i=0; i < response.len; i++, ptr++)
00669         pc.printf("%02x", *ptr);
00670     pc.printf("\n");
00671 }
00672 
00673 //***************************************************************
00674 // Build packet with Board UID (Unique Identification)
00675 //***************************************************************
00676 void sendUID ()
00677 {
00678     UID_RESPONSE response;
00679     unsigned char *ptr = (unsigned char *)&response;
00680     int i;
00681 
00682     response.SOF_flag = TX_SOF;
00683     response.cmd_type = UID_DATA;
00684     response.len = 17;
00685     response.Delim = DELIMETER;
00686     response.UIDMH = (uint32_t)SIM->UIDMH;
00687     response.UIDML = (uint32_t)SIM->UIDML;
00688     response.UIDL = (uint32_t)SIM->UIDL;
00689     response.EOF_flag = TX_EOF;
00690 
00691     // Send response to GUI
00692     for (i=0; i < response.len; i++, ptr++)
00693         pc.printf("%02x", *ptr);
00694     pc.printf("\n");
00695 }
00696 
00697 //***************************************************************
00698 // Build packet with errors to send to GUI
00699 //***************************************************************
00700 void sendError (int chan, float error)
00701 {
00702     RESPONSE_CMD response;
00703     unsigned char *ptr = (unsigned char *)&response;
00704     int i;
00705 
00706     response.SOF_flag = TX_SOF;
00707     response.cmd_type = ERROR_DATA;
00708     response.len = 9;
00709     response.Delim = DELIMETER;
00710     response.data = (float)error;
00711     response.EOF_flag = TX_EOF;
00712 
00713     // Send response to GUI
00714     for (i=0; i < response.len; i++, ptr++)
00715         pc.printf("%02x", *ptr);
00716     pc.printf("\n");
00717 }
00718 
00719 /* Function: error_check
00720    **************************************************************
00721    Description: Checks for any system errors
00722    Recieves: frontTemp: temp. of front thermistor
00723              backTemp: temp. of back thermistor
00724              currTimeMin: currentTime in minutes
00725    Returns: N/A
00726 */
00727 
00728 void error_check(int chnl, float currentTempFront, float currentTempBack, int currTimeMin){
00729     if((currentTempFront >= MAX_TEMP) && (currentTempBack >= MAX_TEMP)){
00730         status_led(chnl, STATUS_BAD);
00731         sendError(chnl, 1);
00732         chnlStatus[chnl].error = 1;
00733         if(DEBUG3) pc.printf("DBG: [%d] ERROR 1 \r\n", chnl);
00734     }
00735     if(((currentTempFront == 0) || (currentTempBack == 0))){
00736         status_led(chnl, STATUS_BAD);
00737         sendError(chnl, 2);
00738         chnlStatus[chnl].error = 1;
00739         if(DEBUG3) pc.printf("DBG: [%d] ERROR 2 \r\n", chnl);
00740     }
00741     if((abs(currentTempBack - currentTempFront) >= TEMP_MARGIN)){
00742         status_led(chnl, STATUS_BAD);
00743         sendError(chnl, 3);
00744         chnlStatus[chnl].error = 1;
00745         if(DEBUG3) pc.printf("DBG: [%d] ERROR 3 \r\n", chnl);
00746     }
00747     if(((currentTempFront <= MIN_TEMP) && (currentTempBack <= MIN_TEMP))){
00748         status_led(chnl, STATUS_BAD);
00749         sendError(chnl, 4);
00750         chnlStatus[chnl].error = 1;
00751         if(DEBUG3) pc.printf("DBG: [%d] ERROR 4 \r\n", chnl);
00752     }
00753     if(chnlStatus[chnl].heater_init_time != 0){
00754         int init_time = chnlStatus[chnl].heater_init_time;
00755         int on_time_heater = currTimeMin - init_time;
00756         //account for 0 crossover
00757         if(init_time > currTimeMin){
00758             on_time_heater = (60 - init_time)+currTimeMin;
00759         }
00760 
00761         if(on_time_heater > MAX_HEATER_ON_TIME){
00762             status_led(chnl, STATUS_BAD);
00763             sendError(chnl, 5);
00764             chnlStatus[chnl].error = 1;
00765             chnlStatus[chnl].heater_init_time = 0;
00766             if(DEBUG3) pc.printf("DBG: [%d] ERROR 5 \r\n", chnl);
00767         }
00768     }
00769     if(chnlStatus[chnl].error == 1){
00770         status_led(chnl, STATUS_BAD);
00771         chnlStatus[chnl].error = 1;
00772     }
00773 }
00774 
00775 
00776 /*************************************************************/
00777 /*                       MAIN FUNCTION                       */
00778 /*************************************************************/
00779 
00780 int main() {
00781     //variables for controlling board
00782     Timer t;
00783     Timer t_cool;
00784     int time_min = 0;
00785     int init_heat_time = 0;
00786     uint32_t UIDMH, UIDML, UIDL;
00787 
00788     // Setup serial port
00789     // Look for RX_EOF
00790     pc.baud(9600);
00791     pc.autoDetectChar(RX_EOF);
00792     pc.attach(&rxInterrupt, MODSERIAL::RxAutoDetect);
00793 
00794     myled = 1;
00795     rLed = 1;
00796     gLed = 0;
00797 
00798     t.start();
00799 
00800     sendUID();
00801 
00802     UIDMH = (uint32_t)SIM->UIDMH;
00803     UIDML = (uint32_t)SIM->UIDML;
00804     UIDL = (uint32_t)SIM->UIDL;
00805 
00806     while(1) {
00807         //test_mcp23008(0);
00808         if(UID_PRINT) {
00809             pc.printf("DBG: <%f>[UID: %04X%08X%08X] PSTARTED\n", t.read(), UIDMH, UIDML, UIDL);
00810         }
00811 
00812         //SETUP TIMER USED TO TRACK HOW LONG THE HEATER IS ON
00813         float time_sec = t.read();
00814 
00815         if(time_sec >= 60){
00816             time_min++;
00817             //time_sec = 0;
00818             t.reset();
00819         }
00820 
00821         if(time_min >= 60){
00822            time_min = 0;
00823         }
00824         
00825         //GET TEMPERATURE DATA
00826         get_temp_data();
00827 
00828         //SEND TEMPERATURE DATA FOR LOGGING
00829         sendTempReadings();
00830         
00831         time_sec = t.read();
00832         if(LOOP_TIME) pc.printf("\r TIME: %f s\r\n", time_sec);
00833 
00834         //CONTROL LOOP: LOOPS THROUGH EVERY CHANNEL AND CONTROLS THE FIXTURE IN RESPONSE
00835         for(int chnl = 0; chnl < CHN_COUNT; chnl++){
00836 
00837             //check if we received data/need to update TCTF data
00838             if(dataReceived){
00839                 dataReceived = false;
00840 #ifdef DEBUG
00841                 pc.printf("DBG: %d bytes Rx'd\n", pc.rxBufferGetCount());
00842 #endif
00843                 pc.move(rxBuf, 50);
00844                 parseRXData();
00845                 pc.rxBufferFlush();
00846             }
00847 
00848             //update channel temperature data
00849             float currentTempFront = channelTempData[chnl].currTempFront;
00850             float currentTempBack = channelTempData[chnl].currTempBack;
00851             
00852             //float currentTempBack = get_temp(chnl, BACK_THERM);
00853             float currentTemp = currentTempBack;
00854 
00855             //Error check on fixture
00856             error_check(chnl, currentTempFront, currentTempBack, time_min);
00857 
00858             if(TEMP_PRINT) pc.printf("DBG: TEMPERATURE: [%d] Temp: F: %f B: %f\r\n", chnl, currentTempFront, currentTempBack);
00859             
00860             //CONTROL LOOP:
00861             if(chnlStatus[chnl].status == 1){
00862                 if(DEBUG) pc.printf("DBG: [%d] Temp: F: %f B: %f\r\n", chnl, currentTempFront, currentTempBack);
00863                 //main loop for channels
00864                 if(chnlStatus[chnl].error == 0){
00865                     if(currentTemp > ((chnlStatus[chnl].setTemp)+HYST_HIGH)){
00866                         if(DEBUG) pc.printf("DBG: [%d] Chiller ON \r\n", chnl);
00867                         //reset heater on time
00868                         chnlStatus[chnl].heater_init_time = 0;
00869                         //Turn chiller on
00870                         turn_valve_on(chnl);
00871                     }
00872                     else if (currentTemp < ((chnlStatus[chnl].setTemp)-HYST_LOW)){
00873                         if(DEBUG) pc.printf("DBG: [%d] Heater ON \r\n", chnl);
00874                         //establish starting time for heater
00875                         if(chnlStatus[chnl].heater_init_time == 0){ //check if it is the first time that heater has turned on
00876                             //make sure time isn't zero, otherwise keeping looping until we are not at 0
00877                             if(time_min != 0){
00878                                 chnlStatus[chnl].heater_init_time = time_min;
00879                             }
00880                         }
00881                         if(DEBUG2) pc.printf("DBG: TIME ON: %d %d %f %d %d\r\n", chnlStatus[chnl].heater_init_time, time_min, time_sec, init_heat_time, (chnlStatus[chnl].heater_init_time == NULL));
00882                         //Turn heater on
00883                         turn_heater_on(chnl);
00884                     }
00885                     else{
00886                         if(DEBUG) pc.printf("DBG: [%d] All OFF \r\n", chnl);
00887                         //reset heater on time
00888                         chnlStatus[chnl].heater_init_time = 0;
00889                         //turn off chiller
00890                         turn_valve_off(chnl);
00891                         //turn off heater
00892                         turn_heater_off(chnl);
00893                         //turn on green LED status light
00894                         status_led(chnl, 1);
00895                     }
00896                 }
00897             }
00898             else{
00899                 if(chnlStatus[chnl].error == 0){
00900                 //turn off chiller
00901                 turn_valve_off(chnl);
00902                 //turn off heater
00903                 turn_heater_off(chnl);
00904                 //turn on green LED status light
00905                 status_led(chnl, 1);
00906                 }
00907                 else{
00908                     status_led(chnl, STATUS_BAD);
00909                 }
00910                 //reset heater on time
00911                 chnlStatus[chnl].heater_init_time = 0;
00912             }
00913         }
00914     }
00915 }