diff --git a/Software/src/battery/BATTERIES.cpp b/Software/src/battery/BATTERIES.cpp index 53d0a7b7..34ea2699 100644 --- a/Software/src/battery/BATTERIES.cpp +++ b/Software/src/battery/BATTERIES.cpp @@ -68,6 +68,8 @@ const char* name_for_battery_type(BatteryType type) { return ChademoBattery::Name; case BatteryType::CmfaEv: return CmfaEvBattery::Name; + case BatteryType::FordMachE: + return FordMachEBattery::Name; case BatteryType::Foxess: return FoxessBattery::Name; case BatteryType::GeelyGeometryC: diff --git a/Software/src/battery/FORD-MACH-E-BATTERY.cpp b/Software/src/battery/FORD-MACH-E-BATTERY.cpp index 144024b0..e44325f4 100644 --- a/Software/src/battery/FORD-MACH-E-BATTERY.cpp +++ b/Software/src/battery/FORD-MACH-E-BATTERY.cpp @@ -167,10 +167,85 @@ void FordMachEBattery::handle_incoming_can_frame(CAN_frame rx_frame) { } void FordMachEBattery::transmit_can(unsigned long currentMillis) { + // Send 10ms CAN Message + if (currentMillis - previousMillis10 >= INTERVAL_10_MS) { + previousMillis10 = currentMillis; + + transmit_can_frame(&FORD_217); + transmit_can_frame(&FORD_442); + } + + // Send 30ms CAN Message + if (currentMillis - previousMillis30 >= INTERVAL_30_MS) { + previousMillis30 = currentMillis; + + counter_30ms = (counter_30ms + 1) % 16; // cycles 0-15 + + // Byte 2: upper nibble = 0xF, lower nibble = (0xF - counter_10ms) % 16 + FORD_7D.data.u8[2] = 0xF0 | ((0xF - counter_30ms) & 0x0F); + // Byte 3: upper nibble = counter_10ms, lower nibble = 0x0 + FORD_7D.data.u8[3] = (counter_30ms << 4) & 0xF0; + + // Byte 0: starts at 0xC0 and increments by 4 each step, wraps every 16 steps + FORD_204.data.u8[0] = 0xC0 + (counter_30ms * 4); + // Byte 5: starts at 0xFC and decrements by 1 each step, wraps every 16 steps + FORD_204.data.u8[5] = 0xFC - counter_30ms; + + // Byte 4: upper nibble = counter_10ms, lower nibble = 0x0 + FORD_4B0.data.u8[4] = (counter_30ms << 4) & 0xF0; + // Byte 7: upper nibble = 0xF, lower nibble = (0xF - counter_10ms) % 16 + FORD_4B0.data.u8[7] = 0xF0 | ((0xF - counter_30ms) & 0x0F); + + // Byte 2: starts at 0xC0 and increments by 4 each step, wraps every 16 steps + FORD_415.data.u8[2] = 0xC0 + (counter_30ms * 4); + // Byte 3: starts at 0xFC and decrements by 1 each step, wraps every 16 steps + FORD_415.data.u8[3] = 0xFC - counter_30ms; + + //TODO: handle FORD_4C properly very odd looping + + transmit_can_frame(&FORD_77); + transmit_can_frame(&FORD_7D); + transmit_can_frame(&FORD_167); + transmit_can_frame(&FORD_48F); //Only sent in AC charging logs! + transmit_can_frame(&FORD_204); + transmit_can_frame(&FORD_4B0); + transmit_can_frame(&FORD_47); + transmit_can_frame(&FORD_230); + transmit_can_frame(&FORD_415); + transmit_can_frame(&FORD_4C); + transmit_can_frame(&FORD_7E); + transmit_can_frame(&FORD_48); + transmit_can_frame(&FORD_165); + } + // Send 50ms CAN Message + if (currentMillis - previousMillis50 >= INTERVAL_50_MS) { + previousMillis50 = currentMillis; + transmit_can_frame(&FORD_42C); + transmit_can_frame(&FORD_42F); + transmit_can_frame(&FORD_43D); + } + // Send 100ms CAN Message if (currentMillis - previousMillis100 >= INTERVAL_100_MS) { previousMillis100 = currentMillis; - //transmit_can_frame(&TEST); + + transmit_can_frame( + &FORD_12F); //This message actually has checksum/counter, but it seems to close contactors without those + transmit_can_frame(&FORD_332); + transmit_can_frame(&FORD_333); + transmit_can_frame(&FORD_42B); + transmit_can_frame(&FORD_2EC); + transmit_can_frame(&FORD_156); + transmit_can_frame( + &FORD_5A); //This message actually has checksum/counter, but it seems to close contactors without those + transmit_can_frame(&FORD_166); + transmit_can_frame(&FORD_175); + } + // Send 1s CAN Message + if (currentMillis - previousMillis1000 >= INTERVAL_1_S) { + previousMillis1000 = currentMillis; + transmit_can_frame(&FORD_3C3); + transmit_can_frame(&FORD_581); } } diff --git a/Software/src/battery/FORD-MACH-E-BATTERY.h b/Software/src/battery/FORD-MACH-E-BATTERY.h index 91018fc1..540afe98 100644 --- a/Software/src/battery/FORD-MACH-E-BATTERY.h +++ b/Software/src/battery/FORD-MACH-E-BATTERY.h @@ -18,9 +18,12 @@ class FordMachEBattery : public CanBattery { static const int MAX_CELL_VOLTAGE_MV = 4250; static const int MIN_CELL_VOLTAGE_MV = 2900; - unsigned long previousMillis10 = 0; // will store last time a 10ms CAN Message was send - unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was send - unsigned long previousMillis10s = 0; // will store last time a 1s CAN Message was send + unsigned long previousMillis10 = 0; // will store last time a 10ms CAN Message was send + unsigned long previousMillis30 = 0; // will store last time a 10ms CAN Message was send + unsigned long previousMillis50 = 0; // will store last time a 100ms CAN Message was send + unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was send + unsigned long previousMillis1000 = 0; // will store last time a 1s CAN Message was send + unsigned long previousMillis10s = 0; // will store last time a 10s CAN Message was send int16_t cell_temperature[6] = {0}; int16_t maximum_temperature = 0; @@ -30,11 +33,158 @@ class FordMachEBattery : public CanBattery { uint16_t maximum_cellvoltage_mV = 3700; uint16_t minimum_cellvoltage_mV = 3700; - CAN_frame TEST = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x123, - .data = {0x10, 0x64, 0x00, 0xB0, 0x00, 0x1E, 0x00, 0x8F}}; + uint8_t counter_30ms = 0; + + CAN_frame FORD_47 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x047, + .data = {0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + CAN_frame FORD_48 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x048, + .data = {0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + CAN_frame FORD_4C = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x04C, + .data = {0x70, 0xAA, 0xBF, 0xDE, 0xCC, 0xEC, 0x00, 0x00}}; + CAN_frame FORD_5A = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x05A, + .data = {0x00, 0x00, 0x00, 0x0B, 0xF2, 0x90, 0x10, 0x00}}; + CAN_frame FORD_77 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x077, + .data = {0x00, 0x00, 0x0F, 0xFE, 0xFF, 0xFF, 0xFB, 0xFE}}; + CAN_frame FORD_7D = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x07D, + .data = {0x00, 0x00, 0xF0, 0xF0, 0x00, 0x3F, 0xEF, 0xFE}}; + CAN_frame FORD_7E = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x07E, + .data = {0x00, 0x00, 0x3E, 0x80, 0x00, 0x04, 0x00, 0x00}}; + CAN_frame FORD_156 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x156, + .data = {0x4B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}}; + CAN_frame FORD_165 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x165, + .data = {0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + CAN_frame FORD_166 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x166, + .data = {0x00, 0x00, 0x00, 0x01, 0x5C, 0x89, 0x00, 0x00}}; + CAN_frame FORD_167 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x167, + .data = {0x00, 0x80, 0x00, 0x11, 0xFF, 0xE0, 0x00, 0x00}}; + CAN_frame FORD_175 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x175, + .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + CAN_frame FORD_12F = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x12F, + .data = {0x0A, 0xF8, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; + CAN_frame FORD_204 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x204, + .data = {0xD4, 0x00, 0x7D, 0x00, 0x00, 0xF7, 0x00, 0x00}}; + CAN_frame FORD_217 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x217, + .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + CAN_frame FORD_230 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x230, + .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}}; + CAN_frame FORD_25B = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x25B, + .data = {0x01, 0xF4, 0x09, 0xF4, 0xE0, 0x00, 0x80, 0x00}}; + CAN_frame FORD_2EC = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x2EC, + .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}}; + CAN_frame FORD_332 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x332, + .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + CAN_frame FORD_333 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x333, + .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + CAN_frame FORD_3C3 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x3C3, + .data = {0x5C, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}}; + CAN_frame FORD_415 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x415, + .data = {0x00, 0x00, 0xC0, 0xFC, 0x0F, 0xFE, 0xEF, 0xFE}}; + CAN_frame FORD_42B = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x42B, + .data = {0xCB, 0xBE, 0x00, 0x02, 0x00, 0x00, 0xCE, 0x00}}; + CAN_frame FORD_42C = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x42C, + .data = {0x80, 0x02, 0x00, 0x00, 0x19, 0xA0, 0x00, 0x00}}; + CAN_frame FORD_42F = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x42F, + .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + CAN_frame FORD_43D = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x43D, + .data = {0x00, 0x00, 0xDC, 0x00, 0x00, 0x77, 0x00, 0x00}}; + CAN_frame FORD_442 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x442, + .data = {0x4E, 0x20, 0x78, 0x7E, 0x7C, 0x00, 0x00, 0x40}}; + CAN_frame FORD_48F = {.FD = false, //Only sent in active charging logs (OBC?) + .ext_ID = false, + .DLC = 8, + .ID = 0x48F, + .data = {0x30, 0x4E, 0x20, 0x80, 0x00, 0x00, 0x80, 0x00}}; + CAN_frame FORD_4B0 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x4B0, + .data = {0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0xF0}}; + CAN_frame FORD_581 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x4B0, + .data = {0x81, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; }; #endif