Rivian Irvine Team
/
TCTF_Control_Main
Control Code with I/O and ADC working
Diff: main.cpp
- Revision:
- 20:cdeed4dad690
- Parent:
- 19:0946665b37c7
- Child:
- 21:f87464a7e7c6
diff -r 0946665b37c7 -r cdeed4dad690 main.cpp --- a/main.cpp Thu Jun 28 21:30:44 2018 +0000 +++ b/main.cpp Mon Jul 16 03:53:59 2018 +0000 @@ -1,34 +1,44 @@ // MBED SCRIPT FOR CONTROLLING THE TEMPERATURE CONTROLLED TEST FIXTURE (TCTF) // DATE: SEPTEMBER 2017 -#define FW_VERSION "V.010" #include "mbed.h" #include "MODSERIAL.h" #include "MCP23008.h" #include "LTC2487.h" #include <string> + //DEFINITIVE VARIABLES -#define DEBUG 0 -#define DEBUG1 0 -#define DEBUG2 0 -#define DEBUG3 0 -#define DEBUG5 0 -#define UID_PRINT 0 -#define TEMP_PRINT 1 -#define LOOP_TIME 0 -#define CHN_COUNT 8 +#define DEBUG_LOOP_TIME 0x00000001 +#define RXDATA_PRINT 0x00000002 +#define UID_PRINT 0x00000004 +#define ERROR_PRINT 0x00000008 +#define ADC_VAL_PRINT 0x00000010 +#define HEATER_CHILLER_PRINT 0x00000020 +#define HEATER_ON_TIME_PRINT 0x00000040 +#define LED_PRINT 0x00000080 +#define TEMP_PRINT 0x00000100 +#define I2C_PRINT 0x00000200 + +#define IO_I2C_LINE 1 +#define ADC_I2C_LINE 2 + + +#define CHAN_COUNT 8 #define MIN_TEMP 10 #define MAX_TEMP 65 -#define TEMP_MARGIN 20 +#define MEGA_MAX_TEMP 75 +#define TEMP_MARGIN 10 #define HYST_LOW 0.3 #define HYST_HIGH 1 #define SAMPLES 5 #define I2C_Freq 2000 #define VALVE 1 #define HEATER 2 -#define STATUS_GOOD 3 -#define STATUS_BAD 0 +#define GREEN_STATUS_ON 3 +#define RED_STATUS_ON 0 +#define ERROR_STATUS_ON 1 +#define STATUS_OFF 4 #define sizeLUT 34 #define BACK_THERM 0 #define FRONT_THERM 1 @@ -38,6 +48,17 @@ #define ROOM_TEMP 22 #define MAX_HEATER_ON_TIME 25 #define MAX_CHILL_TIME 10 //10sec +#define MIN_ERROR_CNT_1 4 //ALL SAFETY RELATEDD CHECKS +#define MIN_ERROR_CNT_2 600 //PEFORMANCE TIME (HAVE TO GIVE FIXTURE TIME TO SETTLE) +#define MIN_ERROR_CNT_3 60 +#define NUM_EMAIL_SEND 2 +#define STATUS_COOLING 1 +#define STATUS_HEATING 2 +#define STATUS_INACTIVE 3 +#define STATUS_STANDBY 4 + +#define READ_TEMP_TASK_TIME .300f //300ms to read one A/D value +#define I2C_READ_WAIT_TIME 0.08f // Defines for use with Serial communication #pragma pack (1) @@ -49,18 +70,52 @@ #define SET_TEMPERATURE 0xB0 #define SELECT_CHANNEL 0xB1 #define READ_UID 0xB2 +#define READ_FW_VERSION 0xB3 +#define DEBUG_CONTROL 0xB4 #define RESPONSE_DATA 0xD0 #define TEMP_DATA 0xD1 #define UID_DATA 0xD2 +#define FW_VERSION_DATA 0xD3 #define ERROR_DATA 0xDF +const char FW_Version[8] = "V0.01C"; unsigned int chanSel_SendTemp = 0; unsigned int chanSel_SetTemp = 0; // Default to chan 0 int currChan = 0; bool newTempSet = false; +bool readFrontThermistor = true; +bool newTempData = false; +bool newTempDataAvailable = false; +unsigned int UID_print_count = 0; +unsigned int debug_control = 0x2; +//*********************************************** +// Timers +//*********************************************** +Ticker frontTempDoneTicker; +Ticker backTempDoneTicker; +Ticker readThermistorTicker; +Ticker frontTempInProgTicker; +Ticker backTempInProgTicker; + +//*********************************************** +// LEDs +//*********************************************** +DigitalOut rLed(LED1); +DigitalOut gLed(LED2); + +//*********************************************** +// Functions Declarations +//*********************************************** +void sendUID (); +void sendFWVersion(); +void read_front_temp(); +void read_back_temp(); +void update_front_temp_data(); +void update_back_temp_data(); +void temperatureDataReady(); //*********************************************** // Serial Rx Packet Format @@ -93,6 +148,7 @@ unsigned char cmd_type; unsigned char len; unsigned char Delim; + uint32_t channel; float data; unsigned char EOF_flag; } RESPONSE_CMD; @@ -102,7 +158,7 @@ unsigned char cmd_type; unsigned char len; unsigned char Delim; - float chTemp[CHN_COUNT]; + float chTemp[CHAN_COUNT]; unsigned char EOF_flag; } RESPONSE_TEMP_CMD; @@ -114,6 +170,22 @@ } READ_UID_CMD; typedef struct { + HOST_CMD_HEADER cmd_header; + unsigned char chanIDSel; + unsigned char chanDelim; + uint32_t commandData; +} GUI_STANDARD_CMD; + +typedef struct { + unsigned char SOF_flag; + unsigned char cmd_type; + unsigned char len; + unsigned char Delim; + unsigned char FW_Version[8]; + unsigned char EOF_flag; +} FW_VERSION_RESPONSE; + +typedef struct { unsigned char SOF_flag; unsigned char cmd_type; unsigned char len; @@ -128,59 +200,21 @@ struct CHNL_DATA{ bool status; float setTemp; - bool error; - int heater_init_time; + int error; + int state; + int errorEmailSent; + int i2cRxed; }; CHNL_DATA chnlStatus[] = { - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, - {0, NULL, 0, 0}, + {0, NULL, 0, 0, 0, 1}, + {0, NULL, 0, 0, 0, 1}, + {0, NULL, 0, 0, 0, 1}, + {0, NULL, 0, 0, 0, 1}, + {0, NULL, 0, 0, 0, 1}, + {0, NULL, 0, 0, 0, 1}, + {0, NULL, 0, 0, 0, 1}, + {0, NULL, 0, 0, 0, 1} }; @@ -198,47 +232,7 @@ {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}, + {0x42, 0x71} }; //THERMISTOR LOOK UP TABLE, CREATED IN EXCEL SHEET (COUNT, TEMP) @@ -284,13 +278,15 @@ {2284,125} }; + + //TCTF CHANNEL TEMPERATURE typedef struct{ float currTempFront; float currTempBack; }CHNL_TEMP; -CHNL_TEMP channelTempData[CHN_COUNT]; +CHNL_TEMP channelTempData[CHAN_COUNT]; //SERIAL COMMUNICATION SETUP MODSERIAL pc(USBTX, USBRX); @@ -309,7 +305,7 @@ volatile bool dataTxReady = false; char rxBuf[50]; int chnlSel; - +bool standbyLED[CHAN_COUNT] = {false,false,false,false,false,false,false,false}; /* Function: turnOffChannel ************************************************************** @@ -332,11 +328,6 @@ Returns: N/A */ -DigitalOut rLed(LED1); -DigitalOut gLed(LED2); - -void sendUID (); - //*********************************************** // Rx Interrupt from serial Host interface //*********************************************** @@ -344,6 +335,7 @@ { gLed = 0; dataReceived = true; + //wait(.5); gLed = 1; } @@ -353,7 +345,9 @@ //*************************************************************** void txInterrupt(MODSERIAL_IRQ_INFO *info) { + gLed = 1; dataTxReady = true; + gLed = 1; } @@ -363,19 +357,20 @@ Receives: chn: The channel we want to put into the channel Returns: N/A */ - -void parseRXData() +void processRxUARTData() { HOST_CMD_HEADER *pRxPktHdr; string data = ""; - unsigned char *ptemp; - int i; pRxPktHdr = (HOST_CMD_HEADER *)rxBuf; -#ifdef DEBUG - pc.printf("DBG: fl=%02x, len=%02x\n", pRxPktHdr->SOF_flag, pRxPktHdr->len); -#endif + if (debug_control & RXDATA_PRINT) { + pc.printf("DBG: SOF=%02x, Len=%02x, CMD=%02x\r\n", pRxPktHdr->SOF_flag, pRxPktHdr->len, pRxPktHdr->cmd_type); + pc.printf("DBG: "); + for (int i=0; i <5; i++) + pc.printf("%02x ", rxBuf[i]); + pc.printf("\n"); + } // Exit if the packet does not contain correct header // Maybe send NAK? @@ -388,10 +383,11 @@ // Process set temp for specified channel { SET_TEMPERATURE_CMD *pRxPkt = (SET_TEMPERATURE_CMD *)(rxBuf); -#ifdef DEBUG - pc.printf("DBG: SETTEMP: ch = %02x, tempSet = %f, chanStat = %02x\n", - pRxPkt->chanID, pRxPkt->setTemp, pRxPkt->chanStat); -#endif + + if (debug_control & RXDATA_PRINT) + pc.printf("DBG: SETTEMP: ch = %02x, tempSet = %f, chanStat = %02x\r\n", + pRxPkt->chanID, pRxPkt->setTemp, pRxPkt->chanStat); + if ((pRxPkt->tempDelim != DELIMETER) || (pRxPkt->chanStatDelim != DELIMETER)) { // Send NAK back pc.printf("DBG: Error\n"); @@ -399,9 +395,11 @@ else { chanSel_SetTemp = pRxPkt->chanID; chnlStatus[pRxPkt->chanID].status = pRxPkt->chanStat; + chnlStatus[pRxPkt->chanID].state = STATUS_INACTIVE; chnlStatus[pRxPkt->chanID].setTemp = pRxPkt->setTemp; chnlStatus[pRxPkt->chanID].error = 0; - chnlStatus[pRxPkt->chanID].heater_init_time = 0; + chnlStatus[pRxPkt->chanID].errorEmailSent = 0; + chnlStatus[pRxPkt->chanID].i2cRxed = 0; newTempSet = true; } } @@ -413,22 +411,44 @@ SELECT_CHANNEL_CMD *pRxPkt = (SELECT_CHANNEL_CMD *)(rxBuf); chanSel_SendTemp = pRxPkt->chanIDSel; -#ifdef DEBUG - pc.printf("DBG: CHAN_SEL: chan=%02x, chanStat = %02x\n", pRxPkt->chanIDSel, pRxPkt->chanStat); -#endif + + // Send back FW version for each select channel + sendFWVersion(); + if (debug_control & RXDATA_PRINT) + pc.printf("DBG: CHAN_SEL: chan=%02x, chanStat = %02x\r\n", pRxPkt->chanIDSel, pRxPkt->chanStat); + } break; case READ_UID: { READ_UID_CMD *pRxPkt = (READ_UID_CMD *)(rxBuf); -#ifdef DEBUG - pc.printf("DBG: Read UID: chan%02x\n", pRxPkt->chanIDSel); -#endif + if (debug_control & RXDATA_PRINT) + pc.printf("DBG: Read UID: chan%02x\n", pRxPkt->chanIDSel); + sendUID(); } break; + case READ_FW_VERSION: + { + sendFWVersion(); + if (debug_control & RXDATA_PRINT) + pc.printf("DBG: Read SW Version\r\n"); + + } + break; + + case DEBUG_CONTROL: + { + GUI_STANDARD_CMD *pRxPkt = (GUI_STANDARD_CMD *)rxBuf; + debug_control = pRxPkt->commandData; + if (debug_control & RXDATA_PRINT) + pc.printf ("DBG: Rx'd DEBUG CMD: %04x\r\n", pRxPkt->commandData); + } + break; + + default: // Error break; @@ -439,7 +459,7 @@ ************************************************************** Description: Convert A/D count to temperature value Receives: ADC_val: the count from the A/D reading - Returns: the temp. of the A/D reading + Returns: the temp. of the A/D reading */ float get_temp(float ADC_val){ @@ -464,42 +484,96 @@ float m = a/b; float y = (m*(ADC_val-thermLUT[i].adc))+thermLUT[i].temp; - if(DEBUG3) pc.printf("DBG: ADC VAL: %f TEMP: %f \r\n", ADC_val, y); + if (debug_control & ADC_VAL_PRINT) + pc.printf("DBG: ADC VAL: %f TEMP: %f \r\n", ADC_val, y); return y; } -/* Function: get_temp_DATA +/* Function: get_front_temp_DATA ************************************************************** - Description: Read A/D data from LTC2487 and set array with front and back temp. + Description: Read A/D data from LTC2487 and set array with front temp. + Save values in CHNL_TEMP data struct + Receives: N/A + Returns: int If the write recieved an ACK +*/ +void read_front_temp_data() +{ + readThermistorTicker.detach(); + //Write to all 8 channels selecting the front port to read + for(int chnl = 0; chnl < CHAN_COUNT; chnl++){ + chnlStatus[chnl].i2cRxed = 0; + ltc2487.setAddress(addrLUT[chnl].adc); + //Check if write was ack'ed (0 = ACK, (non)0 = NACK) + chnlStatus[chnl].i2cRxed = !ltc2487.writePort(FRONT_THERM); + } + //wait until next clock cycle on LTC + //wait(I2C_READ_WAIT_TIME); + frontTempInProgTicker.attach(&update_front_temp_data, I2C_READ_WAIT_TIME); +} + +void update_front_temp_data() +{ + frontTempInProgTicker.detach(); + for(int chnl = 0; chnl < CHAN_COUNT; chnl++){ + ltc2487.setAddress(addrLUT[chnl].adc); + channelTempData[chnl].currTempFront = get_temp(ltc2487.read()); + } + //wait until next clock cycle on LTC + //wait(0.08); + frontTempDoneTicker.attach(&read_back_temp, I2C_READ_WAIT_TIME); +} + +/* Function: get_back_temp_DATA + ************************************************************** + Description: Read A/D data from LTC2487 and set array with back temp. + Save values in CHNL_TEMP data struct Receives: N/A Returns: N/A */ -void get_temp_data(){ +void read_back_temp() +{ + frontTempDoneTicker.detach(); //Write to all 8 channels selecting the front port to read - for(int chnl = 0; chnl < CHN_COUNT; chnl++){ - ltc2487.setAddress(addrLUT[chnl].adc); - ltc2487.writePort(FRONT_THERM); - } - //wait until next clock cycle on LTC - wait(0.08); - for(int chnl = 0; chnl < CHN_COUNT; chnl++){ + for(int chnl = 0; chnl < CHAN_COUNT; chnl++){ + chnlStatus[chnl].i2cRxed = 0; ltc2487.setAddress(addrLUT[chnl].adc); - channelTempData[chnl].currTempFront = get_temp(ltc2487.read()); + //Check if write was ack'ed (0 = ACK, (non)0 = NACK) + chnlStatus[chnl].i2cRxed = !ltc2487.writePort(BACK_THERM); } + //wait until next clock cycle on LTC - wait(0.08); - for(int chnl = 0; chnl < CHN_COUNT; chnl++){ - ltc2487.setAddress(addrLUT[chnl].adc); - ltc2487.writePort(BACK_THERM); - } - //wait until next clock cycle on LTC - wait(0.08); - for(int chnl = 0; chnl < CHN_COUNT; chnl++){ + //wait(I2C_READ_WAIT_TIME); + backTempInProgTicker.attach(&update_back_temp_data, I2C_READ_WAIT_TIME); +} + +void update_back_temp_data() +{ + backTempInProgTicker.detach(); + for(int chnl = 0; chnl < CHAN_COUNT; chnl++){ ltc2487.setAddress(addrLUT[chnl].adc); channelTempData[chnl].currTempBack = get_temp(ltc2487.read()); } + //wait until next clock cycle on LTC + //wait(0.08); + backTempDoneTicker.attach(&temperatureDataReady, I2C_READ_WAIT_TIME); + +} + +/* Function: temperatureDataReady + ************************************************************** + Description: Flag that temperature data is ready to be + processed + Restart task timer + Receives: N/A + Returns: N/A +*/ +void temperatureDataReady() +{ + backTempDoneTicker.detach(); + newTempDataAvailable = true; + readThermistorTicker.attach(&read_front_temp_data, READ_TEMP_TASK_TIME); } /* Function: get_heater_current @@ -508,8 +582,7 @@ Receives: 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){ +void get_heater_current(int chn, int port){ ltc2487.setAddress(addrLUT[chn].adc); ltc2487.writePort(HEAT_FET_AMP); wait(0.08); @@ -524,7 +597,7 @@ Returns: the current into the valve control MOSFET */ -float get_valve_current(int chn, int port){ +void get_valve_current(int chn, int port){ ltc2487.setAddress(addrLUT[chn].adc); ltc2487.writePort(VALVE_FET_AMP); wait(0.08); @@ -593,14 +666,34 @@ */ void status_led(int chn, int status){ - io_control.setAddress(addrLUT[chn].io); - if(status){ + if(status == GREEN_STATUS_ON){ + //green LED + if(debug_control & LED_PRINT) pc.printf("GREEN LED %d \r\n", chn); + io_control.setAddress(addrLUT[chn].io); + io_control.init(); io_control.writeOutput(0,0,1,0); } - else{ + if(status == RED_STATUS_ON){ + //red LED + if(debug_control & LED_PRINT) pc.printf("RED LED %d \r\n", chn); + io_control.setAddress(addrLUT[chn].io); + io_control.init(); + io_control.writeOutput(0,0,0,1); + } + if(status == ERROR_STATUS_ON){ //turn valve on too + if(debug_control & LED_PRINT) pc.printf("RED AND BLUE LED %d \r\n", chn); + io_control.setAddress(addrLUT[chn].io); + io_control.init(); io_control.writeOutput(1,0,0,1); } + if(status == STATUS_OFF){ + //turn valve on too + if(debug_control & LED_PRINT) pc.printf("ALL OFF %d \r\n", chn); + io_control.setAddress(addrLUT[chn].io); + io_control.init(); + io_control.writeOutput(0,0,0,0); + } } /* Function: test_mcp23008 @@ -632,7 +725,7 @@ */ void test_ltc2487(){ - for(int chnl = 0; chnl < CHN_COUNT; chnl++){ + for(int chnl = 0; chnl < CHAN_COUNT; chnl++){ float frontTemp = channelTempData[chnl].currTempFront; float backTemp = channelTempData[chnl].currTempBack; pc.printf("TEMPERATURE READING [%i]:: BACK: %f FRONT: %f \r\n", chnl, backTemp, frontTemp); @@ -642,7 +735,8 @@ //*************************************************************** // Build packet with temperature readings to send to GUI //*************************************************************** -void sendTempReadings(){ +void processTxUARTData() +{ RESPONSE_TEMP_CMD response; unsigned char *ptr = (unsigned char *)&response; int i; @@ -659,6 +753,9 @@ response.chTemp[5] = channelTempData[5].currTempBack; response.chTemp[6] = channelTempData[6].currTempBack; response.chTemp[7] = channelTempData[7].currTempBack; + + // Send Errors Count/Info + /*float *dst = (float *)&response.chTemp[0]; float *src = (float *)&channelTempData[0]; memcpy(dst, src, sizeof(channelTempData));*/ @@ -695,6 +792,35 @@ } //*************************************************************** +// Build packet with SW Version +//*************************************************************** +void sendFWVersion() +{ + FW_VERSION_RESPONSE response; + unsigned char *ptr = (unsigned char *)&response; + int i; + rLed = 1; + + for (i=0; i < 20; i++) + rLed = 0; + + rLed = 1; + + response.SOF_flag = TX_SOF; + response.cmd_type = FW_VERSION_DATA; + response.len = 13; + response.Delim = DELIMETER; + memcpy(response.FW_Version, FW_Version, 8); + response.FW_Version[7] = '\0'; + response.EOF_flag = TX_EOF; + + // Send response to GUI + for (i=0; i < response.len; i++, ptr++) + pc.printf("%02x", *ptr); + pc.printf("\n"); +} + +//*************************************************************** // Build packet with errors to send to GUI //*************************************************************** void sendError (int chan, float error) @@ -703,17 +829,101 @@ unsigned char *ptr = (unsigned char *)&response; int i; + if(chnlStatus[chan].errorEmailSent >= NUM_EMAIL_SEND) + return; + response.SOF_flag = TX_SOF; response.cmd_type = ERROR_DATA; - response.len = 9; + response.len = 13; response.Delim = DELIMETER; + response.channel = chan; response.data = (float)error; + response.EOF_flag = TX_EOF; // Send response to GUI for (i=0; i < response.len; i++, ptr++) pc.printf("%02x", *ptr); pc.printf("\n"); + + chnlStatus[chan].errorEmailSent++; +} + +/* Function: toggleI2C + ************************************************************** + Description: Toggle the I2C line in an attempt to unfreeze it + Receives: N/A + Returns: N/A +*/ + +void toggleI2C(){ + DigitalOut ioSDAIn(PTC9); + DigitalOut adcSDAIn(PTC11); + DigitalOut ioSCLIn(PTC8); + DigitalOut adcSCLIn(PTC10); + + ioSDAIn = 1; + adcSDAIn = 1; + ioSCLIn = 1; + adcSCLIn = 1; + wait(0.5); + ioSDAIn = 0; + adcSDAIn = 0; + ioSCLIn = 0; + adcSCLIn = 0; + wait(0.5); + ioSDAIn = 1; + adcSDAIn = 1; + ioSCLIn = 1; + adcSCLIn = 1; + wait(0.5); + ioSDAIn = 0; + adcSDAIn = 0; + ioSCLIn = 0; + adcSCLIn = 0; + wait(0.5); + + MCP23008 io_control(PTC9, PTC8, 0x10, 100000); //sda, scl + LTC2487 ltc2487(PTC11, PTC10, 0x23, 100000); //sda, scl + +} + +/* Function: softwareReset + ************************************************************** + Description: soft Reset + Recieves: N/A + Returns: N/A +*/ + +void softwareReset(void){ + SCB->AIRCR = (0x5FA<<SCB_AIRCR_VECTKEY_Pos)|SCB_AIRCR_SYSRESETREQ_Msk; + for(;;){} +} + +/* Function: read I2C Line + ************************************************************** + Description: Read the I2C line to check if pulled high + Receives: N/A + Returns: N/A +*/ + +int readI2CLine(int line) +{ + if(line == IO_I2C_LINE){ + DigitalIn ioSDAIn(PTC9); + int ioSDA = ioSDAIn.read(); + if(I2C_PRINT) pc.printf("DBG: TEMPERATURE SDA LINE: %d \r\n", ioSDA); + MCP23008 io_control(PTC9, PTC8, 0x10, 100000); //sda, scl + return ioSDA; + } + if(line == ADC_I2C_LINE){ + DigitalIn adcSDAIn(PTC11); + int adcSDA = adcSDAIn.read(); + if(I2C_PRINT) pc.printf("DBG: IO SDA LINE: %d \r\n", adcSDA); + LTC2487 ltc2487(PTC11, PTC10, 0x23, 100000); //sda, scl + return adcSDA; + } + return 0; } /* Function: error_check @@ -722,213 +932,260 @@ Recieves: frontTemp: temp. of front thermistor backTemp: temp. of back thermistor currTimeMin: currentTime in minutes + ioSDA: voltage on the SDA line + adcSDA: voltage on the SDA line Returns: N/A */ -void error_check(int chnl, float currentTempFront, float currentTempBack, int currTimeMin, int ioSDA, int adcSDA){ - if((currentTempFront >= MAX_TEMP) && (currentTempBack >= MAX_TEMP)){ - status_led(chnl, STATUS_BAD); - sendError(chnl, 1); - chnlStatus[chnl].error = 1; - if(DEBUG3) pc.printf("DBG: [%d] ERROR 1 \r\n", chnl); +int error_check(int chnl, float currentTempFront, float currentTempBack, int currTimeMin, int ioSDA, int adcSDA){ + //check if the thermistors are disconnected + if((currentTempFront == 0) || (currentTempBack == 0)){ + if(chnlStatus[chnl].error >= MIN_ERROR_CNT_1){ + sendError(chnl, 2); + status_led(chnl, RED_STATUS_ON); + } + else{ + chnlStatus[chnl].error++; + } + if(debug_control & ERROR_PRINT) pc.printf("DBG: [%d] ERROR 2 \r\n", chnl); + return 1; + } + //check if the channels are disconnected + if(currentTempBack == currentTempFront){ + if(chnlStatus[chnl].error >= MIN_ERROR_CNT_1){ + sendError(chnl, 8); + status_led(chnl, RED_STATUS_ON); + } + else{ + chnlStatus[chnl].error++; + } + if(debug_control & ERROR_PRINT) pc.printf("DBG: [%d] ERROR 2A \r\n", chnl); + return 1; } - if(((currentTempFront == 0) || (currentTempBack == 0))){ - status_led(chnl, STATUS_BAD); - sendError(chnl, 2); - chnlStatus[chnl].error = 1; - if(DEBUG3) pc.printf("DBG: [%d] ERROR 2 \r\n", chnl); + + //check if there is a temperature difference |b| front and back + if((abs(currentTempBack - currentTempFront) >= TEMP_MARGIN)){ + if(chnlStatus[chnl].error >= MIN_ERROR_CNT_2){ + sendError(chnl, 3); + status_led(chnl, RED_STATUS_ON); + } + else{ + chnlStatus[chnl].error++; + } + if(debug_control & ERROR_PRINT) pc.printf("DBG: [%d] ERROR 3 \r\n", chnl); + return 1; } - if((abs(currentTempBack - currentTempFront) >= TEMP_MARGIN)){ - status_led(chnl, STATUS_BAD); - sendError(chnl, 3); - chnlStatus[chnl].error = 1; - if(DEBUG3) pc.printf("DBG: [%d] ERROR 3 \r\n", chnl); + //check if channels are over the MAX temperature + if((currentTempFront >= MAX_TEMP) || (currentTempBack >= MAX_TEMP)){ + //if fixture over 65C for more than ~60s + if(chnlStatus[chnl].error >= MIN_ERROR_CNT_3){ + sendError(chnl, 1); + status_led(chnl, RED_STATUS_ON); + if(debug_control & ERROR_PRINT) pc.printf("DBG: [%d] ERROR 1 SOFTWARE RESET %d \r\n", chnl, chnlStatus[chnl].error); + softwareReset(); + } + //if fixture over 65C for more than ~1s + else if(chnlStatus[chnl].error >= MIN_ERROR_CNT_1){ + sendError(chnl, 1); + status_led(chnl, RED_STATUS_ON); + if(debug_control & ERROR_PRINT) pc.printf("DBG: [%d] ERROR 1.9 SOFTWARE RESET %d \r\n", chnl, chnlStatus[chnl].error); + chnlStatus[chnl].error++; + } + else{ + chnlStatus[chnl].error++; + } + if(debug_control & ERROR_PRINT) pc.printf("DBG: [%d] ERROR 1 \r\n", chnl); + return 1; } + //check if the valves are stuck open if(((currentTempFront <= MIN_TEMP) && (currentTempBack <= MIN_TEMP))){ - status_led(chnl, STATUS_BAD); - sendError(chnl, 4); - chnlStatus[chnl].error = 1; - if(DEBUG3) pc.printf("DBG: [%d] ERROR 4 \r\n", chnl); + if(chnlStatus[chnl].error >= MIN_ERROR_CNT_1){ + sendError(chnl, 4); + status_led(chnl, RED_STATUS_ON ); + } + else{ + chnlStatus[chnl].error++; + } + if(debug_control & ERROR_PRINT) pc.printf("DBG: [%d] ERROR 4 \r\n", chnl); + return 1; } - if(chnlStatus[chnl].heater_init_time != 0){ - int init_time = chnlStatus[chnl].heater_init_time; - int on_time_heater = currTimeMin - init_time; - //account for 0 crossover - if(init_time > currTimeMin){ - on_time_heater = (60 - init_time)+currTimeMin; - } - if(on_time_heater > MAX_HEATER_ON_TIME){ - status_led(chnl, STATUS_BAD); - sendError(chnl, 5); - chnlStatus[chnl].error = 1; - chnlStatus[chnl].heater_init_time = 0; - if(DEBUG3) pc.printf("DBG: [%d] ERROR 5 \r\n", chnl); - } - } //check that the SDA lines aren't stuck low if((ioSDA != 1) || (adcSDA != 1)){ - status_led(chnl, STATUS_BAD); - sendError(chnl, 6); - chnlStatus[chnl].error = 1; - chnlStatus[chnl].heater_init_time = 0; - if(DEBUG3) pc.printf("DBG: [%d] ERROR 6 \r\n", chnl); - } - if(chnlStatus[chnl].error == 1){ - status_led(chnl, STATUS_BAD); - chnlStatus[chnl].error = 1; + if(chnlStatus[chnl].error >= MIN_ERROR_CNT_1){ + sendError(chnl, 6); + status_led(chnl, RED_STATUS_ON ); + softwareReset(); + } + else{ + toggleI2C(); + chnlStatus[chnl].error++; + } + if(debug_control & ERROR_PRINT) pc.printf("DBG: [%d] ERROR 6 \r\n", chnl); + return 1; } - + //no errors + return 0; } +/* Function: systemLogic + ************************************************************** + Description: Checks for any system errors + Receives: Channel to modify + Returns: N/A +*/ + +void systemLogic(){ + int chan; + float currTemp; + + for (chan=0; chan < CHAN_COUNT; chan++) + { + if(chnlStatus[chan].status == 1){ + //Current Temperature + currTemp = channelTempData[chan].currTempBack; + + if(currTemp > ((chnlStatus[chan].setTemp)+HYST_HIGH)){ + //TURN COOLING ON + chnlStatus[chan].state = STATUS_COOLING; + } + else if(currTemp < ((chnlStatus[chan].setTemp)-HYST_LOW)){ + //TURN HEATER ON + chnlStatus[chan].state = STATUS_HEATING; + } + else{ + //FIXTURE INACTIVE + chnlStatus[chan].state = STATUS_INACTIVE; + } + } + else{ + //FIXTURE STANDBY + chnlStatus[chan].state = STATUS_STANDBY; + } + } + +} + +/* Function: systemControl + ************************************************************** + Description: Checks for any system errors + Receives: chn: Channel to modify + Returns: N/A +*/ + +void systemControl() +{ + int chan; + + for (chan=0; chan < CHAN_COUNT; chan++){ + if(chnlStatus[chan].status == 1){ + if(chnlStatus[chan].state == STATUS_COOLING){ + //TURN COOLING ON + turn_valve_on(chan); + } + else if(chnlStatus[chan].state == STATUS_HEATING){ + //TURN HEATER ON + turn_heater_off(chan); + turn_heater_on(chan); + } + else{ + //FIXTURE INACTIVE + status_led(chan, GREEN_STATUS_ON ); + } + } + else + { + //FIXTURE INACTIVE + if(standbyLED[chan]){ + status_led(chan, GREEN_STATUS_ON); + standbyLED[chan] = !standbyLED[chan]; + } + else{ + status_led(chan, STATUS_OFF); + standbyLED[chan] = !standbyLED[chan]; + } + } + } +} + +void systemDiagnostic() +{ +} + /*************************************************************/ -/* MAIN FUNCTION */ +/* NEW MAIN FUNCTION */ /*************************************************************/ -int main() { - //variables for controlling board - Timer t; - Timer t_cool; - int time_min = 0; - int init_heat_time = 0; - uint32_t UIDMH, UIDML, UIDL; - +int main(){ + /* INITIALIZATION CODE */ // Setup serial port // Look for RX_EOF + uint32_t UIDMH, UIDML, UIDL; + int UID_print_count = 0; + + + //********************************* + // Initial thermistors readings + // Kick off temperature reding + // state machine + //********************************* + readThermistorTicker.attach(&read_front_temp_data, .0001); + pc.baud(9600); pc.autoDetectChar(RX_EOF); pc.attach(&rxInterrupt, MODSERIAL::RxAutoDetect); - myled = 1; - rLed = 1; - gLed = 0; - - t.start(); - - sendUID(); - UIDMH = (uint32_t)SIM->UIDMH; UIDML = (uint32_t)SIM->UIDML; UIDL = (uint32_t)SIM->UIDL; - //print UID once - if(UID_PRINT) pc.printf("DBG: <%f>[UID: %04X%08X%08X] PSTARTED\n", t.read(), UIDMH, UIDML, UIDL); + //print UID three times on start-up to ID Mbed board + if(UID_print_count++ < 3) + pc.printf("DBG: [UID: %04X%08X%08X]\n", UIDMH, UIDML, UIDL); + while(1) { - //test_mcp23008(0); - - //SETUP TIMER USED TO TRACK HOW LONG THE HEATER IS ON - float time_sec = t.read(); + //********************************* + // Process Rx UART data from GUI + //********************************* + if (dataReceived) + { + dataReceived = false; + if (debug_control & RXDATA_PRINT) + pc.printf("DBG: %d bytes Rx'd\n", pc.rxBufferGetCount()); - if(time_sec >= 60){ - time_min++; - //time_sec = 0; - t.reset(); + pc.move(rxBuf, 50); + processRxUARTData(); + pc.rxBufferFlush(); } - if(time_min >= 60){ - time_min = 0; - } - - //GET TEMPERATURE DATA - get_temp_data(); - - //SEND TEMPERATURE DATA FOR LOGGING - sendTempReadings(); - - time_sec = t.read(); - if(LOOP_TIME) pc.printf("DBG: TIME: %f s\n", time_sec); - - //CONTROL LOOP: LOOPS THROUGH EVERY CHANNEL AND CONTROLS THE FIXTURE IN RESPONSE - for(int chnl = 0; chnl < CHN_COUNT; chnl++){ + //********************************* + // Logic Loop + //********************************* + // System Logic/Control + if (newTempDataAvailable) + systemLogic(); - //check if we received data/need to update TCTF data - if(dataReceived){ - dataReceived = false; -#ifdef DEBUG - pc.printf("DBG: %d bytes Rx'd\n", pc.rxBufferGetCount()); -#endif - pc.move(rxBuf, 50); - parseRXData(); - pc.rxBufferFlush(); - } - - //update channel temperature data - float currentTempFront = channelTempData[chnl].currTempFront; - float currentTempBack = channelTempData[chnl].currTempBack; - - //float currentTempBack = get_temp(chnl, BACK_THERM); - float currentTemp = currentTempBack; - - //check if I2C dataline is pulled high - DigitalIn isoSDAIn(PTC9); - DigitalIn adcSDAIn(PTC11); - int isoSDA = isoSDAIn.read(); - int adcSDA = adcSDAIn.read(); - pc.printf("DBG: TEMPERATURE SDA LINE: %d \r\n", isoSDA); - pc.printf("DBG: IO SDA LINE: %d \r\n", adcSDA); - MCP23008 io_control(PTC9, PTC8, 0x10, 100000); //sda, scl - LTC2487 ltc2487(PTC11, PTC10, 0x23, 100000); //sda, scl - - //Error check on fixture - error_check(chnl, currentTempFront, currentTempBack, time_min, isoSDA, adcSDA); + //********************************* + // System Diagnostic & Error Check + //********************************* + systemDiagnostic(); - if(TEMP_PRINT) pc.printf("DBG: TEMPERATURE: [%d] Temp: F: %f B: %f\r\n", chnl, currentTempFront, currentTempBack); - - //CONTROL LOOP: - if(chnlStatus[chnl].status == 1){ - if(DEBUG) pc.printf("DBG: [%d] Temp: F: %f B: %f\r\n", chnl, currentTempFront, currentTempBack); - //main loop for channels - if(chnlStatus[chnl].error == 0){ - if(currentTemp > ((chnlStatus[chnl].setTemp)+HYST_HIGH)){ - if(DEBUG) pc.printf("DBG: [%d] Chiller ON \r\n", chnl); - //reset heater on time - chnlStatus[chnl].heater_init_time = 0; - //Turn chiller on - turn_valve_on(chnl); - } - else if (currentTemp < ((chnlStatus[chnl].setTemp)-HYST_LOW)){ - if(DEBUG) pc.printf("DBG: [%d] Heater ON \r\n", chnl); - //establish starting time for heater - if(chnlStatus[chnl].heater_init_time == 0){ //check if it is the first time that heater has turned on - //make sure time isn't zero, otherwise keeping looping until we are not at 0 - if(time_min != 0){ - chnlStatus[chnl].heater_init_time = time_min; - } - } - 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)); - //Turn heater on - turn_heater_on(chnl); - } - else{ - if(DEBUG) pc.printf("DBG: [%d] All OFF \r\n", chnl); - //reset heater on time - chnlStatus[chnl].heater_init_time = 0; - //turn off chiller - turn_valve_off(chnl); - //turn off heater - turn_heater_off(chnl); - //turn on green LED status light - status_led(chnl, 1); - } - } - } - else{ - if(chnlStatus[chnl].error == 0){ - //turn off chiller - turn_valve_off(chnl); - //turn off heater - turn_heater_off(chnl); - //turn on green LED status light - status_led(chnl, 1); - } - else{ - status_led(chnl, STATUS_BAD); - } - //reset heater on time - chnlStatus[chnl].heater_init_time = 0; - } + //********************************* + // Process Tx UART data + // Send Temperature Data/Error to GUI + //********************************* + if (newTempDataAvailable) + { + processTxUARTData(); + + //********************************* + //Actuate Loop + //********************************* + systemControl(); + newTempDataAvailable = false; } } -} \ No newline at end of file + +}