Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed mbed-STM32F103C8T6
heatcontrol.cpp
- Committer:
- lorded
- Date:
- 2020-07-29
- Revision:
- 11:b571de4666c9
- Parent:
- 10:a82e51837e2b
File content as of revision 11:b571de4666c9:
#include "mbed.h" #include "heatcontrol.h" #include "globals.h" // includes CAN2 #include "espar_can.h" /****************************************************** * Constants ******************************************************/ //#define EASYSTARTFORMAT 1 #define LIN_BAUD 1200 extern void DebugWrite(const char * str); extern char printbuff[256]; extern unsigned long lifetimer; #define NOREPORTING 0 #define HEATERCALLEDON 1 char heaterDetected = 0; //const uint16_t HEATER1ID = 0x0054; //const uint16_t CTRLCHANNEL = 0x07A0; //#define EASYSTARTFORMAT #ifdef EASYSTARTFORMAT const uint16_t HEATER1ID = 0x0054; // 0x009C heater 1 const uint16_t CTRLCHANNEL = 0x07A0; const uint16_t CTRLRESPONSE = 0x073C;// heater1 0x073C, response 0x073D heater 2 const uint16_t HEATER2ID = 0x0057;// 0x009C heater 1 const uint16_t CTRLCHANNEL2 = 0x07A1; const uint16_t CTRLRESPONSE2 = 0x073D;// heater1 0x073C, response 0x073D heater 2 #else const uint16_t HEATER1ID = 0x009C; // 0x009C heater 1 const uint16_t CTRLCHANNEL = 0x07A0; const uint16_t CTRLRESPONSE = 0x073C; // heater1 0x073C, response 0x073D heater 2 const uint16_t HEATER2ID = 0x00F3; // 0x009C heater 1 const uint16_t CTRLCHANNEL2 = 0x07A1; const uint16_t CTRLRESPONSE2 = 0x073D; // heater1 0x073C, response 0x073D heater 2 #endif /****************************************************** * Enumerations ******************************************************/ /****************************************************** * Type Definitions ******************************************************/ /****************************************************** * Structures ******************************************************/ extern struct sSystemSettings Settings; // structure to hold system settings // /****************************************************** * Function Declarations ******************************************************/ void printCAN(CANMessage *canMsg); void printCANTx(CANMessage *canMsg); void printPacketBuffer(unsigned int length, struct sHeatVars *s); void parseLINBuffer(struct sHeatVars *s); void readLINBuffer(struct sHeatVars *s); unsigned char fromHexAscii(char ascii); extern void resetTimerAsync(struct sHeatVars *s); extern void resetTimer(struct sHeatVars *s); int doFindExpectedResponse(CANMessage* msg, const uint16_t expectedID, const char* expectedResponse, int charsInMatch); /****************************************************** * Variable Definitions ******************************************************/ // local vars // external timer variables to use for timing (ie 1 minute, etc.) extern volatile unsigned char idletimer; extern void DebugWrite(const char* str); struct sHeatVars heaterState[HEATERSTATECOUNT]; char otherControllerDetected = 0; /****************************************************** * Function Definitions ******************************************************/ /* * 0-ID,0054:00 00 FE FF FE FF 00 00 0-ID,0625:25 00 B5 54 C0 BB E4 01 0-ID,0054:00 00 FE FF FE FF 00 00 0-ID,0057:00 00 FE FF FE FF 00 00 0-ID,0625:25 00 B5 54 C0 BB E4 01 0-ID,02C4:03 00 04 00 18 03 00 00 0-ID,02C6:F4 01 84 03 00 00 00 00 0-ID,0625:25 00 B5 54 C0 BB E4 01 0-ID,02C6:F4 01 84 03 00 00 00 00 0-ID,073C:02 7E 00 02 7B 00 02 11 0-ID,02C6:F4 01 84 03 00 00 00 00 0-ID,0625:25 00 B5 54 C0 BB E4 01 0-ID,02C6:F4 01 84 03 00 00 00 00 * */ void initHeaterState(struct sHeatVars *s) { s->internalAltitude = 0; s->battV = 0; s->primeFuelPumpCount = 0; s->heatCallDetected = WICED_FALSE; s->heaterTemp = -9999; s->initTimer = 3; // 3s before we do anything other than "I'm here" s->tasksequence = 0; s->currentError = 0xff; s->heatOn = 0; // default 0 //unsigned char errorHistory[8]; s->errorChangeFlag = 0; s->heatcontrolstate = 0; // default 0 s->lastRequest = 0; // default = 0; s->lastResponse = 0; //default = 0; s->noResponseCount = 0; //default = 0; s->retryHC = 0; // = 0; s->heatrunning = 0; // = 0; s->reset_fault_codes = WICED_FALSE; // WICED_FALSE s->isAnalogHeater = WICED_FALSE; s->heattime = 0; s->heatresettime = RESETHEATTIME; s->reportflag = 0; s->preheattime = 0; s->heaterSetpointChange = 0; s->primeFuelPump = WICED_FALSE; s->OBAltitude = WICED_FALSE; s->altitudeMode = WICED_TRUE; } // do checksum calc int testChecksum(unsigned int length, struct sHeatVars *s) { unsigned int checksum = 0; int i; for (i = s->working; i < (s->working + length + 3); i++) { checksum += s->linbuff[i]; } // convert the last 2 bytes to checksum if ((checksum % 256) == (fromHexAscii(s->linbuff[s->working + length + 3]) * 16 + fromHexAscii(s->linbuff[s->working + length + 4]))) { return 1; } return 0; } #define CANSPEED_500 500000 void InitCAN() { if ( can2.frequency(CANSPEED_500) ) { } otherControllerDetected = 0; DebugWrite("Init can\r\n"); int result; // can is just there. } void setHeatSetpoint(struct sHeatVars* s, int setpoint) { printf("setting setpoint of %d\r\n", setpoint); if ((setpoint > 50) && (setpoint <= 380)) { s->heaterSetpointChange = setpoint; } } void primeFuelPump(struct sHeatVars* s) { s->primeFuelPump = WICED_TRUE; } void resetFaultCodes(struct sHeatVars* s) { //printf("Reset Fault codes on\r\n"); s->reset_fault_codes = WICED_TRUE; } void set_heat_con(struct sHeatVars* s, heatcall on_off) { resetTimerAsync(s); if (on_off == HEATCALLINIT) { s->heatOn = HEATCALLINIT; //heattime = 100; //60*Settings.DefaultHeaterRuntime; s->heattime = 24*60*60; s->heatresettime = RESETHEATTIME; s->preheattime = 0; //printf("Init heater, preheat %lu\n", preheattime); } else if (on_off == HEATCALLOFF) { s->heatOn = HEATCALLOFF; s->heattime = 0; s->heatresettime = RESETHEATTIME; s->preheattime = 0; ///printf("Turning heater OFF\n"); } else if (on_off == HEATCALLON) { // skip preheat s->heatOn = HEATCALLON; s->heattime = 24*60*60; s->heatresettime = RESETHEATTIME; s->preheattime = 0; //printf("Turning heater ON (skip preheat)\n"); } else { //printf("\n unknown command\n"); } } void WakeHeater(struct sHeatVars* s) { if (s->heatcontrolstate == 0) { //InitDigHeater(); s->retryHC = 0; s->heatcontrolstate = 1; } } void sendCANCommand(uint16_t id, const char*data, int length) { //return; // listen mode CANMessage TxMessage(id, data, length); can2.write(TxMessage); printCAN(&TxMessage); } void sendRepeatMode(struct sHeatVars* s) { const char wake[8] = { 0x0F, 0x11, 0xC9, 0x22, 0x00, 0x20, 0x60, 0x00 }; if (s->heaternum == 1) { sendCANCommand(0x060F, wake, 8); } //else if (s->heaternum == 2) //{ // sendCANCommand(CTRLCHANNEL2, wake, 8); //} } void sendWakeCommand(struct sHeatVars* s) { //DebugWrite("Wake command\r\n"); // "3e is "tester present" const char wake[8] = { 0x02, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //{0x0F, 0x10, 0x03, 0x00, 0x20, 0x60, 0x00, 0x00}; if (s->heaternum == 1) { sendCANCommand(CTRLCHANNEL, wake, 8); } else if (s->heaternum == 2) { sendCANCommand(CTRLCHANNEL2, wake, 8); } //const char wake2[8] = {0x0F, 0x10, 0x03, 0x00, 0x20, 0x60, 0x00, 0x00}; //sendCANCommand(CTRLCHANNEL2, wake2, 8); } void sendHeatOffCommand(struct sHeatVars* s) { //DebugWrite("Heat Off command\r\n"); const char heatoncmd[8] = #ifdef EASYSTARTFORMAT { 0x00, 0x00, 0xFE, 0xFF, 0xFE, 0xFF, 0x00, 0x00}; #else { 0x05, 0x00, 0xFE, 0xFF, 0xFE, 0xFF, 0x00, 0x00 }; #endif if (s->heaternum == 1) { sendCANCommand(HEATER1ID, heatoncmd, 8); } else if (s->heaternum == 2) { sendCANCommand(HEATER2ID, heatoncmd, 8); } } void sendHeatVentConmmand(struct sHeatVars* s) { DebugWrite("SENDHEATVENT\r\n"); const char heatoncmd[8] = { 0x01, 0x02, 0xFE, 0xFF, 0xF8, 0x02, 0x00, 0x00 }; if (s->heaternum == 1) { sendCANCommand(HEATER1ID, heatoncmd, 8); } else if (s->heaternum == 2) { sendCANCommand(HEATER2ID, heatoncmd, 8); } } void sendHeatOnCommand(struct sHeatVars* s) { DebugWrite("SENDHEATON\r\n"); char heatoncmd[8] = #ifdef EASYSTARTFORMAT { 0x01, 0x01, 0xFE, 0xFF, 0xFE, 0xFF, 0x00, 0x00}; // works? #else { 0x07, 0x01, 0xFE, 0xFF, 0xFE, 0xFF, 0x00, 0x00 }; // works? #endif //{ 0x07, 0x01, 0xFE, 0xFF, 0xFE, 0xFF, 0x00, 0x00 }; uint16_t setpointbytes = 65534; char *usetpoint = (char*) &setpointbytes; // heater 2 has setpoint in 2/3... heater1 in 3/4?????? heatoncmd[2] = usetpoint[0]; // LSB in slot 2 heatoncmd[3] = usetpoint[1]; heatoncmd[4] = usetpoint[0]; // LSB in slot 2 heatoncmd[5] = usetpoint[1]; //{ 0x07, 0x01, 0xFE, 0xFF, 0xFE, 0xFF, 0x00, 0x00 }; // "mode is "preheating"? if (s->heaternum == 1) { //need to reintroduce this... if ((s->OBAltitude == WICED_FALSE)) { char mysteryCommand[8] = { 0x0F, 0x00, 0xC9, 0x22, 0x00, 0x00, 0x00, 0x00 }; sendCANCommand(0x060D, mysteryCommand, 8); } sendCANCommand(HEATER1ID, heatoncmd, 8); } else if (s->heaternum == 2) { sendCANCommand(HEATER2ID, heatoncmd, 8); } } void sendAltitudeMode(struct sHeatVars *s) { if (s->OBAltitude == WICED_TRUE) { return; // don't send if altitude mode on board. } char highAltitudeCmd[8] = { 0x4c, 0x1d, 0, 0, 0, 0, 0, 0 }; // no idea what this is for? //5000 60D 205935687 0008 0D 11 C9 22 00 20 60 00 //#ifdef EASYSTARTFORMAT //#endif // 4C,1D - 7500 for high altitude // 10,27 - 10000 for low altitude //uint16_t setpointbytes = 6800; uint16_t setpointbytes = 6800; if (s->internalAltitude > 0) { setpointbytes = (s->internalAltitude * 10); //sprintf(printbuff, "-- Internal alt\r\n %d\r\n", s->internalAltitude); //DebugWrite(printbuff); } else { setpointbytes = 6800; } char *usetpoint = (char*) &setpointbytes; highAltitudeCmd[0] = usetpoint[0]; // LSB in slot 2 highAltitudeCmd[1] = usetpoint[1]; char lowAltitudeCmd[8] = { 0x10, 0x27, 0, 0, 0, 0, 0, 0 }; if (s->internalAltitude > 0) { setpointbytes = (s->internalAltitude * 10); // sprintf(printbuff, "-- Internal alt %d\r\n", s->internalAltitude); // DebugWrite(printbuff); } else { setpointbytes = 10000; } lowAltitudeCmd[0] = usetpoint[0]; // LSB in slot 2 lowAltitudeCmd[1] = usetpoint[1]; if (s->heaternum == 1) { if (s->altitudeMode == WICED_TRUE) { sendCANCommand(0x0055, highAltitudeCmd, 8); // sendCANCommand(0x0056, highAltitudeCmd, 8); sendCANCommand(HEATER1ID + 1, highAltitudeCmd, 8); } else { sendCANCommand(0x0055, lowAltitudeCmd, 8); // sendCANCommand(0x0056, lowAltitudeCmd, 8); sendCANCommand(HEATER1ID + 1, lowAltitudeCmd, 8); } } /* else if (s->heaternum == 2) { if (s->altitudeMode == WICED_TRUE) { sendCANCommand(HEATER2ID + 1, highAltitudeCmd, 8); sendCANCommand(0x0055, lowAltitudeCmd, 8); sendCANCommand(0x0056, highAltitudeCmd, 8); } else { sendCANCommand(HEATER2ID + 1, lowAltitudeCmd, 8); sendCANCommand(0x0055, lowAltitudeCmd, 8); sendCANCommand(0x0056, lowAltitudeCmd, 8); } } */ } void sendHeatOnCommandSetpoint(struct sHeatVars* s) { DebugWrite("SENDHEATONSETPOINT\r\n"); sprintf(printbuff, "Setpoint is %d", s->setpoint); DebugWrite(printbuff); char heatoncmd[8] = //{ 0x01, 0x04, 0xFE, 0xFF, 0xFE, 0xFF, 0x00, 0x00 }; // "mode is "setpoint with temp"? { 0x07, 0x04, 0xFE, 0xFF, 0xFF, 0xFE, 0x00, 0x00 }; // "mode is "setpoint with temp"? uint16_t setpointbytes = 65534; char *usetpoint = (char*) &setpointbytes; // heater 2 has setpoint in 2/3... heater1 in 3/4?????? heatoncmd[2] = usetpoint[0]; // LSB in slot 2 heatoncmd[3] = usetpoint[1]; heatoncmd[4] = usetpoint[0]; // LSB in slot 2 heatoncmd[5] = usetpoint[1]; setpointbytes = s->setpoint; usetpoint = (char*) &setpointbytes; // heater 2 has setpoint in 2/3... heater1 in 3/4?????? if (s->heaternum == 2) { heatoncmd[2] = usetpoint[0]; // LSB in slot 2 heatoncmd[3] = usetpoint[1]; //heatoncmd[4] = usetpoint[0]; // LSB in slot 2 //heatoncmd[5] = usetpoint[1]; sendCANCommand(HEATER2ID, heatoncmd, 8); } else { heatoncmd[4] = usetpoint[0]; // LSB in slot 2 heatoncmd[5] = usetpoint[1]; sendCANCommand(HEATER1ID, heatoncmd, 8); } } void doOtherResetSequence(struct sHeatVars* s) { //DebugWrite("**************\r\n"); CANMessage msg; DebugWrite("Send wake\r\n"); sendWakeCommand(s); int id = CTRLCHANNEL; int resp = CTRLRESPONSE; if (s->heaternum == 2) { id = CTRLCHANNEL2; resp = CTRLRESPONSE2; } char switchToSession[8] = { 0x10, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; sendCANCommand(id, switchToSession, 8); DebugWrite("Switch To Session\r\n"); if (doFindExpectedResponse(&msg, resp, NULL, 0) > 0) { DebugWrite("Got a response!\r\n"); printCAN(&msg); //return; } else { } // request seed //DebugWrite("**************\r\n"); } void doPrimeSequence(struct sHeatVars* s) { int extrabyte = 0; int count; sendWakeCommand(s); CANMessage msg; int id = CTRLCHANNEL; int resp = CTRLRESPONSE; if (s->heaternum == 2) { id = CTRLCHANNEL2; resp = CTRLRESPONSE2; } char pump[8] = { 0x07, 0x31, 0x01, 0xF0, 0x00, 0x64, 0x00, 0x05 }; char pump2[8] = { 0x04, 0x31, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00 }; // read data F1F2 identifiers... char reset1[8] = { 0x03, 0x22, 0xF1, 0xF2, 0x00, 0x00, 0x00, 0x00 }; char res1[5] = { 0x10, 0x09, 0x62, 0xF1, 0xF2 }; // not sure char reset2[8] = { 0x30, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00 }; char res2[5] = { 0x21, 0x00, 0x00, 0x60, 0xF2 }; // security access char reset3[8] = { 0x02, 0x27, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00 }; // security response char res3[4] = { 0x06, 0x67, 0x63, 0x00 }; char reset3a[8] = { 0x02, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; char res3a[3] = { 0x06, 0x50, 0x01 }; // change to session '60' char reset3b[8] = { 0x02, 0x10, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00 }; char res3b[3] = { 0x06, 0x50, 0x60 }; // scurity access char reset4a[8] = { 0x06, 0x27, 0x64, 0x00, 0x00, 0x10, 0x60, 0x00 }; char res4a[4] = { 0x02, 0x67, 0x64, 0x00 }; count = 0; DebugWrite("***RESET1\r\n"); sendCANCommand(id, reset1, 8); while (count++ < 20) { if (doFindExpectedResponse(&msg, resp, res1, 3) > 0) { printf("1!\r\n"); break; } else { if (msg.id == 0x073) { DebugWrite("Got-"); printCAN(&msg); } } } if (count >= 20) { DebugWrite("FAILED(1)\r\n"); return; } count = 0; sendCANCommand(id, reset2, 8); DebugWrite("***RESET2\r\n"); while (count++ < 20) { if (doFindExpectedResponse(&msg, resp, res2, 3) > 0) { DebugWrite("2!\r\n"); break; } else { } } if (count >= 20) { DebugWrite("FAILED(2)\r\n"); return; } // check msg byte 4, if 01, additional commands extrabyte = msg.data[3]; if (extrabyte > 0) { count = 0; sendCANCommand(id, reset3a, 8); while (count++ < 20) { if (doFindExpectedResponse(&msg, resp, res3a, 3) > 0) { DebugWrite("3a!\r\n"); break; } else { } } if (count >= 20) { DebugWrite("FAILED(3)\r\n"); return; } count = 0; sendCANCommand(id, reset3b, 8); while (count++ < 20) { if (doFindExpectedResponse(&msg, resp, res3b, 3) > 0) { DebugWrite("3b!\r\n"); break; } else { } } if (count >= 20) { DebugWrite("FAILED(4)\r\n"); return; } } count = 0; sendCANCommand(id, reset3, 8); while (count++ < 20) { if (doFindExpectedResponse(&msg, resp, res3, 3) > 0) { DebugWrite("3!\r\n"); break; } else { } } if (count >= 20) { DebugWrite("FAILED(5)\r\n"); return; } if (extrabyte > 0) { count = 0; sendCANCommand(id, reset4a, 8); while (count++ < 20) { if (doFindExpectedResponse(&msg, resp, res4a, 3) > 0) { DebugWrite("4a!\r\n"); break; } else { } } if (count >= 20) { DebugWrite("FAILED(6)\r\n"); return; } } count = 0; DebugWrite("SENDING PUMP COMMAND\r\n"); sendCANCommand(id, pump, 8); DebugWrite("SEQUENCE ON COMMAND\r\n"); sendCANCommand(id, pump2, 8); s->primeFuelPumpCount = 5; } void doResetSequence(struct sHeatVars* s) { int extrabyte = 0; int count; sendWakeCommand(s); CANMessage msg; int id = CTRLCHANNEL; int resp = CTRLRESPONSE; if (s->heaternum == 2) { id = CTRLCHANNEL2; resp = CTRLRESPONSE2; } // read data F1F2 identifiers... char reset1[8] = { 0x03, 0x22, 0xF1, 0xF2, 0x00, 0x00, 0x00, 0x00 }; char res1[5] = { 0x10, 0x09, 0x62, 0xF1, 0xF2 }; // not sure char reset2[8] = { 0x30, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00 }; char res2[5] = { 0x21, 0x00, 0x00, 0x60, 0xF2 }; // security access char reset3[8] = { 0x02, 0x27, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00 }; // security response char res3[4] = { 0x06, 0x67, 0x63, 0x00 }; // clear diagnostics char reset4[8] = { 0x04, 0x14, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00 }; // response char res4[4] = { 0x01, 0x54, 0x63, 0x00 }; // routine control char reset5[8] = { 0x04, 0x31, 0x01, 0xF0, 0x05, 0x00, 0x00, 0x00 }; char res5[5] = { 0x04, 0x71, 0x01, 0xF0, 0x05 }; char reset3a[8] = { 0x02, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; char res3a[3] = { 0x06, 0x50, 0x01 }; // change to session '60' char reset3b[8] = { 0x02, 0x10, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00 }; char res3b[3] = { 0x06, 0x50, 0x60 }; // scurity access char reset4a[8] = { 0x06, 0x27, 0x64, 0x00, 0x00, 0x10, 0x60, 0x00 }; char res4a[4] = { 0x02, 0x67, 0x64, 0x00 }; count = 0; DebugWrite("***RESET1\r\n"); sendCANCommand(id, reset1, 8); while (count++ < 20) { if (doFindExpectedResponse(&msg, resp, res1, 3) > 0) { printf("1!\r\n"); break; } else { if (msg.id == 0x073) { DebugWrite("Got-"); printCAN(&msg); } } } if (count >= 20) { DebugWrite("FAILED(1)\r\n"); return; } count = 0; sendCANCommand(id, reset2, 8); DebugWrite("***RESET2\r\n"); while (count++ < 20) { if (doFindExpectedResponse(&msg, resp, res2, 3) > 0) { DebugWrite("2!\r\n"); break; } else { } } if (count >= 20) { DebugWrite("FAILED(2)\r\n"); return; } // check msg byte 4, if 01, additional commands extrabyte = msg.data[3]; if (extrabyte > 0) { count = 0; sendCANCommand(id, reset3a, 8); while (count++ < 20) { if (doFindExpectedResponse(&msg, resp, res3a, 3) > 0) { DebugWrite("3a!\r\n"); break; } else { } } if (count >= 20) { DebugWrite("FAILED(3)\r\n"); return; } count = 0; sendCANCommand(id, reset3b, 8); while (count++ < 20) { if (doFindExpectedResponse(&msg, resp, res3b, 3) > 0) { DebugWrite("3b!\r\n"); break; } else { } } if (count >= 20) { DebugWrite("FAILED(4)\r\n"); return; } } count = 0; sendCANCommand(id, reset3, 8); while (count++ < 20) { if (doFindExpectedResponse(&msg, resp, res3, 3) > 0) { DebugWrite("3!\r\n"); break; } else { } } if (count >= 20) { DebugWrite("FAILED(5)\r\n"); return; } if (extrabyte > 0) { count = 0; sendCANCommand(id, reset4a, 8); while (count++ < 20) { if (doFindExpectedResponse(&msg, resp, res4a, 3) > 0) { DebugWrite("4a!\r\n"); break; } else { } } if (count >= 20) { DebugWrite("FAILED(6)\r\n"); return; } } count = 0; sendCANCommand(id, reset4, 8); while (count++ < 20) { if (doFindExpectedResponse(&msg, resp, res4, 3) > 0) { printf("4!\r\n"); break; } else { } } if (count >= 20) { printf("FAILED(7)\r\n"); return; } count = 0; sendCANCommand(id, reset5, 8); while (count++ < 20) { if (doFindExpectedResponse(&msg, resp, res5, 3) > 0) { printf("5!\r\n"); break; } else { } } if (count >= 20) { printf("FAILED(8)\r\n"); return; } printf("SUCCESS\r\n"); } int doFindExpectedResponse(CANMessage* msg, const uint16_t expectedID, const char* expectedResponse, int charsInMatch) { char buff[256]; //printf("fe-a\r\n"); int timeout = 0; wiced_bool_t couldRead = WICED_FALSE; int incoming = 0; while ((incoming == 0) && (timeout++ < 10)) { incoming = can2.read(*msg); //printf("fe-b %d\r\n", incoming); if (incoming > 0) { couldRead = WICED_TRUE; } if (!couldRead) { wait(0.01); } } //printf("fe-c\r\n"); if (incoming > 0) { //CAN_FIFORelease(CAN1, CAN_FIFO0); if (msg->id != expectedID) { //sprintf(buff, "No match: %04X\r\n", (unsigned int) msg->StdId); //DebugWrite(buff); return 0; // not a match } // ignore byte 1 for (int i = 1; i < charsInMatch; i++) { if (!(msg->data[i] == expectedResponse[i])) { // no match return 0; } return 1; // match } // no chars in match, always a match? return 1; } else { return -1; // no read } } void printCAN(CANMessage *canMsg) { char buff[256]; sprintf(buff, "ID,%04X:", (unsigned int) canMsg->id); DebugWrite(buff); for (int i = 0; i < canMsg->len; i++) { sprintf(buff, "%02X ", canMsg->data[i]); DebugWrite(buff); } DebugWrite("\r\n"); } void printCANTx(CANMessage *canMsg) { char buff[256]; sprintf(buff, "->ID,%04X:", (unsigned int) canMsg->id); DebugWrite(buff); for (int i = 0; i < canMsg->len; i++) { sprintf(buff, "%02X ", canMsg->data[i]); DebugWrite(buff); } DebugWrite("\r\n"); } void sendGetRuntime(struct sHeatVars *s, char *buff) { int count = 0; CANMessage rxMsg; int id; int resp; id = CTRLCHANNEL; resp = CTRLRESPONSE; if (s->heaternum == 2) { id = CTRLCHANNEL2; resp = CTRLRESPONSE2; } const char msgbytes[8] = { 0x03, 0x22, 0xFD, 0x17, 0x00, 0x00, 0x00, 0x00 }; const char continuePacket[8] = { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; sendCANCommand(id, msgbytes, 8); //The control unit reads out the operating hours counter using the UDS service 22 ID: FD17 while (count++ < 10) { // just expect the ID (0 if (doFindExpectedResponse(&rxMsg, resp, msgbytes, 0) > 0) { printCAN(&rxMsg); // response in the format 59 // the first byte dictates the length //073C:03 59 02 7B 05 48 C3 01 if (rxMsg.data[0] < 0x10) { DebugWrite("Single Message. Shouldn't happen\r\n"); } else if (rxMsg.data[0] < 0x20) { int totalLength = rxMsg.data[1]; unsigned int totalExpectedPackets = ((totalLength - 7) / 7) + 1; unsigned char dataBytes[6 + totalExpectedPackets * 7]; memset(dataBytes, 0, 6 + totalExpectedPackets * 7); // first packet contains 6 bytes of data, additional contain 7 // length 11: 1 extra packet ((11 - 6 - 1) \ 7) + = 4\7 + 1 = 1 // length 13: 1 extra packet ((13 - 6 - 1) \ 7) + = 6\7 + 1 = 1 // length 14: 2 packets ((14 - 6 - 1) \ 7) + = 7\7 + 1 = 2 // length 20: 2 packets ((20 - 6 - 1) \ 7) + = 7\7 + 1 = 2 // length 21: 3 packets ((21 - 6 - 1) \ 7) + = 7\7 + 1 = 3 // Packets = lenght is ((length - 7) \ 7) + 1 sprintf(buff, "multi message start, length %d\r\n", rxMsg.data[1]); DebugWrite(buff); printCAN(&rxMsg); /*Query 03 19 02 08 * ID,073C:[10 0B] [59 02] [7B] 00 02 11] * ID,073C:21 2B 00 02 A1 2A xx xx * 10: Multi message start packet * 0B: Length (11 DATA bytes). x'd out non-data * 59: response type 59 * 02: subfunction 2 * 7B: mask * 00 02 11: first 3 bytes of fault. Need next part */ // get the first fault code, bytes 4-7 sendCANCommand(id, continuePacket, 8); CANMessage additionalRxMsg[totalExpectedPackets]; int currentPacket = 0; while (count++ < 10) { if (doFindExpectedResponse(&(additionalRxMsg[currentPacket]), resp, msgbytes, 0) > 0) { count = 0; currentPacket++; if (currentPacket >= totalExpectedPackets) { DebugWrite("Found all additional packets\r\n"); memcpy(dataBytes, rxMsg.data + 2, 6); // 6 initial data bytes for (int i = 0; i < totalExpectedPackets; i++) { memcpy(dataBytes + 6 + (totalExpectedPackets * i), additionalRxMsg[i].data + 1, 7); } DebugWrite("Runtime Data bytes: "); for (int i = 0; i < totalLength; i++) { sprintf(buff, "%02X ", dataBytes[i]); DebugWrite(buff); } //DebugWrite("\r\n"); long runtime = -1; // bytes 3-6 are runtime if (totalLength > 6) { runtime = dataBytes[3]; runtime = runtime << 8; runtime = runtime + dataBytes[4]; runtime = runtime << 8; runtime = runtime + dataBytes[5]; runtime = runtime << 8; runtime = runtime + dataBytes[6]; s->heaterRuntime = runtime; } s->heaterRuntime = runtime; break; } } } // outer while } } } // while printf("f-b\r\n"); if (count >= 10) { printf("FAILED or done\r\n"); return; } return; } wiced_result_t sendGetGeneric(struct sHeatVars *s, char *buff, const char msgbytes[8], CANMessage* rxMsg) { int id; int resp = CTRLRESPONSE; id = CTRLCHANNEL; if (s->heaternum == 2) { id = CTRLCHANNEL2; resp = CTRLRESPONSE2; } const char continuePacket[8] = { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //DebugWrite("************\r\n"); sendCANCommand(id, msgbytes, 8); if (doFindExpectedResponse(rxMsg, resp, msgbytes, 0) > 0) { return WICED_SUCCESS; } return WICED_NOT_FOUND; } void sendGetTemperatures(struct sHeatVars *s, char *buff) { int id; int count; int resp = CTRLRESPONSE; id = CTRLCHANNEL; if (s->heaternum == 2) { id = CTRLCHANNEL2; resp = CTRLRESPONSE2; } CANMessage rxMsg; const char msgbytes[8] = { 0x03, 0x22, 0xFD, 0x01, 0x00, 0x00, 0x00, 0x00 }; const char continuePacket[8] = { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; count = 0; //DebugWrite("************\r\n"); sendCANCommand(id, msgbytes, 8); // just expect the ID (0 if (doFindExpectedResponse(&rxMsg, resp, msgbytes, 0) > 0) { //DebugWrite("********(a)****\r\n"); printCAN(&rxMsg); // response is a multi part if (rxMsg.data[0] < 0x10) { DebugWrite("Single Message. Shouldn't happen\r\n"); } else if (rxMsg.data[0] < 0x20) { int totalLength = rxMsg.data[1]; unsigned int totalExpectedPackets = ((totalLength - 7) / 7) + 1; unsigned char dataBytes[6 + totalExpectedPackets * 7]; memset(dataBytes, 0, 6 + totalExpectedPackets * 7); // first packet contains 6 bytes of data, additional contain 7 // length 11: 1 extra packet ((11 - 6 - 1) \ 7) + = 4\7 + 1 = 1 // length 13: 1 extra packet ((13 - 6 - 1) \ 7) + = 6\7 + 1 = 1 // length 14: 2 packets ((14 - 6 - 1) \ 7) + = 7\7 + 1 = 2 // length 20: 2 packets ((20 - 6 - 1) \ 7) + = 7\7 + 1 = 2 // length 21: 3 packets ((21 - 6 - 1) \ 7) + = 7\7 + 1 = 3 // Packets = lenght is ((length - 7) \ 7) + 1 sprintf(buff, "multi message start, length %d\r\n", rxMsg.data[1]); DebugWrite(buff); printCAN(&rxMsg); /*Query 03 19 02 08 * ID,073C:[10 0B] [59 02] [7B] 00 02 11] * ID,073C:21 2B 00 02 A1 2A xx xx * 10: Multi message start packet * 0B: Length (11 DATA bytes). x'd out non-data * 59: response type 59 * 02: subfunction 2 * 7B: mask * 00 02 11: first 3 bytes of fault. Need next part */ // get the first fault code, bytes 4-7 sendCANCommand(id, continuePacket, 8); CANMessage additionalRxMsg[totalExpectedPackets]; int currentPacket = 0; while (count++ < 10) { if (doFindExpectedResponse(&(additionalRxMsg[currentPacket]), resp, msgbytes, 0) > 0) { count = 0; currentPacket++; if (currentPacket >= totalExpectedPackets) { //DebugWrite("Found all additional packets\r\n"); memcpy(dataBytes, rxMsg.data + 2, 6); // 6 initial data bytes for (int i = 0; i < totalExpectedPackets; i++) { memcpy(dataBytes + 6 + (totalExpectedPackets * i), additionalRxMsg[i].data + 1, 7); } s->flameTemp = dataBytes[3]; s->flameTemp = s->flameTemp << 8; s->flameTemp += dataBytes[4]; s->flameTemp -= 5000; s->inletTemp = dataBytes[5]; s->inletTemp = s->inletTemp << 8; s->inletTemp += dataBytes[6]; s->inletTemp -= 5000; s->outletTemp = dataBytes[7]; s->outletTemp = s->outletTemp << 8; s->outletTemp += dataBytes[8]; s->outletTemp -= 5000; DebugWrite(" **\r\n"); //DebugWrite("\r\n"); //long runtime = -1; // bytes 3-6 are runtime /* if (totalLength > 6) { runtime = dataBytes[3]; runtime = runtime << 8; runtime = runtime + dataBytes[4]; runtime = runtime << 8; runtime = runtime + dataBytes[5]; runtime = runtime << 8; runtime = runtime + dataBytes[6]; s->heaterRuntime = runtime; } s->heaterRuntime = runtime; */ break; } } } } } printf("f-b\r\n"); if (count >= 10) { printf("FAILED\r\n"); return; } return; } void sendGetBattery(struct sHeatVars *s, char *buff) { int count; CANMessage rxMsg; char msgbytes[8] = { 0x03, 0x22, 0xFD, 0x04, 0x00, 0x00, 0x00, 0x00 }; // response is on 73C: 0x05, 0x62, 0xFD, 0x04, [0x00, 0x7D], 0xB0, 0x1C int id; int resp = CTRLRESPONSE; id = CTRLCHANNEL; if (s->heaternum == 2) { id = CTRLCHANNEL2; resp = CTRLRESPONSE2; } count = 0; sendCANCommand(id, msgbytes, 8); int batt = 0; msgbytes[1] = 0x62; while (count++ < 10) { // just expect the ID (0 if (doFindExpectedResponse(&rxMsg, resp, msgbytes, 4) > 0) { printCAN(&rxMsg); batt = rxMsg.data[4]; batt = batt << 8; batt += rxMsg.data[5]; s->battV = batt; } } } void sendGetAltitude(struct sHeatVars *s, char *buff) { //DebugWrite("ALTITUDE******\r\n"); int count; CANMessage rxMsg; char msgbytes[8] = { 0x03, 0x22, 0xFD, 0x36, 0x00, 0x00, 0x00, 0x00 }; // response is on 73C: 0x05, 0x62, 0xFD, 0x04, [0x00, 0x7D], 0xB0, 0x1C int id; int resp = CTRLRESPONSE; id = CTRLCHANNEL; if (s->heaternum == 2) { id = CTRLCHANNEL2; resp = CTRLRESPONSE2; } count = 0; sendCANCommand(id, msgbytes, 8); int alt = 0; msgbytes[1] = 0x62; while (count++ < 10) { // just expect the ID (0 if (doFindExpectedResponse(&rxMsg, resp, msgbytes, 4) > 0) { printCAN(&rxMsg); alt = rxMsg.data[4]; alt = alt << 8; alt += rxMsg.data[5]; s->altitude = alt / 10; } } //DebugWrite("ALTITUDE******\r\n"); } void sendGetFault(struct sHeatVars *s, char *buff) { //DebugWrite("Fault command\r\n"); CANMessage rxMsg; int count; // 3 bytes, function 19, command 2, mask 8 (all confirmed errors) (failed this cycle) const char msgbytes[8] = { 0x03, 0x19, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00 }; const char continuePacket[8] = { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; int id; int resp = CTRLRESPONSE; id = CTRLCHANNEL; if (s->heaternum == 2) { id = CTRLCHANNEL2; resp = CTRLRESPONSE2; } count = 0; sendCANCommand(id, msgbytes, 8); while (count++ < 10) { // just expect the ID (0 if (doFindExpectedResponse(&rxMsg, resp, msgbytes, 0) > 0) { printCAN(&rxMsg); // response in the format 59 // the first byte dictates the length //073C:03 59 02 7B 05 48 C3 01 if (rxMsg.data[0] < 0x10) { DebugWrite("Single Message. "); if (rxMsg.data[0] == 0x03) { // 59 is a resonse. Mask info isnt useful because no faults if (rxMsg.data[1] == 0x59) { // no faults if (s->currentError != 0) { s->errorChangeFlag = 1; } sprintf(buff, "NO FAULTS (reset)\r\n"); DebugWrite(buff); s->currentError = 0x00; s->errorHistory[0] = 0x0; s->errorHistory[1] = 0x0; s->errorHistory[2] = 0x0; s->errorHistory[3] = 0x0; s->errorHistory[4] = 0x0; s->errorHistory[5] = 0x0; break; // out of the loop } } else if ((rxMsg.data[0] == 0x07) && rxMsg.data[1] == 0x59) { //ID,073C:07 59 02 7B 00 02 11 2A // 07 length // 59 response // one fault. Is it a current fault? if ((rxMsg.data[5] == 0x00) && (rxMsg.data[6] == 0x00)) { // the fault isn't a fault. sprintf(buff, "NO FAULTS\r\n"); DebugWrite(buff); if (s->currentError != 0) { s->errorChangeFlag = 1; } s->currentError = 0x00; s->errorHistory[0] = 0x0; s->errorHistory[1] = 0x0; s->errorHistory[2] = 0x0; s->errorHistory[3] = 0x0; s->errorHistory[4] = 0x0; s->errorHistory[5] = 0x0; } else { //A: 0010 1010 bit 1 is test failed this cycle //B: 0010 1011 bit 0 is test failed. Seems to be considered // active if bit 0 is '1' // bit 5 test failed since last clear //07 59 02 7B 00 02 11 2A uint16_t newError = rxMsg.data[5]; newError *= 256; newError += rxMsg.data[6]; wiced_bool_t gotAnError = WICED_FALSE; // is it a current fault? if ((rxMsg.data[7] & 0x01) == 0x01) { gotAnError = WICED_TRUE; if (s->currentError != newError) { s->errorChangeFlag = 1; } // active fault s->currentError = newError; } if (!gotAnError) { s->currentError = 0; } // also first history fault s->errorHistory[0] = newError; sprintf(buff, "FAULT(h%d): %02X%02X\r\n", s->heaternum, rxMsg.data[5], rxMsg.data[6]); DebugWrite(buff); // if (s->currentError != newError) // { // s->errorChangeFlag = 1; // } //errorChangeFlag } } } else if (rxMsg.data[0] < 0x20) { int totalLength = rxMsg.data[1]; unsigned int totalExpectedPackets = ((totalLength - 7) / 7) + 1; unsigned char dataBytes[6 + totalExpectedPackets * 7]; memset(dataBytes, 0, 6 + totalExpectedPackets * 7) ; // first packet contains 6 bytes of data, additional contain 7 // length 11: 1 extra packet ((11 - 6 - 1) \ 7) + = 4\7 + 1 = 1 // length 13: 1 extra packet ((13 - 6 - 1) \ 7) + = 6\7 + 1 = 1 // length 14: 2 packets ((14 - 6 - 1) \ 7) + = 7\7 + 1 = 2 // length 20: 2 packets ((20 - 6 - 1) \ 7) + = 7\7 + 1 = 2 // length 21: 3 packets ((21 - 6 - 1) \ 7) + = 7\7 + 1 = 3 // Packets = lenght is ((length - 7) \ 7) + 1 // sprintf(buff, "multi message start, length %d\r\n", rxMsg.data[1]); // DebugWrite(buff); printCAN(&rxMsg); /*Query 03 19 02 08 * ID,073C:[10 0B] [59 02] [7B] 00 02 11] * ID,073C:21 2B 00 02 A1 2A xx xx * 10: Multi message start packet * 0B: Length (11 DATA bytes). x'd out non-data * 59: response type 59 * 02: subfunction 2 * 7B: mask * 00 02 11: first 3 bytes of fault. Need next part */ // get the first fault code, bytes 4-7 sendCANCommand(id, continuePacket, 8); CANMessage additionalRxMsg[totalExpectedPackets]; int currentPacket = 0; while (count++ < 10) { if (doFindExpectedResponse(&(additionalRxMsg[currentPacket]), resp, msgbytes, 0) > 0) { count = 0; currentPacket++; if (currentPacket >= totalExpectedPackets) { DebugWrite("Found all additional packets\r\n"); memcpy(dataBytes, rxMsg.data + 2, 6); // 6 initial data bytes for (int i = 0; i < totalExpectedPackets; i++) { sprintf(printbuff, "- copying packet %d to databytes + %d\r\n", i, 6 + (i) * 7); DebugWrite(printbuff); memcpy(dataBytes + 6 + ((i) * 7), additionalRxMsg[i].data + 1, 7); } DebugWrite("Data bytes: "); for (int i = 0; i < totalLength; i++) { sprintf(buff, "%02X ", dataBytes[i]); DebugWrite(buff); } DebugWrite("\r\n"); uint16_t newError; wiced_bool_t gotAnError = WICED_FALSE; //Data bytes: 59 02 7B [00 02 11 2B] [00 02 A1 28] for (int i = 0; i < 6; i++) { s->errorHistory[i] = 0; } for (int i = 3; i < totalLength; i += 4) { newError = dataBytes[i + 1]; newError *= 256; newError += dataBytes[i + 2]; // is it a current fault? if ((dataBytes[i + 3] & 0x01) == 0x01) { gotAnError = WICED_TRUE; if (s->currentError != newError) { s->errorChangeFlag = 1; } // active fault s->currentError = newError; } // history fault if (((i - 3) / 4) < 6) { s->errorHistory[(i - 3) / 4] = newError; } sprintf(buff, "FAULT: %02X%02X\r\n", dataBytes[i + 1], dataBytes[i + 2]); DebugWrite(buff); } if (!gotAnError) { s->currentError = 0; // no error to start. } // clear the remainder break; } } } } } } // while printf("f-b\r\n"); if (count >= 10) { printf("FAILED\r\n"); return; } printf("f-c\r\n"); if ((rxMsg.data[0] == 0x03) && (rxMsg.data[1] == 0x59) && (rxMsg.data[5] == 0x56) && (rxMsg.data[6] == 0x78)) { if (s->currentError != 0) { s->errorChangeFlag = 1; } sprintf(buff, "NO FAULTS (reset)\r\n"); DebugWrite(buff); s->currentError = 0x00; s->errorHistory[0] = 0x0; s->errorHistory[0] = 0x0; s->errorHistory[0] = 0x0; s->errorHistory[0] = 0x0; s->errorHistory[0] = 0x0; s->errorHistory[0] = 0x0; } else if ((rxMsg.data[0] == 0x03) && (rxMsg.data[1] == 0x59) && (rxMsg.data[5] == 0x00) && (rxMsg.data[6] == 0x00)) { if (s->currentError != 0) { s->errorChangeFlag = 1; } sprintf(buff, "NO FAULTS(1)\r\n"); DebugWrite(buff); s->currentError = 0x00; s->errorHistory[0] = 0x0; s->errorHistory[0] = 0x0; s->errorHistory[0] = 0x0; s->errorHistory[0] = 0x0; s->errorHistory[0] = 0x0; s->errorHistory[0] = 0x0; } else if ((rxMsg.data[0] == 0x07) && (rxMsg.data[1] == 0x59) && (rxMsg.data[2] == 0x02)) { if ((rxMsg.data[5] == 0x00) && (rxMsg.data[6] == 0x00)) { sprintf(buff, "NO FAULTS\r\n"); DebugWrite(buff); if (s->currentError != 0) { s->errorChangeFlag = 1; } s->currentError = 0x00; s->errorHistory[0] = 0x0; s->errorHistory[1] = 0x0; s->errorHistory[2] = 0x0; s->errorHistory[3] = 0x0; s->errorHistory[4] = 0x0; s->errorHistory[5] = 0x0; } else { sprintf(buff, "FAULT: %02X%02X\r\n", rxMsg.data[5], rxMsg.data[6]); DebugWrite(buff); uint16_t newError = rxMsg.data[5]; newError *= 256; newError += rxMsg.data[6]; if (s->currentError != newError) { s->errorChangeFlag = 1; } //errorChangeFlag s->currentError = newError; s->errorHistory[0] = newError; } printf("SUCCESS\r\n"); } else if ((rxMsg.data[0] == 0x03) && (rxMsg.data[1] == 0x59) && (rxMsg.data[2] == 0x02)) { // this means cleared in both cases! if (s->currentError != 0) { s->errorChangeFlag = 1; } sprintf(buff, "NO FAULTS(2)\r\n"); DebugWrite(buff); s->currentError = 0x00; s->errorHistory[0] = 0x0; s->errorHistory[1] = 0x0; s->errorHistory[2] = 0x0; s->errorHistory[3] = 0x0; s->errorHistory[4] = 0x0; s->errorHistory[5] = 0x0; } else if ((rxMsg.data[0] == 0x10) && (rxMsg.data[1] == 0x0B)) { sprintf(buff, " MULTI FAULT: %02X%02X\r\n", rxMsg.data[6], rxMsg.data[7]); DebugWrite(buff); uint16_t newError = rxMsg.data[6]; newError *= 256; newError += rxMsg.data[7]; if (s->currentError != newError) { s->errorChangeFlag = 1; } s->currentError = newError; s->errorHistory[0] = newError; } else { sprintf(buff, "OTHER RESPONSE\r\n"); DebugWrite(buff); printCAN(&rxMsg); } printf("f-d\r\n"); } void readCAN(struct sHeatVars *s) { // find the heater to update in some cases int count = 0; struct sHeatVars* heaterToUpdate = NULL; //DebugWrite("read\r\n"); CANMessage canMsg; int incoming = can2.read(canMsg); while ((incoming > 0) && (count++ < 10)) { led1 = 1; // start blank if ((canMsg.id == 0x0055)) { // sub our own DebugWrite("SUBSTITUTE ALTITUDE CMD\r\n"); sendAltitudeMode(s); } if ((canMsg.id == 0x07A0) || (canMsg.id == 0x060D) || (canMsg.id == 0x0057) ) { otherControllerDetected = 300; DebugWrite("\r\n****OTHER CONTROLLER ON NETWORK*****\r\n"); } if (((canMsg.id != 0x0625) && (canMsg.id != 0x02C4)) && (canMsg.id != 0x02C6) && (canMsg.id != 0x0626) && (canMsg.id != 0x02D0) && (canMsg.id != 0x02CE)) { DebugWrite("0-"); printCAN(&canMsg); } else if ((canMsg.id == 0x0625) || (canMsg.id == 0x0626)) { if ((canMsg.id == 0x0625) && (heaterState[0].bustype == HEATERTYPECAN) && (heaterState[0].heaternum == 1)) { heaterToUpdate = &(heaterState[0]); } else if ((canMsg.id == 0x0626) && (heaterState[0].bustype == HEATERTYPECAN) && (heaterState[0].heaternum == 2)) { heaterToUpdate = &(heaterState[0]); } heaterToUpdate->heaterDetected = 60; // preserve for a min. // unpack and document NM_Heater_1_t heaterInfo; Unpack_NM_Heater_1_mydbc(&heaterInfo, canMsg.data, 0); //DebugWrite("NM_HEATER_"); /* sprintf(printbuff, "%d,%lu,", heaterToUpdate->heaternum, heaterInfo.SerialNumber); DebugWrite(printbuff); if (heaterInfo.HeaterInitFinished) { DebugWrite("DoneInit,"); } else { DebugWrite("NOINIT,"); } */ if (heaterInfo.HeaterType == 0) { // DebugWrite("Air,"); if (heaterToUpdate->setpoint == 0) { heaterToUpdate->setpoint = 250; } } else if (heaterInfo.HeaterType == 1) { // DebugWrite("Water,"); heaterToUpdate->setpoint = 0; } else { // DebugWrite("Unknown,"); } if (heaterInfo.AltitudeSensorOnBoard) { // DebugWrite("OB Alt,"); heaterToUpdate->OBAltitude = WICED_TRUE; } else { // DebugWrite("NO OB ALT,"); heaterToUpdate->OBAltitude = WICED_FALSE; } /*( if (heaterInfo.OperateEasyFan) { DebugWrite("EZFAN,"); } else { DebugWrite("NO-EZFAN,"); } sprintf(printbuff, "Op:%u,", heaterInfo.OperatingModes); DebugWrite(printbuff); DebugWrite(","); DebugWrite("\r\n"); */ } else if ((canMsg.id == 0x02C6) || (canMsg.id == 0x02D0)) { if (canMsg.id == 0x02C6) { if ((heaterState[0].bustype == HEATERTYPECAN) && (heaterState[0].heaternum == 1)) { heaterToUpdate = &(heaterState[0]); } else { DebugWrite("Unable to update 0x02C6\r\n"); } } else if (canMsg.id == 0x02D0) { if ((heaterState[0].bustype == HEATERTYPECAN) && (heaterState[0].heaternum == 2)) { heaterToUpdate = &(heaterState[0]); } else { DebugWrite("Unable to update 0x02D0\r\n"); } } if (heaterToUpdate == NULL) { DebugWrite("HEATERTOUPDATENULL\r\n"); return; } int lowRange = canMsg.data[1]; lowRange = lowRange << 8; lowRange += canMsg.data[0]; int highRange = canMsg.data[3]; highRange = highRange << 8; highRange += canMsg.data[2]; if (lowRange > highRange) { int temp = lowRange; lowRange = highRange; highRange = temp; } //sprintf(printbuff, "Temp range %d - %d heater %d\r\n", lowRange, highRange, heaterToUpdate->heaternum); //DebugWrite(printbuff); //printCAN(&canMsg); /* * now detected by heater NM command if (heaterToUpdate->heaternum == 2) { // eventually replace with the equivalent of 0x0625 if (highRange > 500) { //sprintf(printbuff, "heater %d setpoint > 500\r\n", heaterToUpdate->heaternum); //DebugWrite(printbuff); heaterToUpdate->setpoint = 0; // fluid heater } else { // if (heaterToUpdate->setpoint == 0) { // sprintf(printbuff, "heater %d setpoint 250", heaterToUpdate->heaternum); // DebugWrite(printbuff); heaterToUpdate->setpoint = 250; // default value. Ignored mostly in CAN land. } } } */ } else if ((canMsg.id == 0x02C4) || (canMsg.id == 0x02CE)) { int heater = 1; if (canMsg.id == 0x02CE) { heater = 2; } if ((heaterState[0].bustype == HEATERTYPECAN) && (heaterState[0].heaternum == heater)) { heaterToUpdate = &(heaterState[0]); } else { DebugWrite("Unable to update 0x02C6\r\n"); } //DebugWrite("OBK_STATUS_HEATER_1\r\n"); OBK_Status_Heater_1_t heaterStatus; Unpack_OBK_Status_Heater_1_mydbc(&heaterStatus, canMsg.data, 0); heaterToUpdate->heaterTemp = heaterStatus.HeaterTemperature; //sprintf(printbuff, "OBK_STATUS_HEATER_%d,temp %ld,", heater, heaterStatus.HeaterTemperature); //DebugWrite(printbuff); if (heaterStatus.isValid) { DebugWrite("Valid,"); } else { DebugWrite("!Valid,"); } if (heaterStatus.noHeatModeActive) { DebugWrite("NOHEAT,"); heaterToUpdate->heatCallDetected = WICED_FALSE; } if (heaterStatus.standbyHeatingActive) { DebugWrite("STANBYHEAT,"); heaterToUpdate->heatCallDetected = WICED_TRUE; } if (heaterStatus.standbyHeatingWithSetpointActive) { DebugWrite("STANDBYHEATSETPOINT,"); heaterToUpdate->heatCallDetected = WICED_TRUE; } if (heaterStatus.ResidualHeat > 0) { DebugWrite("RESIDUAL,"); } if (heaterStatus.ErrorClass1) { DebugWrite("F1,"); } if (heaterStatus.ErrorClass2) { DebugWrite("F2,"); } if (heaterStatus.ErrorClass3) { DebugWrite("F3,"); } if (heaterStatus.ErrorClass4) { DebugWrite("F4,"); } if (heaterStatus.ErrorClass5) { DebugWrite("F5,"); } if (heaterStatus.ErrorClass6) { DebugWrite("F6,"); } if (heaterStatus.HeatingUpActive) { DebugWrite("HUA,"); } if (heaterStatus.SetpointInvalid) { DebugWrite("SetpointInvalid,"); } else { DebugWrite("SetpointValid,"); } if (heaterStatus.AltitudeModeActive) { DebugWrite("!!**ALT**!!,"); } else { DebugWrite("NoALT,"); } DebugWrite("V"); sprintf(printbuff, "%d", heaterStatus.ventilationActive); DebugWrite(printbuff); DebugWrite("\r\n"); } incoming = can2.read(canMsg); } //incoming = CAN_MessagePending(CAN1, CAN_FIFO1); //DebugWrite("doneread\r\n"); } //#define LISTENONLY /* primary heat task start */ wiced_bool_t repeatSent = WICED_FALSE; void doHeatTaskCAN(struct sHeatVars *s) { if (!(s->bustype == HEATERTYPECAN)) { return; } char buff[256]; #ifdef LISTENONLY // sprintf(buff,"heattask %d\r\n", s->tasksequence); // DebugWrite(buff); #endif sprintf(buff,"heattask %d\r\n", s->tasksequence); DebugWrite(buff); //DebugWrite("Listen Only\r\n"); readCAN(s); if ((otherControllerDetected > 0)) { s->tasksequence = 0; s->heatOn = HEATCALLOFF; return; // don't send anything. } #ifdef LISTENONLY return; #endif //return; // listen only. idletimer = 60; // disable idle if ((s->heatOn != HEATCALLOFF)) { idletimer = 60; } if ((idletimer <= 0) && (s->heatOn == HEATCALLOFF)) { s->tasksequence = -1; DebugWrite("*idle*\r\n"); return; } if (s->initTimer > 0) { sprintf(printbuff,"InitTimer %d\r\n", s->initTimer); DebugWrite(printbuff); s->tasksequence = 0; } else if (s->primeFuelPump == WICED_TRUE) { s->tasksequence = 2; } else if (s->reset_fault_codes == WICED_TRUE) { s->tasksequence = 2; } switch (s->tasksequence++) { case 4: //60F: 0F 11 C9 22 00 20 60 00 if ((s->heaterDetected > 0) && s->heaternum == 1) // only send if heater is detected. { if (!repeatSent) { repeatSent = WICED_TRUE; sendRepeatMode(s); break; } } //no break case 0: case 8: case 12: printf("SendWake\r\n"); sendWakeCommand(s); break; case 1: case 5: case 9: case 13: sendGetBattery(s, buff); sendAltitudeMode(s); if ((s->heatOn == HEATCALLINIT) || (s->heatOn == HEATCALLON)) { // a cyclic heat call is always required. if (s->setpoint > 0) { if (s->heaterSetpointChange != s->setpoint) { s->setpoint = s->heaterSetpointChange; } sendHeatOnCommandSetpoint(s); } else { sendHeatOnCommand(s); } if (s->heatOn == HEATCALLINIT) { s->heatOn = HEATCALLON; } } else if (s->heatOn == HEATCALLOFF) { sendHeatOffCommand(s); // double-if just for clarity if ((s->OBAltitude == WICED_FALSE) && (s->heatCallDetected)) { if ((s->altitudeMode == WICED_TRUE) || (s->internalAltitude > 0)) { // send ONLY if heater is in "ON" state. char mysteryCommand[8] = { 0x0F, 0x00, 0xC9, 0x22, 0x00, 0x00, 0x00, 0x00 }; sendCANCommand(0x060D, mysteryCommand, 8); } } } break; case 2: case 6: case 10: case 14: if ((s->heatOn == HEATCALLOFF) && (s->primeFuelPump == WICED_TRUE)) { DebugWrite("IN prime call\r\n"); s->primeFuelPump = WICED_FALSE; // no prime allowed if heat on doPrimeSequence(s); } else if (s->primeFuelPump == WICED_TRUE) { DebugWrite("IN prime call FORCED FALSE\r\n"); s->primeFuelPump = WICED_FALSE; // no prime allowed if heat on } if (s->reset_fault_codes == WICED_TRUE) { // doPrimeSequence(s); // s->reset_fault_codes = WICED_FALSE; printf("RESET faults\r\n"); s->reset_fault_codes = WICED_FALSE; doResetSequence(s); // reset fault codes printf("****sendGetFaults***\r\n"); sendGetFault(s, buff); printf("***doneGetFaults***\r\n"); } else { printf("****sendGetFaults***\r\n"); sendGetFault(s, buff); if ((s->errorHistory[0] == 0) || (s->errorHistory[0] == 255)) { s->reset_fault_codes = WICED_FALSE; } printf("***doneGetFaults***\r\n"); } // check faults break; case 3: sendGetTemperatures(s, buff); break; case 7: sendGetRuntime(s, buff); break; case 11: sendGetBattery(s, buff); break; //case 4: case 15: sendGetAltitude(s, buff); break; default: s->tasksequence = 0; break; } printf("/done\r\n"); // start with "Wake" message return; } // imported from picus void doHeatLogicTask(struct sHeatVars* s) { // error flag valid after LINPulse 0. if (s->errorChangeFlag == 1) { s->errorChangeFlag = 0; //printf("Error Change %d \r\n",currentError); //printf("History %d,%d,%d,%d,%d\r\n",errorHistory[0],errorHistory[1],errorHistory[2],errorHistory[3],errorHistory[4]); // reset timer resetTimer(s); s->reportflag = 1; //UARTWrite(1,"Timer reset\r\n"); } //sprintf(printbuff, "tickcount: %d, heaton: %d, heattime: %d\n", s->tickcount, s->heatOn, s->heattime); //DebugWrite(printbuff); // if the error is stable for 15 seconds, report. if (s->reportflag == 1 && s->tickcount > 15000 && s->heatOn > 0 && (s->heatcontrolstate != IDLE) && s->resettick == 0) { // stable for 15 seconds, do report if (s->currentError == 0 && s->heatOn > 0) { s->reportflag = 0; } else if (s->currentError != 0xFF) { //printf("Error (heatOn & currentError !=0xFF) \r\n"); s->reportflag = 0; s->heatOn = HEATCALLOFF; // disabled retry function per neil at this point. } else { //printf( "Error FF: No communication. Allow heat to continue, but report\r\n"); // -OR- // Retry algorighm on LIN pulse s->reportflag = 0; } } else { //sprintf(printbuff,"%d\r\n",tickcount); //UARTWrite(1,printbuff); } if (s->heatOn == HEATCALLON && (s->heattime == 0 || s->heattime > 86400)) { //printf("Heat off due to time expiry."); // no final report. if (s->heattime > 0) { s->heatOn = HEATCALLLONGRUN; s->heatresettime = RESETHEATTIME ; // reset heat timer } else { s->heatOn = HEATCALLOFF; } s->reportflag = 0; } } //========================================================= unsigned char fromHexAscii(char ascii) { if (ascii >= '0' && ascii <= '9') { return ascii - '0'; } else if (ascii >= 'A' && ascii <= 'F') { return ascii - 'A' + 10; } else { return 255; } }