System Management code
Dependencies: mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP
Fork of SystemManagement by
inCommands/inCommands.cpp@36:0afc0fc8f86b, 2015-01-22 (annotated)
- 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?
User | Revision | Line number | New 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 | } |