cancel
Showing results for 
Search instead for 
Did you mean: 

AEK-MCU-C4MLIT1 BMS with CAN Project

Vipuls
Associate II

Hello Community,

I am trying to build a 333V Battery Pack with AEK-MCU-C4MLIT1 as the Master, AEK-ISOSPI Translator and multiple AEK-POW-BMS69EN as slaves in daisy chain configuration. I would like to get the information such as cell voltages, SOC, and Balancing commands from the slave and send it onto the Vehicle CAN Network.

As of now, I have been able to get the cell voltages on the serial terminal from one 48V dummy pack which I have built. And, I have been able to send some dummy data from the AEK-MCU-C4MLIT1 Master CAN 1 Channel and read it with the help of a CAN KVASER Dongle.

Now, When I went for combining these two functionality the project didn't seem to work. 

I suspect that maybe the pins which I am using to establish the ISOSPI communication between the Master and the Slave are interfering when I am trying to establish the CAN Communication. But, I tried configuring the pins on the CAN0 channel (Pin 101 as RX and Pin 102 as TX) but I am not seeing anything on the CAN_1_L and CAN_1_H lines on the PCB. I have enabled the MCAN0 channel in the CAN Configuration. 

What could I be doing wrong? Is there some example to which I could refer?

I have attached an image of my PIN map and my code. 

PS: You can see that I am quite new to learning Embedded programming but I am trying. 

 My main.c file:

 

/****************************************************************************
 *
 * Copyright © 2022 STMicroelectronics - All Rights Reserved
 *
 * License terms: STMicroelectronics Proprietary in accordance with licensing
 * terms SLA0089 at www.st.com.
 *
 * THIS SOFTWARE IS DISTRIBUTED "AS IS," AND ALL WARRANTIES ARE DISCLAIMED,
 * INCLUDING MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * EVALUATION ONLY – NOT FOR USE IN PRODUCTION
 *****************************************************************************/
 
/* Inclusion of the main header files of all the imported components in the
 order specified in the application wizard. The file is generated
 automatically.*/
 
#include "components.h"
#include "AEK_POW_BMS63EN_Appl.h"
#include "wkpu_lld_cfg.h"
#include "serial_lld_cfg.h"
#include <stdio.h>
#include <string.h>
#include "can_lld_cfg.h"
 
volatile uint8_t i_device_disp=0;
 
void send_temp_data(AEK_POW_BMS63EN_module_t *batteryModule){
CANTxFrame txf_temp;
 
txf_temp.TYPE = CAN_ID_STD;   // Standard CAN frame
txf_temp.ID = 0x615;          // CAN ID for Temperature Message
txf_temp.DLC = 8U;
 
uint16_t temp1 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellTemperatureNTC[0]);
uint16_t temp2 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellTemperatureNTC[3]);
uint16_t temp3 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellTemperatureNTC[6]);
uint16_t temp4 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellTemperatureNTC[9]);
uint16_t temp5 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellTemperatureNTC[12]);
 
 
txf_temp.data32[0] = ((temp1 & 0xFFF) << 0)  |  // 12 bits
                 ((temp2 & 0xFFF) << 12) |  // 12 bits
                 ((temp3 & 0xFFF) << 24);   // Upper 8 bits of temp3
 
txf_temp.data32[1] = ((temp3 & 0xFFF) >> 8)  |  // Lower 4 bits of temp3
                 ((temp4 & 0xFFF) << 4)  |  // 12 bits
                 ((temp5 & 0xFFF) << 16);   // 12 bits
 
can_lld_transmit(&CAND1, CAN_DEDICATED_TXBUFFER, &txf_temp);
 
}
 
void send_cell_voltages_CAN(AEK_POW_BMS63EN_module_t *batteryModule) {
 
CANTxFrame txf_volt1;
 
    txf_volt1.TYPE = CAN_ID_STD;   // Standard CAN frame
    txf_volt1.ID = 0x602;          // CAN ID
    txf_volt1.DLC = 8U;            // Data Length (8 bytes per frame)
 
 
    CANTxFrame txf_volt2;
 
    txf_volt2.TYPE = CAN_ID_STD;   // Standard CAN frame
    txf_volt2.ID = 0x603;          // CAN ID
    txf_volt2.DLC = 8U;            // Data Length (8 bytes per frame)
 
 
    // Send 7 cell voltages in the first frame
    uint16_t voltage1 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellVoltage[0] * 100);
    uint16_t voltage2 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellVoltage[1] * 100);
    uint16_t voltage3 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellVoltage[2] * 100);
    uint16_t voltage4 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellVoltage[3] * 100);
    uint16_t voltage5 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellVoltage[4] * 100);
    uint16_t voltage6 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellVoltage[5] * 100);
    uint16_t voltage7 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellVoltage[6] * 100);
 
 
    //Send remaining 7 cell voltages in the second frame
    uint16_t voltage8 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellVoltage[7] * 100);
    uint16_t voltage9 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellVoltage[8] * 100);
    uint16_t voltage10 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellVoltage[9] * 100);
    uint16_t voltage11 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellVoltage[10] * 100);
    uint16_t voltage12 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellVoltage[11] * 100);
    uint16_t voltage13 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellVoltage[12] * 100);
    uint16_t voltage14 = (uint16_t)(batteryModule->AEK_POW_BMS63EN_Pack_CellVoltage[13] * 100);
 
 
    txf_volt1.data32[0] =  ((voltage1 & 0x1FF) << 0)  |   // 9 bits
             ((voltage2 & 0x1FF) << 9)  |   // 9 bits
             ((voltage3 & 0x1FF) << 18) |   // 9 bits
             ((voltage4 & 0x1FF) << 27);
 
 
    txf_volt1.data32[1] =  ((voltage4 >> 5) & 0x07)  |    // Remaining 4 bits of voltage[3]
            ((voltage5 & 0x1FF) << 4)  |   // 9 bits
            ((voltage6 & 0x1FF) << 13) |   // 9 bits
            ((voltage7 & 0x1FF) << 22);
 
    txf_volt2.data32[0] =  ((voltage8 & 0x1FF) << 0)  |   // 9 bits
                 ((voltage9 & 0x1FF) << 9)  |   // 9 bits
                 ((voltage10 & 0x1FF) << 18) |   // 9 bits
                 ((voltage11 & 0x1FF) << 27);
 
 
    txf_volt2.data32[1] =  ((voltage11 >> 5) & 0x07)  |    // Remaining 4 bits of voltage[3]
                ((voltage12 & 0x1FF) << 4)  |   // 9 bits
                ((voltage13 & 0x1FF) << 13) |   // 9 bits
                ((voltage14 & 0x1FF) << 22);
 
 
    can_lld_transmit(&CAND1, CAN_DEDICATED_TXBUFFER, &txf_volt1);
 
    can_lld_transmit(&CAND1, CAN_DEDICATED_TXBUFFER, &txf_volt2);
 
}
 
 
void main_core0(void) {
  char message[11];
  AEK_POW_BMS63EN_module_t AEK_POW_BMS63EN_BatteryModule;
  uint8_t cell_idx = 0;
  /* Enable Interrupts */
  irqIsrEnable();
  sd_lld_start(&SD5,&serial_config_BMS_serial);
  can_lld_start(&CAND1, &can_config_mcanconf);/*MCAN SUB 0 CAN 1*/
 
  /* Application main loop.*/
  for ( ; ; ) {
 
  if((osalThreadGetMilliseconds()%500)==0){
    AEK_POW_BMS63EN_BatteryModule = AEK_POW_BMS63EN_GetModule(i_device_disp);
 
 
    send_cell_voltages_CAN(&AEK_POW_BMS63EN_BatteryModule);
    //send_temp_data(&AEK_POW_BMS63EN_BatteryModule);
 
//SOC Elaboration Done
sprintf(message, "DEV:%d     \n", (int)(i_device_disp+1));
sd_lld_write(&SD5, (uint8_t *)message, (uint16_t)(sizeof(message)/sizeof(message[0])));
//Printing SOC
for(cell_idx = AEK_POW_BMS63EN_CELL1; cell_idx <= AEK_POW_BMS63EN_CELL14; cell_idx ++){
sprintf(message, "S%.2d:%.3d    ", cell_idx+1, (int)((AEK_POW_BMS63EN_BatteryModule.AEK_POW_BMS63EN_Pack_SOC[cell_idx]) * 100));
sd_lld_write(&SD5, (uint8_t *)message, (uint16_t)(sizeof(message)/sizeof(message[0])));
}
sprintf(message,"          \n");
sd_lld_write(&SD5, (uint8_t *)message, (uint16_t)(sizeof(message)/sizeof(message[0])));
//Printing Bal
for(cell_idx = AEK_POW_BMS63EN_CELL1; cell_idx <= AEK_POW_BMS63EN_CELL14; cell_idx ++){
sprintf(message, "B%.2d:%.3d    ", cell_idx+1, AEK_POW_BMS63EN_BatteryModule.AEK_POW_BMS63EN_Pack_Bal_cmd[cell_idx]);
sd_lld_write(&SD5, (uint8_t *)message, (uint16_t)(sizeof(message)/sizeof(message[0])));
}
sprintf(message,"          \n");
sd_lld_write(&SD5, (uint8_t *)message, (uint16_t)(sizeof(message)/sizeof(message[0])));
//Printing Voltage
for(cell_idx = AEK_POW_BMS63EN_CELL1; cell_idx <= AEK_POW_BMS63EN_CELL14; cell_idx ++){
sprintf(message, "V%.2d:%.3f  ", cell_idx+1, AEK_POW_BMS63EN_BatteryModule.AEK_POW_BMS63EN_Pack_CellVoltage[cell_idx]);
sd_lld_write(&SD5, (uint8_t *)message, (uint16_t)(sizeof(message)/sizeof(message[0])));
}
sprintf(message,"          \n");
sd_lld_write(&SD5, (uint8_t *)message, (uint16_t)(sizeof(message)/sizeof(message[0])));
//Printing Current
sprintf(message, "C:%.4f    \n", AEK_POW_BMS63EN_BatteryModule.AEK_POW_BMS63EN_Pack_Current);
sd_lld_write(&SD5, (uint8_t *)message, (uint16_t)(sizeof(message)/sizeof(message[0])));
}
  }
 
}
 
 
void *sbrk(size_t incr)
{
extern uint8_t __heap_base__;
extern uint8_t __heap_end__;
static uint8_t *p=&__heap_base__;
static uint8_t *newp;
 
newp = p+ incr;
if(newp> &__heap_end__)
{
return (void*)-1;
}
return p =newp;
}
 
 
void int28_irq_cb(WKPUDriver *wkpup)
{
(void)wkpup;
i_device_disp = i_device_disp+1;
if (i_device_disp==AEK_POW_BMS63EN_N_BMS) i_device_disp=0;
 
}
 
 
int main(void) {
 
componentsInit();
irqIsrEnable();
wkpu_lld_start(&WKPUD1, &wkpu_config_wkpu_cfg);
 
AEK_POW_BMS63EN_init();
runCore0();
AEK_POW_BMS63EN_Start_Mgn_exec();
 
 
 
while (1) {
}
 
}
 
 
 
 
1 REPLY 1
Vipuls
Associate II

Hello Community,

I was going through the CAN Communication demo document, which is present online and realized that I haven't configured the RX buffers for any filters in my case. Is it necessary to configure the RX Buffer even when you are not planning to receive any CAN Message from the board? I saw somewhere on this forum that it is necessary to enable the RX filters for establishing CAN Communication.    

Thanks,

Vipuls