/* * charger_gbt.c * * Created on: Apr 18, 2024 * Author: colorbass */ #include "charger_gbt.h" #include "main.h" #include "board.h" #include "stdio.h" #include "j1939.h" #include "string.h" #include "edcan.h" #include "lock.h" #include "connector.h" #include "soft_rtc.h" uint8_t GBT_CC_GetStateRaw(); gbtState_t GBT_State; uint32_t GBT_state_tick; //Tick after state switch uint32_t GBT_delay_start; uint32_t GBT_delay; uint8_t GBT_BAT_INFO_recv; uint8_t GBT_BAT_STAT_recv; uint8_t GBT_BRO_recv; uint8_t GBT_BHM_recv; uint8_t GBT_BSD_recv; uint8_t EV_ready; //uint8_t GBT_Charger_Enable; //FIX //uint8_t GBT_Charger_Permission;//FIX GBT_CML_t GBT_MaxLoad; GBT_CRM_t GBT_ChargerInfo; GBT_BHM_t GBT_MaxVoltage; GBT_BRM_t GBT_EVInfo; GBT_BCP_t GBT_BATStat; GBT_BCL_t GBT_ReqPower; GBT_BCL_t GBT_CurrPower; GBT_BCS_t GBT_ChargingStatus; GBT_BSM_t GBT_BatteryStatus; GBT_CCS_t GBT_ChargerCurrentStatus; GBT_CSD_t GBT_ChargerStop; uint8_t GBT_BRO; uint32_t GBT_TimeChargingStarted; uint32_t GBT_StopCauseCode; uint32_t GBT_ErrorCode; extern GBT_EDCAN_Output_t GBT_EDCAN_Output; extern GBT_EDCAN_Input_t GBT_EDCAN_Input; void GBT_Init(){ GBT_State = GBT_DISABLED; GBT_EDCAN_Input.chargeControl = CHARGING_NOT_ALLOWED; GBT_Reset(); } void GBT_ChargerTask(){ //GBT_LockTask(); if(j_rx.state == 2){ switch (j_rx.PGN){ case 0x2700: //PGN BHM GBT_BHM_recv = 1; memcpy (&GBT_MaxVoltage, j_rx.data, sizeof(GBT_MaxVoltage)); break; case 0x0200: //PGN BRM LONG GBT_BAT_INFO_recv = 1; memcpy (&GBT_EVInfo, j_rx.data, sizeof(GBT_EVInfo)); break; case 0x0600: //PGN BCP LONG GBT_BAT_STAT_recv = 1; memcpy (&GBT_BATStat, j_rx.data, sizeof(GBT_BATStat)); break; case 0x0900: //PGN BRO GBT_BRO_recv = 1; if(j_rx.data[0] == 0xAA) EV_ready = 1; else EV_ready = 0; GBT_BRO = j_rx.data[0]; break; case 0x1000: //PGN BCL //TODO: power block memcpy (&GBT_ReqPower, j_rx.data, sizeof(GBT_ReqPower)); uint16_t volt=GBT_ReqPower.requestedVoltage; GBT_EDCAN_Output.requestedVoltage = volt; uint16_t curr=4000-GBT_ReqPower.requestedCurrent; GBT_EDCAN_Output.requestedCurrent = curr; break; case 0x1100: //PGN BCS //TODO memcpy (&GBT_ChargingStatus, j_rx.data, sizeof(GBT_ChargingStatus)); GBT_EDCAN_Output.chargingRemainingTimeMin = GBT_ChargingStatus.estimatedRemainingChargingTime; GBT_EDCAN_Output.chargingPercentage = GBT_ChargingStatus.currentChargeState; break; case 0x1300: //PGN BSM //TODO memcpy (&GBT_BatteryStatus, j_rx.data, sizeof(GBT_BatteryStatus)); break; case 0x1500: //PGN BMV //TODO break; case 0x1600: //PGN BMT //TODO break; case 0x1700: //PGN BSP //TODO break; //this handler in j1939.c // case 0x1900: //PGN BST // break; case 0x1C00: //PGN BSD //TODO SOC Voltage Temp GBT_BSD_recv = 1; break; //this handler in j1939.c // case 0x1E00: //PGN BEM // break; //BSM BMV BMT BSP BST BSD BEM } j_rx.state = 0; } if((HAL_GetTick() - GBT_delay_start) < GBT_delay){ //waiting }else switch (GBT_State){ case GBT_DISABLED: RELAY_Write(RELAY_AUX, 0); if(connectorState == CONN_Charging){ GBT_Reset(); GBT_Start();//TODO IF protections (maybe not needed) } break; // case GBT_S0_UNCONNECTED: // if(!GBT_Charger_Enable){ // GBT_Stop(); // break; // } // if(GBT_CC_GetState()==GBT_CC_4V){ // // GBT_SwitchState(GBT_S1_CONNECTED); // GBT_Delay(500); // } // break; // case GBT_S1_CONNECTED: // if(!GBT_Charger_Enable){ // GBT_Stop(); // break; // } // if(GBT_CC_GetState()==GBT_CC_4V){ // // GBT_Lock(1); // GBT_SwitchState(GBT_S2_LOCKED); // GBT_Delay(500); // }else{ // GBT_SwitchState(GBT_S0_UNCONNECTED); // } // break; // case GBT_S2_LOCKED: // if(!GBT_Charger_Enable){ // GBT_Stop(); // break; // } // if(1){ //TODO: charge permission // RELAY_Write(RELAY_AUX, 1); // 13.8V AUX ON // GBT_SwitchState(GBT_S3_STARTED); // GBT_Delay(500); // } // break; case GBT_S3_STARTED: GBT_SwitchState(GBT_S31_WAIT_BHM); GBT_Delay(500); break; case GBT_S31_WAIT_BHM: if(j_rx.state == 0) GBT_SendCHM(); GBT_Delay(250); if(GBT_BHM_recv) { GBT_SwitchState(GBT_S4_ISOTEST); } //Timeout 10S if((GBT_BHM_recv == 0) && (GBT_StateTick()>10000)) { //BHM Timeout GBT_Error(0xFCF0C0FC); EDCAN_printf(LOG_WARN, "BHM Timeout\n"); } break; case GBT_S4_ISOTEST: if(j_rx.state == 0) GBT_SendCHM(); GBT_Delay(250); GBT_EDCAN_Output.requestedVoltage = GBT_MaxVoltage.maxOutputVoltage; GBT_EDCAN_Output.requestedCurrent = 10; // 1A max GBT_EDCAN_Output.enablePSU = 1; //TODO: Isolation test trigger if(GBT_EDCAN_Input.chargingError == GBT_ERR_INSULATION){ GBT_Stop(GBT_CST_OTHERFALUT); } if(GBT_StateTick()>5000){ GBT_SwitchState(GBT_S5_BAT_INFO); GBT_EDCAN_Output.requestedVoltage = 50; GBT_EDCAN_Output.requestedCurrent = 10; // 1A max GBT_EDCAN_Output.enablePSU = 0; } break; case GBT_S5_BAT_INFO: if(j_rx.state == 0) GBT_SendCRM(0x00); GBT_Delay(250); if(GBT_BAT_INFO_recv){ //BRM //Got battery info GBT_SwitchState(GBT_S6_BAT_STAT); EDCAN_printf(LOG_INFO, "EV info:\n"); EDCAN_printf(LOG_INFO, "GBT_ver V%d.%d%d\n",GBT_EVInfo.version[0],GBT_EVInfo.version[1],GBT_EVInfo.version[2]); EDCAN_printf(LOG_INFO, "Battery type: %d\n",GBT_EVInfo.batteryType); EDCAN_printf(LOG_INFO, "Battery capacity: %d\n", GBT_EVInfo.batteryCapacity); // 0.1Ah/bit EDCAN_printf(LOG_INFO, "Battery voltage: %d\n", GBT_EVInfo.batteryVoltage); // 0.1V/bit EDCAN_printf(LOG_INFO, "Battery vendor: %.4s\n", GBT_EVInfo.batteryVendor); // Battery vendor (ASCII string) EDCAN_printf(LOG_INFO, "Battery SN: %lu\n", GBT_EVInfo.batterySN); // int EDCAN_printf(LOG_INFO, "Battery manufacture date: %02d.%02d.%04d\n", GBT_EVInfo.batteryManuD, GBT_EVInfo.batteryManuM ,GBT_EVInfo.batteryManuY+1985); // year (offset 1985) EDCAN_printf(LOG_INFO, "Battery cycles: %d\n", GBT_EVInfo.batteryCycleCount); //uint24_t EDCAN_printf(LOG_INFO, "Own auto: %d\n", GBT_EVInfo.ownAuto); // 0 = lizing, 1 = own auto EDCAN_printf(LOG_INFO, "EVIN: %.17s\n", GBT_EVInfo.EVIN); //EVIN EDCAN_printf(LOG_INFO, "EV_SW_VER: %.8s\n", GBT_EVInfo.EV_SW_VER); } //Timeout if((GBT_StateTick()>5000) && (GBT_BAT_INFO_recv == 0)){ GBT_Error(0xFDF0C0FC); //BRM Timeout EDCAN_printf(LOG_WARN, "BRM Timeout\n"); } break; case GBT_S6_BAT_STAT: if(j_rx.state == 0) GBT_SendCRM(0xAA); GBT_Delay(250); if(GBT_BAT_STAT_recv){ //Got battery status GBT_SwitchState(GBT_S7_BMS_WAIT); EDCAN_printf(LOG_INFO, "Battery info:\n"); EDCAN_printf(LOG_INFO, "maxCV %dV\n",GBT_BATStat.maxCellVoltage/100); // 0.01v/bit EDCAN_printf(LOG_INFO, "maxCC %dA\n",GBT_BATStat.maxChargingCurrent/10); // 0.1A/bit EDCAN_printf(LOG_INFO, "totE %dkWh\n",GBT_BATStat.totalEnergy/10); // 0.1kWh EDCAN_printf(LOG_INFO, "maxCV %dV\n",GBT_BATStat.maxChargingVoltage/10); // 0.1V/ bit EDCAN_printf(LOG_INFO, "maxT %dC\n",(int16_t)GBT_BATStat.maxTemp-50); // 1C/bit, -50C offset EDCAN_printf(LOG_INFO, "SOC %dp\n",GBT_BATStat.SOC/10); // 0.1%/bit , 0..100% EDCAN_printf(LOG_INFO, "Volt. %dV\n",GBT_BATStat.measVoltage/10); // 0.1V/bit } if((GBT_StateTick()>5000) && (GBT_BAT_STAT_recv == 0)){ GBT_Error(0xFCF1C0FC); //BCP Timeout EDCAN_printf(LOG_WARN, "BCP Timeout\n"); } break; case GBT_S7_BMS_WAIT: if(j_rx.state == 0) GBT_SendCTS(); HAL_Delay(2); if(j_rx.state == 0) GBT_SendCML(); GBT_Delay(250); if((GBT_StateTick()>5000) && (GBT_BRO_recv == 0)){ GBT_Error(0xFCF4C0FC); //BRO Timeout EDCAN_printf(LOG_WARN, "BRO Timeout\n"); } if(EV_ready){ //EV ready (AA) GBT_SwitchState(GBT_S8_INIT_CHARGER); }else{ if((GBT_StateTick()>60000) && (GBT_BRO_recv == 1)){ GBT_Error(0xFCF4C0FC); //BRO Timeout EDCAN_printf(LOG_WARN, "BRO Timeout\n"); } } break; case GBT_S8_INIT_CHARGER: if(j_rx.state == 0) GBT_SendCRO(0x00); //TODO GBT_Delay(250); if(GBT_StateTick()>1500){ //Power Modules initiated GBT_SwitchState(GBT_S9_WAIT_BCL); } break; case GBT_S9_WAIT_BCL: if(j_rx.state == 0) GBT_SendCRO(0xAA); GBT_Delay(250); if(GBT_ReqPower.chargingMode != 0){ //REFACTORING //BCL power requirements received GBT_SwitchState(GBT_S10_CHARGING); CONN_SetState(CONN_Charging); uint16_t curr=4000-GBT_ReqPower.requestedCurrent; uint16_t volt=GBT_ReqPower.requestedVoltage; //TODO Limits GBT_EDCAN_Output.requestedVoltage = volt; GBT_EDCAN_Output.requestedCurrent = curr; GBT_EDCAN_Output.enablePSU = 1; GBT_TimeChargingStarted = get_Current_Time(); } break; case GBT_S10_CHARGING: //CHARGING //TODO BCL BCS BSM missing ERRORS if(GBT_EDCAN_Input.chargeControl == CHARGING_NOT_ALLOWED) GBT_Stop(GBT_CST_SUSPENDS_ARTIFICIALLY); if(GBT_EDCAN_Input.chargeControl == FORCE_UNLOCK) GBT_Stop(GBT_CST_SUSPENDS_ARTIFICIALLY);//GBT_ForceStop(); if(GBT_LockState.error) GBT_Stop(GBT_CST_OTHERFALUT); if((GBT_ReadTemp(0) > 90) || (GBT_ReadTemp(1) > 90)) { GBT_Stop(GBT_CST_CONNECTOR_OVER_TEMP); EDCAN_printf(LOG_WARN, "Connector overheat %d %d\n", GBT_ReadTemp(0), GBT_ReadTemp(1)); } if(GBT_EDCAN_Input.chargingError == GBT_ERR_INSULATION) { GBT_Stop(GBT_CST_OTHERFALUT); EDCAN_printf(LOG_WARN, "Isolation error\n"); } //GBT_ChargerCurrentStatus.chargingPermissible = 0b1111111111111100;//NOT PERMITTED GBT_ChargerCurrentStatus.chargingPermissible = 0b1111111111111101; GBT_ChargerCurrentStatus.chargingTime = (get_Current_Time() - GBT_TimeChargingStarted)/60; // GBT_ChargerCurrentStatus.outputCurrent = 4000 - GBT_EDCAN_Output.requestedCurrent; // GBT_ChargerCurrentStatus.outputVoltage = GBT_EDCAN_Output.requestedVoltage; GBT_ChargerCurrentStatus.outputCurrent = 4000 - GBT_EDCAN_Input.measuredCurrent; GBT_ChargerCurrentStatus.outputVoltage = GBT_EDCAN_Input.measuredVoltage; GBT_EDCAN_Output.chargingElapsedTimeMin = (get_Current_Time() - GBT_TimeChargingStarted)/60; GBT_EDCAN_Output.chargingElapsedTimeSec = (get_Current_Time() - GBT_TimeChargingStarted)%60; if(j_rx.state == 0) GBT_SendCCS(); GBT_Delay(50); //TODO: снижение тока если перегрев контактов break; case GBT_STOP: GBT_Delay(10); GBT_EDCAN_Output.enablePSU = 0; GBT_SendCST(GBT_StopCauseCode); //RELAY_Write(RELAY_OUTPUT, 0); //GBT_SwitchState(GBT_DISABLED); if(GBT_StateTick()>10000){ EDCAN_printf(LOG_WARN, "BSD Timeout\n"); GBT_Error(0xFCF0C0FD); //BSD Timeout } if(GBT_BSD_recv != 0){ GBT_SwitchState(GBT_STOP_CSD); } break; case GBT_STOP_CSD: GBT_Delay(250); GBT_SendCSD(); if(GBT_StateTick()>2500){ //2.5S GBT_SwitchState(GBT_COMPLETE); // GBT_Reset(); //CONN_SetState(CONN_Occupied_complete); //if(connectorState == CONN_Occupied_charging) //PSU_Mode(0x0100); } break; case GBT_ERROR: GBT_SendCEM(GBT_ErrorCode); //2.5S GBT_SwitchState(GBT_COMPLETE); // GBT_Reset(); // break; case GBT_COMPLETE: if(connectorState != CONN_Finishing) GBT_SwitchState(GBT_DISABLED); break; default: GBT_SwitchState(GBT_DISABLED); } } void GBT_SwitchState(gbtState_t state){ GBT_State = state; ED_status = state; GBT_state_tick = HAL_GetTick(); if(GBT_State == GBT_DISABLED) printf ("GBT_DISABLED\n"); // if(GBT_State == GBT_S0_UNCONNECTED) printf ("GBT_S0_UNCONNECTED\n"); // if(GBT_State == GBT_S1_CONNECTED) printf ("GBT_S1_CONNECTED\n"); // if(GBT_State == GBT_S2_LOCKED) printf ("GBT_S2_LOCKED\n"); if(GBT_State == GBT_S3_STARTED) printf ("GBT_S3_STARTED\n"); if(GBT_State == GBT_S31_WAIT_BHM) printf ("GBT_S31_WAIT_BHM\n"); if(GBT_State == GBT_S4_ISOTEST) printf ("GBT_S4_ISOTEST\n"); if(GBT_State == GBT_S5_BAT_INFO) printf ("GBT_S5_BAT_INFO\n"); if(GBT_State == GBT_S6_BAT_STAT) printf ("GBT_S6_BAT_STAT\n"); if(GBT_State == GBT_S7_BMS_WAIT) printf ("GBT_S7_BMS_WAIT\n"); if(GBT_State == GBT_S8_INIT_CHARGER)printf ("GBT_S8_INIT_CHARGER\n"); if(GBT_State == GBT_S9_WAIT_BCL) printf ("GBT_S9_WAIT_BCL\n"); if(GBT_State == GBT_S10_CHARGING) printf ("GBT_S10_CHARGING\n"); if(GBT_State == GBT_STOP) printf ("GBT_STOP\n"); if(GBT_State == GBT_STOP_CSD) printf ("GBT_STOP_CSD\n"); if(GBT_State == GBT_ERROR) printf ("GBT_ERROR\n"); if(GBT_State == GBT_COMPLETE) printf ("GBT_COMPLETE\n"); if(GBT_State == GBT_DISABLED) EDCAN_printf(LOG_INFO, "GBT_DISABLED\n"); if(GBT_State == GBT_S3_STARTED) EDCAN_printf(LOG_INFO, "GBT_S3_STARTED\n"); if(GBT_State == GBT_S31_WAIT_BHM) EDCAN_printf(LOG_INFO, "GBT_S31_WAIT_BHM\n"); if(GBT_State == GBT_S4_ISOTEST) EDCAN_printf(LOG_INFO, "GBT_S4_ISOTEST\n"); if(GBT_State == GBT_S5_BAT_INFO) EDCAN_printf(LOG_INFO, "GBT_S5_BAT_INFO\n"); if(GBT_State == GBT_S6_BAT_STAT) EDCAN_printf(LOG_INFO, "GBT_S6_BAT_STAT\n"); if(GBT_State == GBT_S7_BMS_WAIT) EDCAN_printf(LOG_INFO, "GBT_S7_BMS_WAIT\n"); if(GBT_State == GBT_S8_INIT_CHARGER)EDCAN_printf(LOG_INFO, "GBT_S8_INIT_CHARGER\n"); if(GBT_State == GBT_S9_WAIT_BCL) EDCAN_printf(LOG_INFO, "GBT_S9_WAIT_BCL\n"); if(GBT_State == GBT_S10_CHARGING) EDCAN_printf(LOG_INFO, "GBT_S10_CHARGING\n"); if(GBT_State == GBT_STOP) EDCAN_printf(LOG_INFO, "GBT_STOP\n"); if(GBT_State == GBT_STOP_CSD) EDCAN_printf(LOG_INFO, "GBT_STOP_CSD\n"); if(GBT_State == GBT_ERROR) EDCAN_printf(LOG_WARN, "GBT_ERROR\n"); if(GBT_State == GBT_COMPLETE) EDCAN_printf(LOG_INFO, "GBT_COMPLETE\n"); } uint32_t GBT_StateTick(){ return HAL_GetTick() - GBT_state_tick; } void GBT_Delay(uint32_t delay){ GBT_delay_start = HAL_GetTick(); GBT_delay = delay; } void GBT_Stop(uint32_t causecode){ GBT_StopCauseCode = causecode; if(GBT_State != GBT_STOP) GBT_SwitchState(GBT_STOP); } void GBT_Error(uint32_t errorcode){ EDCAN_printf(LOG_WARN, "GBT Error code: 0x%X\n", errorcode); GBT_ErrorCode = errorcode; GBT_SwitchState(GBT_ERROR); } void GBT_ForceStop(){ GBT_EDCAN_Output.enablePSU = 0; GBT_SwitchState(GBT_COMPLETE); GBT_Lock(0); RELAY_Write(RELAY_AUX, 0); } void GBT_Reset(){ GBT_BAT_INFO_recv = 0; GBT_BAT_STAT_recv = 0; GBT_BRO_recv = 0; GBT_BHM_recv = 0; GBT_BSD_recv = 0; EV_ready = 0; memset(&GBT_EVInfo, 0, sizeof (GBT_EVInfo)); memset(&GBT_BATStat, 0, sizeof (GBT_BATStat)); memset(&GBT_ReqPower, 0, sizeof (GBT_ReqPower)); memset(&GBT_CurrPower, 0, sizeof (GBT_CurrPower)); memset(&GBT_MaxVoltage, 0, sizeof (GBT_MaxVoltage)); memset(&GBT_ChargingStatus, 0, sizeof (GBT_ChargingStatus)); memset(&GBT_BatteryStatus, 0, sizeof (GBT_BatteryStatus)); memset(&GBT_ChargerCurrentStatus, 0, sizeof (GBT_ChargerCurrentStatus)); memset(&GBT_ChargerStop, 0, sizeof (GBT_ChargerStop)); GBT_CurrPower.requestedCurrent = 4000; //0A GBT_CurrPower.requestedVoltage = 500; //50V GBT_TimeChargingStarted = 0; GBT_BRO = 0x00; } void GBT_Start(){ RELAY_Write(RELAY_AUX, 1); GBT_SwitchState(GBT_S3_STARTED); }