CAN Update

This commit is contained in:
Dmitriy Semenov
2023-04-03 21:51:33 +03:00
parent 68f478625e
commit 9c2667bbe5
16 changed files with 854 additions and 288 deletions

331
firmware/Libs/CAN/can.c Normal file
View File

@@ -0,0 +1,331 @@
//
// Created by enik on 02.06.22.
//
#include "can.h"
//#include "Settings.h"
#if CAN_TESTING_LOOPBACK
#define CAN_BASIC_MODE CAN_MODE_SILENT_LOOPBACK
#else
#define CAN_BASIC_MODE CAN_MODE_NORMAL
#endif
#include "can_messenger.h"
extern CAN_HandleTypeDef hcan1;
extern CAN_HandleTypeDef hcan2;
CAN_FilterTypeDef can1Filter;
CAN_FilterTypeDef can2Filter;
CAN_RxHeaderTypeDef can1RX, can2RX;
u8_t can1Data[8] = {0,}, can2Data[8] = {0,};
typedef struct CAN_SPD_VAL {
u32_t Prescaler;
u32_t TimeSeg1;
u32_t TimeSeg2;
} CAN_SPD_VAL;
// PSC - 2 | Time1 - 15 | Time2 - 2
const CAN_SPD_VAL spd1000 = {.Prescaler = 2, .TimeSeg1 = CAN_BS1_15TQ, .TimeSeg2 = CAN_BS2_2TQ};
// PSC - 3 | Time1 - 12 | Time2 - 2
const CAN_SPD_VAL spd800 = {.Prescaler = 3, .TimeSeg1 = CAN_BS1_12TQ, .TimeSeg2 = CAN_BS2_2TQ};
// PSC - 4 | Time1 - 15 | Time2 - 2
const CAN_SPD_VAL spd500 = {.Prescaler = 4, .TimeSeg1 = CAN_BS1_15TQ, .TimeSeg2 = CAN_BS2_2TQ};
// PSC - 8 | Time1 - 15 | Time2 - 2
const CAN_SPD_VAL spd250 = {.Prescaler = 8, .TimeSeg1 = CAN_BS1_15TQ, .TimeSeg2 = CAN_BS2_2TQ};
// PSC - 16 | Time1 - 15 | Time2 - 2
const CAN_SPD_VAL spd125 = {.Prescaler = 16, .TimeSeg1 = CAN_BS1_15TQ, .TimeSeg2 = CAN_BS2_2TQ};
// PSC - 20 | Time1 - 15 | Time2 - 2
const CAN_SPD_VAL spd100 = {.Prescaler = 20, .TimeSeg1 = CAN_BS1_15TQ, .TimeSeg2 = CAN_BS2_2TQ};
// PSC - 40 | Time1 - 15 | Time2 - 2
const CAN_SPD_VAL spd50 = {.Prescaler = 40, .TimeSeg1 = CAN_BS1_15TQ, .TimeSeg2 = CAN_BS2_2TQ};
// PSC - 100 | Time1 - 15 | Time2 - 2
const CAN_SPD_VAL spd20 = {.Prescaler = 100, .TimeSeg1 = CAN_BS1_15TQ, .TimeSeg2 = CAN_BS2_2TQ};
// PSC - 200 | Time1 - 15 | Time2 - 2
const CAN_SPD_VAL spd10 = {.Prescaler = 200, .TimeSeg1 = CAN_BS1_15TQ, .TimeSeg2 = CAN_BS2_2TQ};
/**
* @brief Set Speed for CAN Bus
* @param[in] spd #CAN_SPEED enum
* @param[in] can Pointer to HAL CAN_HandleTypeDef
*/
void CAN_SetSpeed(CAN_SPEED spd, CAN_HandleTypeDef *can) {
//if (HAL_CAN_GetState(can) == HAL_CAN_STATE_LISTENING)
HAL_CAN_Stop(can);
can->Instance = (can == &hcan1) ? CAN1 : CAN2; // Can Instance
can->Init.SyncJumpWidth = CAN_SJW_1TQ; // Default
can->Init.TimeTriggeredMode = DISABLE; // Default
can->Init.AutoBusOff = ENABLE; // Default
can->Init.AutoWakeUp = ENABLE; // Default
can->Init.AutoRetransmission = DISABLE; // Default
can->Init.ReceiveFifoLocked = DISABLE; // Default
can->Init.TransmitFifoPriority = ENABLE; // Default
can->Init.Mode = CAN_BASIC_MODE; // Set Mode
switch (spd) {
case CAN_SPD_1000:
can->Init.Prescaler = spd1000.Prescaler;
can->Init.TimeSeg1 = spd1000.TimeSeg1;
can->Init.TimeSeg2 = spd1000.TimeSeg2;
break;
case CAN_SPD_800:
can->Init.Prescaler = spd800.Prescaler;
can->Init.TimeSeg1 = spd800.TimeSeg1;
can->Init.TimeSeg2 = spd800.TimeSeg2;
break;
case CAN_SPD_500:
can->Init.Prescaler = spd500.Prescaler;
can->Init.TimeSeg1 = spd500.TimeSeg1;
can->Init.TimeSeg2 = spd500.TimeSeg2;
break;
case CAN_SPD_250:
can->Init.Prescaler = spd250.Prescaler;
can->Init.TimeSeg1 = spd250.TimeSeg1;
can->Init.TimeSeg2 = spd250.TimeSeg2;
break;
case CAN_SPD_125:
can->Init.Prescaler = spd125.Prescaler;
can->Init.TimeSeg1 = spd125.TimeSeg1;
can->Init.TimeSeg2 = spd125.TimeSeg2;
break;
case CAN_SPD_100:
can->Init.Prescaler = spd100.Prescaler;
can->Init.TimeSeg1 = spd100.TimeSeg1;
can->Init.TimeSeg2 = spd100.TimeSeg2;
break;
case CAN_SPD_50:
can->Init.Prescaler = spd50.Prescaler;
can->Init.TimeSeg1 = spd50.TimeSeg1;
can->Init.TimeSeg2 = spd50.TimeSeg2;
break;
case CAN_SPD_20:
can->Init.Prescaler = spd20.Prescaler;
can->Init.TimeSeg1 = spd20.TimeSeg1;
can->Init.TimeSeg2 = spd20.TimeSeg2;
break;
case CAN_SPD_10:
can->Init.Prescaler = spd10.Prescaler;
can->Init.TimeSeg1 = spd10.TimeSeg1;
can->Init.TimeSeg2 = spd10.TimeSeg2;
break;
default:
break;
}
if (HAL_CAN_Init(can) != HAL_OK) {
Error_Handler();
}
CAN_FilterTypeDef *filt;
if (can == &hcan1) {
filt = &can1Filter;
filt->FilterBank = 0;
filt->FilterFIFOAssignment = CAN_RX_FIFO0;
} else if (can == &hcan2) {
filt = &can2Filter;
filt->FilterBank = 14;
filt->FilterFIFOAssignment = CAN_RX_FIFO1;
filt->SlaveStartFilterBank = 14;
} else {
return;
}
filt->FilterMode = CAN_FILTERMODE_IDMASK;
filt->FilterScale = CAN_FILTERSCALE_32BIT;
filt->FilterIdHigh = 0x0000;
filt->FilterIdLow = 0x0000;
filt->FilterMaskIdHigh = 0x0000;
filt->FilterMaskIdLow = 0x0000;
filt->FilterActivation = ENABLE;
if (HAL_CAN_ConfigFilter(can, filt) != HAL_OK) {
Error_Handler();
}
// HAL_CAN_Start(can);
volatile HAL_StatusTypeDef status = HAL_CAN_Start(can);
__NOP();
volatile HAL_CAN_StateTypeDef st = HAL_CAN_GetState(can);
if (st != HAL_CAN_STATE_LISTENING){
__USR_BKPT();
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_12, GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_14, GPIO_PIN_SET);
}
HAL_CAN_ActivateNotification(can,
((can == &hcan1) ? CAN_IT_RX_FIFO0_MSG_PENDING : CAN_IT_RX_FIFO1_MSG_PENDING)
| CAN_IT_ERROR | CAN_IT_BUSOFF | CAN_IT_LAST_ERROR_CODE);
}
/**
* @brief Set Silent mode
* @param[in] is_silent 1 if silent mode needed
* @param[in] can Pointer to HAL CAN_HandleTypeDef
*/
void CAN_SetMode(bool is_silent, CAN_HandleTypeDef *can) {
can->Init.Mode = !is_silent ? CAN_MODE_NORMAL : CAN_MODE_SILENT;
}
/**
* @brief Set Silent Loopback mode
* @param[in] is_loopback 1 if loopback mode needed
* @param[in] can Pointer to HAL CAN_HandleTypeDef
*/
void CAN_SetLoopback(bool is_loopback, CAN_HandleTypeDef *can) {
can->Init.Mode = !is_loopback ? CAN_MODE_NORMAL : CAN_MODE_SILENT_LOOPBACK;
}
/**
* @brief Check if CAN is opened
* @param[in] can Pointer to HAL CAN_HandleTypeDef
* @return 1 if Opened / 0 if Closed
*/
bool CAN_IsOpened(CAN_HandleTypeDef *can) {
return HAL_CAN_GetState(can) == HAL_CAN_STATE_LISTENING ? 1 : 0;
}
/**
* @brief Check if CAN is in silent mode
* @param[in] can Pointer to HAL CAN_HandleTypeDef
* @return 1 if Silent / 0 if not
*/
bool CAN_IsSilent(CAN_HandleTypeDef *can) {
return (HAL_CAN_GetState(can) == HAL_CAN_STATE_LISTENING &&
(can->Init.Mode == CAN_MODE_SILENT ||
can->Init.Mode == CAN_MODE_SILENT_LOOPBACK)) ? 0 : 1;
}
/**
* @brief Check if CAN is in silent loopbsck mode
* @param[in] can Pointer to HAL CAN_HandleTypeDef
* @return 1 if Silent Loopback / 0 if else
*/
bool CAN_IsLoopback(CAN_HandleTypeDef *can) {
return (can->Init.Mode == CAN_MODE_SILENT_LOOPBACK) ? 1 : 0;
}
/**
* @brief Set filter mode
* @param[in] id_only 1 if ID_LIST mode / 0 if ID_MASK mode
* @param[in] can Pointer to HAL CAN_HandleTypeDef
*/
void CAN_SetFilterMode(bool id_only, CAN_HandleTypeDef *can) {
CAN_FilterTypeDef *filt;
if (can == &hcan1) {
filt = &can1Filter;
} else if (can == &hcan2) {
filt = &can2Filter;
} else {
return;
}
filt->FilterMode = id_only ? CAN_FILTERMODE_IDLIST : CAN_FILTERMODE_IDMASK;
}
/**
* @brief Set ID for filter
* @warning Not realized
* @param[in] filt_id Pointer to filter ID array
* @param[in] can Pointer to HAL CAN_HandleTypeDef
*/
void CAN_SetFilterID(u8_t *filt_id, CAN_HandleTypeDef *can) {
CAN_FilterTypeDef *filt;
if (can == &hcan1) {
filt = &can1Filter;
} else if (can == &hcan2) {
filt = &can2Filter;
} else {
return;
}
}
/**
* @brief Set Mask for filter
* @warning Not realized
* @param[in] filt_mask Pointer to filter mask
* @param[in] can Pointer to HAL CAN_HandleTypeDef
*/
void CAN_SetFilterMask(u8_t *filt_mask, CAN_HandleTypeDef *can) {
CAN_FilterTypeDef *filt;
if (can == &hcan1) {
filt = &can1Filter;
} else if (can == &hcan2) {
filt = &can2Filter;
} else {
return;
}
}
/**
* @brief Common transmit prototype
* @param[in] id CAN Packet ID
* @param[in] ext 0 if 11-bit ID / 1 if 29-bit ID
* @param[in] rtr 0 if standard frame / 1 if remote frame
* @param[in] len Length of payload
* @param[in] data Pointer to payload array
* @param[in] can Pointer to HAL CAN_HandleTypeDef
*/
void CAN_Transmit_Proto(u32_t id, bool ext, bool rtr, u8_t len, u8_t *data, CAN_HandleTypeDef *can) {
CAN_TxHeaderTypeDef tx;
tx.StdId = !ext ? id : 0;
tx.ExtId = ext ? id : 0;
tx.RTR = !rtr ? CAN_RTR_DATA : CAN_RTR_REMOTE;
tx.IDE = !ext ? CAN_ID_STD : CAN_ID_EXT;
tx.DLC = len;
tx.TransmitGlobalTime = 0;
u32_t mb;
HAL_CAN_AddTxMessage(can, &tx, data, &mb);
}
/**
* @brief Transmit standard (11-bit) data frame
* @param[in] id 11-bit frame ID
* @param[in] data Pointer to payload to be sent
* @param[in] len Length of the payload to be sent
* @param[in] can Pointer to HAL CAN_HandleTypeDef
*/
void CAN_Transmit(u32_t id, u8_t *data, u8_t len, CAN_HandleTypeDef *can) {
CAN_Transmit_Proto((u32_t) id, 0, 0, len, data, can);
}
/**
* @brief Transmit extended (29-bit) data frame
* @param[in] id 29-bit frame ID
* @param[in] data Pointer to payload to be sent
* @param[in] len Length of the payload to be sent
* @param[in] can Pointer to HAL CAN_HandleTypeDef
*/
void CAN_TransmitExt(u32_t id, u8_t *data, u8_t len, CAN_HandleTypeDef *can) {
CAN_Transmit_Proto(id, 1, 0, len, data, can);
}
/**
* @brief Transmit standard (11-bit) remote frame
* @param[in] id 11-bit frame ID
* @param[in] len Length of remote frame
* @param[in] can Pointer to HAL CAN_HandleTypeDef
*/
void CAN_TransmitRTR(u32_t id, u8_t len, CAN_HandleTypeDef *can) {
CAN_Transmit_Proto((u32_t) id, 0, 1, len, NULL, can);
}
/**
* @brief Transmit extended (29-bit) remote frame
* @param[in] id 29-bit frame ID
* @param[in] len Length of remote frame
* @param[in] can Pointer to HAL CAN_HandleTypeDef
*/
void CAN_TransmitExtRTR(u32_t id, u8_t len, CAN_HandleTypeDef *can) {
CAN_Transmit_Proto((u32_t) id, 1, 1, len, NULL, can);
}
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) {
if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &can1RX, can1Data) == HAL_OK) {
//can_irq_receive(&can1RX, can1Data, 1);
}
}
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) {
if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO1, &can2RX, can2Data) == HAL_OK) {
can2_receive_from_irq(&can2RX, can2Data);
//can_irq_receive(&can2RX, can2Data, 2);
}
}

56
firmware/Libs/CAN/can.h Normal file
View File

@@ -0,0 +1,56 @@
//
// Created by enik on 02.06.22.
//
#ifndef USBCANV1_CAN_H
#define USBCANV1_CAN_H
//#include "libs.h"
#include <stdbool.h>
#include "stm32f1xx_hal.h"
typedef uint8_t u8_t; ///< 8-bit unsigned
typedef int8_t i8_t; ///< 8-bit signed
typedef uint16_t u16_t; ///< 16-bit unsigned
typedef int16_t i16_t; ///< 16-bit signed
typedef uint32_t u32_t; ///< 32-bit unsigned
typedef int32_t i32_t; ///< 32-bit signed
typedef float fl_t; ///< float type
#define __USR_BKPT() __asm__ __volatile__("BKPT")
/**
* @brief CAN Speed in KBit/s
*/
typedef enum CAN_SPEED {
CAN_SPD_1000,
CAN_SPD_800,
CAN_SPD_500,
CAN_SPD_250,
CAN_SPD_125,
CAN_SPD_100,
CAN_SPD_50,
CAN_SPD_20,
CAN_SPD_10,
} CAN_SPEED;
void CAN_SetSpeed(CAN_SPEED spd, CAN_HandleTypeDef *can); //
void CAN_SetMode(bool is_silent, CAN_HandleTypeDef *can); //
void CAN_SetLoopback(bool is_loopback, CAN_HandleTypeDef *can); //
bool CAN_IsOpened(CAN_HandleTypeDef *can); //
bool CAN_IsSilent(CAN_HandleTypeDef *can); //
bool CAN_IsLoopback(CAN_HandleTypeDef *can); //
void CAN_SetFilterMode(bool id_only, CAN_HandleTypeDef *can); //
void CAN_SetFilterID(u8_t *filt_id, CAN_HandleTypeDef *can); //
void CAN_SetFilterMask(u8_t *filt_mask, CAN_HandleTypeDef *can); //
void CAN_Transmit(u32_t id, u8_t *data, u8_t len, CAN_HandleTypeDef *can); //
void CAN_TransmitExt(u32_t id, u8_t *data, u8_t len, CAN_HandleTypeDef *can); //
void CAN_TransmitRTR(u32_t id, u8_t len, CAN_HandleTypeDef *can); //
void CAN_TransmitExtRTR(u32_t id, u8_t len, CAN_HandleTypeDef *can); //
#endif //USBCANV1_CAN_H

View File

@@ -0,0 +1,354 @@
//
// Created by enik on 03.04.23.
//
#include "can_messenger.h"
#include "can.h"
//#include "modCommands.h"
#include "modPowerElectronics.h"
#include <string.h>
#include "../RingBuffer/RingBuffer.h"
extern uint64_t TIM_Clock;
extern CAN_HandleTypeDef hcan1;
extern CAN_HandleTypeDef hcan2;
uint64_t can1_transmit_clock = 0;
uint64_t can2_transmit_clock = 0;
typedef struct CAN_MSG_t {
u16_t id;
u8_t len;
u8_t msg[8];
} CAN_MSG_t;
static volatile CAN_MSG_t can1_transmit_q_msg[45]; // 540 bytes
static volatile CAN_MSG_t can2_transmit_q_msg[10]; // 120 bytes
static volatile RINGBUF_t can1_ring;
static volatile RINGBUF_t can2_ring;
static volatile CAN_MSG_t can1_buf = {0,}; // Buf for 1 packet
static volatile CAN_MSG_t can2_buf = {0,}; // Buf for 1 packet
static volatile CAN_MSG_t can1_tx_buf = {0,}; // Buf for 1 TX packet
static volatile CAN_MSG_t can2_tx_buf = {0,}; // Buf for 1 TX packet
extern modPowerElectronicsPackStateTypedef packState;
extern modConfigGeneralConfigStructTypedef *generalConfig;
static volatile bool threshold_request = 0;
static volatile bool active_request = 0;
void can_msgr_init() {
RingBuf_Init((void *) &can1_transmit_q_msg, 45, sizeof(CAN_MSG_t), (RINGBUF_t *) &can1_ring);
RingBuf_Init((void *) &can2_transmit_q_msg, 10, sizeof(CAN_MSG_t), (RINGBUF_t *) &can2_ring);
}
void transmitCan1Packet() {
if ((TIM_Clock - can1_transmit_clock) < 1000) {
return;
}
uint8_t data1[8] = {0x45};
CAN_Transmit(300, data1, 8, &hcan1);
can1_transmit_clock = TIM_Clock;
return;
CAN_TxHeaderTypeDef header;
header.IDE = CAN_ID_STD;
header.RTR = CAN_RTR_DATA;
header.StdId = 0x444;
header.DLC = 1;
uint8_t data[32] = {};
uint32_t mailbox = 0;
// sending SOC, SOH and number of cells
uint16_t id = 0x101;
memcpy(data, &id, sizeof(id));
memcpy(data + 2, &packState.SoC, sizeof(packState.SoC));
memcpy(data + 6, &packState.SoCCapacityAh, sizeof(packState.SoCCapacityAh));
memcpy(data + 10, &generalConfig->noOfCellsSeries, sizeof(generalConfig->noOfCellsSeries));
header.DLC = 11;
HAL_CAN_AddTxMessage(&hcan1, &header, data, &mailbox);
// sending charge current, discharge current // TODO
id = 0x102;
memcpy(data, &id, sizeof(id));
memcpy(data + 2, &packState.packCurrent, sizeof(packState.packCurrent));
memcpy(data + 6, &packState.loCurrentLoadCurrent, sizeof(packState.loCurrentLoadCurrent));
header.DLC = 10;
HAL_CAN_AddTxMessage(&hcan1, &header, data, &mailbox);
// sending BMS state, input state, output state // TODO
id = 0x103;
memcpy(data, &id, sizeof(id));
memcpy(data + 2, &packState.cellVoltageLow, sizeof(packState.cellVoltageLow));
memcpy(data + 6, &packState.cellVoltageAverage, sizeof(packState.cellVoltageAverage));
memcpy(data + 10, &packState.cellVoltageHigh, sizeof(packState.cellVoltageHigh));
header.DLC = 12;
HAL_CAN_AddTxMessage(&hcan1, &header, data, &mailbox);
// sending cell voltages
id = 0x200;
for (int cellPointer = 0;
cellPointer < generalConfig->noOfCellsSeries * generalConfig->noOfParallelModules; ++cellPointer) {
++id;
memcpy(data, &id, sizeof(id));
float voltage = 0;
if (packState.cellVoltagesIndividual[cellPointer].cellBleedActive)
voltage = packState.cellVoltagesIndividual[cellPointer].cellVoltage * -1000;
else
voltage = packState.cellVoltagesIndividual[cellPointer].cellVoltage * 1000;
memcpy(data + 2, &voltage, sizeof(voltage));
header.DLC = 6;
HAL_CAN_AddTxMessage(&hcan1, &header, data, &mailbox);
}
// sending temperatures
id = 0x300;
for (int sensorPointer = 0; sensorPointer < NoOfTempSensors; ++sensorPointer) {
++id;
memcpy(data, &id, sizeof(id));
float temperature = packState.temperatures[sensorPointer];
memcpy(data + 2, &temperature, sizeof(temperature));
header.DLC = 6;
HAL_CAN_AddTxMessage(&hcan1, &header, data, &mailbox);
}
can1_transmit_clock = TIM_Clock;
}
int getIndexBySoc() {
const float soc = packState.SoC;
if (soc <= 0) {
return 0;
} else if (soc <= 10 && soc > 0) {
return 1;
} else if (soc <= 20 && soc > 10) {
return 2;
} else if (soc <= 30 && soc > 20) {
return 3;
} else if (soc <= 40 && soc > 30) {
return 4;
} else if (soc <= 50 && soc > 40) {
return 5;
} else if (soc <= 60 && soc > 50) {
return 6;
} else if (soc <= 70 && soc > 60) {
return 7;
} else if (soc <= 80 && soc > 70) {
return 8;
} else if (soc <= 95 && soc > 80) {
return 9;
} else if (soc > 95) {
return 10;
}
return -1;
}
int getIndexByTemperature() {
const float temp = packState.tempBatteryAverage;
if (temp < 0) {
return 0;
} else if (temp < 2 && temp >= 0) {
return 1;
} else if (temp < 7 && temp >= 2) {
return 2;
} else if (temp < 15 && temp >= 7) {
return 3;
} else if (temp < 20 && temp >= 15) {
return 4;
} else if (temp < 45 && temp >= 20) {
return 5;
} else if (temp < 50 && temp >= 45) {
return 6;
} else if (temp < 55 && temp >= 50) {
return 7;
} else if (temp >= 55) {
return 8;
}
return -1;
}
u16_t get_table_current() {
// sending table current and end-of-charge current command
const int socIndex = getIndexBySoc();
const int temperatureIndex = getIndexByTemperature();
float tableCurrent = 0;
if (socIndex != -1 && temperatureIndex != -1) {
float tableValue = generalConfig->externalChargeCurrentTable[temperatureIndex][socIndex];
float pureCurrent = generalConfig->externalChargeUnitTable[temperatureIndex][socIndex];
return (u16_t) roundf(pureCurrent ? tableValue : generalConfig->batteryCapacity * tableValue);
}
return 0;
}
void can2_send_status() {
// id - CAN_BMS_STATUS
// len - 7
// msg[0:0] = 0: permission, 1: end_charge, 2: charging
// msg[1:2] = set_curr
// msg[3:6] = end_voltage
u8_t b0 = 0;
b0 |= (packState.chargeAllowed & 0b1) << 0; // bit 0
b0 |= ((packState.SoC > 95) & 0b1) << 1; // bit 1
b0 |= (charge_switch_state & 0b1) << 2; // bit 2
u16_t curr = get_table_current();
const float endVoltage = generalConfig->cellHardOverVoltage * (float) generalConfig->noOfCellsSeries;
can2_buf.id = CAN_BMS_STATUS;
can2_buf.len = 7;
can2_buf.msg[0] = b0; // set msg[0]
memcpy((void *) can2_buf.msg + sizeof(b0), &curr, sizeof(curr)); // set msg[1]
memcpy((void *) can2_buf.msg + sizeof(b0) + sizeof(curr), &endVoltage, sizeof(endVoltage)); // set msg[3]
RingBuf_CellPut(&can2_buf, &can2_ring);
}
void can2_send_volt_threshold() {
// id - CAN_BMS_VOLT_THRESH
// len - 8
// msg[0:3] = start_voltage
// msg[4:7] = end_voltage
// TODO: Check it
const float startVoltage = generalConfig->cellHardUnderVoltage * (float) generalConfig->noOfCellsSeries;
const float endVoltage = generalConfig->cellHardOverVoltage * (float) generalConfig->noOfCellsSeries;
can2_buf.id = CAN_BMS_VOLT_THRESH;
can2_buf.len = 8;
memcpy((void *) can2_buf.msg, &startVoltage, sizeof(startVoltage));
memcpy((void *) can2_buf.msg + sizeof(startVoltage), &endVoltage, sizeof(endVoltage));
RingBuf_CellPut(&can2_buf, &can2_ring);
}
void can2_send_volt_alarm() {
// id - CAN_BMS_VOLT_ALARM
// len - 8
// msg[0:3] = volt_alarm_lo
// msg[4:7] = volt_alarm_up
// TODO: Check it
const float startFaultVoltage = generalConfig->cellLCSoftUnderVoltage * (float) generalConfig->noOfCellsSeries;
const float endFaultVoltage = generalConfig->cellSoftOverVoltage * (float) generalConfig->noOfCellsSeries;
can2_buf.id = CAN_BMS_VOLT_ALARM;
can2_buf.len = 8;
memcpy((void *) can2_buf.msg, &startFaultVoltage, sizeof(startFaultVoltage));
memcpy((void *) can2_buf.msg + sizeof(startFaultVoltage), &endFaultVoltage, sizeof(endFaultVoltage));
RingBuf_CellPut(&can2_buf, &can2_ring);
}
void can2_send_current() {
// id - CAN_BMS_CURRENT
// len - 8
// msg[0:1] = [u16] start_current
// msg[2:3] = [u16] start_current_interval
// msg[4:5] = [u16] set_current
// msg[6:7] = [u16] end_current
u16_t chargeStartingCurrent = 15; // TODO move to generalConfig
u16_t chargeStartingCurrentInterval = 20; // in seconds TODO move to generalConfig
u16_t curr = get_table_current();
u16_t chargeEndingCurrent = 5; // TODO move to generalConfig
can2_buf.id = CAN_BMS_CURRENT;
can2_buf.len = 8;
memcpy((void *) can2_buf.msg, &chargeStartingCurrent, sizeof(chargeStartingCurrent));
memcpy((void *) can2_buf.msg + sizeof(chargeStartingCurrent),
&chargeStartingCurrentInterval,
sizeof(chargeStartingCurrentInterval));
memcpy((void *) can2_buf.msg + sizeof(chargeStartingCurrent) + sizeof(chargeStartingCurrentInterval),
&curr,
sizeof(curr));
memcpy((void *) can2_buf.msg + sizeof(chargeStartingCurrent) + sizeof(chargeStartingCurrentInterval) + sizeof(curr),
&chargeEndingCurrent,
sizeof(chargeEndingCurrent));
RingBuf_CellPut(&can2_buf, &can2_ring);
}
void can2_send_active() {
// id - CAN_BMS_ACT_VAL
// len - 6
// msg[0:3] = [float] sum_voltage
// msg[4:5] = [u16] sum_current
can2_buf.id = CAN_BMS_ACT_VAL;
can2_buf.len = 6;
memcpy((void *) can2_buf.msg, &packState.packVoltage, sizeof(packState.packVoltage));
memcpy((void *) can2_buf.msg + sizeof(packState.packVoltage),
&packState.packCurrent, sizeof(packState.packCurrent));
RingBuf_CellPut(&can2_buf, &can2_ring);
}
void transmitCan2Packet() {
if (threshold_request) {
// Send 501 - status, 503 - volt. threshold, 504 - volt. alarm, 505 - current
can2_send_status(); // 501
can2_send_volt_threshold(); // 503
can2_send_volt_alarm(); // 504
can2_send_current(); // 505
threshold_request = 0;
}
if (active_request){
// send 507 - active values
can2_send_active();
active_request = 0;
}
if ((TIM_Clock - can2_transmit_clock) < 10) {
return;
}
can2_transmit_clock = TIM_Clock;
can2_send_status();
}
void transmitCanPacketFromQueueCan1(void) {
if (!HAL_CAN_GetTxMailboxesFreeLevel(&hcan1)) return; // if no free mailboxes
u16_t len = 0;
RingBuf_Available(&len, &can1_ring);
if (!len) return;
RingBuf_CellRead(&can1_tx_buf, &can1_ring);
CAN_Transmit(can1_tx_buf.id, can1_tx_buf.msg, can1_tx_buf.len, &hcan1);
}
u32_t ctr;
void transmitCanPacketFromQueueCan2(void) {
if (!HAL_CAN_GetTxMailboxesFreeLevel(&hcan2)) return; // if no free mailboxes
u16_t len = 0;
RingBuf_Available(&len, &can2_ring);
if (!len) return;
// volatile u32_t delta = HAL_GetTick() - ctr;
// ctr = HAL_GetTick();
//
// __NOP();
RingBuf_CellRead(&can2_tx_buf, &can2_ring);
CAN_Transmit(can2_tx_buf.id, can2_tx_buf.msg, can2_tx_buf.len, &hcan2);
}
void can2_receive_from_irq(CAN_RxHeaderTypeDef *hdr, uint8_t *data) {
// If remote frame with STD ID
if (hdr->RTR == CAN_RTR_REMOTE && hdr->IDE == CAN_ID_STD) {
if (hdr->StdId == CAN_BMS_THRESH_REQ) { // if Threshold request
threshold_request = 1;
} else if (hdr->StdId == CAN_BMS_ACT_REQ) { // if Active request
active_request = 1;
}
}
}

View File

@@ -0,0 +1,38 @@
//
// Created by enik on 03.04.23.
//
#ifndef BMS_V3_CAN_MESSENGER_H
#define BMS_V3_CAN_MESSENGER_H
#include "../Core/Inc/main.h"
/**
* @brief CAN BMS ID description enum
*/
typedef enum CAN_BMS_ID {
CAN_BMS_HEARTBEAT = 0x500U, ///< [BMS->Charger][RTR] Heartbeat
CAN_BMS_STATUS = 0x501U, ///< [BMS->Charger][L:7] Status packet
CAN_BMS_THRESH_REQ = 0x502U, ///< [Charger->BMS][RTR] Threshold request
CAN_BMS_VOLT_THRESH = 0x503U, ///< [BMS->Charger][L:8] Voltage threshold
CAN_BMS_VOLT_ALARM = 0x504U, ///< [BMS->Charger][L:8] Voltage alarm
CAN_BMS_CURRENT = 0x505U, ///< [BMS->Charger][L:6] Current control
CAN_BMS_ACT_REQ = 0x506U, ///< [Charger->BMS][RTR] Active values request
CAN_BMS_ACT_VAL = 0x507U, ///< [BMS->Charger][L:6] Active values
} CAN_BMS_ID;
void can_msgr_init();
void transmitCan1Packet();
int getIndexBySoc();
int getIndexByTemperature();
void transmitCan2Packet();
void addCanPacketToQueue(uint16_t id, uint8_t len, uint8_t *data, uint8_t *queue, uint16_t *queueSize);
//void transmitCanPacketFromQueue(uint8_t* queue, uint16_t* queueSize, CAN_HandleTypeDef* hcan);
void transmitCanPacketFromQueueCan1(void);
void transmitCanPacketFromQueueCan2(void);
void can2_receive_from_irq(CAN_RxHeaderTypeDef *hdr, uint8_t* data);
#endif //BMS_V3_CAN_MESSENGER_H