if it breaks, I’m in the mountains

This commit is contained in:
2026-03-24 04:38:40 +03:00
parent 8574ffadc9
commit 14b4f0595f
64 changed files with 38499 additions and 39958 deletions

BIN
Core/Src/.DS_Store vendored

Binary file not shown.

View File

@@ -85,10 +85,11 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
__HAL_RCC_GPIOB_CLK_ENABLE();
/**ADC1 GPIO Configuration
PA3 ------> ADC1_IN3
PA4 ------> ADC1_IN4
PB0 ------> ADC1_IN8
PB1 ------> ADC1_IN9
*/
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Pin = GPIO_PIN_3|CP_ADC_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
@@ -115,10 +116,11 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
/**ADC1 GPIO Configuration
PA3 ------> ADC1_IN3
PA4 ------> ADC1_IN4
PB0 ------> ADC1_IN8
PB1 ------> ADC1_IN9
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_3);
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_3|CP_ADC_Pin);
HAL_GPIO_DeInit(GPIOB, ADC_NTC1_Pin|ADC_NTC2_Pin);

View File

@@ -2,16 +2,19 @@
#include "main.h"
#include "board.h"
#include "tim.h"
#include "sma_filter.h"
extern ADC_HandleTypeDef hadc1;
//TODO:
//TEMP READ
//GBT_TEMP_SENSORS
// Connector temperature sensors
InfoBlock_t *InfoBlock = (InfoBlock_t *)(VERSION_OFFSET);
uint8_t RELAY_State[RELAY_COUNT];
static volatile uint8_t adc_lock = 0;
static SMAFilter_t conn_temp_adc_filter[2];
void RELAY_Write(relay_t num, uint8_t state){
switch (num) {
@@ -30,6 +33,9 @@ void RELAY_Write(relay_t num, uint8_t state){
case RELAY_AC:
HAL_GPIO_WritePin(RELAY5_GPIO_Port, RELAY5_Pin, state);
break;
case RELAY_CP:
HAL_GPIO_WritePin(RELAY_CP_GPIO_Port, RELAY_CP_Pin, state);
break;
case RELAY_CC:
HAL_GPIO_WritePin(RELAY_CC_GPIO_Port, RELAY_CC_Pin, state);
break;
@@ -89,8 +95,12 @@ void Init_Peripheral(){
RELAY_Write(RELAY3, 0);
RELAY_Write(RELAY_DC, 0);
RELAY_Write(RELAY_AC, 0);
RELAY_Write(RELAY_CP, 1);
RELAY_Write(RELAY_CC, 1);
RELAY_Write(RELAY_DC1, 0);
SMAFilter_Init(&conn_temp_adc_filter[0]);
SMAFilter_Init(&conn_temp_adc_filter[1]);
}
float pt1000_to_temperature(float resistance) {
@@ -119,7 +129,9 @@ float calculate_NTC_resistance(int adc_value, float Vref, float Vin, float R) {
return R_NTC;
}
int16_t GBT_ReadTemp(uint8_t ch){
int16_t CONN_ReadTemp(uint8_t ch){
ADC_LockBlocking();
//TODO
if(ch)ADC_Select_Channel(ADC_CHANNEL_8);
else ADC_Select_Channel(ADC_CHANNEL_9);
@@ -136,19 +148,28 @@ int16_t GBT_ReadTemp(uint8_t ch){
// Остановка АЦП (по желанию)
HAL_ADC_Stop(&hadc1);
if(adcValue>4000) return 20; //Термодатчик не подключен
int32_t adc_filtered = SMAFilter_Update(&conn_temp_adc_filter[ch ? 1u : 0u], (int32_t)adcValue);
if((uint32_t)adc_filtered > 4000u) {
ADC_Unlock();
return 20; //Термодатчик не подключен
}
// int adc_value = 2048; // Пример значения АЦП
float Vref = 3.3; // Напряжение опорное
float Vin = 5.0; // Входное напряжение
float R = 1000; // Сопротивление резистора в Омах
float temp = pt1000_to_temperature(calculate_NTC_resistance(adcValue, Vref, Vin, R));
float temp = pt1000_to_temperature(calculate_NTC_resistance((int)adc_filtered, Vref, Vin, R));
ADC_Unlock();
return (int16_t)temp;
}
int16_t GBT_ReadTemp(uint8_t ch){
return CONN_ReadTemp(ch);
}
void ADC_Select_Channel(uint32_t ch) {
ADC_ChannelConfTypeDef conf = {
.Channel = ch,
@@ -159,3 +180,34 @@ void ADC_Select_Channel(uint32_t ch) {
Error_Handler();
}
}
uint8_t ADC_TryLock(void) {
uint32_t primask = __get_PRIMASK();
__disable_irq();
if (adc_lock != 0u) {
if (primask == 0u) {
__enable_irq();
}
return 0u;
}
adc_lock = 1u;
if (primask == 0u) {
__enable_irq();
}
return 1u;
}
void ADC_LockBlocking(void) {
while (ADC_TryLock() == 0u) {
/* wait in main context until ADC is free */
}
}
void ADC_Unlock(void) {
uint32_t primask = __get_PRIMASK();
__disable_irq();
adc_lock = 0u;
if (primask == 0u) {
__enable_irq();
}
}

View File

@@ -1,10 +1,12 @@
#include "charger_control.h"
#include "charger_config.h"
#include "lock.h"
#include "psu_control.h"
#include "connector.h"
#include "debug.h"
ChargingConnector_t CONN;
CONN_State_t connectorState;
void CONN_Init(){
@@ -21,9 +23,7 @@ void CONN_Loop(){
CONN.connControl = CMD_NONE;
}
if(GBT_LockState.error){
CONN.chargingError = CONN_ERR_LOCK;
} else if(PSU0.cont_fault){
if(PSU0.cont_fault){
CONN.chargingError = CONN_ERR_CONTACTOR;
} else if(PSU0.psu_fault){
CONN.chargingError = CONN_ERR_PSU_FAULT;
@@ -38,6 +38,48 @@ void CONN_Loop(){
}
void CONN_Task(){
/* CCS state machine is handled in serial.c.
* Keep this task lightweight for scheduler compatibility.
*/
if (CONN.chargingError != CONN_NO_ERROR) {
CONN_SetState(Disabled);
return;
}
if (connectorState == Unknown) {
CONN_SetState(Unplugged);
} else if (connectorState == Disabled && CONN.chargingError == CONN_NO_ERROR) {
CONN_SetState(Unplugged);
}
}
void CONN_SetState(CONN_State_t state){
if (connectorState == state) {
CONN.connState = state;
return;
}
connectorState = state;
if(connectorState == Unknown) log_printf(LOG_INFO, "Connector: Unknown\n");
if(connectorState == Unplugged) log_printf(LOG_INFO, "Connector: Unplugged\n");
if(connectorState == Disabled) log_printf(LOG_INFO, "Connector: Disabled\n");
if(connectorState == Preparing) log_printf(LOG_INFO, "Connector: Preparing\n");
if(connectorState == AuthRequired) log_printf(LOG_INFO, "Connector: AuthRequired\n");
if(connectorState == WaitingForEnergy) log_printf(LOG_INFO, "Connector: WaitingForEnergy\n");
if(connectorState == ChargingPausedEV) log_printf(LOG_INFO, "Connector: ChargingPausedEV\n");
if(connectorState == ChargingPausedEVSE) log_printf(LOG_INFO, "Connector: ChargingPausedEVSE\n");
if(connectorState == Charging) log_printf(LOG_INFO, "Connector: Charging\n");
if(connectorState == AuthTimeout) log_printf(LOG_INFO, "Connector: AuthTimeout\n");
if(connectorState == Finished) log_printf(LOG_INFO, "Connector: Finished\n");
if(connectorState == FinishedEVSE) log_printf(LOG_INFO, "Connector: FinishedEVSE\n");
if(connectorState == FinishedEV) log_printf(LOG_INFO, "Connector: FinishedEV\n");
if(connectorState == Replugging) log_printf(LOG_INFO, "Connector: Replugging\n");
CONN.connState = state;
}
void CONN_PrintChargingTotal(){
printf("CONN%d Charging Finished:\n", 0);
// printf("Charging Time: %d\n", CONN.chargingTime);

View File

@@ -1,593 +0,0 @@
/*
* 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 "lock.h"
#include "connector.h"
#include "soft_rtc.h"
#include "debug.h"
#include "charger_config.h"
#include "serial_control.h"
#include "lock.h"
#include "psu_control.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;
/** Время последнего приёма любого из PGN BCL/BCS/BSM; общий таймаут в GBT_S10_CHARGING */
uint32_t GBT_last_BCL_BCS_BSM_tick;
#define GBT_BCL_BCS_BSM_TIMEOUT_MS 2000
uint32_t GBT_StopCauseCode;
uint32_t GBT_ErrorCode;
GBT_StopSource_t GBT_StopSource;
extern ConfigBlock_t config;
void GBT_Init(){
GBT_State = GBT_DISABLED;
GBT_Reset();
GBT_MaxLoad.maxOutputVoltage = PSU_MAX_VOLTAGE*10; // 1000V
GBT_MaxLoad.minOutputVoltage = PSU_MIN_VOLTAGE*10; //150V
GBT_MaxLoad.maxOutputCurrent = 4000 - (PSU_MAX_CURRENT*10); //100A
GBT_MaxLoad.minOutputCurrent = 4000 - (PSU_MIN_CURRENT*10); //1A
}
void GBT_SetConfig(){
set_Time(config.unixTime);
GBT_ChargerInfo.chargerLocation[0] = config.location[0];
GBT_ChargerInfo.chargerLocation[1] = config.location[1];
GBT_ChargerInfo.chargerLocation[2] = config.location[2];
GBT_ChargerInfo.chargerNumber = config.chargerNumber;
}
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
GBT_last_BCL_BCS_BSM_tick = HAL_GetTick();
//TODO: power block
memcpy (&GBT_ReqPower, j_rx.data, sizeof(GBT_ReqPower));
uint16_t volt = GBT_ReqPower.requestedVoltage; // 0.1V/bit
uint16_t curr = 4000 - GBT_ReqPower.requestedCurrent; // 0.1A/bit
CONN.RequestedVoltage = volt / 10; // В
CONN.WantedCurrent = curr; // 0.1A
break;
case 0x1100: //PGN BCS
GBT_last_BCL_BCS_BSM_tick = HAL_GetTick();
//TODO
memcpy (&GBT_ChargingStatus, j_rx.data, sizeof(GBT_ChargingStatus));
CONN.SOC = GBT_ChargingStatus.currentChargeState;
break;
case 0x1300: //PGN BSM
GBT_last_BCL_BCS_BSM_tick = HAL_GetTick();
//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_AUX0, 0);
RELAY_Write(RELAY_AUX1, 0);
if(connectorState == Preparing){
GBT_Reset();
GBT_Start();//TODO IF protections (maybe not needed)
}
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_WAIT_PSU_READY);
}
//Timeout 10S
if((GBT_BHM_recv == 0) && (GBT_StateTick()>10000)) { //BHM Timeout
GBT_Error(0xFCF0C0FC);
CONN.chargingError = CONN_ERR_EV_COMM;
log_printf(LOG_ERR, "BHM Timeout\n");
}
break;
case GBT_S4_WAIT_PSU_READY:
if(j_rx.state == 0) GBT_SendCHM();
GBT_Delay(250);
if(PSU0.ready){
GBT_SwitchState(GBT_S4_WAIT_PSU_ON);
}
if(GBT_StateTick()>10000){
GBT_StopEVSE(GBT_CST_OTHERFALUT);
CONN.chargingError = CONN_ERR_PSU_FAULT;
log_printf(LOG_ERR, "PSU ready timeout, stopping...\n");
break;
}
break;
case GBT_S4_WAIT_PSU_ON:
if(j_rx.state == 0) GBT_SendCHM();
GBT_Delay(250);
CONN.RequestedVoltage = GBT_MaxVoltage.maxOutputVoltage / 10; // 0.1V -> V
CONN.WantedCurrent = 10; // 1A max (0.1A units)
CONN.EnableOutput = 1;
if(PSU0.state == PSU_CONNECTED){
GBT_SwitchState(GBT_S4_ISOTEST);
}
if(GBT_StateTick()>10000){
GBT_StopEVSE(GBT_CST_OTHERFALUT);
CONN.chargingError = CONN_ERR_PSU_FAULT;
log_printf(LOG_ERR, "PSU on timeout, stopping...\n");
break;
}
break;
case GBT_S4_ISOTEST:
if(j_rx.state == 0) GBT_SendCHM();
GBT_Delay(250);
//TODO: Isolation test trigger
if(CONN.chargingError != CONN_NO_ERROR){
GBT_StopEVSE(GBT_CST_OTHERFALUT);
}
if(GBT_StateTick()>5000){
GBT_SwitchState(GBT_S4_WAIT_PSU_OFF);
}
if(ISO.isolationResistance < (ISO.voltageComm/2)){ // *100/1000
CONN.chargingError = CONN_ERR_INSULATION;
log_printf(LOG_WARN, "Isolation warning\n");
} // 500 Ohm/V
if(ISO.isolationResistance < (ISO.voltageComm/10)){ // *100/1000
CONN.chargingError = CONN_ERR_INSULATION;
log_printf(LOG_WARN, "Current leakage, insulation error, stopping...\n");
GBT_StopEVSE(GBT_CST_OTHERFALUT);
} // 100 Ohm/V
break;
case GBT_S4_WAIT_PSU_OFF:
CONN.RequestedVoltage = 0;
CONN.WantedCurrent = 0;
CONN.EnableOutput = 0;
if(GBT_StateTick()>5000){
GBT_StopEVSE(GBT_CST_OTHERFALUT);
CONN.chargingError = CONN_ERR_PSU_FAULT;
log_printf(LOG_ERR, "PSU off timeout, stopping...\n");
break;
}
if(PSU0.PSU_enabled == 0){
GBT_SwitchState(GBT_S5_BAT_INFO);
}
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);
log_printf(LOG_INFO, "EV info:\n");
log_printf(LOG_INFO, "GBT_ver V%d.%d%d\n",GBT_EVInfo.version[0],GBT_EVInfo.version[1],GBT_EVInfo.version[2]);
log_printf(LOG_INFO, "Battery type: %d\n",GBT_EVInfo.batteryType);
log_printf(LOG_INFO, "Battery capacity: %d\n", GBT_EVInfo.batteryCapacity); // 0.1Ah/bit
log_printf(LOG_INFO, "Battery voltage: %d\n", GBT_EVInfo.batteryVoltage); // 0.1V/bit
log_printf(LOG_INFO, "Battery vendor: %.4s\n", GBT_EVInfo.batteryVendor); // Battery vendor (ASCII string)
log_printf(LOG_INFO, "Battery SN: %lu\n", GBT_EVInfo.batterySN); // int
log_printf(LOG_INFO, "Battery manufacture date: %02d.%02d.%04d\n", GBT_EVInfo.batteryManuD, GBT_EVInfo.batteryManuM ,GBT_EVInfo.batteryManuY+1985); // year (offset 1985)
log_printf(LOG_INFO, "Battery cycles: %d\n", GBT_EVInfo.batteryCycleCount); //uint24_t
log_printf(LOG_INFO, "Own auto: %d\n", GBT_EVInfo.ownAuto); // 0 = lizing, 1 = own auto
log_printf(LOG_INFO, "EVIN: %.17s\n", GBT_EVInfo.EVIN); //EVIN
log_printf(LOG_INFO, "EV_SW_VER: %.8s\n", GBT_EVInfo.EV_SW_VER);
}
//Timeout
if((GBT_StateTick()>5000) && (GBT_BAT_INFO_recv == 0)){
CONN.chargingError = CONN_ERR_EV_COMM;
GBT_Error(0xFDF0C0FC); //BRM Timeout
log_printf(LOG_ERR, "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);
log_printf(LOG_INFO, "Battery info:\n");
log_printf(LOG_INFO, "maxCV %dV\n",GBT_BATStat.maxCellVoltage/100); // 0.01v/bit
log_printf(LOG_INFO, "maxCC %dA\n",GBT_BATStat.maxChargingCurrent/10); // 0.1A/bit
log_printf(LOG_INFO, "totE %dkWh\n",GBT_BATStat.totalEnergy/10); // 0.1kWh
log_printf(LOG_INFO, "maxCV %dV\n",GBT_BATStat.maxChargingVoltage/10); // 0.1V/ bit
log_printf(LOG_INFO, "maxT %dC\n",(int16_t)GBT_BATStat.maxTemp-50); // 1C/bit, -50C offset
log_printf(LOG_INFO, "SOC %dp\n",GBT_BATStat.SOC/10); // 0.1%/bit , 0..100%
log_printf(LOG_INFO, "Volt. %dV\n",GBT_BATStat.measVoltage/10); // 0.1V/bit
}
if((GBT_StateTick()>5000) && (GBT_BAT_STAT_recv == 0)){
CONN.chargingError = CONN_ERR_EV_COMM;
GBT_Error(0xFCF1C0FC); //BCP Timeout
log_printf(LOG_ERR, "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)){
CONN.chargingError = CONN_ERR_EV_COMM;
GBT_Error(0xFCF4C0FC); //BRO Timeout
log_printf(LOG_ERR, "BRO Timeout\n");
}
if(EV_ready){
//EV ready (AA)
GBT_SwitchState(GBT_S8_INIT_CHARGER);
}else{
if((GBT_StateTick()>60000) && (GBT_BRO_recv == 1)){
CONN.chargingError = CONN_ERR_EV_COMM;
GBT_Error(0xFCF4C0FC); //BRO Timeout
log_printf(LOG_ERR, "EV not ready for a 60s\n");
}
}
break;
case GBT_S8_INIT_CHARGER:
if(j_rx.state == 0) GBT_SendCRO(0x00);
//TODO
GBT_Delay(250);
// if(GBT_StateTick()>1500){
if(PSU0.ready){
//Power Modules initiated
GBT_SwitchState(GBT_S9_WAIT_BCL);
}
if((GBT_StateTick()>6000) && (PSU0.ready == 0)){
GBT_StopEVSE(GBT_CST_OTHERFALUT);
CONN.chargingError = CONN_ERR_PSU_FAULT;
log_printf(LOG_ERR, "PSU not ready, stopping...\n");
}
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);
GBT_last_BCL_BCS_BSM_tick = HAL_GetTick();
CONN_SetState(Charging);
uint16_t curr = 4000 - GBT_ReqPower.requestedCurrent;
uint16_t volt = GBT_ReqPower.requestedVoltage;
//TODO Limits
CONN.RequestedVoltage = volt / 10; // В
CONN.WantedCurrent = curr; // 0.1A
CONN.EnableOutput = 1;
GBT_TimeChargingStarted = get_Current_Time();
}
break;
case GBT_S10_CHARGING:
//CHARGING
if((HAL_GetTick() - GBT_last_BCL_BCS_BSM_tick) > GBT_BCL_BCS_BSM_TIMEOUT_MS){
GBT_StopEVSE(GBT_CST_OTHERFALUT);
CONN.chargingError = CONN_ERR_EV_COMM;
log_printf(LOG_WARN, "BCL/BCS/BSM timeout, stopping...\n");
break;
}
if(CONN.connControl == CMD_STOP) GBT_StopOCPP(GBT_CST_SUSPENDS_ARTIFICIALLY);
if(CONN.connControl == CMD_FORCE_UNLOCK) GBT_StopOCPP(GBT_CST_SUSPENDS_ARTIFICIALLY); // --> Finished
if(GBT_LockState.error) {
GBT_StopEVSE(GBT_CST_OTHERFALUT); // --> Suspend EVSE
CONN.chargingError = CONN_ERR_LOCK;
log_printf(LOG_WARN, "Lock error, stopping...\n");
break;
}
if(CONN_CC_GetState()!=GBT_CC_4V){
GBT_StopEVSE(GBT_CST_OTHERFALUT);
CONN.chargingError = CONN_ERR_HOTPLUG;
log_printf(LOG_WARN, "Hotplug detected, stopping...\n");
break;
}
if((GBT_ReadTemp(0) > 90) || (GBT_ReadTemp(1) > 90)) {
GBT_StopEVSE(GBT_CST_CONNECTOR_OVER_TEMP);
CONN.chargingError = CONN_ERR_CONN_TEMP;
log_printf(LOG_WARN, "Connector overheat %d %d, stopping...\n", GBT_ReadTemp(0), GBT_ReadTemp(1));
break;
}
if(ISO.isolationResistance < (ISO.voltageComm/10)){ // *100/1000
CONN.chargingError = CONN_ERR_INSULATION;
log_printf(LOG_WARN, "Current leakage, insulation error, stopping...\n");
} // 100 Ohm/V
if(CONN.chargingError != CONN_NO_ERROR){ // --> Suspend EVSE
GBT_StopEVSE(GBT_CST_OTHERFALUT);
}
//GBT_ChargerCurrentStatus.chargingPermissible = 0b1111111111111100;//NOT PERMITTED
GBT_ChargerCurrentStatus.chargingPermissible = 0b1111111111111101;
GBT_ChargerCurrentStatus.chargingTime = (get_Current_Time() - GBT_TimeChargingStarted)/60;
GBT_ChargerCurrentStatus.outputCurrent = 4000 - CONN.MeasuredCurrent; // 0.1A
GBT_ChargerCurrentStatus.outputVoltage = CONN.MeasuredVoltage * 10; // V -> 0.1V
if(j_rx.state == 0) {
GBT_SendCCS();
GBT_Delay(49);
}else{
GBT_Delay(10); // Resend packet if not sent
}
//TODO: снижение тока если перегрев контактов
break;
case GBT_STOP:
GBT_Delay(10);
CONN.EnableOutput = 0;
GBT_SendCST(GBT_StopCauseCode);
//RELAY_Write(RELAY_OUTPUT, 0);
//GBT_SwitchState(GBT_DISABLED);
if(GBT_StateTick()>10000){
log_printf(LOG_ERR, "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);
}
break;
case GBT_ERROR:
GBT_SendCEM(GBT_ErrorCode); //2.5S
GBT_SwitchState(GBT_COMPLETE);
break;
case GBT_COMPLETE:
if(connectorState != Finished) {
GBT_SwitchState(GBT_DISABLED);
GBT_Reset();//CHECK
}
break;
default:
GBT_SwitchState(GBT_DISABLED);
}
if (CONN_CC_GetState()==GBT_CC_4V) CONN.EvConnected = 1;
else CONN.EvConnected = 0;
}
void GBT_SwitchState(gbtState_t state){
GBT_State = state;
GBT_state_tick = HAL_GetTick();
if(GBT_State == GBT_DISABLED) log_printf(LOG_INFO, "Disabled\n");
if(GBT_State == GBT_S3_STARTED) log_printf(LOG_INFO, "Charging started\n");
if(GBT_State == GBT_S31_WAIT_BHM) log_printf(LOG_INFO, "Waiting for BHM\n");
if(GBT_State == GBT_S4_WAIT_PSU_READY) log_printf(LOG_INFO, "Waiting for PSU ready\n");
if(GBT_State == GBT_S4_ISOTEST) log_printf(LOG_INFO, "Isolation test\n");
if(GBT_State == GBT_S5_BAT_INFO) log_printf(LOG_INFO, "Waiting for battery info\n");
if(GBT_State == GBT_S6_BAT_STAT) log_printf(LOG_INFO, "Waiting for battery status\n");
if(GBT_State == GBT_S7_BMS_WAIT) log_printf(LOG_INFO, "Waiting for BMS\n");
if(GBT_State == GBT_S8_INIT_CHARGER)log_printf(LOG_INFO, "Initializing charger\n");
if(GBT_State == GBT_S9_WAIT_BCL) log_printf(LOG_INFO, "Waiting for BCL\n");
if(GBT_State == GBT_S10_CHARGING) log_printf(LOG_INFO, "Charging in progress\n");
if(GBT_State == GBT_STOP) log_printf(LOG_INFO, "Charging Stopped\n");
if(GBT_State == GBT_STOP_CSD) log_printf(LOG_INFO, "Charging Stopped with CSD\n");
if(GBT_State == GBT_ERROR) log_printf(LOG_INFO, "Charging Error\n");
if(GBT_State == GBT_COMPLETE) log_printf(LOG_INFO, "Charging Finished\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_StopEV(uint32_t causecode){ // --> Suspend EV
if (CONN.chargingError){
GBT_StopSource = GBT_STOP_EVSE;
}else{
GBT_StopSource = GBT_STOP_EV;
}
GBT_StopCauseCode = causecode;
if(GBT_State != GBT_STOP) GBT_SwitchState(GBT_STOP);
}
void GBT_StopEVSE(uint32_t causecode){ // --> Suspend EVSE
GBT_StopSource = GBT_STOP_EVSE;
GBT_StopCauseCode = causecode;
if(GBT_State != GBT_STOP) GBT_SwitchState(GBT_STOP);
}
void GBT_StopOCPP(uint32_t causecode){ // --> Finished
GBT_StopSource = GBT_STOP_OCPP;
GBT_StopCauseCode = causecode;
if(GBT_State != GBT_STOP) GBT_SwitchState(GBT_STOP);
}
void GBT_ForceStop(){ // --> Suspend EV
GBT_StopSource = GBT_STOP_EV;
CONN.EnableOutput = 0;
GBT_SwitchState(GBT_COMPLETE);
GBT_Lock(0);
RELAY_Write(RELAY_AUX0, 0);
RELAY_Write(RELAY_AUX1, 0);
}
void GBT_Error(uint32_t errorcode){ // --> Suspend EV
GBT_StopSource = GBT_STOP_EV;
log_printf(LOG_ERR, "GBT Error code: 0x%X\n", errorcode);
GBT_ErrorCode = errorcode;
GBT_SwitchState(GBT_ERROR);
}
void GBT_Reset(){
GBT_last_BCL_BCS_BSM_tick = HAL_GetTick();
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;
CONN.SOC = 0;
CONN.EnableOutput = 0;
CONN.WantedCurrent = 0;
CONN.RequestedVoltage = 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;
GBT_LockResetError();
}
void GBT_Start(){
RELAY_Write(RELAY_AUX0, 1);
RELAY_Write(RELAY_AUX1, 1);
GBT_SwitchState(GBT_S3_STARTED);
}

View File

@@ -1,221 +0,0 @@
/*
* connector.c
*
* All initialization before 12v_aux
*/
#include "connector.h"
#include "lock.h"
#include "board.h"
#include "debug.h"
CONN_State_t connectorState;
extern uint8_t config_initialized;
gbtCcState_t CC_STATE_FILTERED;
// name - уникальный идентификатор таймера для данного места использования
// cond - условие, которое должно непрерывно держаться delay_ms мс
// delay_ms - задержка в миллисекундах
#define DELAYED_HOLD_MS(name, cond, delay_ms) \
({ \
static uint32_t name = 0; \
uint8_t __hold_result = 0; \
if (cond) { \
if (name == 0) { \
name = HAL_GetTick(); \
} else if ((HAL_GetTick() - name) >= (uint32_t)(delay_ms)) {\
__hold_result = 1; \
name = 0; \
} \
} else { \
name = 0; \
} \
__hold_result; \
})
void CONN_Task(){
switch (connectorState){
case Unknown: // unlocked, waiting for config
GBT_Lock(0);
if (config_initialized) {
CONN_SetState(Unplugged);
}
break;
case Disabled: // faulted, unlocked
GBT_Lock(0);
if(CONN.chargingError == 0) CONN_SetState(Unplugged);
if(CONN.connControl == CMD_FORCE_UNLOCK) GBT_ForceLock(0);
break;
case Unplugged: // unlocked, waiting to connect
GBT_Lock(0);
if(CONN.chargingError != 0) CONN_SetState(Disabled);
if(CONN.connControl == CMD_FORCE_UNLOCK) GBT_ForceLock(0);
if((CONN_CC_GetState()==GBT_CC_4V) && (CONN.connControl != CMD_FORCE_UNLOCK)){
CONN_SetState(AuthRequired);
GBT_Lock(0);
}
break;
case AuthRequired: // plugged, waiting to start charge
GBT_Lock(0);
if(CONN.connControl == CMD_FORCE_UNLOCK) GBT_ForceLock(0);
if(CONN_CC_GetState()==GBT_CC_4V){
if(CONN.connControl == CMD_START){
CONN_SetState(Preparing);
}
if(CONN.connControl == CMD_FORCE_UNLOCK){
CONN_SetState(Unplugged);
}
// if CHARGING_NOT_ALLOWED — stay here
}else{
CONN_SetState(Unplugged);
}
break;
case Preparing: // charging, locked
GBT_Lock(1);
if(GBT_State == GBT_COMPLETE){
if(GBT_StopSource == GBT_STOP_EVSE){
CONN_SetState(FinishedEVSE);
}else if(GBT_StopSource == GBT_STOP_EV){
CONN_SetState(FinishedEV);
}else if(GBT_StopSource == GBT_STOP_OCPP){
CONN_SetState(Finished);
}else{
CONN_SetState(FinishedEVSE);
}
}
if(GBT_State == GBT_S10_CHARGING){
CONN_SetState(Charging);
}
break;
case Charging: // charging, locked
GBT_Lock(1);
if(GBT_State == GBT_COMPLETE){
if(GBT_StopSource == GBT_STOP_EVSE){
CONN_SetState(FinishedEVSE);
}else if(GBT_StopSource == GBT_STOP_EV){
CONN_SetState(FinishedEV);
}else if(GBT_StopSource == GBT_STOP_OCPP){
CONN_SetState(Finished);
}else{
CONN_SetState(FinishedEVSE);
}
}
break;
case FinishedEV: // charging completed by EV, waiting to transaction stop
GBT_Lock(0);
CONN_SetState(Finished);
break;
case FinishedEVSE: // charging completed by EVSE, waiting to transaction stop
GBT_Lock(0);
CONN_SetState(Finished);
break;
case Finished: // charging completed, waiting to disconnect, unlocked
GBT_Lock(0);
//TODO Force unlock time limit
if(CONN.connControl == CMD_FORCE_UNLOCK) GBT_ForceLock(0);
if(DELAYED_HOLD_MS(cc6v_hold_tick, CONN_CC_GetState()==GBT_CC_6V, 5000)){
GBT_Lock(0);
CONN_SetState(Unplugged);
}
break;
default:
CONN_SetState(Unknown);
}
}
//external
//CONN_SetState(Disabled);
void CONN_SetState(CONN_State_t state){
connectorState = state;
if(connectorState == Unknown) log_printf(LOG_INFO, "Connector: Unknown\n");
if(connectorState == Unplugged) log_printf(LOG_INFO, "Connector: Unplugged\n");
if(connectorState == Disabled) log_printf(LOG_INFO, "Connector: Disabled\n");
if(connectorState == Preparing) log_printf(LOG_INFO, "Connector: Preparing\n");
if(connectorState == AuthRequired) log_printf(LOG_INFO, "Connector: AuthRequired\n");
if(connectorState == WaitingForEnergy) log_printf(LOG_INFO, "Connector: WaitingForEnergy\n");
if(connectorState == ChargingPausedEV) log_printf(LOG_INFO, "Connector: ChargingPausedEV\n");
if(connectorState == ChargingPausedEVSE) log_printf(LOG_INFO, "Connector: ChargingPausedEVSE\n");
if(connectorState == Charging) log_printf(LOG_INFO, "Connector: Charging\n");
if(connectorState == AuthTimeout) log_printf(LOG_INFO, "Connector: AuthTimeout\n");
if(connectorState == Finished) log_printf(LOG_INFO, "Connector: Finished\n");
if(connectorState == FinishedEVSE) log_printf(LOG_INFO, "Connector: FinishedEVSE\n");
if(connectorState == FinishedEV) log_printf(LOG_INFO, "Connector: FinishedEV\n");
if(connectorState == Replugging) log_printf(LOG_INFO, "Connector: Replugging\n");
CONN.connState = state;
}
void CONN_CC_ReadStateFiltered() {
static uint32_t last_change_time = 0;
static uint32_t last_check_time = 0;
static uint8_t prev_state = 0;
if((HAL_GetTick()-last_check_time)<100) return;
last_check_time = HAL_GetTick();
uint8_t new_state = CONN_CC_GetStateRaw();
if (new_state != prev_state) {
last_change_time = HAL_GetTick();
prev_state = new_state;
} else if ((HAL_GetTick() - last_change_time) >= 300) {
CC_STATE_FILTERED = prev_state;
}
}
uint8_t CONN_CC_GetState(){
return CC_STATE_FILTERED;
}
uint8_t CONN_CC_GetStateRaw(){
float volt = CONN_CC_GetAdc();
// if((volt<12.6f) && (volt>11.4f)) return GBT_CC_12V;
// if((volt<6.8f) && (volt>5.2f)) return GBT_CC_6V;
// if((volt<4.8f) && (volt>3.2f)) return GBT_CC_4V;
// if((volt<2.8f) && (volt>1.2f)) return GBT_CC_2V;
if((volt<13.0f) && (volt>11.0f)) return GBT_CC_12V;
if((volt<7.2f) && (volt>4.8f)) return GBT_CC_6V;
if((volt<4.8f) && (volt>3.0f)) return GBT_CC_4V;
if((volt<3.0f) && (volt>1.0f)) return GBT_CC_2V;
return GBT_CC_UNKNOWN;
}
float CONN_CC_GetAdc(){
//TODO: Filters
//Vref=3.3v = 4095
//k=1/11
//Vin = 12v
//Vin*k= 1.09v
//12vin = 1353 ADC
uint32_t adc;
float volt;
ADC_Select_Channel(ADC_CHANNEL_3);
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
adc = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
volt = (float)adc/113.4f;
return volt;
}

115
Core/Src/cp.c Normal file
View File

@@ -0,0 +1,115 @@
#include "cp.h"
#include "adc.h"
#include "board.h"
#include "tim.h"
#include <stdint.h>
#define MAX_DUTY 450
static int32_t cp_voltage_mv = 0;
static uint8_t cp_duty = 0;
CP_State_t fake_cp_state = EV_STATE_ACQUIRING;
static uint32_t CP_ReadAdcChannel(uint32_t ch) {
uint32_t adc = 0;
ADC_Select_Channel(ch);
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 10);
adc = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
return adc;
}
#define VREFINT_CAL_ADDR ((uint16_t*)0x1FFFF7BA) // для STM32F1!
static int32_t CP_ReadVoltageMv(void)
{
uint32_t adc = 0;
int32_t v_adc_mv = 0;
int32_t v_out_mv = 0;
adc = CP_ReadAdcChannel((uint32_t)4u);
v_adc_mv = (int32_t)((adc * 3300u) / 4095u);
v_out_mv = ((v_adc_mv - 1723) * 1000) / 130;
return v_out_mv;
}
void CP_Init(void) {
/* TIM3_CH2 (PA7): set 1kHz PWM like original CCS logic. */
htim3.Instance->PSC = 160 - 1;
htim3.Instance->ARR = MAX_DUTY - 1;
#if DUTY_INVERT == 0
htim3.Instance->CCR2 = MAX_DUTY;
htim3.Instance->CCR1 = MAX_DUTY + 5;
#else
htim3.Instance->CCR2 = 0;
htim3.Instance->CCR1 = 0;
#endif
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
HAL_TIM_OC_Start_IT(&htim3, TIM_CHANNEL_1);
}
void CP_SetDuty(uint8_t percentage) {
uint32_t pwmduty = MAX_DUTY * percentage / 100;
cp_duty = percentage;
#if DUTY_INVERT == 0
htim3.Instance->CCR2 = pwmduty;
htim3.Instance->CCR1 = 0 + 1;
#else
htim3.Instance->CCR2 = MAX_DUTY - pwmduty;
htim3.Instance->CCR1 = MAX_DUTY - pwmduty + 5;
#endif
}
uint8_t CP_GetDuty(void) {
return cp_duty;
}
int32_t CP_GetVoltage(void) {
return cp_voltage_mv;
}
CP_State_t CP_GetState(void) {
int32_t voltage_real = cp_voltage_mv;
if(fake_cp_state != EV_STATE_ACQUIRING) {
return fake_cp_state;
}
if (voltage_real >= (12000-1000)) {
return EV_STATE_A_IDLE;
} else if (voltage_real >= (9000-1000) && voltage_real <= (9000+1000)) {
return EV_STATE_B_CONN_PREP;
} else if (voltage_real >= (6000-1000) && voltage_real <= (6000+1000)) {
return EV_STATE_C_CONN_ACTIVE;
} else if (voltage_real >= (3000-1000) && voltage_real <= (3000 + 1000)) {
return EV_STATE_D_CONN_ACT_VENT;
} else if (voltage_real >= (0-1000) && voltage_real <= (0+2000)){
return EV_STATE_E_NO_POWER;
} else if (voltage_real <= (-12000+1000)) {
return EV_STATE_F_ERROR;
} else {
return EV_STATE_ACQUIRING;
}
}
void CP_Loop(void) {
(void)CP_GetState();
}
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM3 && htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
if (ADC_TryLock() == 0u) {
return;
}
cp_voltage_mv = CP_ReadVoltageMv();
ADC_Unlock();
}
}

View File

@@ -12,7 +12,6 @@
#include <stdarg.h>
#include "debug.h"
#include "board.h"
#include "charger_gbt.h"
#include "usart.h"
#include <time.h>
#include <connector.h>

View File

@@ -1,120 +0,0 @@
/*
* gbt_packet.c
*
* Created on: Jul 23, 2024
* Author: colorbass
*/
// GB/T Time Synchronization Packet
#include "main.h"
#include "soft_rtc.h"
#include "charger_gbt.h"
void GBT_SendCTS(){
uint8_t data[7];
unix_to_bcd(get_Current_Time(), data);
// data[0] = 0x00; //seconds
// data[1] = 0x30; //minutes
// data[2] = 0x23; //hours
// data[3] = 0x05; //days
// data[4] = 0x05; //month
// data[5] = 0x24; //years
// data[6] = 0x20; //centuries
J_SendPacket(0x000700, 6, 7, data);
}
//GB/T Max Load Packet
void GBT_SendCML(){
// uint8_t data[8];
// data[0] = 0x94; //450V max output voltage
// data[1] = 0x11; //
// data[2] = 0xB0; //120V min output voltage
// data[3] = 0x04; //
// data[4] = 0xC4; //-150A maximum output current
// data[5] = 0x09; //
// data[6] = 0x8C; //-2A minimum output current
// data[7] = 0x0F; //
J_SendPacket(0x000800, 6, 8, (uint8_t*)&GBT_MaxLoad);
}
//GB/T Version packet
void GBT_SendCHM(){
uint8_t data[3];
data[0] = 0x01;
data[1] = 0x01;
data[2] = 0x00;
J_SendPacket(0x2600, 6, 3, data);
}
//GB/T CRM Packet (state=BMS identified)
void GBT_SendCRM(uint8_t state){
// uint8_t data[8];
// data[0] = state; // 0x00 / 0xAA
// data[1] = 0x40; //TODO: Charger Number 123456
// data[2] = 0xE2;
// data[3] = 0x01;
// data[4] = 0x00;
// data[5] = 0x42; //TODO: location BFG
// data[6] = 0x46;
// data[7] = 0x47;
GBT_ChargerInfo.bmsIdentified = state;
J_SendPacket(0x100, 6, 8, (uint8_t *)&GBT_ChargerInfo);
}
//GB/T CRO packet (Charger ready)
void GBT_SendCRO(uint8_t state){
uint8_t data[1];
data[0] = state;
J_SendPacket(0xA00, 4, 1, data);
}
//GB/T CCS packet (Charger current status)
void GBT_SendCCS(){
// uint8_t data[8];
// data[0] = GBT_CurrPower.requestedVoltage; //
// data[1] = GBT_CurrPower.requestedVoltage>>8; //output voltage
// data[2] = GBT_CurrPower.requestedCurrent; //смещение 400а, границы
// //-400A = 0
// // 0A = 4000
// // -100A = 3000
// data[3] = GBT_CurrPower.requestedCurrent>>8; //TODO: current
// data[4] = GBT_StateTick()/60000; //charging time (min)
// data[5] = 0; //TODO: 255 min+
// data[6] = 0b11111101; //charging not permitted
// data[7] = 0xFF;
J_SendPacket(0x1200, 6, 8, (uint8_t *)&GBT_ChargerCurrentStatus);
}
// GB/T Charging Stop packet
void GBT_SendCST(uint32_t Cause){
uint8_t data[8];
data[0] = (Cause>>24) & 0xFF; // Error
data[1] = (Cause>>16) & 0xFF; //
data[2] = (Cause>>8) & 0xFF; //
data[3] = Cause & 0xFF; //
J_SendPacket(0x1A00, 4, 4, data);
}
void GBT_SendCSD(){
GBT_ChargerStop.chargerNumber = GBT_ChargerInfo.chargerNumber;
GBT_ChargerStop.outputEnergy = 0; //TODO Energy meters
GBT_ChargerStop.chargingTime = GBT_ChargerCurrentStatus.chargingTime;
J_SendPacket(0x1D00, 6, 7, (uint8_t *)&GBT_ChargerStop);
}
void GBT_SendCEM(uint32_t ErrorCode){
uint8_t data[8];
data[0] = (ErrorCode>>24) & 0xFF; // Error
data[1] = (ErrorCode>>16) & 0xFF; //
data[2] = (ErrorCode>>8) & 0xFF; //
data[3] = ErrorCode & 0xFF; //
J_SendPacket(0x1F00, 4, 4, data);
}

View File

@@ -54,7 +54,7 @@ void MX_GPIO_Init(void)
__HAL_RCC_GPIOD_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, LOCK_A_Pin|LOCK_B_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, RELAY_CP_Pin|LOCK_A_Pin|LOCK_B_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOE, RELAY1_Pin|RELAY2_Pin|RELAY3_Pin|RELAY4_Pin
@@ -69,6 +69,13 @@ void MX_GPIO_Init(void)
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(EE_WP_GPIO_Port, EE_WP_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : RELAY_CP_Pin LOCK_A_Pin LOCK_B_Pin */
GPIO_InitStruct.Pin = RELAY_CP_Pin|LOCK_A_Pin|LOCK_B_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pin : IN_SW0_Pin */
GPIO_InitStruct.Pin = IN_SW0_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
@@ -81,13 +88,6 @@ void MX_GPIO_Init(void)
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(IN_SW1_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : LOCK_A_Pin LOCK_B_Pin */
GPIO_InitStruct.Pin = LOCK_A_Pin|LOCK_B_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pins : IN0_Pin AC_OK_Pin ISO_IN_Pin */
GPIO_InitStruct.Pin = IN0_Pin|AC_OK_Pin|ISO_IN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;

View File

@@ -1,197 +0,0 @@
/*
* j1939.c
*
* Created on: May 3, 2024
* Author: colorbass
*/
#include "main.h"
#include "j1939.h"
#include "charger_gbt.h"
#include "string.h"
#include "can.h"
#include "debug.h"
extern GBT_BCL_t GBT_ReqPower;
extern GBT_BCL_t GBT_CurrPower;
j_receive_t j_rx;
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
CAN_RxHeaderTypeDef RxHeader;
uint8_t RxData[8] = {0,};
if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData) == HAL_OK)
{
if((RxHeader.ExtId & 0x00FFFF) == ((J_ID_SE << 8) | J_ID_EV)){ // SA, DA match
switch ((RxHeader.ExtId>>8) & 0x00FF00){
case 0xEC00: //PGN Connection Management Message
if(RxData[0] == 16){ //Request to Send
/* Set the RTS values */
j_rx.size = RxData[1] | (RxData[2]<<8);
j_rx.packet = 1;
j_rx.packets = RxData[3];
j_rx.step = 2; //TODO
j_rx.step_cts_remain = j_rx.step;
j_rx.PGN = (RxData[7] << 16) | (RxData[6] << 8) | RxData[5];
if(j_rx.size<256) { //TODO: valid check
J_SendCTS(j_rx);
j_rx.state = 1;
}
}
if(RxData[0] == 255){ //Connection Abort
j_rx.state = 0;
}
//if(RxData[0] == 32){}//Broadcast Announce Message
/*
* 1CEC56F4 10 31 00 07 07 00 02 00
* 1CECF456 11 02 01 FF FF 00 02 00
* 1CEB56F4 01 01 01 00 03 46 05 40
* 1CEC56F4 FF FF FF FF FF 00 00 00
*/
break;
case 0xEB00: //PGN Data Message
if(j_rx.state != 1) break;
if((RxData[0]>0) && (RxData[0]<35)){ //Array limit check
if(j_rx.packet == RxData[0]){ //step check
memcpy (&j_rx.data[(RxData[0]-1)*7], &RxData[1],7);
j_rx.packet++;
if(j_rx.packet > j_rx.packets){
//End of transmission
J_SendACK(j_rx);
j_rx.state = 2;
}else{
if(j_rx.step_cts_remain > 0) j_rx.step_cts_remain--;
if(j_rx.step_cts_remain == 0){
J_SendCTS(j_rx);
j_rx.step_cts_remain = 2;
}
}
}
}
break;
case 0x1E00: //PGN BEM (ERROR)
//Error force stop
// --> Suspend EV
log_printf(LOG_ERR, "BEM Received, force stopping...\n");
log_printf(LOG_ERR, "BEM: %02X %02X %02X %02X", RxData[0], RxData[1], RxData[2], RxData[3]);
log_printf(LOG_ERR, " %02X %02X %02X %02X\n", RxData[4], RxData[5], RxData[6], RxData[7]);
GBT_ForceStop();
break;
case 0x1900: //PGN BST (STOP)
//Normal stop
// --> Suspend EV
log_printf(LOG_INFO, "BST Received, stopping...\n");
log_printf(LOG_INFO, "BST: %02X %02X %02X %02X", RxData[0], RxData[1], RxData[2], RxData[3]);
log_printf(LOG_INFO, " %02X %02X %02X %02X\n", RxData[4], RxData[5], RxData[6], RxData[7]);
GBT_StopEV(GBT_CST_BMS_ACTIVELY_SUSPENDS);
break;
default:
if(j_rx.state == 0){//TODO protections
//Short packet
j_rx.size = RxHeader.DLC;
j_rx.packet = 1;
j_rx.packets = 1;
j_rx.step = 1;
j_rx.step_cts_remain = 0;
j_rx.PGN = (RxHeader.ExtId>>8) & 0x00FF00;
j_rx.state = 2;
memcpy (j_rx.data, RxData, j_rx.size);
}
}
}
}
}
void GBT_CAN_ReInit(){
HAL_CAN_Stop(&hcan1);
MX_CAN1_Init();
GBT_CAN_FilterInit();
HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
}
void J_SendPacket(uint32_t PGN, uint8_t pri, uint8_t DLC, uint8_t *data){
CAN_TxHeaderTypeDef tx_header;
uint32_t tx_mailbox;
tx_header.ExtId = (pri << 26) | (PGN << 8) | (J_ID_EV << 8) | J_ID_SE;
tx_header.RTR = CAN_RTR_DATA;
tx_header.IDE = CAN_ID_EXT;
tx_header.DLC = DLC;
//TODO buffer wait
HAL_CAN_AddTxMessage(&hcan1, &tx_header, data, &tx_mailbox);
//HAL_Delay(2);
}
//void J_SendPacketLong(){
// //TODO (no need)
//}
// J1939 sequence Clear To Send packet
void J_SendCTS(j_receive_t rx){
//if(rx.packets <= rx.packet) return; TODO
uint8_t data[8];
data[0] = 17; //CONTROL_BYTE_TP_CM_CTS
data[1] = rx.step;//total_number_of_packages_transmitted
if (rx.step > (rx.packets - rx.packet+1)) data[1] = rx.packets - rx.packet+1;
data[2] = rx.packet;//next_packet_number_transmitted
data[3] = 0xFF; /* Reserved */
data[4] = 0xFF;
data[5] = rx.PGN;
data[6] = rx.PGN >> 8;
data[7] = rx.PGN >> 16;
J_SendPacket(0x00EC00, 7, 8, data);
}
// J1939 sequence ACK packet
void J_SendACK(j_receive_t rx){//uint32_t PGN, uint8_t step, uint8_t packet){
uint8_t data[8];
data[0] = 19; //CONTROL_BYTE_TP_CM_ACK
data[1] = j_rx.size;
data[2] = j_rx.size>>8;
data[3] = j_rx.packets;
data[4] = 0xFF;//TODO
data[5] = rx.PGN;
data[6] = rx.PGN >> 8;
data[7] = rx.PGN >> 16;
J_SendPacket(0x00EC00, 7, 8, data);
}
void GBT_CAN_FilterInit(){
CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterBank = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterIdHigh = 0x0000;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
sFilterConfig.FilterActivation = ENABLE;
//sFilterConfig.SlaveStartFilterBank = 14;
if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
{
Error_Handler();
}
}

View File

@@ -1,169 +0,0 @@
/*
* lock.c
*
* Created on: Jul 31, 2024
* Author: colorbass
*/
#include "lock.h"
#include "debug.h"
uint8_t LOCK_POLARITY = 1; // 1 for v1
uint8_t LOCK_MOTOR_POLARITY = 1;
uint16_t LOCK_DELAY = 100;
GBT_LockState_t GBT_LockState = {
.demand = 0,
.error = 0,
.action_requested = 255, // нет запрошенного действия
.motor_state = 0, // idle
.last_action_time = 0,
.retry_count = 0,
.error_tick = 0
};
void GBT_ForceLock(uint8_t state){
// Устанавливаем флаг для выполнения действия
GBT_LockState.action_requested = state ? 1 : 0;
GBT_LockState.retry_count = 0;
}
uint8_t GBT_LockGetState(){
//1 = locked
//0 = unlocked
if(LOCK_POLARITY){
return HAL_GPIO_ReadPin(IN0_GPIO_Port, IN0_Pin);
}else{
return !HAL_GPIO_ReadPin(IN0_GPIO_Port, IN0_Pin);
}
}
void GBT_Lock(uint8_t state){
GBT_LockState.demand = state;
}
void GBT_ManageLockSolenoid(){
static uint32_t tick;
if(HAL_GetTick() - tick < 50) return;
tick = HAL_GetTick();
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, GBT_LockState.demand ? 1 : 0);
}
void GBT_ManageLockMotor(){
static const uint8_t MAX_RETRIES = 5;
uint32_t current_tick = HAL_GetTick();
// Проверяем таймаут сброса ошибки (до проверки error, чтобы можно было сбросить)
GBT_ResetErrorTimeout();
if (GBT_LockState.error) {
return;
}
// Проверяем, нужно ли выполнить действие
bool lock_is_open = GBT_LockGetState() == 0;
bool lock_should_be_open = GBT_LockState.demand == 0;
// Если есть запрошенное действие или состояние не соответствует требуемому
if (GBT_LockState.action_requested != 255 || (lock_is_open != lock_should_be_open)) {
// Если действие еще не запрошено, запрашиваем его
if (GBT_LockState.action_requested == 255) {
GBT_LockState.action_requested = lock_should_be_open ? 0 : 1;
GBT_LockState.retry_count = 0;
}
// Управление мотором через машину состояний
switch (GBT_LockState.motor_state) {
case 0: // idle - мотор выключен
// Определяем, какой пин нужно включить
if (LOCK_MOTOR_POLARITY) {
if (GBT_LockState.action_requested == 1) { // LOCK
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, 1);
} else { // UNLOCK
HAL_GPIO_WritePin(LOCK_A_GPIO_Port, LOCK_A_Pin, 1);
}
} else {
if (GBT_LockState.action_requested == 1) { // LOCK
HAL_GPIO_WritePin(LOCK_A_GPIO_Port, LOCK_A_Pin, 1);
} else { // UNLOCK
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, 1);
}
}
GBT_LockState.motor_state = 1; // motor_on
GBT_LockState.last_action_time = current_tick;
break;
case 1: // motor_on - мотор включен, ждем LOCK_DELAY
if (current_tick - GBT_LockState.last_action_time >= LOCK_DELAY) {
// Выключаем оба пина
HAL_GPIO_WritePin(LOCK_A_GPIO_Port, LOCK_A_Pin, 0);
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, 0);
GBT_LockState.motor_state = 2; // waiting_off
GBT_LockState.last_action_time = current_tick;
}
break;
case 2: // waiting_off - ждем немного перед проверкой состояния
// Небольшая задержка перед проверкой состояния (например, 50мс)
if (current_tick - GBT_LockState.last_action_time >= 50) {
// Проверяем, достигнуто ли требуемое состояние
lock_is_open = GBT_LockGetState() == 0;
bool action_success = (lock_is_open == (GBT_LockState.action_requested == 0));
if (action_success) {
// Действие выполнено успешно
GBT_LockState.action_requested = 255; // сбрасываем флаг
GBT_LockState.motor_state = 0; // idle
GBT_LockState.retry_count = 0;
} else {
// Действие не выполнено, повторяем попытку
GBT_LockState.retry_count++;
if (GBT_LockState.retry_count >= MAX_RETRIES) {
// Превышено количество попыток
GBT_LockState.error = 1;
GBT_LockState.error_tick = current_tick; // сохраняем время установки ошибки
GBT_LockState.action_requested = 0; // пытаемся разблокировать
GBT_LockState.motor_state = 0;
GBT_LockState.retry_count = 0;
log_printf(LOG_ERR, "Lock error\n");
} else {
// Повторяем попытку
GBT_LockState.motor_state = 0; // возвращаемся к началу
}
}
}
break;
}
} else {
// Состояние соответствует требуемому, сбрасываем флаги
if (GBT_LockState.motor_state != 0) {
HAL_GPIO_WritePin(LOCK_A_GPIO_Port, LOCK_A_Pin, 0);
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, 0);
GBT_LockState.motor_state = 0;
}
GBT_LockState.action_requested = 255;
GBT_LockState.retry_count = 0;
}
}
void GBT_LockResetError(){
GBT_LockState.error = 0;
GBT_LockState.error_tick = 0;
log_printf(LOG_INFO, "Lock error reset\n");
}
void GBT_ResetErrorTimeout(){
static const uint32_t ERROR_TIMEOUT_MS = 300000; // 5 минут
if (GBT_LockState.error && GBT_LockState.error_tick != 0) {
if ((HAL_GetTick()-GBT_LockState.error_tick) >= ERROR_TIMEOUT_MS) {
// Прошло 5 минут, сбрасываем ошибку
GBT_LockResetError();
}
}
}

View File

@@ -1,295 +1,301 @@
/* USER CODE BEGIN Header */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "can.h"
#include "crc.h"
#include "rtc.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "can.h"
#include "board.h"
#include <stdio.h>
#include "debug.h"
#include "charger_gbt.h"
#include "soft_rtc.h"
#include "j1939.h"
#include "lock.h"
#include "connector.h"
#include "serial_control.h"
#include "charger_config.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/**
* @brief Vector base address configuration. It should no longer be at the start of
* flash memory but moved forward because the first part of flash is
* reserved for the bootloader. Note that this is already done by the
* bootloader before starting this program. Unfortunately, function
* SystemInit() overwrites this change again.
* @return none.
*/
static void VectorBase_Config(void)
{
/* The constant array with vectors of the vector table is declared externally in the
* c-startup code.
*/
extern const unsigned long g_pfnVectors[];
/* Remap the vector table to where the vector table is located for this program. */
SCB->VTOR = (unsigned long)&g_pfnVectors[0];
}
uint8_t ED_TraceWarning(uint8_t flag, uint8_t id){
static uint8_t memory[32];
if(id > 31) return 0;
uint8_t result = 0;
if(memory[id] != flag){
result = 1;
}
memory[id] = flag;
return result;
}
void ED_Delay(uint32_t Delay)
{
uint32_t tickstart = HAL_GetTick();
uint32_t wait = Delay;
/* Add a freq to guarantee minimum wait */
if (wait < HAL_MAX_DELAY)
{
wait += (uint32_t)(uwTickFreq);
}
while ((HAL_GetTick() - tickstart) < wait){
CONN_CC_ReadStateFiltered();
GBT_ManageLockMotor();
CONN_Task();
GBT_ChargerTask();
LED_Task();
SC_Task();
// if(huart2.gState != HAL_UART_STATE_BUSY_TX) debug_buffer_send(); // TEST
}
}
void StopButtonControl(){
//Charging do nothing
if(!IN_ReadInput(IN_ESTOP)){
CONN.connControl = CMD_STOP;
}
}
uint8_t temp0, temp1;
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
VectorBase_Config();
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
HAL_RCC_DeInit();
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_CAN1_Init();
MX_CAN2_Init();
MX_RTC_Init();
MX_TIM4_Init();
MX_USART2_UART_Init();
MX_CRC_Init();
MX_UART5_Init();
MX_USART1_UART_Init();
MX_USART3_UART_Init();
/* USER CODE BEGIN 2 */
Init_Peripheral();
LED_Init();
HAL_Delay(300);
GBT_Init();
SC_Init();
log_printf(LOG_INFO, "GBT Charger v%d.%d\n", GBT_CH_VER_MAJOR, GBT_CH_VER_MINOR);
ReadVersion();
log_printf(LOG_INFO, "Serial number: %d\n", infoPacket.serialNumber);
log_printf(LOG_INFO, "Board revision: %d\n", infoPacket.boardVersion);
log_printf(LOG_INFO, "FW version: %d.%d.%d\n", infoPacket.fw_version_major, infoPacket.fw_version_minor, infoPacket.fw_version_patch);
GBT_SetConfig();
GBT_CAN_ReInit();
PSU_Init();
CONN_Init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
PSU_ReadWrite();
PSU_Task();
ED_Delay(10);
METER_CalculateEnergy();
CONN_Loop();
LED_Write();
ED_Delay(10);
StopButtonControl();
ED_Delay(50);
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV5;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.Prediv1Source = RCC_PREDIV1_SOURCE_PLL2;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
RCC_OscInitStruct.PLL2.PLL2State = RCC_PLL2_ON;
RCC_OscInitStruct.PLL2.PLL2MUL = RCC_PLL2_MUL8;
RCC_OscInitStruct.PLL2.HSEPrediv2Value = RCC_HSE_PREDIV2_DIV5;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_ADC;
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
/** Configure the Systick interrupt time
*/
__HAL_RCC_PLLI2S_ENABLE();
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/* USER CODE BEGIN Header */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "can.h"
#include "crc.h"
#include "rtc.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "can.h"
#include "board.h"
#include <stdio.h>
#include "debug.h"
#include "soft_rtc.h"
#include "connector.h"
#include "serial_control.h"
#include "charger_config.h"
#include "serial.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/**
* @brief Vector base address configuration. It should no longer be at the start of
* flash memory but moved forward because the first part of flash is
* reserved for the bootloader. Note that this is already done by the
* bootloader before starting this program. Unfortunately, function
* SystemInit() overwrites this change again.
* @return none.
*/
static void VectorBase_Config(void)
{
/* The constant array with vectors of the vector table is declared externally in the
* c-startup code.
*/
extern const unsigned long g_pfnVectors[];
/* Remap the vector table to where the vector table is located for this program. */
SCB->VTOR = (unsigned long)&g_pfnVectors[0];
}
uint8_t ED_TraceWarning(uint8_t flag, uint8_t id){
static uint8_t memory[32];
if(id > 31) return 0;
uint8_t result = 0;
if(memory[id] != flag){
result = 1;
}
memory[id] = flag;
return result;
}
void ED_Delay(uint32_t Delay)
{
uint32_t tickstart = HAL_GetTick();
uint32_t wait = Delay;
if (wait < HAL_MAX_DELAY)
{
wait += (uint32_t)(uwTickFreq);
}
while ((HAL_GetTick() - tickstart) < wait){
CCS_SerialLoop();
// CP_Loop();
CONN_Task();
LED_Task();
SC_Task();
}
}
void StopButtonControl(){
//Charging do nothing
if(!IN_ReadInput(IN_ESTOP)){
CONN.connControl = CMD_STOP;
}
}
uint8_t temp0, temp1;
static void CAN1_MinimalReInit(void)
{
HAL_CAN_Stop(&hcan1);
MX_CAN1_Init();
if (HAL_CAN_Start(&hcan1) != HAL_OK) {
Error_Handler();
}
if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) {
Error_Handler();
}
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
VectorBase_Config();
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
HAL_RCC_DeInit();
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_CAN1_Init();
MX_CAN2_Init();
MX_RTC_Init();
MX_TIM4_Init();
MX_USART2_UART_Init();
MX_CRC_Init();
MX_UART5_Init();
MX_USART1_UART_Init();
MX_USART3_UART_Init();
MX_TIM3_Init();
/* USER CODE BEGIN 2 */
Init_Peripheral();
LED_Init();
HAL_Delay(300);
CCS_Init();
SC_Init();
log_printf(LOG_INFO, "CCS module start\n");
ReadVersion();
log_printf(LOG_INFO, "Serial number: %d\n", infoPacket.serialNumber);
log_printf(LOG_INFO, "Board revision: %d\n", infoPacket.boardVersion);
log_printf(LOG_INFO, "FW version: %d.%d.%d\n", infoPacket.fw_version_major, infoPacket.fw_version_minor, infoPacket.fw_version_patch);
CAN1_MinimalReInit();
PSU_Init();
CONN_Init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
PSU_ReadWrite();
PSU_Task();
ED_Delay(10);
METER_CalculateEnergy();
CONN_Loop();
LED_Write();
ED_Delay(10);
StopButtonControl();
ED_Delay(50);
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV5;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.Prediv1Source = RCC_PREDIV1_SOURCE_PLL2;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
RCC_OscInitStruct.PLL2.PLL2State = RCC_PLL2_ON;
RCC_OscInitStruct.PLL2.PLL2MUL = RCC_PLL2_MUL8;
RCC_OscInitStruct.PLL2.HSEPrediv2Value = RCC_HSE_PREDIV2_DIV5;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_ADC;
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
/** Configure the Systick interrupt time
*/
__HAL_RCC_PLLI2S_ENABLE();
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

View File

@@ -6,7 +6,6 @@
#include "stdio.h"
#include "charger_config.h"
#include "charger_control.h"
#include "charger_gbt.h"
#include "board.h"
#include "debug.h"

427
Core/Src/serial.c Normal file
View File

@@ -0,0 +1,427 @@
#include "serial.h"
#include "cp.h"
#include "connector.h"
#include "board.h"
#include "debug.h"
#include <stdint.h>
#include <string.h>
#include "charger_config.h"
#include "psu_control.h"
extern UART_HandleTypeDef huart3;
static void send_state(void);
static void CCS_SendResetReason(void);
CCS_MaxLoad_t CCS_MaxLoad;
uint32_t CCS_Power = 0;
uint32_t CCS_EnergyWs = 0;
uint32_t CCS_Energy = 0;
uint32_t last_cmd_sent = 0;
uint32_t last_stop_sent = 0;
CONN_Control_t last_cmd = CMD_NONE;
uint8_t ev_enable_output = 0;
#define CMD_INTERVAL 10
#define MAX_TX_BUFFER_SIZE 256
#define MAX_RX_BUFFER_SIZE 256
static uint8_t rx_buffer[MAX_RX_BUFFER_SIZE];
static uint8_t tx_buffer[MAX_TX_BUFFER_SIZE];
static uint8_t rx_armed = 0;
uint8_t ESTOP = 0;
uint8_t REPLUG = 0;
static uint8_t enabled = 0;
static uint8_t pwm_duty_percent = 100;
uint8_t isolation_enable = 0;
static uint32_t last_host_seen = 0;
static CP_State_t cp_state_buffer = EV_STATE_ACQUIRING;
CCS_State_t CCS_State;
CCS_EvInfo_t CCS_EvInfo;
CONN_State_t CCS_EvseState;
CCS_ConnectorState_t CCS_ConnectorState = CCS_UNPLUGGED;
static uint8_t process_received_packet(const uint8_t* packet, uint16_t packet_len);
void CCS_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size) {
if (huart != &huart3) {
return;
}
rx_armed = 0;
if (size > 0 && size <= sizeof(rx_buffer)) {
process_received_packet(rx_buffer, size);
}
}
void CCS_SerialLoop(void) {
static uint32_t replug_tick = 0;
static uint32_t replug_watchdog_tick = 0;
static uint32_t replug_watchdog1_tick = 0;
static uint32_t last_state_sent = 0;
if (!rx_armed && HAL_UART_GetState(&huart3) == HAL_UART_STATE_READY) {
if (HAL_UARTEx_ReceiveToIdle_IT(&huart3, rx_buffer, sizeof(rx_buffer)) == HAL_OK) {
rx_armed = 1;
}
}
/* Read CP once per loop and use buffered value below. */
cp_state_buffer = CP_GetState();
if (CONN.connControl != CMD_NONE) {
last_cmd = CONN.connControl;
}
if((HAL_GetTick() - last_cmd_sent) > CMD_INTERVAL){
if ((HAL_GetTick() - last_state_sent) >= 200) {
send_state();
last_state_sent = HAL_GetTick();
}
if (ESTOP) {
log_printf(LOG_ERR, "ESTOP triggered\n");
CCS_SendEmergencyStop();
ESTOP = 0;
}
if (((CONN.connControl == CMD_STOP) ||
(CONN.chargingError != CONN_NO_ERROR)) &&
((HAL_GetTick() - last_stop_sent) > 1000)) {
last_stop_sent = HAL_GetTick();
log_printf(LOG_WARN, "Stopping charging...\n");
CCS_SendEmergencyStop();
}
if (((CCS_EvseState == FinishedEV) || (CCS_EvseState == FinishedEVSE)) &&
((HAL_GetTick() - last_stop_sent) > 1000)) {
last_stop_sent = HAL_GetTick();
log_printf(LOG_WARN, "FinishedEV, stopping...\n");
CCS_SendEmergencyStop();
}
}
(void)replug_watchdog_tick;
(void)replug_watchdog1_tick;
switch(CCS_ConnectorState){
case CCS_DISABLED:
RELAY_Write(RELAY_CP, 0);
CONN_SetState(Disabled);
if (CONN.chargingError == CONN_NO_ERROR){
CCS_ConnectorState = CCS_UNPLUGGED;
}
break;
case CCS_UNPLUGGED:
RELAY_Write(RELAY_CP, 1);
CONN_SetState(Unplugged);
if ((cp_state_buffer == EV_STATE_B_CONN_PREP) || (cp_state_buffer == EV_STATE_C_CONN_ACTIVE)){
CCS_ConnectorState = CCS_AUTH_REQUIRED;
}
if (CONN.chargingError != CONN_NO_ERROR){
log_printf(LOG_ERR, "Charging error %d, state -> disabled\n", CONN.chargingError);
CCS_ConnectorState = CCS_DISABLED;
}
break;
case CCS_AUTH_REQUIRED:
RELAY_Write(RELAY_CP, 1);
CONN_SetState(AuthRequired);
if(CONN.connControl == CMD_START){
log_printf(LOG_INFO, "Charging permitted, start charging\n");
CCS_ConnectorState = CCS_CONNECTED;
}
if (cp_state_buffer == EV_STATE_A_IDLE){
log_printf(LOG_INFO, "Car unplugged\n");
CCS_ConnectorState = CCS_UNPLUGGED;
}
break;
case CCS_CONNECTED:
RELAY_Write(RELAY_CP, 1);
if(CCS_EvseState < Preparing) {
CONN_SetState(Preparing);
} else {
CONN_SetState(CCS_EvseState);
}
if (cp_state_buffer == EV_STATE_A_IDLE){
log_printf(LOG_INFO, "Car unplugged\n");
CCS_ConnectorState = CCS_UNPLUGGED;
}
if(REPLUG > 0){
log_printf(LOG_INFO, "Replugging...\n");
CCS_ConnectorState = CCS_REPLUGGING;
}
break;
case CCS_REPLUGGING:
RELAY_Write(RELAY_CP, 0);
CONN_SetState(Replugging);
if((HAL_GetTick() - replug_tick) > 1000){
replug_tick = HAL_GetTick();
if(REPLUG > 0){
if (REPLUG != 0xFF) REPLUG--;
} else {
log_printf(LOG_INFO, "Replugging finished, but car unplugged\n");
CCS_ConnectorState = CCS_UNPLUGGED;
}
}
if(REPLUG == 0){
if(cp_state_buffer == EV_STATE_B_CONN_PREP){
log_printf(LOG_INFO, "Replugging finished, car plugged, state -> auth required\n");
CCS_ConnectorState = CCS_AUTH_REQUIRED;
}
}
break;
}
if (last_host_seen > 0 && (HAL_GetTick() - last_host_seen) > 500) {
CONN.EnableOutput = 0;
CCS_EvseState = Unknown;
CP_SetDuty(100);
log_printf(LOG_ERR, "Everest timeout\n");
} else {
if (last_cmd == CMD_STOP) {
CONN.EnableOutput = 0;
} else {
CONN.EnableOutput = ev_enable_output ? 1 : 0;
if((CONN.EnableOutput == 0) && (CONN.connState == Preparing)){
CONN.EnableOutput = 0;
}
}
}
if ((cp_state_buffer == EV_STATE_B_CONN_PREP) ||
(cp_state_buffer == EV_STATE_C_CONN_ACTIVE) ||
(cp_state_buffer == EV_STATE_D_CONN_ACT_VENT)) {
CONN.EvConnected = 1;
} else {
CONN.EvConnected = 0;
}
}
void CCS_Init(void){
CP_Init();
CP_SetDuty(100);
CCS_MaxLoad.maxVoltage = PSU_MAX_VOLTAGE; // 1000V
CCS_MaxLoad.minVoltage = PSU_MIN_VOLTAGE; //150V
CCS_MaxLoad.maxCurrent = PSU_MAX_CURRENT*10; //100A
CCS_MaxLoad.minCurrent = PSU_MIN_CURRENT*10; //1A
CCS_MaxLoad.maxPower = PSU_MAX_POWER; //30000W
CCS_SendResetReason();
log_printf(LOG_INFO, "CCS init\n");
}
static uint16_t crc16_ibm(const uint8_t* data, uint16_t length) {
uint16_t crc = 0xFFFFu;
for (uint16_t i = 0; i < length; i++) {
crc ^= data[i];
for (uint8_t j = 0; j < 8; j++) {
if (crc & 1u) {
crc = (crc >> 1) ^ 0xA001u;
} else {
crc >>= 1;
}
}
}
return crc;
}
static uint16_t CCS_BuildPacket(uint8_t cmd, const void* payload, uint16_t payload_len, uint8_t* out, uint16_t out_max) {
uint16_t total_len = (uint16_t)(1u + payload_len + 2u);
if (total_len > out_max) return 0;
out[0] = cmd;
if (payload_len && payload != NULL) {
memcpy(&out[1], payload, payload_len);
}
uint16_t crc = crc16_ibm(out, (uint16_t)(1u + payload_len));
out[1u + payload_len] = (uint8_t)(crc & 0xFFu);
out[1u + payload_len + 1u] = (uint8_t)((crc >> 8) & 0xFFu);
return total_len;
}
static void CCS_SendPacket(uint8_t cmd, const void* payload, uint16_t payload_len) {
uint16_t len = CCS_BuildPacket(cmd, payload, payload_len, tx_buffer, sizeof(tx_buffer));
if (len > 0) {
HAL_UART_Transmit(&huart3, tx_buffer, len, 1000);
}
last_cmd_sent = HAL_GetTick();
}
static void CCS_SendResetReason(void) {
CCS_SendPacket(CMD_M2E_RESET, NULL, 0);
}
void CCS_SendEmergencyStop(void) {
CCS_SendPacket(CMD_M2E_ESTOP, NULL, 0);
}
void CCS_SendStart(void) {
CCS_SendPacket(CMD_M2E_START, NULL, 0);
}
static void CCS_CalculateEnergy(void) {
static uint32_t lastTick = 0;
uint32_t currentTick = HAL_GetTick();
uint32_t elapsedTimeMs = currentTick - lastTick;
lastTick = currentTick;
CCS_Power = CONN.MeasuredVoltage * CONN.MeasuredCurrent / 10;
CCS_EnergyWs += (CCS_Power * elapsedTimeMs) / 1000;
if(CCS_EvseState == Unplugged) {
CCS_EnergyWs = 0;
}
CCS_Energy = CCS_EnergyWs / 3600;
}
static void send_state(void) {
CCS_CalculateEnergy();
CCS_State.DutyCycle = CP_GetDuty();
CCS_State.OutputEnabled = PSU0.CONT_enabled;
CCS_State.MeasuredVoltage = (uint16_t)CONN.MeasuredVoltage;
CCS_State.MeasuredCurrent = (uint16_t)CONN.MeasuredCurrent;
CCS_State.Power = CCS_Power;
CCS_State.Energy = CCS_Energy;
if(CCS_ConnectorState == CCS_CONNECTED){
CCS_State.CpState = cp_state_buffer;
} else {
CCS_State.CpState = EV_STATE_A_IDLE;
}
CCS_State.MaxVoltage = CCS_MaxLoad.maxVoltage;
CCS_State.MinVoltage = CCS_MaxLoad.minVoltage;
CCS_State.MaxCurrent = CCS_MaxLoad.maxCurrent;
CCS_State.MinCurrent = CCS_MaxLoad.minCurrent;
CCS_State.MaxPower = CCS_MaxLoad.maxPower;
CCS_State.IsolationValid = isolation_enable;
CCS_State.IsolationResistance = 900000;
CCS_SendPacket(CMD_M2E_STATE, &CCS_State, sizeof(CCS_State));
}
static uint16_t expected_payload_len(uint8_t cmd) {
switch (cmd) {
case CMD_E2M_PWM_DUTY: return sizeof(e2m_pwm_duty_t);
case CMD_E2M_ENABLE_OUTPUT: return sizeof(e2m_enable_output_t);
case CMD_E2M_RESET: return sizeof(e2m_reset_t);
case CMD_E2M_ENABLE: return sizeof(e2m_enable_t);
case CMD_E2M_REPLUG: return sizeof(e2m_replug_t);
case CMD_E2M_SET_OUTPUT_VOLTAGE: return sizeof(e2m_set_output_t);
case CMD_E2M_ISOLATION_CONTROL: return sizeof(e2m_isolation_control_t);
case CMD_E2M_EV_INFO: return sizeof(CCS_EvInfo_t);
case CMD_E2M_EVSE_STATE: return sizeof(CONN_State_t);
case CMD_E2M_KEEP_ALIVE: return 0;
default: return 0xFFFFu;
}
}
static void apply_command(uint8_t cmd, const uint8_t* payload, uint16_t payload_len) {
(void)payload_len;
last_host_seen = HAL_GetTick();
switch (cmd) {
case CMD_E2M_PWM_DUTY: {
const e2m_pwm_duty_t* p = (const e2m_pwm_duty_t*)payload;
uint8_t duty = p->pwm_duty_percent;
if (duty > 100) duty = 100;
pwm_duty_percent = duty;
CP_SetDuty(duty);
break;
}
case CMD_E2M_ENABLE_OUTPUT: {
const e2m_enable_output_t* p = (const e2m_enable_output_t*)payload;
ev_enable_output = (p->enable_output != 0);
break;
}
case CMD_E2M_RESET: {
const e2m_reset_t* p = (const e2m_reset_t*)payload;
if (p->reset) {
log_printf(LOG_WARN, "Everest reset command\n");
CCS_SendResetReason();
HAL_Delay(10);
NVIC_SystemReset();
}
break;
}
case CMD_E2M_ENABLE: {
const e2m_enable_t* p = (const e2m_enable_t*)payload;
enabled = (p->enable != 0);
(void)enabled;
break;
}
case CMD_E2M_SET_OUTPUT_VOLTAGE: {
const e2m_set_output_t* p = (const e2m_set_output_t*)payload;
CONN.RequestedVoltage = p->voltage_V;
CONN.WantedCurrent = p->current_0p1A;
break;
}
case CMD_E2M_ISOLATION_CONTROL: {
const e2m_isolation_control_t* p = (const e2m_isolation_control_t*)payload;
isolation_enable = p->command;
break;
}
case CMD_E2M_EV_INFO: {
memcpy(&CCS_EvInfo, payload, sizeof(CCS_EvInfo_t));
CONN.SOC = (uint8_t)(CCS_EvInfo.soc / 10);
break;
}
case CMD_E2M_EVSE_STATE: {
CCS_EvseState = (CONN_State_t)payload[0];
break;
}
case CMD_E2M_REPLUG: {
(void)payload;
CP_SetDuty(pwm_duty_percent);
break;
}
case CMD_E2M_KEEP_ALIVE: {
last_host_seen = HAL_GetTick();
break;
}
default:
break;
}
}
static uint8_t process_received_packet(const uint8_t* packet, uint16_t packet_len) {
if (packet_len < 3) return 0;
uint8_t cmd = packet[0];
uint16_t payload_len = (uint16_t)(packet_len - 3);
uint16_t received_crc = (uint16_t)packet[packet_len - 2u] |
(uint16_t)packet[packet_len - 1u] << 8;
uint16_t calculated_crc = crc16_ibm(packet, (uint16_t)(1 + payload_len));
if (received_crc != calculated_crc) {
log_printf(LOG_ERR, "Packet CRC error\n");
return 0;
}
uint16_t expected_len = expected_payload_len(cmd);
if (expected_len == 0xFFFF) {
log_printf(LOG_WARN, "Unknown cmd 0x%02x\n", cmd);
return 0;
}
if (expected_len != payload_len) {
log_printf(LOG_ERR, "Packet len mismatch cmd=0x%02x\n", cmd);
return 0;
}
if (payload_len > 0) {
apply_command(cmd, &packet[1], payload_len);
} else {
apply_command(cmd, NULL, 0);
}
return 1;
}

View File

@@ -1,6 +1,7 @@
#include "serial_control.h"
#include "usart.h"
#include "board.h"
#include "serial.h"
// Приватные функции
static uint32_t calculate_crc32(const uint8_t* data, uint16_t length);
@@ -111,6 +112,8 @@ void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
SC_CommandHandler((ReceivedCommand_t*)&serial_iso.received_command);
}
HAL_UARTEx_ReceiveToIdle_IT(&huart5, serial_iso.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
} else if (huart->Instance == huart3.Instance) {
CCS_RxEventCallback(huart, Size);
}
}

View File

@@ -1,15 +1,13 @@
#include "serial_control.h"
#include "charger_gbt.h"
#include "usart.h"
#include "charger_control.h"
#include "charger_gbt.h"
#include "board.h"
#include "psu_control.h"
#include "debug.h"
#include <string.h>
#ifdef USE_WEB_INTERFACE
extern uint8_t GBT_BAT_STAT_recv;
extern volatile SC_Source_t g_sc_command_source;
IsolationStatusPacket_t ISO = {
@@ -52,10 +50,7 @@ void SC_CommandHandler(ReceivedCommand_t* cmd) {
case CMD_SET_CONFIG:
if (cmd->argument_length == sizeof(ConfigBlock_t)) {
memcpy(&config, cmd->argument, sizeof(ConfigBlock_t));
GBT_SetConfig();
config_initialized = 1;
GBT_SetConfig();
// CONN.connState = CONN_Available; //
log_printf(LOG_INFO, "Set Config: %s %d\n", config.location, config.chargerNumber);
response_code = RESP_SUCCESS;
break;
@@ -147,38 +142,40 @@ void monitoring_data_callback() {
statusPacket.relayAC = RELAY_Read(RELAY_AC);
statusPacket.relayDC = RELAY_Read(RELAY_DC);
statusPacket.relayAUX = RELAY_Read(RELAY_AUX0);
statusPacket.lockState = GBT_LockGetState();
statusPacket.lockState = 0;
statusPacket.stopButton = !IN_ReadInput(IN_ESTOP);
statusPacket.logAvailable = (debug_buffer_available()>0)?1:0;
statusPacket.evInfoAvailable = GBT_BAT_STAT_recv;
statusPacket.evInfoAvailable = 0;
statusPacket.psuOnline = PSU0.online;
statusPacket.tempConnector0 = GBT_ReadTemp(0); // температура коннектора
statusPacket.tempConnector1 = GBT_ReadTemp(1);
statusPacket.tempConnector0 = CONN_ReadTemp(0); // температура коннектора
statusPacket.tempConnector1 = CONN_ReadTemp(1);
statusPacket.tempAmbient = PSU0.tempAmbient; // температура окружающего воздуха
statusPacket.tempBatteryMax = GBT_BatteryStatus.batteryHighestTemp; // максимальная температура батареи
statusPacket.tempBatteryMin = GBT_BatteryStatus.batteryLowestTemp; // минимальная температура батареи
statusPacket.tempBatteryMax = 0;
statusPacket.tempBatteryMin = 0;
statusPacket.highestVoltageOfBatteryCell = GBT_ChargingStatus.highestVoltageOfBatteryCell;
statusPacket.batteryStatus = GBT_BatteryStatus.batteryStatus;
statusPacket.highestVoltageOfBatteryCell = 0;
statusPacket.batteryStatus = 0;
statusPacket.phaseVoltageAB = PSU_06.VAB;
statusPacket.phaseVoltageBC = PSU_06.VBC;
statusPacket.phaseVoltageCA = PSU_06.VCA;
memcpy(statusPacket.VIN, GBT_EVInfo.EVIN, sizeof(GBT_EVInfo.EVIN));
// GBT TODO
memset(statusPacket.VIN, 0, sizeof(statusPacket.VIN));
statusPacket.batteryType = GBT_EVInfo.batteryType;
statusPacket.batteryCapacity = GBT_EVInfo.batteryCapacity;
statusPacket.batteryVoltage = GBT_EVInfo.batteryVoltage;
memcpy(statusPacket.batteryVendor, GBT_EVInfo.batteryVendor, sizeof(statusPacket.batteryVendor));
statusPacket.batterySN = GBT_EVInfo.batterySN;
statusPacket.batteryManuD = GBT_EVInfo.batteryManuD;
statusPacket.batteryManuM = GBT_EVInfo.batteryManuM;
statusPacket.batteryManuY = GBT_EVInfo.batteryManuY;
statusPacket.batteryCycleCount = GBT_EVInfo.batteryCycleCount;
statusPacket.ownAuto = GBT_EVInfo.ownAuto;
memcpy(statusPacket.EV_SW_VER, GBT_EVInfo.EV_SW_VER, sizeof(statusPacket.EV_SW_VER));
// GBT TODO
statusPacket.batteryType = 0;
statusPacket.batteryCapacity = 0;
statusPacket.batteryVoltage = 0;
memset(statusPacket.batteryVendor, 0, sizeof(statusPacket.batteryVendor));
statusPacket.batterySN = 0;
statusPacket.batteryManuD = 0;
statusPacket.batteryManuM = 0;
statusPacket.batteryManuY = 0;
statusPacket.batteryCycleCount = 0;
statusPacket.ownAuto = 0;
memset(statusPacket.EV_SW_VER, 0, sizeof(statusPacket.EV_SW_VER));
statusPacket.testMode = 0;
statusPacket.testVoltage = 0;

40
Core/Src/sma_filter.c Normal file
View File

@@ -0,0 +1,40 @@
#include "sma_filter.h"
void SMAFilter_Init(SMAFilter_t* f)
{
if (f == 0) return;
f->sum = 0;
f->idx = 0;
f->count = 0;
for (uint16_t i = 0; i < SMA_FILTER_WINDOW; i++) {
f->buffer[i] = 0;
}
}
int32_t SMAFilter_Update(SMAFilter_t* f, int32_t x)
{
if (f == 0) return x;
// Пока окно не заполнено полностью, делим по фактическому count.
if (f->count < SMA_FILTER_WINDOW) {
f->buffer[f->idx] = x;
f->sum += x;
f->idx++;
if (f->idx >= SMA_FILTER_WINDOW) f->idx = 0;
f->count++;
return (int32_t)(f->sum / (int32_t)f->count);
}
// Окно заполнено: "вычитаем старое + добавляем новое".
int32_t old = f->buffer[f->idx];
f->buffer[f->idx] = x;
f->sum += (x - old);
f->idx++;
if (f->idx >= SMA_FILTER_WINDOW) f->idx = 0;
return (int32_t)(f->sum / (int32_t)SMA_FILTER_WINDOW);
}

View File

@@ -57,6 +57,7 @@
/* External variables --------------------------------------------------------*/
extern CAN_HandleTypeDef hcan1;
extern CAN_HandleTypeDef hcan2;
extern TIM_HandleTypeDef htim3;
extern UART_HandleTypeDef huart5;
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
@@ -217,6 +218,20 @@ void CAN1_RX0_IRQHandler(void)
/* USER CODE END CAN1_RX0_IRQn 1 */
}
/**
* @brief This function handles TIM3 global interrupt.
*/
void TIM3_IRQHandler(void)
{
/* USER CODE BEGIN TIM3_IRQn 0 */
/* USER CODE END TIM3_IRQn 0 */
HAL_TIM_IRQHandler(&htim3);
/* USER CODE BEGIN TIM3_IRQn 1 */
/* USER CODE END TIM3_IRQn 1 */
}
/**
* @brief This function handles USART1 global interrupt.
*/

View File

@@ -24,8 +24,73 @@
/* USER CODE END 0 */
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim4;
/* TIM3 init function */
void MX_TIM3_Init(void)
{
/* USER CODE BEGIN TIM3_Init 0 */
/* USER CODE END TIM3_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
htim3.Instance = TIM3;
htim3.Init.Prescaler = 0;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 65535;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_OC_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_TIMING;
sConfigOC.Pulse = 1;
if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM3_Init 2 */
/* USER CODE END TIM3_Init 2 */
HAL_TIM_MspPostInit(&htim3);
}
/* TIM4 init function */
void MX_TIM4_Init(void)
{
@@ -92,7 +157,22 @@ void MX_TIM4_Init(void)
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM4)
if(tim_baseHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspInit 0 */
/* USER CODE END TIM3_MspInit 0 */
/* TIM3 clock enable */
__HAL_RCC_TIM3_CLK_ENABLE();
/* TIM3 interrupt Init */
HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM3_IRQn);
/* USER CODE BEGIN TIM3_MspInit 1 */
/* USER CODE END TIM3_MspInit 1 */
}
else if(tim_baseHandle->Instance==TIM4)
{
/* USER CODE BEGIN TIM4_MspInit 0 */
@@ -108,7 +188,25 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(timHandle->Instance==TIM4)
if(timHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspPostInit 0 */
/* USER CODE END TIM3_MspPostInit 0 */
__HAL_RCC_GPIOA_CLK_ENABLE();
/**TIM3 GPIO Configuration
PA7 ------> TIM3_CH2
*/
GPIO_InitStruct.Pin = CP_PWM_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(CP_PWM_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN TIM3_MspPostInit 1 */
/* USER CODE END TIM3_MspPostInit 1 */
}
else if(timHandle->Instance==TIM4)
{
/* USER CODE BEGIN TIM4_MspPostInit 0 */
@@ -137,7 +235,21 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM4)
if(tim_baseHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspDeInit 0 */
/* USER CODE END TIM3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM3_CLK_DISABLE();
/* TIM3 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM3_IRQn);
/* USER CODE BEGIN TIM3_MspDeInit 1 */
/* USER CODE END TIM3_MspDeInit 1 */
}
else if(tim_baseHandle->Instance==TIM4)
{
/* USER CODE BEGIN TIM4_MspDeInit 0 */