Working on rewriting how we acquire data from LTC chip and sending all temp data over serial for python logging
Fork of TCTF_Control_Main by
main.cpp
- Committer:
- jrodenburg
- Date:
- 2018-03-20
- Revision:
- 7:8a5e65e63e2a
- Parent:
- 6:c980535393ed
- Child:
- 8:dbf8bd4815f8
File content as of revision 7:8a5e65e63e2a:
// MBED SCRIPT FOR CONTROLLING THE TEMPERATURE CONTROLLED TEST FIXTURE (TCTF) // DATE: SEPTEMBER 2017 #include "mbed.h" #include "MODSERIAL.h" #include "MCP23008.h"A #include "LTC2487.h" #include <string> //DEFINITIVE VARIABLES #define DEBUG 0 #define DEBUG1 1 #define DEBUG2 1 #define DEBUG3 1 #define CHN_COUNT 8 #define MIN_TEMP 15 #define MAX_TEMP 60 #define TEMP_MARGIN 5 #define HYST 0.3 #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 VALVE_FET_AMP 3 #define FET_ON_CURRENT 1.12 #define ROOM_TEMP 22 //TCTF CHANNEL DATA struct CHNL_DATA{ bool status; float setTemp; bool error; }; CHNL_DATA chnlStatus[] = { {1, 16, 0}, {1, 56, 0}, {1, 31, 0}, {1, 30, 0}, {1, 15, 0}, {1, 0, 0}, {1, 40, 0}, {1, 45, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, {0, NULL, 0}, }; //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, 400000); //sda, scl //I2C FOR LTC2487 (ADC Control) LTC2487 ltc2487(PTC11, PTC10, 0x23, 200000); //sda, scl //GLOBAL VARIABLES volatile bool dataRecieved = false; //used to check if data has been recieved char rxBuf[50]; int chnlSel; /* Function: turnOffChannel ************************************************************** Description: Turns off a channel Recieves: chnl: channel to turn off Returns: N/A */ void turnOffChannel(int chnl){ io_control.setAddress(addrLUT[chnl].io); io_control.init(); io_control.writeOutput(0,0,0,0); } /* 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 //IF CHANNEL IS TURNED OFF, TURN THE STATUS OFF FIRST! chnlStatus[chnl].status = atoi(data.c_str()); if(chnlStatus[chnl].status == 0) turnOffChannel(chnl); 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 port: the I/O channel to read Returns: the temperature of the fixture (front or back) */ float get_temp(int chn, int port){ myled = 1; ltc2487.setAddress(addrLUT[chn].adc); float ADC_val = ltc2487.readOutput(port); //(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(DEBUG2) pc.printf("CHNL: %i PORT: %i ADC VAL: %f TEMP: %f \r\n", chn, port, 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, int port){ return ltc2487.readOutput(port); } /* 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, int port){ return ltc2487.readOutput(port); } /* 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(0.5); turn_valve_off(chn); wait(0.5); turn_heater_on(chn); wait(0.5); turn_heater_off(chn); wait(0.5); status_led(chn, 0); wait(0.5); 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, FRONT_THERM); wait(0.1); get_temp(chn, BACK_THERM); wait(0.1); //get_temp(chn, VALV_FET_AMP); //wait(0.1); //if(DEBUG1) pc.printf("TEMPERATURE READING: %f \r\n", get_temp(chn)); } /* Function: error_check ************************************************************** Description: Checks for any system errors Recieves: frontTemp: temp. of front thermistor backTemp: temp. of back thermistor valveFet: current through valve FET heaterFet: current through heater FET Returns: N/A */ void error_check(int chn, float frontTemp, float backTemp, float valveFet, float heaterFet){ float setTemp = chnlStatus[chn].setTemp; //CHECK IF THERMISTOR READINGS ARE OFF (> 5 DEGREES) if(abs(frontTemp-backTemp) > 5){ //ERROR 6: Thermistor reading off chnlStatus[chn].error = 1; } //CHECK IF HEATER'S STUCK ON OR CELL OVERHEATING if((frontTemp >= (setTemp+TEMP_MARGIN)) || (backTemp >= (setTemp+TEMP_MARGIN))){ //ERROR 0 chnlStatus[chn].error = 1; status_led(chn, STATUS_BAD); if(heaterFet >= FET_ON_CURRENT){ //ERROR 1: Heater FET stuck on } if(valveFet <= FET_ON_CURRENT){ //ERROR 2: valve FET stuck off } } //CHECK IF VALVE STUCK ON OR CELL OVERHEATING if((frontTemp <= (setTemp-TEMP_MARGIN)) || (backTemp <= (setTemp-TEMP_MARGIN))){ //ERROR 0 chnlStatus[chn].error = 1; status_led(chn, STATUS_BAD); if(heaterFet <= FET_ON_CURRENT){ //ERROR 2: Heater FET stuck off } else if(valveFet >= FET_ON_CURRENT){ //ERROR 3: Chiller FET stuck on } } } /*************************************************************/ /* MAIN FUNCTION */ /*************************************************************/ int main() { //pc.baud(9600); //pc.autoDetectChar('E'); //pc.attach(&rxInterrupt, MODSERIAL::RxAutoDetect); myled = 1; //FRONT_THERM, BACK_THERM, HEAT_FET_AMP, VALV_FET_AMP while(1) { //test_all_IO(); if(DEBUG3) 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 currentTempFront = get_temp(chnl, FRONT_THERM); float currentTempBack = get_temp(chnl, BACK_THERM); float valveCurrent = get_valve_current(chnl, VALVE_FET_AMP); float heaterCurrent = get_heater_current(chnl, HEAT_FET_AMP); float currentTemp = (currentTempFront + currentTempBack)/2; //CONTROL LOOP: if(chnlStatus[chnl].status == 1){ if(DEBUG3) pc.printf("TEMP: %f \r\n", currentTempFront); //Error check on fixture error_check(chnl, currentTempFront, currentTempBack, valveCurrent, heaterCurrent); if(chnlStatus[chnl].error == 0){ if((currentTemp > ((chnlStatus[chnl].setTemp)+HYST))){ if(DEBUG3) pc.printf("CHILLER ON \r\n"); //Turn chiller on turn_valve_on(chnl); } else if (currentTemp < ((chnlStatus[chnl].setTemp)-HYST)){ if(DEBUG3) pc.printf("HEATER ON \r\n"); //Turn heater on turn_heater_on(chnl); } else{ if(DEBUG3) pc.printf("ALL OFF \r\n"); //turn off chiller turn_valve_off(chnl); //turn off heater turn_heater_off(chnl); //turn on green LED status light status_led(chnl, 1); } } } } } }