Files
CuboBmsFirmware/firmware/Libs/CAN/can_messenger.c
Dmitriy Semenov 9c2667bbe5 CAN Update
2023-04-03 21:51:33 +03:00

354 lines
11 KiB
C

//
// 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;
}
}
}