diff --git a/Documentation/CAN dbcs/oi-inverter.dbc b/Documentation/CAN dbcs/oi-inverter.dbc new file mode 100644 index 0000000..8d964dd --- /dev/null +++ b/Documentation/CAN dbcs/oi-inverter.dbc @@ -0,0 +1,72 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: +VAL_TABLE_ Opmode 2 "ManualRun" 1 "Run" 0 "Off" ; + + +BO_ 400 InverterFeedback: 8 Vector__XXX + SG_ Inv_Voltage : 8|16@1+ (0.1,0) [0|6553.5] "V" Vector__XXX + SG_ Inv_Speed : 24|16@1+ (1,0) [0|65535] "rpm" Vector__XXX + SG_ Inv_Opmode : 7|8@0+ (1,0) [0|255] "" Vector__XXX + SG_ Inv_MotorTemp : 55|8@0+ (1,-30) [-30|225] "C" Vector__XXX + SG_ Inv_HeatsinkTemp : 47|8@0+ (1,-30) [-30|225] "C" Vector__XXX + +BO_ 2147483711 Vector__XXXMsg99: 8 Vector__XXX + SG_ pot : 0|12@1+ (1,0) [0|1] "" Vector__XXX + SG_ pot2 : 12|12@1+ (1,0) [0|1] "" Vector__XXX + SG_ cruise : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ start : 25|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ brake : 26|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ forward : 27|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ reverse : 28|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ bms : 29|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ cruisespeed : 32|14@1+ (1,0) [0|1] "" Vector__XXX + SG_ regenpreset : 48|8@1+ (1,0) [0|1] "" Vector__XXX + + + +BA_DEF_ BO_ "GenMsgBackgroundColor" STRING ; +BA_DEF_ BO_ "GenMsgForegroundColor" STRING ; +BA_DEF_ BO_ "matchingcriteria" INT 0 0; +BA_DEF_ BO_ "filterlabeling" INT 0 0; +BA_DEF_DEF_ "GenMsgBackgroundColor" "#ffffff"; +BA_DEF_DEF_ "GenMsgForegroundColor" "#000000"; +BA_DEF_DEF_ "matchingcriteria" 0; +BA_DEF_DEF_ "filterlabeling" 1; +BA_ "GenMsgBackgroundColor" BO_ 2147483711 "#57e389"; +BA_ "GenMsgForegroundColor" BO_ 2147483711 "#000000"; +VAL_ 400 Inv_Opmode 2 "ManualRun" 1 "Run" 0 "Off" ; + diff --git a/ZombieVerter_Regen.pdf b/Documentation/ZombieVerter_Regen.pdf similarity index 100% rename from ZombieVerter_Regen.pdf rename to Documentation/ZombieVerter_Regen.pdf diff --git a/include/Can_OI.h b/include/Can_OI.h index 7829be5..8fd331c 100644 --- a/include/Can_OI.h +++ b/include/Can_OI.h @@ -26,25 +26,41 @@ #include "canhardware.h" #include +#define NODEIDCANOI 1 + class Can_OI: public Inverter { public: - void Task100Ms() override; - void DecodeCAN(int, uint32_t*) override; - void SetTorque(float torquePercent) override; - float GetMotorTemperature() override { return motor_temp; } - float GetInverterTemperature() override { return inv_temp; } - float GetInverterVoltage() override { return voltage; } - float GetMotorSpeed() override { return speed; } - int GetInverterState() override; - void SetCanInterface(CanHardware* c) override; + void Task100Ms() override; + void DecodeCAN(int, uint32_t*) override; + void SetTorque(float torquePercent) override; + float GetMotorTemperature() override + { + return motor_temp; + } + float GetInverterTemperature() override + { + return inv_temp; + } + float GetInverterVoltage() override + { + return voltage; + } + float GetMotorSpeed() override + { + return speed; + } + int GetInverterState() override; + void SetCanInterface(CanHardware* c) override; + void ConfigCan(); private: - static int16_t speed; - static int16_t inv_temp; - static int16_t motor_temp; - static uint16_t voltage; - static int16_t final_torque_request; + static int16_t speed; + static int16_t inv_temp; + static int16_t motor_temp; + static uint16_t voltage; + static int16_t final_torque_request; + static void handleSDO(uint32_t data[2]); }; #endif // CAN_OI_H diff --git a/include/iomatrix.h b/include/iomatrix.h index f5be9ff..e2f304f 100644 --- a/include/iomatrix.h +++ b/include/iomatrix.h @@ -32,7 +32,7 @@ class IOMatrix { NONE, CHADEMOALLOW, OBCENABLE, HEATERENABLE, RUNINDICATION, WARNINDICATION, COOLANTPUMP, NEGCONTACTOR, BRAKELIGHT, REVERSELIGHT, HEATREQ, HVREQ, - DCFCREQUEST, BRAKEVACPUMP, COOLINGFAN, HVACTIVE, PWM_TIM3,CP_SPOOF, + DCFCREQUEST, BRAKEVACPUMP, COOLINGFAN, HVACTIVE, SHIFTLOCKNO, PWM_TIM3,CP_SPOOF, GS450HOIL,PWMTEMPGAUGE, PWMSOCGAUGE, LAST }; //order of these matters! diff --git a/include/param_prj.h b/include/param_prj.h index ff4d7a3..95d78e8 100644 --- a/include/param_prj.h +++ b/include/param_prj.h @@ -18,7 +18,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#define VER 2.30.TA + +#define VER 2.31.TE /* Entries must be ordered as follows: @@ -26,7 +27,7 @@ 2. Temporary parameters (id = 0) 3. Display values */ -//Next param id (increase when adding new parameter!): 139 +//Next param id (increase when adding new parameter!): 149 /* category name unit min max default id */ #define PARAM_LIST \ PARAM_ENTRY(CAT_SETUP, Inverter, INVMODES, 0, 8, 0, 5 ) \ @@ -48,6 +49,7 @@ PARAM_ENTRY(CAT_SETUP, DCDCCan, CAN_DEV, 0, 1, 1, 107 ) \ PARAM_ENTRY(CAT_SETUP, HeaterCan, CAN_DEV, 0, 1, 1, 138 ) \ PARAM_ENTRY(CAT_SETUP, MotActive, MotorsAct,0, 3, 0, 129 ) \ + PARAM_ENTRY(CAT_SETUP, ConfigCANOI, ONOFF, 0, 1, 0, 149 ) \ PARAM_ENTRY(CAT_THROTTLE, potmin, "dig", 0, 4095, 0, 7 ) \ PARAM_ENTRY(CAT_THROTTLE, potmax, "dig", 0, 4095, 4095, 8 ) \ PARAM_ENTRY(CAT_THROTTLE, pot2min, "dig", 0, 4095, 4095, 9 ) \ @@ -59,6 +61,8 @@ PARAM_ENTRY(CAT_THROTTLE, regenramp, "%/10ms", 0.1, 100, 1, 68 ) \ PARAM_ENTRY(CAT_THROTTLE, potmode, POTMODES, 0, 1, 0, 11 ) \ PARAM_ENTRY(CAT_THROTTLE, dirmode, DIRMODES, 0, 4, 1, 12 ) \ + PARAM_ENTRY(CAT_THROTTLE, DirChange, DIRLIM, 0, 2, 0, 147 ) \ + PARAM_ENTRY(CAT_THROTTLE, DirChangeRpm,"rpm", 0, 20000, 500, 139 ) \ PARAM_ENTRY(CAT_THROTTLE, reversemotor, ONOFF, 0, 1, 0, 127 ) \ PARAM_ENTRY(CAT_THROTTLE, throtramp, "%/10ms", 1, 100, 10, 13 ) \ PARAM_ENTRY(CAT_THROTTLE, throtramprpm,"rpm", 0, 20000, 20000, 14 ) \ @@ -119,14 +123,14 @@ PARAM_ENTRY(CAT_CLOCK, Pre_Min, "Mins", 0, 59, 0, 54 ) \ PARAM_ENTRY(CAT_CLOCK, Pre_Dur, "Mins", 0, 60, 0, 55 ) \ PARAM_ENTRY(CAT_IOPINS, PumpPWM, PumpOutType,0, 2, 0, 135 ) \ - PARAM_ENTRY(CAT_IOPINS, Out1Func, PINFUNCS, 0, 15, 6, 80 ) \ - PARAM_ENTRY(CAT_IOPINS, Out2Func, PINFUNCS, 0, 15, 7, 81 ) \ - PARAM_ENTRY(CAT_IOPINS, Out3Func, PINFUNCS, 0, 15, 3, 82 ) \ - PARAM_ENTRY(CAT_IOPINS, SL1Func, PINFUNCS, 0, 15, 0, 83 ) \ - PARAM_ENTRY(CAT_IOPINS, SL2Func, PINFUNCS, 0, 15, 0, 84 ) \ - PARAM_ENTRY(CAT_IOPINS, PWM1Func, PINFUNCS, 0, 20, 0, 85 ) \ - PARAM_ENTRY(CAT_IOPINS, PWM2Func, PINFUNCS, 0, 20, 4, 86 ) \ - PARAM_ENTRY(CAT_IOPINS, PWM3Func, PINFUNCS, 0, 20, 2, 87 ) \ + PARAM_ENTRY(CAT_IOPINS, Out1Func, PINFUNCS, 0, 16, 6, 80 ) \ + PARAM_ENTRY(CAT_IOPINS, Out2Func, PINFUNCS, 0, 16, 7, 81 ) \ + PARAM_ENTRY(CAT_IOPINS, Out3Func, PINFUNCS, 0, 16, 3, 82 ) \ + PARAM_ENTRY(CAT_IOPINS, SL1Func, PINFUNCS, 0, 16, 0, 83 ) \ + PARAM_ENTRY(CAT_IOPINS, SL2Func, PINFUNCS, 0, 16, 0, 84 ) \ + PARAM_ENTRY(CAT_IOPINS, PWM1Func, PINFUNCS, 0, 21, 0, 85 ) \ + PARAM_ENTRY(CAT_IOPINS, PWM2Func, PINFUNCS, 0, 21, 4, 86 ) \ + PARAM_ENTRY(CAT_IOPINS, PWM3Func, PINFUNCS, 0, 21, 2, 87 ) \ PARAM_ENTRY(CAT_IOPINS, GP12VInFunc, PINFUNCS, 0, 13, 12, 98 ) \ PARAM_ENTRY(CAT_IOPINS, HVReqFunc, PINFUNCS, 0, 13, 12, 99 ) \ PARAM_ENTRY(CAT_IOPINS, PB1InFunc, PINFUNCS, 0, 13, 12, 140 ) \ @@ -204,6 +208,7 @@ VALUE_ENTRY(din_reverse, ONOFF, 2039 ) \ VALUE_ENTRY(din_bms, ONOFF, 2040 ) \ VALUE_ENTRY(din_12Vgp, ONOFF, 2071 ) \ + VALUE_ENTRY(ShiftLock, ONOFF, 2108 ) \ VALUE_ENTRY(handbrk, ONOFF, 2041 ) \ VALUE_ENTRY(Gear1, ONOFF, 2042 ) \ VALUE_ENTRY(Gear2, ONOFF, 2043 ) \ @@ -247,7 +252,7 @@ VALUE_ENTRY(powerheater, "W", 2098 ) \ VALUE_ENTRY(VehLockSt, ONOFF, 2100 ) \ -//Next value Id: 2108 +//Next value Id: 2109 //Dead params /* @@ -259,8 +264,8 @@ #define VERSTR STRINGIFY(4=VER) #define PINFUNCS "0=None, 1=ChaDeMoAlw, 2=OBCEnable, 3=HeaterEnable, 4=RunIndication, 5=WarnIndication," \ "6=CoolantPump, 7=NegContactor, 8=BrakeLight, 9=ReverseLight, 10=HeatReq, 11=HVRequest," \ - "12=DCFCRequest, 13=BrakeVacPump, 14=CoolingFan, 15=HvActive, 16=PwmTim3, 17=CpSpoof,"\ - "18=GS450pump, 19=PwmTempGauge, 20=PwmSocGauge" + "12=DCFCRequest, 13=BrakeVacPump, 14=CoolingFan, 15=HvActive, 16=ShiftLockNO, 17=PwmTim3, 18=CpSpoof,"\ + "19=GS450pump, 20=PwmTempGauge, 21=PwmSocGauge" #define APINFUNCS "0=None, 1=ProxPilot, 2=BrakeVacSensor" #define SHIFTERS "0=None, 1=BMW_F30, 2=JLR_G1, 3=JLR_G2, 4=BMW_E65" #define SHNTYPE "0=None, 1=ISA, 2=SBOX, 3=VAG" @@ -315,6 +320,7 @@ #define MotorsAct "0=Mg1and2, 1=Mg1, 2=Mg2, 3=BlendingMG2and1" #define PumpOutType "0=GS450hOil, 1=TachoOut, 2=SpeedoOut" #define LIMITREASON "0=None, 1=UDClimLow, 2=UDClimHigh, 4=IDClimLow, 8=IDClimHigh, 16=TempLim" +#define DIRLIM "0=None, 1=SpeedThres, 2=SpeedBrake" #define CAN_PERIOD_100MS 0 #define CAN_PERIOD_10MS 1 diff --git a/src/Can_OI.cpp b/src/Can_OI.cpp index fa099f1..dc4bc5a 100644 --- a/src/Can_OI.cpp +++ b/src/Can_OI.cpp @@ -33,14 +33,34 @@ uint8_t Inv_Opmode=0; int opmode; uint16_t InvStartTimeout=0; +static bool RespondReq = 0; +static bool EmptyField = 0; +static bool ActionSuccess = 0; +static bool CanField = 0; +static uint8_t ConfigStep = 0; +static uint8_t IntStep = 0; +static uint8_t EmptyCount = 0; + +static uint16_t xarr=0; + +static uint8_t CanConfigTxArr[5][11]= +{ + {0x90,0x01,0x00,0x00,0xD0,0x07,0x00,0x08,0xE8,0x03,0x00}, + {0x90,0x01,0x00,0x00,0xD1,0x07,0x08,0x10,0x10,0x27,0x00}, + {0x90,0x01,0x00,0x00,0xDC,0x07,0x18,0x10,0xE8,0x03,0x00}, + {0x90,0x01,0x00,0x00,0xE3,0x07,0x28,0x08,0xE8,0x03,0x1E}, + {0x90,0x01,0x00,0x00,0xE4,0x07,0x30,0x08,0xE8,0x03,0x1E} +}; + void Can_OI::SetCanInterface(CanHardware* c) { - can = c; + can = c; - can->RegisterUserMessage(0x190);//Open Inv Msg. Dec 400 for RPM. - can->RegisterUserMessage(0x19A);//Open Inv Msg. Dec 410 for temps - can->RegisterUserMessage(0x1A4);//Open Inv Msg. Dec 420 for Voltage. - can->RegisterUserMessage(0x1AE);//Open Inv Msg. Dec 430 for Opmode. + can->RegisterUserMessage(0x190);//Open Inv Msg. Dec 400 for RPM. + //can->RegisterUserMessage(0x19A);//Open Inv Msg. Dec 410 for temps + //can->RegisterUserMessage(0x1A4);//Open Inv Msg. Dec 420 for Voltage. + //can->RegisterUserMessage(0x1AE);//Open Inv Msg. Dec 430 for Opmode. + can->RegisterUserMessage(0x580 + NODEIDCANOI); //For config responses to check if it conflicts with FOCCI NODE 22 Response } void Can_OI::DecodeCAN(int id, uint32_t* data) @@ -49,77 +69,136 @@ void Can_OI::DecodeCAN(int id, uint32_t* data) //0x190 bits 0-15 motor rpm x1 //0x19A bits 0-15 heatsink temp x10 - uint8_t* bytes = (uint8_t*)data;// arrgghhh this converts the two 32bit array into bytes. See comments are useful:) - - if (id == 0x1A4)// THIS MSG CONTAINS INV VOLTAGE - { - voltage=((bytes[1]<<8)|(bytes[0]))/10; - } - else if (id == 0x190)// THIS MSG CONTAINS MOTOR RPM - { - speed=((bytes[1]<<8)|(bytes[0])); - } - else if (id == 0x19A)// THIS MSG CONTAINS INVERTER HEATSINK TEMP - { - inv_temp = ((bytes[1]<<8)|(bytes[0]))/10;//INVERTER TEMP - motor_temp = 0;//MOTOR TEMP - } - - else if (id == 0x1AE)// THIS MSG CONTAINS OPMODE - { - Inv_Opmode = bytes[0];//INVERTER OPMODE - //0=Off, 1=Run, 2=ManualRun, 3=Boost, 4=Buck, 5=Sine, 6=AcHeat - - } + uint8_t* bytes = (uint8_t*)data;// arrgghhh this converts the two 32bit array into bytes. See comments are useful:) + + if (id == 0x190)// Configured message + { + Inv_Opmode = bytes[0];//INVERTER OPMODE + //0=Off, 1=Run, 2=ManualRun, 3=Boost, 4=Buck, 5=Sine, 6=AcHeat + voltage=((bytes[2]<<8)|(bytes[1]))/10; + speed=((bytes[4]<<8)|(bytes[3])); + inv_temp = bytes[5]-30;//INVERTER TEMP + motor_temp = bytes[6]-30;//MOTOR TEMP + } + else if (id == 0x580 + NODEIDCANOI)// Response on config Id 1 would be 0x581 + { + handleSDO(data); + } +} + +void Can_OI::handleSDO(uint32_t data[2]) //SDO responses handling +{ + uint8_t* bytes = (uint8_t*)data;// arrgghhh this converts the two 32bit array into bytes. See comments are useful:) + if(RespondReq == 1)//only look at this if we have sent a message looking for a response + { + if(bytes[0] == 0x80) + { + EmptyField = true; + EmptyCount++; + } + else if(bytes[0] == 0x43) + { + CanField = true; + EmptyCount = 0; + } + else if(bytes[0] == 0x60) + { + ActionSuccess = true; + EmptyCount = 0; + } + else + { + EmptyCount = 0; + } + RespondReq = 0; //recieved message so clear respond request + + if(EmptyCount > 4)//4 empty fields/Aborts recieved stop configuring + { + ConfigStep = 5; + } + } + } void Can_OI::SetTorque(float torquePercent) { - final_torque_request = torquePercent * 10; - Param::SetInt(Param::torque,final_torque_request);//post processed final torue value sent to inv to web interface - int opmode = Param::GetInt(Param::opmode); - uint8_t tempIO=0; - - if(Param::GetBool(Param::din_forward) && opmode==MOD_RUN) tempIO+=8;//only send direction data if in run mode - if(Param::GetBool(Param::din_reverse) && opmode==MOD_RUN) tempIO+=16;//only send direction data if in run mode - if(Param::GetBool(Param::din_brake)) tempIO+=4; - //if(Param::GetBool(Param::din_start)) tempIO+=2; - if(opmode==MOD_RUN && InvStartTimeout!=0)//Set the start signal true for 3 seconds on vcu entering run mode. + //Not used + final_torque_request = torquePercent * 10; + Param::SetInt(Param::torque,final_torque_request);//!!! NOT USED BY IO inverter post processed final torue value sent to inv to web interface + //// + + int opmode = Param::GetInt(Param::opmode); + int dir = Param::GetInt(Param::dir); + + uint8_t tempIO=0; + + if(opmode==MOD_RUN) + { + if(dir == 1)//Forward + { + tempIO+=8;//Forward, only send direction data if in run mode + } + else if(dir == -1)//Reverse + { + tempIO+=16;//Reverse, only send direction data if in run mode + } + } + + if(Param::GetBool(Param::din_brake)) tempIO+=4; + //if(Param::GetBool(Param::din_start)) tempIO+=2; + if(opmode==MOD_RUN && InvStartTimeout!=0)//Set the start signal true for 3 seconds on vcu entering run mode. { - InvStartTimeout--; - tempIO+=2;//inv start signal on for 3 secs once enter vcu run mode + InvStartTimeout--; + tempIO+=2;//inv start signal on for 3 secs once enter vcu run mode } - if(opmode==MOD_OFF) - { - InvStartTimeout=300; - } + if(opmode==MOD_OFF) + { + InvStartTimeout=300; + } - uint32_t data[2]; - uint32_t pot = Param::GetInt(Param::pot) & 0xFFF; - uint32_t pot2 = Param::GetInt(Param::pot2) & 0xFFF; - uint32_t canio = tempIO & 0x3F; - uint32_t ctr = Param::GetInt(Param::canctr) & 0x3; - uint32_t cruise = Param::GetInt(Param::cruisespeed) & 0x3FFF; - uint32_t regen = 0x00;//Param::GetInt(Param::potbrake) & 0x7F; + /* + pot[0:11] + pot2[12:23] + canio[24:29] + cruise[24] + start[25] + brake[26] + forward[27] + reverse[28] + bms[29] + canrun1[30:31] + cruisespeed[32:45] + canrun2[46:47] + regenpreset[48:55] + cancrc[56:63] + */ - data[0] = pot | (pot2 << 12) | (canio << 24) | (ctr << 30); - data[1] = cruise | (ctr << 14) | (regen << 16); + uint32_t data[2]; + uint32_t pot = Param::GetInt(Param::pot) & 0xFFF; + uint32_t pot2 = Param::GetInt(Param::pot2) & 0xFFF; + uint32_t canio = tempIO & 0x3F; + uint32_t ctr = Param::GetInt(Param::canctr) & 0x3; + uint32_t cruise = 0;//Param::GetInt(Param::cruisespeed) & 0x3FFF; // Cruise disabled + uint32_t regen = 100& 0x7F;//Param::GetInt(Param::potbrake) & 0x7F; // Fixed for now 100% regen allowed - crc_reset(); - uint32_t crc = crc_calculate_block(data, 2) & 0xFF; - data[1] |= crc << 24; + data[0] = pot | (pot2 << 12) | (canio << 24) | (ctr << 30); + data[1] = cruise | (ctr << 14) | (regen << 16); - can->Send(0x3F,data);//send 0x3F + crc_reset(); + uint32_t crc = crc_calculate_block(data, 2) & 0xFF; + data[1] |= crc << 24; + + can->Send(0x3F,data);//send 0x3F } int Can_OI::GetInverterState() { - if(Inv_Opmode==0) statusInv = 0; - if(Inv_Opmode==1) statusInv = 1; - if(opmode==MOD_OFF) statusInv = 0;//Resort to off if vcu is in off state. - return statusInv; + if(Inv_Opmode==0) statusInv = 0; + if(Inv_Opmode==1) statusInv = 1; + if(opmode==MOD_OFF) statusInv = 0;//Resort to off if vcu is in off state. + return statusInv; } @@ -127,19 +206,275 @@ int Can_OI::GetInverterState() void Can_OI::Task100Ms() { -opmode = Param::GetInt(Param::opmode); -if(opmode==MOD_OFF) -{ - voltage=0;//Clear all vals when in off mode to ensure real vals are displayed on next start - speed=0; - inv_temp=0; - motor_temp=0; - Inv_Opmode=0; - final_torque_request=0; -} + opmode = Param::GetInt(Param::opmode); + if(opmode==MOD_OFF) + { + voltage=0;//Clear all vals when in off mode to ensure real vals are displayed on next start + speed=0; + inv_temp=0; + motor_temp=0; + Inv_Opmode=0; + final_torque_request=0; + } + if(Param::GetInt(Param::ConfigCANOI)==1)//do the config shit + { + ConfigCan(); + } } +void Can_OI::ConfigCan() +{ + +//CAN sending// + uint8_t bytes[8]; + + if(ConfigStep == 0)//Clear all TX CAN configs + { + if(RespondReq == 0 && EmptyField == 0) + { + bytes[0] = 0x23; //write request general + bytes[1] = 0x00; //Can TX message index + bytes[2] = 0x31; //Can TX message + bytes[3] = 0x00; //sub index + bytes[4] = 0x00; + bytes[5] = 0x00; + bytes[6] = 0x00; + bytes[7] = 0x00; + can->Send(0x600 + NODEIDCANOI, (uint32_t*)bytes,8); // + + RespondReq = 1; + } + if(EmptyField == 1) + { + EmptyField = 0; + ConfigStep++; + } + } + else if(ConfigStep == 1)//Clear all RX CAN configs + { + if(RespondReq == 0 && EmptyField == 0) + { + bytes[0] = 0x23; //write request general + bytes[1] = 0x80; //Can RX message index + bytes[2] = 0x31; //Can message + bytes[3] = 0x00; //sub index + bytes[4] = 0x00; + bytes[5] = 0x00; + bytes[6] = 0x00; + bytes[7] = 0x00; + can->Send(0x600 + NODEIDCANOI, (uint32_t*)bytes,8); // + + RespondReq = 1; + } + if(EmptyField == 1) + { + EmptyField = 0; + ConfigStep++; + IntStep= 0; + ActionSuccess = false; + } + } + else if(ConfigStep == 2)//Config TX CAN frames + { + if(xarr < 6) + { + if(IntStep == 0) + { + if(ActionSuccess == true) + { + IntStep= 1; + ActionSuccess = false; + } + else if(RespondReq == 0) + { + bytes[0] = 0x23; //write request general + bytes[1] = 0x00; //write request general + bytes[2] = 0x30; //write request can tx + bytes[3] = 0x00; //write request can tx index + bytes[4] = CanConfigTxArr[xarr][0]; //CAN ID + bytes[5] = CanConfigTxArr[xarr][1]; //CAN ID + bytes[6] = CanConfigTxArr[xarr][2]; //CAN ID + bytes[7] = CanConfigTxArr[xarr][3]; //CAN ID + + can->Send(0x600 + NODEIDCANOI, (uint32_t*)bytes,8); // + + RespondReq = 1; + } + } + + if(IntStep == 1) + { + if(ActionSuccess == true) + { + IntStep= 2; + ActionSuccess = false; + } + else if(RespondReq == 0) + { + bytes[0] = 0x23; //write request general + bytes[1] = 0x00; //write request general + bytes[2] = 0x30; //write request can tx + bytes[3] = 0x01; //write request can tx index + bytes[4] = CanConfigTxArr[xarr][4]; //Param ID + bytes[5] = CanConfigTxArr[xarr][5]; //Param ID + bytes[6] = CanConfigTxArr[xarr][6]; //Start Bit + bytes[7] = CanConfigTxArr[xarr][7]; //Length in Bit + + can->Send(0x600 + NODEIDCANOI, (uint32_t*)bytes,8); // + RespondReq = 1; + } + } + + if(IntStep == 2) + { + if(ActionSuccess == true) + { + IntStep= 0; + ActionSuccess = false; + xarr++; + } + else if(RespondReq == 0) + { + bytes[0] = 0x23; //write request general + bytes[1] = 0x00; //write request general + bytes[2] = 0x30; //write request can tx + bytes[3] = 0x02; //write request can tx index + bytes[4] = CanConfigTxArr[xarr][8]; //Gain LSB + bytes[5] =CanConfigTxArr[xarr][9]; //Gain MSB + bytes[6] = 0x00; //Offset LSB - No change for mapping + bytes[7] = CanConfigTxArr[xarr][10];; //Offset MSB + can->Send(0x600 + NODEIDCANOI, (uint32_t*)bytes,8); // + + RespondReq = 1; + } + } + } + else + { + RespondReq = 0; + IntStep = 0; + xarr = 0; + ConfigStep++; + } + } + else if(ConfigStep == 3)//Config RX CAN frames + { + /* //NO RX FRAMES needed + if(xarr < 7) + { + if(IntStep == 0) + { + if(ActionSuccess == true) + { + IntStep= 1; + ActionSuccess = false; + } + else if(RespondReq == 0) + { + bytes[0] = 0x23; //write request general + bytes[1] = 0x01; //write request can rx + bytes[2] = 0x30; //write request can rx + bytes[3] = 0x00; //write request can rx index + bytes[4] = CanConfigRxArr[xarr][0]; //CAN ID + bytes[5] = CanConfigRxArr[xarr][1]; //CAN ID + bytes[6] = CanConfigRxArr[xarr][2]; //CAN ID + bytes[7] = CanConfigRxArr[xarr][3]; //CAN ID + + can->Send(0x600 + NODEIDCANOI, (uint32_t*)bytes,8); // + RespondReq = 1; + } + } + + if(IntStep == 1) + { + if(ActionSuccess == true) + { + IntStep= 2; + ActionSuccess = false; + } + else if(RespondReq == 0) + { + bytes[0] = 0x23; //write request general + bytes[1] = 0x01; //write request can rx + bytes[2] = 0x30; //write request can rx + bytes[3] = 0x01; //write request can tx index + bytes[4] = CanConfigRxArr[xarr][4]; //Param ID + bytes[5] = CanConfigRxArr[xarr][5]; //Param ID + bytes[6] = CanConfigRxArr[xarr][6]; //Start Bit + bytes[7] = CanConfigRxArr[xarr][7]; //Length in Bit + + can->Send(0x600 + NODEIDCANOI, (uint32_t*)bytes,8); // + RespondReq = 1; + } + } + + if(IntStep == 2) + { + if(ActionSuccess == true) + { + IntStep= 0; + ActionSuccess = false; + xarr++; + } + else if(RespondReq == 0) + { + bytes[0] = 0x23; //write request general + bytes[1] = 0x01; //write request can rx + bytes[2] = 0x30; //write request can rx + bytes[3] = 0x02; //write request can tx index + bytes[4] = 0xE8; //Gain LSB - No change for mapping + bytes[5] = 0x03; //Gain MSB - No change for mapping + bytes[6] = 0x00; //Offset LSB - No change for mapping + bytes[7] = 0x00; //Offset MSB - No change for mapping + + can->Send(0x600 + NODEIDCANOI, (uint32_t*)bytes,8); // + RespondReq = 1; + } + } + } + else + { + RespondReq = 0; + IntStep = 0; + xarr = 0; + ActionSuccess = false; + ConfigStep++; + } + */ + RespondReq = 0; + IntStep = 0; + xarr = 0; + ActionSuccess = false; + ConfigStep++; + } + else if(ConfigStep == 4)//Save CAN Mapping to flash + { + if(RespondReq == 0 && ActionSuccess == false) + { + bytes[0] = 0x23; //write request general + bytes[1] = 0x02; + bytes[2] = 0x50; //Save all to flash + bytes[3] = 0x00; + bytes[4] = 0x00; + bytes[5] = 0x00; + bytes[6] = 0x00; + bytes[7] = 0x00; + + can->Send(0x600 + NODEIDCANOI, (uint32_t*)bytes,8); // + ActionSuccess = false; + RespondReq = true; + } + else if(ActionSuccess == true) + { + ConfigStep++; + } + } + else if(ConfigStep == 5)//Config completed + { + Param::SetInt(Param::ConfigCANOI,0); + } +} diff --git a/src/JLR_G1.cpp b/src/JLR_G1.cpp index a0f8cd5..c159062 100644 --- a/src/JLR_G1.cpp +++ b/src/JLR_G1.cpp @@ -1,7 +1,7 @@ /* * This file is part of the Zombieverter project. * - * Copyright (C) 2023 Damien Maguire + * Copyright (C) 2023 Damien Maguire & Tom de Bree * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -60,6 +60,8 @@ void JLR_G1::sendcan() { uint8_t bytes[8]; //-1=Reverse, 0=Neutral, 1=Forward , 2=Park + //int8_t selectedDir = Param::GetInt(Param::dir); + if(Param::GetInt(Param::opmode)==!MOD_RUN) DirJLRG1=JLR_Park; if (DirJLRG1 == JLR_Park) @@ -93,7 +95,6 @@ void JLR_G1::sendcan() bytes[5] = 0xFF; bytes[6] = 0x01; bytes[7] = 0x00; - this->gear = REVERSE; } @@ -105,7 +106,6 @@ void JLR_G1::sendcan() bytes[5] = 0xFF; bytes[6] = 0x02; bytes[7] = 0x00; - this->gear = NEUTRAL; } @@ -117,7 +117,6 @@ void JLR_G1::sendcan() bytes[5] = 0xFF; bytes[6] = 0x04; bytes[7] = 0x00; - this->gear = DRIVE; } @@ -140,24 +139,24 @@ void JLR_G1::Task10Ms() { if(ShtdwnCnt < 20) { - Cnt20ms++; - if (Cnt20ms==2) - { - sendcan(); - Cnt3f3 ++; - if (DirJLRG1 == JLR_Park) + Cnt20ms++; + if (Cnt20ms==2) { - if (Cnt3f3 == 0x02) + sendcan(); + Cnt3f3 ++; + if (DirJLRG1 == JLR_Park) { - Cnt3f3 = 0x04; + if (Cnt3f3 == 0x02) + { + Cnt3f3 = 0x04; + } } + if (Cnt3f3 == 0xF) + { + Cnt3f3 = 0x00; + } + Cnt20ms = 0; } - if (Cnt3f3 == 0xF) - { - Cnt3f3 = 0x00; - } - Cnt20ms = 0; - } } } diff --git a/src/JLR_G2.cpp b/src/JLR_G2.cpp index 0e08c48..b77ace7 100644 --- a/src/JLR_G2.cpp +++ b/src/JLR_G2.cpp @@ -1,7 +1,7 @@ /* * This file is part of the Zombieverter project. * - * Copyright (C) 2023 Damien Maguire + * Copyright (C) 2023 Damien Maguire & Tom de Bree * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,8 +36,8 @@ uint8_t KnobPos, KnobPosDes = 0; uint8_t Knoblock = 0; -#define Unlocked 0x40 -#define Locked 0x00 +#define Unlocked 0x40//0x40 +#define Locked 0x00//0x00 uint16_t Cnt02C = 0; uint8_t Cnt0E0; @@ -74,6 +74,9 @@ void JLR_G2::sendcan() { uint8_t bytes[8]; //-1=Reverse, 0=Neutral, 1=Forward , 2=Park + + int8_t selectedDir = Param::GetInt(Param::dir); + if(Param::GetInt(Param::opmode)==!MOD_RUN) DirJLRG2=JLR_Park; bytes[0] = 0x00; //0x1E; @@ -87,19 +90,30 @@ void JLR_G2::sendcan() else { */ + if(Param::GetInt(Param::opmode)==MOD_RUN) + { + bytes[2] = 0x01;// on + } + else + { + bytes[2] = 0x00; + } if (KnobPosDes == Raise) { - bytes[2] = 0x09; + bytes[2] = 0x08 | bytes[2]; } if (KnobPosDes == Lower) { - bytes[2] = 0x10; + bytes[2] = 0x10 |bytes[2]; } /* KnobPos = KnobPosDes; } */ + bytes[6] = 0x00; + bytes[7] = 0x00; + if (DirJLRG2 == JLR_Park) { bytes[3] = Knoblock | 0x12; @@ -115,9 +129,11 @@ void JLR_G2::sendcan() bytes[3] = Knoblock | 0x00; bytes[4] = byte4G2[Cnt02C]; bytes[5] = byte5RG2[Cnt02C]; - bytes[6] = 0x01; - bytes[7] = 0x00; - + if(selectedDir == -1) + { + bytes[6] = 0x01; + bytes[7] = 0x00; + } this->gear = REVERSE; } @@ -126,9 +142,11 @@ void JLR_G2::sendcan() bytes[3] = Knoblock | 0x01; bytes[4] = byte4G2[Cnt02C]; bytes[5] = byte5NG2[Cnt02C]; - bytes[6] = 0x02; - bytes[7] = 0x00; - + if(selectedDir == 0) + { + bytes[6] = 0x02; + bytes[7] = 0x00; + } this->gear = NEUTRAL; } @@ -137,9 +155,11 @@ void JLR_G2::sendcan() bytes[3] = Knoblock | 0x04; bytes[4] = byte4G2[Cnt02C] | 0x0B; bytes[5] = byte5DG2[Cnt02C]; - bytes[6] = 0x04; - bytes[7] = 0x00; - + if(selectedDir == 1) + { + bytes[6] = 0x04; + bytes[7] = 0x00; + } this->gear = DRIVE; } diff --git a/src/stm32_vcu.cpp b/src/stm32_vcu.cpp index 4cdf684..717c679 100644 --- a/src/stm32_vcu.cpp +++ b/src/stm32_vcu.cpp @@ -506,6 +506,16 @@ static void Ms100Task(void) { IOMatrix::GetPin(IOMatrix::HVACTIVE)->Clear();//HV Active Off } + + //ShiftLock Out output + if(opmode==MOD_RUN && Param::GetInt(Param::ShiftLock) == 1) + { + IOMatrix::GetPin(IOMatrix::SHIFTLOCKNO)->Set();//Shift Lock Out On + } + else + { + IOMatrix::GetPin(IOMatrix::SHIFTLOCKNO)->Clear();//Shift Lock Out Off + } } static void ControlCabHeater(int opmode) diff --git a/src/utils.cpp b/src/utils.cpp index a014cdf..bdc7fe9 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -196,24 +196,27 @@ void SelectDirection(Vehicle* vehicle, Shifter* shifter) Shifter::Sgear gearS; int8_t selectedDir = Param::GetInt(Param::dir); int8_t userDirSelection = 0; + int8_t prevValidDir = 0; int8_t dirSign = (Param::GetInt(Param::dirmode) & DIR_REVERSED) ? -1 : 1; + uint8_t ChangeLim = Param::GetInt(Param::DirChange); //"0=None, 1=Speed Thres, 2=Speed+Brake" + //Collecting Inputs// if (vehicle->GetGear(gear)) { // if the vehicle class supplies gear selection then use that switch (gear) { case Vehicle::PARK: - selectedDir = 2; // Park + userDirSelection = 2; // Park break; case Vehicle::REVERSE: - selectedDir = -1; // Reverse + userDirSelection = -1; // Reverse break; case Vehicle::NEUTRAL: - selectedDir = 0; // Neutral + userDirSelection = 0; // Neutral break; case Vehicle::DRIVE: - selectedDir = 1; // Drive + userDirSelection = 1; // Drive break; } } @@ -223,20 +226,19 @@ void SelectDirection(Vehicle* vehicle, Shifter* shifter) switch (gearS) { case Shifter::PARK: - selectedDir = 2; // Park + userDirSelection = 2; // Park break; case Shifter::REVERSE: - selectedDir = -1; // Reverse + userDirSelection = -1; // Reverse break; case Shifter::NEUTRAL: - selectedDir = 0; // Neutral + userDirSelection = 0; // Neutral break; case Shifter::DRIVE: - selectedDir = 1; // Drive + userDirSelection = 1; // Drive break; } } - else { // otherwise use the traditional inputs @@ -271,17 +273,73 @@ void SelectDirection(Vehicle* vehicle, Shifter* shifter) else if (Param::GetBool(Param::din_reverse)) userDirSelection = -1 * dirSign; } + } + + //Change Allowed Logic// + + if(selectedDir != userDirSelection)//only run if requested change + { + if(ChangeLim == 0)//No limits on requesting new direction + { + selectedDir = userDirSelection; //direct pass through + } + else if (ChangeLim == 1 || 2)//speed limit only when changing F to R or R to F, note last selected direction is valid,ignore neautral + { + if(userDirSelection != 0 && userDirSelection != prevValidDir)//neutral changes always allowed, check if we are not going back into same mode as before neutral + { + if(Param::GetInt(Param::DirChangeRpm) > (ABS(Param::GetInt(Param::speed)))) + { + if (Param::GetBool(Param::din_brake) && ChangeLim == 2) + { + selectedDir = userDirSelection; + prevValidDir = selectedDir;//update only when its a valid forward or reverse action under speed threshold + } + else if(ChangeLim == 1) + { + selectedDir = userDirSelection; + prevValidDir = selectedDir;//update only when its a valid forward or reverse action under speed threshold + } + } + } + else + { + selectedDir = userDirSelection; //direct pass through + } + } + } - /* Only change direction when below certain motor speed */ -// if ((int)Encoder::GetSpeed() < Param::GetInt(Param::dirchrpm)) - selectedDir = userDirSelection; + //Shiftlock out control + if(ChangeLim == 0)//No limits on requesting new direction + { + SetInt(Param::ShiftLock,0);//No shift lock out ever + } + else if(Param::GetInt(Param::DirChangeRpm) > (ABS(Param::GetInt(Param::speed))))//speed based limit + { + if (Param::GetBool(Param::din_brake) && ChangeLim == 2)//brake input required + { + SetInt(Param::ShiftLock,1);//Solenoid pull out brake pressed and speed low + } + else if(ChangeLim == 1)//if only speed + { + SetInt(Param::ShiftLock,1);//Solenoid pull out speed low + } + else + { + SetInt(Param::ShiftLock,0);//No shift lock out speed too high + } + } + else + { + SetInt(Param::ShiftLock,0);//No shift lock out speed too high + } - /* Current direction doesn't match selected direction -> neutral */ - if (selectedDir != userDirSelection) - selectedDir = 0; + //Always off outside of run + if(Param::GetInt(Param::opmode)!=MOD_RUN) + { + SetInt(Param::ShiftLock,0);//No shift lock out speed too high } - Param::SetInt(Param::dir, selectedDir); + Param::SetInt(Param::dir, selectedDir);//final writing of DIR } float ProcessUdc(int motorSpeed)