System Management code

Dependencies:   mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP

Fork of SystemManagement by Martin Deng

Committer:
pspatel321
Date:
Thu Jan 22 07:58:51 2015 +0000
Revision:
36:0afc0fc8f86b
Parent:
34:18bcf276d3bf
Child:
38:8efacce315ae
Tested in car with other systems.  Most features are good to go.  Except xbees need work.  The DC-DC protection features were giving problems due to spurious current measurements.  They have been edited to reduce glitchy errors.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pspatel321 34:18bcf276d3bf 1 #include "inCommands.h"
pspatel321 30:91af74a299e1 2
pspatel321 34:18bcf276d3bf 3 bool inCommands::serviceCAN(CANMessage* fromXbee)
pspatel321 33:6bc82b6b62e5 4 {
pspatel321 30:91af74a299e1 5 CANMessage msg;
pspatel321 33:6bc82b6b62e5 6 if (fromXbee != NULL) {
pspatel321 33:6bc82b6b62e5 7 memcpy((void*)&msg, (void*)fromXbee, sizeof(CANMessage));
pspatel321 33:6bc82b6b62e5 8 } else {
pspatel321 33:6bc82b6b62e5 9 if (!can.rxRead(msg)) return false;
pspatel321 33:6bc82b6b62e5 10 }
pspatel321 33:6bc82b6b62e5 11
pspatel321 33:6bc82b6b62e5 12 switch (msg.id) {
pspatel321 33:6bc82b6b62e5 13 case FAN_CONTROL_ID:
pspatel321 33:6bc82b6b62e5 14 if (msg.len != 2*sizeof(float)) break;
pspatel321 33:6bc82b6b62e5 15 memcpy((void*)&CANdata.dcdcFan1Duty, &msg.data[0], sizeof(float));
pspatel321 33:6bc82b6b62e5 16 memcpy((void*)&CANdata.dcdcFan2Duty, &msg.data[4], sizeof(float));
pspatel321 33:6bc82b6b62e5 17 dcdc.setPwm(FAN1, CANdata.dcdcFan1Duty);
pspatel321 33:6bc82b6b62e5 18 dcdc.setPwm(FAN2, CANdata.dcdcFan2Duty);
pspatel321 33:6bc82b6b62e5 19 break;
pspatel321 33:6bc82b6b62e5 20
pspatel321 33:6bc82b6b62e5 21 case PUMP_CONTROL_ID:
pspatel321 33:6bc82b6b62e5 22 if (msg.len != 2*sizeof(float)) break;
pspatel321 33:6bc82b6b62e5 23 memcpy((void*)&CANdata.dcdcPump1Duty, &msg.data[0], sizeof(float));
pspatel321 33:6bc82b6b62e5 24 memcpy((void*)&CANdata.dcdcPump2Duty, &msg.data[4], sizeof(float));
pspatel321 33:6bc82b6b62e5 25 dcdc.setPwm(PUMP1, CANdata.dcdcPump1Duty);
pspatel321 33:6bc82b6b62e5 26 dcdc.setPwm(PUMP2, CANdata.dcdcPump2Duty);
pspatel321 33:6bc82b6b62e5 27 break;
pspatel321 33:6bc82b6b62e5 28
pspatel321 33:6bc82b6b62e5 29 case DCDC_CONTROL_ID:
pspatel321 33:6bc82b6b62e5 30 if (msg.len != sizeof(char)) break;
pspatel321 33:6bc82b6b62e5 31 if (msg.data[0] == 1) dcdc.set(1);
pspatel321 33:6bc82b6b62e5 32 else dcdc.set(0);
pspatel321 33:6bc82b6b62e5 33 break;
pspatel321 33:6bc82b6b62e5 34
pspatel321 36:0afc0fc8f86b 35 case AMS_MODE_ID:
pspatel321 33:6bc82b6b62e5 36 if (msg.len != sizeof(char)) break;
pspatel321 36:0afc0fc8f86b 37 if (msg.data[0] & 1<<2) { // AIRs closed?
pspatel321 33:6bc82b6b62e5 38 CANdata.airsClosed = true;
pspatel321 33:6bc82b6b62e5 39 dcdc.set(1);
pspatel321 33:6bc82b6b62e5 40 } else {
pspatel321 33:6bc82b6b62e5 41 CANdata.airsClosed = false;
pspatel321 33:6bc82b6b62e5 42 dcdc.set(0);
pspatel321 33:6bc82b6b62e5 43 }
pspatel321 33:6bc82b6b62e5 44 break;
pspatel321 33:6bc82b6b62e5 45
pspatel321 36:0afc0fc8f86b 46 case GLVBAT_SETSOC_ID:
pspatel321 33:6bc82b6b62e5 47 if (msg.len != sizeof(float)) break;
pspatel321 33:6bc82b6b62e5 48 glvBat.resetToSOC(*((float*)(&msg.data[0])));
pspatel321 33:6bc82b6b62e5 49 break;
pspatel321 33:6bc82b6b62e5 50
pspatel321 36:0afc0fc8f86b 51 case GLVBAT_SETAH_ID:
pspatel321 33:6bc82b6b62e5 52 if (msg.len != sizeof(float)) break;
pspatel321 33:6bc82b6b62e5 53 glvBat.resetToAh(*((float*)(&msg.data[0])));
pspatel321 33:6bc82b6b62e5 54 break;
pspatel321 33:6bc82b6b62e5 55
pspatel321 33:6bc82b6b62e5 56 case GLVBAT_SETCAPAC_ID:
pspatel321 33:6bc82b6b62e5 57 if (msg.len != sizeof(float)) break;
pspatel321 33:6bc82b6b62e5 58 glvBat.changeCapacity(*((float*)(&msg.data[0])));
pspatel321 33:6bc82b6b62e5 59 break;
pspatel321 33:6bc82b6b62e5 60 case STEERING_RESET_ID:
pspatel321 33:6bc82b6b62e5 61 NVIC_SystemReset();
pspatel321 33:6bc82b6b62e5 62 break;
pspatel321 33:6bc82b6b62e5 63 default:
pspatel321 33:6bc82b6b62e5 64 break;
pspatel321 33:6bc82b6b62e5 65 }
pspatel321 33:6bc82b6b62e5 66
pspatel321 33:6bc82b6b62e5 67 return true;
pspatel321 33:6bc82b6b62e5 68
pspatel321 33:6bc82b6b62e5 69 }
pspatel321 34:18bcf276d3bf 70 // Check for incoming messages from the xbees, relay them to the CAN function and send them out on the bus
pspatel321 34:18bcf276d3bf 71 bool inCommands::receiveMsgXbee()
pspatel321 33:6bc82b6b62e5 72 {
pspatel321 33:6bc82b6b62e5 73 CANMessage msg;
pspatel321 33:6bc82b6b62e5 74 if (xbeeRelay.receive(msg)) { // Incoming CAN message string received
pspatel321 33:6bc82b6b62e5 75 if (!can.txWrite(msg)) data.canFault = true; // Send it out on the CAN bus
pspatel321 33:6bc82b6b62e5 76 serviceCAN(&msg); // Send it into the local serviceCAN routine
pspatel321 31:7eaa5e881b56 77 return true;
pspatel321 33:6bc82b6b62e5 78 } else return false;
pspatel321 34:18bcf276d3bf 79 }
pspatel321 34:18bcf276d3bf 80
pspatel321 34:18bcf276d3bf 81 // Compare string to a word in the serial input, shorter to type
pspatel321 34:18bcf276d3bf 82 #define CMP(w, string) if (!strcasecmp(word[w-1], string))
pspatel321 36:0afc0fc8f86b 83
pspatel321 34:18bcf276d3bf 84 // Serial input
pspatel321 34:18bcf276d3bf 85 int inCommands::serviceSerial()
pspatel321 34:18bcf276d3bf 86 {
pspatel321 36:0afc0fc8f86b 87 static int end = 0; // End of string position
pspatel321 34:18bcf276d3bf 88
pspatel321 36:0afc0fc8f86b 89 int c=0;
pspatel321 36:0afc0fc8f86b 90 if (pc.readable()) c = pc.getc();
pspatel321 34:18bcf276d3bf 91 if (c == -1) return -2; // Invalid char, no char available
pspatel321 36:0afc0fc8f86b 92
pspatel321 34:18bcf276d3bf 93 char b = c; // Casted to char type
pspatel321 34:18bcf276d3bf 94 bool process = false; // Is string complete (ready to parse)?
pspatel321 34:18bcf276d3bf 95
pspatel321 34:18bcf276d3bf 96 if (b == '\n' || b == '\r') { // Enter key was pressed, dump for processing
pspatel321 34:18bcf276d3bf 97 tempData.inputStr[end] = 0; // Null terminate
pspatel321 34:18bcf276d3bf 98 end = 0; // Reset to start
pspatel321 34:18bcf276d3bf 99 process = true; // Flag for processing
pspatel321 34:18bcf276d3bf 100
pspatel321 34:18bcf276d3bf 101 } else if (b == '\b' || b == 127) { // Backspace or delete
pspatel321 34:18bcf276d3bf 102 if (end > 0) end--; // Move back one char
pspatel321 34:18bcf276d3bf 103 tempData.inputStr[end] = 0; // Erase char
pspatel321 34:18bcf276d3bf 104
pspatel321 34:18bcf276d3bf 105 } else if (b > 31 && b < 127) { // New valid displayable char
pspatel321 36:0afc0fc8f86b 106 tempData.inputStr[end++] = b; // Add to buffer
pspatel321 34:18bcf276d3bf 107 tempData.inputStr[end] = 0; // Add null terminator
pspatel321 34:18bcf276d3bf 108 if (end >= RX_SIZE) {
pspatel321 34:18bcf276d3bf 109 end = 0; // Reset end location
pspatel321 34:18bcf276d3bf 110 process = true; // Flag for processing
pspatel321 34:18bcf276d3bf 111 }
pspatel321 34:18bcf276d3bf 112 }
pspatel321 34:18bcf276d3bf 113 // Continue to parsing section only if flagged as complete and string not empty
pspatel321 36:0afc0fc8f86b 114 if (!process || strlen((char*)tempData.inputStr) == 0) return 0;
pspatel321 36:0afc0fc8f86b 115
pspatel321 36:0afc0fc8f86b 116 static char word[3][RX_SIZE+1]; // Hold 3 words
pspatel321 34:18bcf276d3bf 117 int pieces = sscanf(tempData.inputStr, "%s %s %s", word[0], word[1], word[2]); // Populate words
pspatel321 34:18bcf276d3bf 118 tempData.inputStr[0] = 0; // Empty the string displayed on screen
pspatel321 36:0afc0fc8f86b 119 char *next; // Used by strtof and strtoul
pspatel321 34:18bcf276d3bf 120
pspatel321 34:18bcf276d3bf 121 // One word commands
pspatel321 34:18bcf276d3bf 122 if (pieces == 1) {
pspatel321 34:18bcf276d3bf 123 // Reset the microcontroller
pspatel321 34:18bcf276d3bf 124 CMP(1, "reset") {
pspatel321 34:18bcf276d3bf 125 NVIC_SystemReset();
pspatel321 34:18bcf276d3bf 126 return 1;
pspatel321 34:18bcf276d3bf 127 }
pspatel321 34:18bcf276d3bf 128 }
pspatel321 36:0afc0fc8f86b 129 // Two word commands
pspatel321 34:18bcf276d3bf 130 if (pieces == 2) {
pspatel321 34:18bcf276d3bf 131 // Manual DC-DC on/off control
pspatel321 34:18bcf276d3bf 132 CMP(1, "dcdc") {
pspatel321 34:18bcf276d3bf 133 CMP(2, "on") {
pspatel321 34:18bcf276d3bf 134 dcdc.set(1);
pspatel321 34:18bcf276d3bf 135 return 1;
pspatel321 34:18bcf276d3bf 136 }
pspatel321 34:18bcf276d3bf 137 CMP(2, "off") {
pspatel321 34:18bcf276d3bf 138 dcdc.set(0);
pspatel321 34:18bcf276d3bf 139 return 1;
pspatel321 34:18bcf276d3bf 140 }
pspatel321 34:18bcf276d3bf 141 return -1;
pspatel321 34:18bcf276d3bf 142 }
pspatel321 34:18bcf276d3bf 143 // Artificially update the SOC (battery life %)
pspatel321 34:18bcf276d3bf 144 CMP(1, "SOC") {
pspatel321 34:18bcf276d3bf 145 CMP(2, "Reset") { // Command was "SOC reset" - reset to 100%, do this after a full charge
pspatel321 34:18bcf276d3bf 146 glvBat.resetToSOC(1);
pspatel321 34:18bcf276d3bf 147 return 1;
pspatel321 34:18bcf276d3bf 148 }
pspatel321 34:18bcf276d3bf 149 float soc = strtod(word[1], &next); // Command was "SOC xxx" where xxx is float between 0 and 1
pspatel321 34:18bcf276d3bf 150 if (*next == 0) {
pspatel321 34:18bcf276d3bf 151 if (glvBat.resetToSOC(soc)) return 1;
pspatel321 34:18bcf276d3bf 152 }
pspatel321 34:18bcf276d3bf 153 return -1;
pspatel321 34:18bcf276d3bf 154 }
pspatel321 34:18bcf276d3bf 155 // Artificially update the AmpHours count (linked with SOC)
pspatel321 34:18bcf276d3bf 156 CMP(1, "Ah") {
pspatel321 34:18bcf276d3bf 157 CMP(2, "Reset") { // Command was "Amphours reset", equivalent to "SOC reset"
pspatel321 34:18bcf276d3bf 158 glvBat.resetToSOC(1);
pspatel321 34:18bcf276d3bf 159 return 1;
pspatel321 34:18bcf276d3bf 160 }
pspatel321 34:18bcf276d3bf 161 float ah = strtod(word[1], &next); // Command was "Amphours xxx" where xxx is a float in amphours
pspatel321 34:18bcf276d3bf 162 if (*next == 0) {
pspatel321 34:18bcf276d3bf 163 if (glvBat.resetToAh(ah)) return 1;
pspatel321 34:18bcf276d3bf 164 }
pspatel321 34:18bcf276d3bf 165 return -1;
pspatel321 34:18bcf276d3bf 166 }
pspatel321 34:18bcf276d3bf 167 // Change the battery capacity setting for calculating Amphours
pspatel321 34:18bcf276d3bf 168 CMP(1, "Capacity") {
pspatel321 34:18bcf276d3bf 169 float cap = strtod(word[1], &next); // Command was "SOC xxx" where xxx is float between 0 and 1
pspatel321 34:18bcf276d3bf 170 if (*next == 0) {
pspatel321 34:18bcf276d3bf 171 if (glvBat.changeCapacity(cap)) return 1;
pspatel321 34:18bcf276d3bf 172 }
pspatel321 36:0afc0fc8f86b 173 return -1;
pspatel321 34:18bcf276d3bf 174 }
pspatel321 34:18bcf276d3bf 175 }
pspatel321 36:0afc0fc8f86b 176 // Three word commands
pspatel321 34:18bcf276d3bf 177 if (pieces == 3) {
pspatel321 34:18bcf276d3bf 178 // Fan Duty
pspatel321 34:18bcf276d3bf 179 CMP(1, "Fan") {
pspatel321 34:18bcf276d3bf 180 float val1 = strtod(word[1], &next);
pspatel321 34:18bcf276d3bf 181 if (*next == 0) {
pspatel321 34:18bcf276d3bf 182 float val2 = strtod(word[2], &next);
pspatel321 34:18bcf276d3bf 183 if (*next == 0) {
pspatel321 34:18bcf276d3bf 184 dcdc.setPwm(FAN1, val1);
pspatel321 34:18bcf276d3bf 185 dcdc.setPwm(FAN2, val2);
pspatel321 34:18bcf276d3bf 186 return 1;
pspatel321 34:18bcf276d3bf 187 }
pspatel321 34:18bcf276d3bf 188 }
pspatel321 34:18bcf276d3bf 189 return -1;
pspatel321 34:18bcf276d3bf 190 }
pspatel321 34:18bcf276d3bf 191
pspatel321 34:18bcf276d3bf 192 // Pump Duty
pspatel321 34:18bcf276d3bf 193 CMP(1, "Pump") {
pspatel321 34:18bcf276d3bf 194 float val1 = strtod(word[1], &next);
pspatel321 34:18bcf276d3bf 195 if (*next == 0) {
pspatel321 34:18bcf276d3bf 196 float val2 = strtod(word[2], &next);
pspatel321 34:18bcf276d3bf 197 if (*next == 0) {
pspatel321 34:18bcf276d3bf 198 dcdc.setPwm(FAN1, val1);
pspatel321 34:18bcf276d3bf 199 dcdc.setPwm(FAN2, val2);
pspatel321 34:18bcf276d3bf 200 return 1;
pspatel321 34:18bcf276d3bf 201 }
pspatel321 34:18bcf276d3bf 202 }
pspatel321 34:18bcf276d3bf 203 return -1;
pspatel321 34:18bcf276d3bf 204 }
pspatel321 34:18bcf276d3bf 205 }
pspatel321 34:18bcf276d3bf 206 return -1;
pspatel321 36:0afc0fc8f86b 207 }
pspatel321 36:0afc0fc8f86b 208
pspatel321 36:0afc0fc8f86b 209 void inCommands::thread_getInputs(void const* args)
pspatel321 36:0afc0fc8f86b 210 {
pspatel321 36:0afc0fc8f86b 211 while(1) {
pspatel321 36:0afc0fc8f86b 212 inCommands::serviceCAN();
pspatel321 36:0afc0fc8f86b 213 inCommands::receiveMsgXbee();
pspatel321 36:0afc0fc8f86b 214
pspatel321 36:0afc0fc8f86b 215 int ret = inCommands::serviceSerial();
pspatel321 36:0afc0fc8f86b 216 if (ret == -1) tempData.parseGoodChar = 'x';
pspatel321 36:0afc0fc8f86b 217 if (ret == 1) tempData.parseGoodChar = 251;
pspatel321 36:0afc0fc8f86b 218 osSignalSet((osThreadId)(tempData.wdtThreadId), 1<<2); // Signal watchdog thread
pspatel321 36:0afc0fc8f86b 219 }
pspatel321 30:91af74a299e1 220 }