/****************************************************************************** * * @file outputs.c * @author ECS, Falko Jahn * @version V1.0.0 * @date 2020-05-01 * @brief * ******************************************************************************/ //--- INCLUDES ----------------------------------------------------------------- #include "outputs.h" #include "main.h" #include "stdio.h" #include "sysdata.h" //--- EXTERNE VARIABLEN -------------------------------------------------------- //--- LOKALE DEFINES - bitte hier dokumentieren -------------------------------- //--- LOKALE TYPE DEFS - bitte hier dokumentieren------------------------------- //--- DEFINITIONEN GLOBALER VARIABLEN - Bitte in Header dokumentieren ---------- //--- LOKALE VARIABLEN - bitte hier dokumentieren ------------------------------ //--- LOKALE FUNKTIONS PROTOTYPEN ---------------------------------------------- /* * @brief Heizungssteuerung * @param kein * @retval kein */ void AuxModeHeaterExec(void); //--- LOKALE FUNKTIONEN - bitte hier dokumentieren ----------------------------- // --- GLOBALE FUNKTIONEN - bitte in Header dokumentieren------------------------ void OUTPUTS_Init(void) { sys_data.s.values.lvpState = OUTPUTS_LVP_UNKNOWN; sys_data.s.values.ovpState = OUTPUTS_OVP_UNKNOWN; } /* * @brief Prüfen ob LVP Signal abgeschaltet werden muss * LVP Signal kommt vom BMS und schaltet die Lasten ab. Wird hier auch abgeschaltet wenn der Laststrom zu hoch ist, * oder wenn die Geräte Temperatur zu hoch oder zu niedrig ist. * @param kein * @retval kein */ void OUTPUTS_CheckLVP(void) { static uint16_t lastMode; if (sys_data.s.parameter.lvpMode == OUTPUTS_LVP_MODE_AUTO) { if (lastMode != OUTPUTS_LVP_MODE_AUTO) { sys_data.s.values.lvpState = OUTPUTS_LVP_UNKNOWN; } if ((sys_data.s.values.lvpState == OUTPUTS_LVP_OK) || (sys_data.s.values.lvpState == OUTPUTS_LVP_UNKNOWN)) { if(sys_data.s.values.batteryVoltage < sys_data.s.parameter.lvpStart) { printf("OUTPUTS_LVP_BATTERY_UNDERVOLTAGE\n"); sys_data.s.values.lvpState = OUTPUTS_LVP_BATTERY_UNDERVOLTAGE; HAL_GPIO_WritePin(DISCHARGE_ENABLE_GPIO_Port, DISCHARGE_ENABLE_Pin, OUTPUTS_DISCHARGE_NOT_ALLOWED); } else if(sys_data.s.values.batteryCurrent < ((int32_t)sys_data.s.parameter.loadCurrentLimit*1000)) { printf("OUTPUTS_LVP_OVERCURRENT\n"); sys_data.s.values.lvpState = OUTPUTS_LVP_OVERCURRENT; HAL_GPIO_WritePin(DISCHARGE_ENABLE_GPIO_Port, DISCHARGE_ENABLE_Pin, OUTPUTS_DISCHARGE_NOT_ALLOWED); } else if(sys_data.s.values.shuntTemperature > sys_data.s.parameter.dischargeStopHighTemperatureStart) { printf("OUTPUTS_LVP_SHUNT_OVERTEMPERATURE\n"); sys_data.s.values.lvpState = OUTPUTS_LVP_SHUNT_OVERTEMPERATURE; HAL_GPIO_WritePin(DISCHARGE_ENABLE_GPIO_Port, DISCHARGE_ENABLE_Pin, OUTPUTS_DISCHARGE_NOT_ALLOWED); } else if(sys_data.s.values.chipTemperature > sys_data.s.parameter.dischargeStopHighTemperatureStart) { printf("OUTPUTS_LVP_CHIP_OVERTEMPERATURE\n"); sys_data.s.values.lvpState = OUTPUTS_LVP_CHIP_OVERTEMPERATURE; HAL_GPIO_WritePin(DISCHARGE_ENABLE_GPIO_Port, DISCHARGE_ENABLE_Pin, OUTPUTS_DISCHARGE_NOT_ALLOWED); } else if(sys_data.s.values.shuntTemperature < sys_data.s.parameter.dischargeStopLowTemperatureStart) { printf("OUTPUTS_LVP_SHUNT_UNDERTEMPERATURE\n"); sys_data.s.values.lvpState = OUTPUTS_LVP_SHUNT_UNDERTEMPERATURE; HAL_GPIO_WritePin(DISCHARGE_ENABLE_GPIO_Port, DISCHARGE_ENABLE_Pin, OUTPUTS_DISCHARGE_NOT_ALLOWED); } else if(sys_data.s.values.chipTemperature < sys_data.s.parameter.dischargeStopLowTemperatureStart) { printf("OUTPUTS_LVP_CHIP_OVERTEMPERATURE\n"); sys_data.s.values.lvpState = OUTPUTS_LVP_CHIP_UNDERTEMPERATURE; HAL_GPIO_WritePin(DISCHARGE_ENABLE_GPIO_Port, DISCHARGE_ENABLE_Pin, OUTPUTS_DISCHARGE_NOT_ALLOWED); } } if ((sys_data.s.values.lvpState != OUTPUTS_LVP_OK) && (sys_data.s.values.batteryVoltage > sys_data.s.parameter.lvpStop) && (sys_data.s.values.batteryCurrent > ((int32_t)sys_data.s.parameter.loadCurrentLimit * 1000)) && (sys_data.s.values.shuntTemperature < sys_data.s.parameter.dischargeStopHighTemperatureStop) && (sys_data.s.values.chipTemperature < sys_data.s.parameter.dischargeStopHighTemperatureStop) && (sys_data.s.values.shuntTemperature > sys_data.s.parameter.dischargeStopLowTemperatureStop) && (sys_data.s.values.chipTemperature > sys_data.s.parameter.dischargeStopLowTemperatureStop)) { //Abschaltkriterien für LVP liegen nicht mehr vor //Wenn Abschaltung aufgrund zu hohem Lade/Lastrom erfolgt ist, muss Fehler durch Geräte Reset zurück gesetzt werden //Andere Fehler automatisches Reset, wenn Fehler nicht mehr vorliegt. //Kunde könnte automatische Reset verhindern, indem er die Stop Werte anders programmiert //z.B. //Temperabschaltung Start 80°C //Temperaturabschaltung Stop -99°C if (sys_data.s.values.lvpState != OUTPUTS_LVP_OVERCURRENT) { //Andere Fehler, automatisches zurücksetzen, wenn keine Fehlerbedingungen mehr vorliegen printf("OUTPUT LVP OK\n"); sys_data.s.values.lvpState = OUTPUTS_LVP_OK; HAL_GPIO_WritePin(DISCHARGE_ENABLE_GPIO_Port, DISCHARGE_ENABLE_Pin, OUTPUTS_DISCHARGE_ALLOWED); } } } else if (sys_data.s.parameter.lvpMode == OUTPUTS_LVP_MODE_MANUAL_ON) { HAL_GPIO_WritePin(DISCHARGE_ENABLE_GPIO_Port, DISCHARGE_ENABLE_Pin, OUTPUTS_DISCHARGE_ALLOWED); } else if (sys_data.s.parameter.lvpMode == OUTPUTS_LVP_MODE_MANUAL_OFF) { HAL_GPIO_WritePin(DISCHARGE_ENABLE_GPIO_Port, DISCHARGE_ENABLE_Pin, OUTPUTS_DISCHARGE_NOT_ALLOWED); } else HAL_GPIO_WritePin(DISCHARGE_ENABLE_GPIO_Port, DISCHARGE_ENABLE_Pin, OUTPUTS_DISCHARGE_NOT_ALLOWED); lastMode = sys_data.s.parameter.lvpMode; } /* * @brief Prüfen ob OVP Signal abgeschaltet werden muss * OVP Signal kommt vom BMS und schaltet die Ladequellen ab. Wird hier auch abgeschaltet wenn der Ladestrom zu hoch ist, * oder wenn die Geräte Temperatur zu hoch oder zu niedrig ist. * @param kein * @retval kein */ void OUTPUTS_CheckOVP(void) { static uint16_t lastMode; if (sys_data.s.parameter.ovpMode == OUTPUTS_OVP_MODE_AUTO) { if (lastMode != OUTPUTS_OVP_MODE_AUTO) { sys_data.s.values.ovpState = OUTPUTS_OVP_UNKNOWN; } if ((sys_data.s.values.ovpState == OUTPUTS_OVP_OK) || (sys_data.s.values.ovpState == OUTPUTS_OVP_UNKNOWN)) { if(sys_data.s.values.batteryVoltage > sys_data.s.parameter.ovpStart) { printf("OUTPUTS_OVP_BATTERY_OVERVOLTAGE\n"); sys_data.s.values.ovpState = OUTPUTS_OVP_BATTERY_OVERVOLTAGE; HAL_GPIO_WritePin(CHARGE_ENABLE_GPIO_Port, CHARGE_ENABLE_Pin, OUTPUTS_CHARGE_NOT_ALLOWED); } else if(sys_data.s.values.batteryCurrent > ((int32_t) sys_data.s.parameter.chargeCurrentLimit * 1000)) { printf("OUTPUTS_OVP_OVERCURRENT\n"); sys_data.s.values.ovpState = OUTPUTS_OVP_OVERCURRENT; HAL_GPIO_WritePin(CHARGE_ENABLE_GPIO_Port, CHARGE_ENABLE_Pin, OUTPUTS_CHARGE_NOT_ALLOWED); } else if(sys_data.s.values.shuntTemperature > sys_data.s.parameter.chargeStopHighTemperatureStart) { printf("OUTPUTS_OVP_SHUNT_OVERTEMPERATURE\n"); sys_data.s.values.ovpState = OUTPUTS_OVP_SHUNT_OVERTEMPERATURE; HAL_GPIO_WritePin(CHARGE_ENABLE_GPIO_Port, CHARGE_ENABLE_Pin, OUTPUTS_CHARGE_NOT_ALLOWED); } else if(sys_data.s.values.chipTemperature > sys_data.s.parameter.chargeStopHighTemperatureStart) { printf("OUTPUTS_OVP_CHIP_OVERTEMPERATURE\n"); sys_data.s.values.ovpState = OUTPUTS_OVP_CHIP_OVERTEMPERATURE; HAL_GPIO_WritePin(CHARGE_ENABLE_GPIO_Port, CHARGE_ENABLE_Pin, OUTPUTS_CHARGE_NOT_ALLOWED); } else if(sys_data.s.values.shuntTemperature < sys_data.s.parameter.chargeStopLowTemperatureStart) { printf("OUTPUTS_OVP_SHUNT_UNDERTEMPERATURE\n"); sys_data.s.values.ovpState = OUTPUTS_OVP_SHUNT_UNDERTEMPERATURE; HAL_GPIO_WritePin(CHARGE_ENABLE_GPIO_Port, CHARGE_ENABLE_Pin, OUTPUTS_CHARGE_NOT_ALLOWED); } else if(sys_data.s.values.chipTemperature < sys_data.s.parameter.chargeStopLowTemperatureStart) { printf("OUTPUTS_OVP_CHIP_UNDETEMPERATURE\n"); sys_data.s.values.ovpState = OUTPUTS_OVP_CHIP_UNDERTEMPERATURE; HAL_GPIO_WritePin(CHARGE_ENABLE_GPIO_Port, CHARGE_ENABLE_Pin, OUTPUTS_CHARGE_NOT_ALLOWED); } } if ((sys_data.s.values.ovpState != OUTPUTS_OVP_OK) && (sys_data.s.values.batteryVoltage < sys_data.s.parameter.ovpStop) && (sys_data.s.values.batteryCurrent < ( (int32_t) sys_data.s.parameter.chargeCurrentLimit*1000)) && (sys_data.s.values.shuntTemperature < sys_data.s.parameter.chargeStopHighTemperatureStop) && (sys_data.s.values.chipTemperature < sys_data.s.parameter.chargeStopHighTemperatureStop) && (sys_data.s.values.shuntTemperature > sys_data.s.parameter.chargeStopLowTemperatureStop) && (sys_data.s.values.chipTemperature > sys_data.s.parameter.chargeStopLowTemperatureStop)) { //Abschaltkriterien für OVP liegen nicht mehr vor //Wenn Abschaltung aufgrund zu hohem Lade/Lastrom erfolgt ist, dann muss Rücksetzen durch Reset Button erfolgen //Andere Fehler, automatisches zurücksetzen, wenn keine Fehlerbedingungen mehr vorliegen if (sys_data.s.values.ovpState != OUTPUTS_OVP_OVERCURRENT) { printf("OUTPUT OVP OK\n"); sys_data.s.values.ovpState = OUTPUTS_OVP_OK; HAL_GPIO_WritePin(CHARGE_ENABLE_GPIO_Port, CHARGE_ENABLE_Pin, OUTPUTS_CHARGE_ALLOWED); } } } else if (sys_data.s.parameter.ovpMode == OUTPUTS_OVP_MODE_MANUAL_ON) { HAL_GPIO_WritePin(CHARGE_ENABLE_GPIO_Port, CHARGE_ENABLE_Pin, OUTPUTS_CHARGE_ALLOWED); } else if (sys_data.s.parameter.ovpMode == OUTPUTS_OVP_MODE_MANUAL_OFF) { HAL_GPIO_WritePin(CHARGE_ENABLE_GPIO_Port, CHARGE_ENABLE_Pin, OUTPUTS_CHARGE_NOT_ALLOWED); } else HAL_GPIO_WritePin(CHARGE_ENABLE_GPIO_Port, CHARGE_ENABLE_Pin, OUTPUTS_CHARGE_NOT_ALLOWED); lastMode = sys_data.s.parameter.ovpMode; } #define LVP_DETECTION_LEVEL 6000 //< 6 V #define CHARGE_DETECT_HYSTERESE 10 void AuxModeHeaterExec(void) { static int outputState=0; int offv = sys_data.s.parameter.auxOutputSetpointOn - CHARGE_DETECT_HYSTERESE; int onv = sys_data.s.parameter.auxOutputSetpointOn + CHARGE_DETECT_HYSTERESE; if ((sys_data.s.values.shuntVoltage > onv) && (sys_data.s.values.ovp_sense < LVP_DETECTION_LEVEL) && (outputState == 0)) { printf("Heater on\r\n"); outputState = 1; if (sys_data.s.parameter.auxOutputInverted == 0) { HAL_GPIO_WritePin(AUX_EN_GPIO_Port, AUX_EN_Pin, GPIO_PIN_SET); } else { HAL_GPIO_WritePin(AUX_EN_GPIO_Port, AUX_EN_Pin, GPIO_PIN_RESET); } } //Ausschalten //Wenn Spannung am Shunt < setpoint (ladegeräteerkennung 14,8V?) und Entladung //Oder wenn OVP wieder da ist //sys_data.s.values.batteryCurrent < sys_data.s.parameter.auxOutputSetpointOff if ((sys_data.s.values.shuntVoltage < offv ) || (sys_data.s.values.ovp_sense > LVP_DETECTION_LEVEL)) { if (outputState == 1) { printf("Heater off\r\n"); outputState = 0; if (sys_data.s.parameter.auxOutputInverted == 0) { HAL_GPIO_WritePin(AUX_EN_GPIO_Port, AUX_EN_Pin, GPIO_PIN_RESET); } else { HAL_GPIO_WritePin(AUX_EN_GPIO_Port, AUX_EN_Pin, GPIO_PIN_SET); } } } } void AuxModeSOCExec(void) { static int outputState=0; if ((sys_data.s.values.soc > (sys_data.s.parameter.auxOutputSetpointOn*1000)) && (outputState == 0)) { printf("AUX on (SOC Mode)\r\n"); outputState = 1; if (sys_data.s.parameter.auxOutputInverted == 0) { HAL_GPIO_WritePin(AUX_EN_GPIO_Port, AUX_EN_Pin, GPIO_PIN_SET); } else { HAL_GPIO_WritePin(AUX_EN_GPIO_Port, AUX_EN_Pin, GPIO_PIN_RESET); } } if ((sys_data.s.values.soc < (sys_data.s.parameter.auxOutputSetpointOff*1000)) && (outputState == 1)) { printf("AUX off (SOC Mode)\r\n"); outputState = 0; if (sys_data.s.parameter.auxOutputInverted == 0) { HAL_GPIO_WritePin(AUX_EN_GPIO_Port, AUX_EN_Pin, GPIO_PIN_RESET); } else { HAL_GPIO_WritePin(AUX_EN_GPIO_Port, AUX_EN_Pin, GPIO_PIN_SET); } } } int16_t loadCurrentLimit; // 30 maximaler Laststrom in A wenn der Strom grer ist als der eingestelle Wert dann wird die Laststrom Protection aktiv, darf nicht unsigned sein, da Entladestrom mit Minus angegeben [A] Default -500 A int16_t chargeCurrentLimit; // 31 maximaler Ladestrom in A wenn der Strom grer ist als der eingestelle Wert dann wird die Ladestrom Protection aktiv [A] Default:500A int16_t chargeStopHighTemperatureStart; // 32 Abschalttemperatur Ladung wegen zu hoher Temperatur [C * 100] int16_t chargeStopHighTemperatureStop; // 33 Wiedereinschalttemperatur [C * 100] int16_t chargeStopLowTemperatureStart; // 34 Abschalttemperatur Ladung wegen zu niedriger Temperatur [C * 100] int16_t chargeStopLowTemperatureStop; // 35 Wiedereinschalttemperatur [C * 100] int16_t dischargeStopHighTemperatureStart; // 36 Abschalttemperatur Entladung wegen zu hoher Temperatur [C * 100] int16_t dischargeStopHighTemperatureStop; // 37 Wiedereinschalttemperatur[C * 100] int16_t dischargeStopLowTemperatureStart; // 38 Abschalttemperatur EntLadung wegen zu niedriger Temperatur int16_t dischargeStopLowTemperatureStop; // 39 Wiedereinschalttemperatur void AuxModeAlarmExec(void) { static int outputState=0; if ( (sys_data.s.values.shuntTemperature > (chargeStopHighTemperatureStart - 500)) || (sys_data.s.values.chipTemperature > (chargeStopHighTemperatureStart - 500)) || (sys_data.s.values.shuntTemperature < (chargeStopLowTemperatureStart + 500)) || (sys_data.s.values.chipTemperature < (chargeStopLowTemperatureStart + 500)) || (sys_data.s.values.shuntTemperature > (dischargeStopHighTemperatureStart - 500)) || (sys_data.s.values.chipTemperature > (dischargeStopHighTemperatureStart - 500)) || (sys_data.s.values.shuntTemperature < (dischargeStopLowTemperatureStart + 500)) || (sys_data.s.values.chipTemperature < (dischargeStopLowTemperatureStart + 500)) || (sys_data.s.values.batteryCurrent > ((chargeCurrentLimit*1000LL) - 10000)) || (sys_data.s.values.batteryCurrent < ((loadCurrentLimit*1000LL) + 10000)) ) { if ( outputState == 0) { printf("AUX on (Alarm Mode)\r\n"); outputState = 1; if (sys_data.s.parameter.auxOutputInverted == 0) { HAL_GPIO_WritePin(AUX_EN_GPIO_Port, AUX_EN_Pin, GPIO_PIN_SET); } else { HAL_GPIO_WritePin(AUX_EN_GPIO_Port, AUX_EN_Pin, GPIO_PIN_RESET); } } } else // Alles OK { if ( outputState == 0) { printf("AUX off (Alarm Mode)\r\n"); outputState = 0; if (sys_data.s.parameter.auxOutputInverted == 0) { HAL_GPIO_WritePin(AUX_EN_GPIO_Port, AUX_EN_Pin, GPIO_PIN_RESET); } else { HAL_GPIO_WritePin(AUX_EN_GPIO_Port, AUX_EN_Pin, GPIO_PIN_SET); } } } } void OUTPUTS_CheckAUX(void) { switch (sys_data.s.parameter.auxOutputMode) { case AUX_MODE_OFF: HAL_GPIO_WritePin(AUX_EN_GPIO_Port, AUX_EN_Pin, GPIO_PIN_RESET); break; case AUX_MODE_HEATER: AuxModeHeaterExec(); break; case AUX_MODE_SOC: AuxModeSOCExec(); break; case AUX_MODE_ALARM: AuxModeAlarmExec(); break; default: HAL_GPIO_WritePin(AUX_EN_GPIO_Port, AUX_EN_Pin, GPIO_PIN_RESET); break; } } /*************************** End of file ****************************/