BMS主要就是---上下电控制
均衡
电压电流温度信息采集
SOX(SOC,SOH,SOP等)计算
电池故障保护(包含绝缘)
1 从板硬件
大致项目实践规划:
先用两个6811采集芯片电压
自己做DBC,复杂can消息收发,导入simulink,再用canoe做上位机整体监控
如果项目变大,采集板用菊花链。即片上FAE芯片接电池,线束上留一正一负,互相连,再配一个主板,菊花链最后连主板上的解码芯片上,这个解码芯片再和主板上的单片机或者CPU通讯,之后主板再控制输出。----------这种也称为分布式系统(多个电池组的大货车)
如果把采集和主控放在一个板子上,就称为一体式,这种一般用在乘用车上。
被动均衡---找最高的单体放电(电流小,50-100ma,好的2-5A);
主动均衡---找最小的单体进行充电(电流大);
一般在调试芯片的时候,检查芯片是否正常,先看和芯片接地的GND相连的5V参考电压
有没有出来;如果没出来,那肯定不能正常工作。这里的5V主要是采集温度用的(提供基准)。
采集板上不同传感器接地方式最好区分一下,以免搞混
项目中最好在ref5V参考电压上放一个放光二极管,来实时判断芯片是否正常工作
电压和adc值的关系(搜索:单片机位数和电压值的数学关系):
adc的输出和输入电压之间的关系为:v=(adc值/2n次方)* Vref
V是输入电压,adc值是单片机读取的值,,n是adc位数,Vref是adc的参考电压
有CAN通讯的地方一定要上共模电感,和专用的TVS(为了EMC),共模电感主要是
抑制共模干扰信号,TVS是钳制瞬时高压,保护器件
SOC上采集的数据一般用铁电存储器保存起来(在片外),掉电不失。
===============================================================================================================================
2 主板
扩展:BMS主板主要有哪些功能--SOX即电量SOC,健康SOH,能量评估SOE,峰值功率SOP
保护电池(处理电压电流温度异常;绝缘监测,不能有绝缘故障;诊断电池包)
高压上下电(快慢充电,放电控制)
做均衡
通讯(与VCU,PDU电池分配单元)
数据处理,如故障读写等
从板的任务--采集+均衡(自己不能自己做,要主板给指令才行)
主板---
1)绝缘检测---车辆低压和高压部分应当绝缘,即高压和低压部分不能共地(一般是正极接地或者负极接地,途中穿上等效电阻绝缘,这个电阻越大,对人越安全,正常情况下本都是兆欧)
标准:看高压部分和低压部分等效电阻是多少,低了就故障。新国标100欧/V,老国标500欧/V。也就是说判断等效电阻,首先要知道总电压才行。具体见“绝缘等级分级标准”
分级:大约1000欧/V=无故障;1000-500欧/V=一级故障,只警示;500-100欧/V=二级故障,须警示+信息提示;小于500欧/V=三级故障,须断开高压,无法驾驶
具体检测方法:
1)低频信号注入法:类似万用表原理,给个低频信号,正常是载波,如果有故障会变平或者幅值变小
2)综合判据法:略
3)平衡/不平衡电桥法:一般不平衡电桥法用的多。原理就是正极采集路出现绝缘故障,就闭合负极采集路,反之亦然。然后,正和负那一路分别搞出一个分压电阻,电压分别Vp和Vn,对应的采集路
测得的就是Vp'和Vn',然后对比二者,Vp和Vn作为标准的参考。如果Vp>Vn,则Rp>Rn,那么就失衡了,就有绝缘故障。
注意:绝缘电阻不是一个实际存在的电阻,而是一个概念上的等效电阻。理想情况下是无穷大。 (走线时候高压线区块和低压线区块互为自闭环,且相互隔离,不能有任何连接)
===============================================================================================================================
3 从手动解析can通信内容,到把can协议构建成dbc,再到把dbc导入到simulink。导入后,就可以忽略打包和解包过程
1.项目里面,只要是非一体化的,分布式的项目,主板和从板一般是用CAN通讯。
2.从板发,主板接收,上位机对主板上的电池信息进行标定/显示。
3.主板另一个连接,即是和充电机通讯
4.一般地,节点分为例如:
a.BMS发送 b.上位机发送标定目标值 c.BMS发送标定后的值
d.从板1,2,3发送数据/ e。BMS发送从板第二路CAN
5.怎么样新建dbc过程 :
a)在左边,新建主板,从板它们之间的报文这些为messages,具体的报文中包含的每个信号为signals
b)一般选摩托罗拉格式byte order 数位精度factor选好(0.1或0.01)
c)dbc编辑好后拖进去的时候按顺序拖,从signals拖到messages里面即可。
d)拖好后点message里面进去看,layout里面可以看到已经编辑好了的dbc
6.电池包里面分为pack电压和link电压,pack是整个系统里面的电压,link是里面分区模块的节点电压。绝缘电压一样,也分。
具体地就是,动能电池会经过一个接收器,pack电压在继电器之前,link在继电器之后
7.(单体电压一般用mV毫伏来表示,比如3.2V那就是3200mv)
8.完事之后再CANdb++里面点左上角保存。然后来到Matlab,先在里面找到对应的CAN_TX模版,是一个slx文件(在vehicle network toolbox里面),双击它,进去后点“浏览”,找到打开刚才保存的dbc文件,选择dbc文件里面的具体哪个ID报文即可(因为一个dbc里面可以包含很多个报文,所以我们在设定dbc的时候,报文文件名记得用ID编号)。
之后再直接添加In1,In2这样的输入信号,连到它上面即可。
(注意:模块出来的顺序不一定按照我们编辑的顺序走,是随机的。)
9.如此一来,输入的信号In1 ,In2 等经过dbc后,直接把信号打包成CAN格式的数据了。
打包好后,在后面的system update模块,会统一发送函数。
10.在做电流信号的时候,因为电流是有方向的,所以value type这里选signed;对应的,如果信号本身没有负值,比如是电压,那么就选unsigned-----那对应的后面生成的min和max也要改成0-xxx
11.看报文里面,哪个byte到哪个byte是代表一个信号,因为一个byte是8个bit嘛,如果一个信号占了2个byte位,那么我们在做它的dbc时候,设置这里,length(bit)我们就填写16
12.length后面的byte order一般都选motorola格式 ,unit单位就选具体的信号的单位,factor就是系数,是多少选多少(一般在报文面的格式说明里有),offset和最大最小没有就不选。然后直接点击calculate minimun and maxium。
13.然后看点了自动生成的calculate后的结果,如果想节约的话,也可以把这个最大最小手动改一下。
14.信号进出去向的ID号怎么填?GOTO模块具体去哪个模块,点进去相应的CAN模块,里面有个“CAN标识符”,就是这个东西,但是这个这里是已经转成了十进制的。这里的GOTO模块,其实是一个临时变量,可以自己手动改了,改一个自己喜欢的名字,比如ID1,ID2,这个不会影响它实际最终的去向,这个自定义的ID1,ID2,只是一个临时的指代变量。但是,相应的地方自己改了,其他的也记得改成一样的。(点开GOTO,修改“GOTO标记”即可)
15.模型搭好后,在关联线上面要加上对应的信号名字,只在最外面的模型加。这是为了代码生成,只是仿真的话不需要。这一步搞好后就开始脚本了。
16.所有模型搭建好之后,在最外层搞一个总览的模型,把所有子模型的输入拖到这个总览模型的左边输入侧,这是为了方便总览。相当于一个目录索引
17.脚本怎么写:先对每个输入变量定义一下 ,比如
BMS_SEND_BUS_CUR = mpt.Signal; //定义信号是mpt类型(总类型,代码生成的)
BMS_SEND_BUS_CUR.DataType = 'single'; //定义它的数据(子类型)是浮点数
(数据类型不清楚不确定的情况下,全用single类型即可)
18.matlab里面输入的数据,哪怕是小数,进到模型里,会自动转化成模型里面的数据格式
19.在这个脚本定义过程中,一定要注意每个数据的数据类型,请根据第四期第五课演示的各个变量的类型,牢记。
20.定义完了之后,运行一下,让数据进工作区;然后再把模型运行一下,保证模型没有问题。都没有问题之后,就可以生成代码了。
21.以上都没问题后,ctrl+B一下,build生成代码,生成完毕后,文件里面一般包含:
a)模型文件,如MCU_CAN_TX.c 和MCU_CAN_TX.h和MCU_CAN_TX_types.h
b)数据文件,这个里面会有global的全局变量,它们都是输出。这些文件一般形如
global_MCU_CAN_TX.c和global_MCU_CAN_TX.h
此时,一定要进到.c文件里面去找这些全局变量,看他们缺不缺。
如果缺,那么就回到模型里面,找到这些输出,也就是之前的信号输出的箭头线,和箭头线下面的名字。然后对箭头线点右键--属性--“信号名称必须解析为simulink信号对象”(勾选后信号名前会有猫抓符号)来把他们逐个地强制关联上,让生成代码时候带上他们。 之后再点生成,代码就会带上他们。
c)实用工具文件,形如rtwtype.h
d)接口文件,形如 rtmodel.h
22.再次生成代码,进到数据文件的.c里面,看强制关联的变量是不是都在全局变量里面。他们都声明出来了后就好办了,只需要底层代码对这些全局变量赋值就行了。
这种赋值行为就是实现应用层和底层的传递和交互
23.注意,生成出来的代码和直接建模的时候里面的模型里面的can标识位里面的数字,这些,数据格式会不一样,计算的时候会转成十进制
24.数据文件里面的.c文件,这里面都是全局变量的声明,它参与编译,但不参与主流程执行;真正的流程代码,是在模型文件的.c文件里面(这里面代码是不允许改的)。
25.模型建模界面上面蓝色部分,在仿真--调试--后面有个“建模”,点开,下面“模型设置”里面--“代码布局”里面,有个“数据定义”。有“在单独的源文件中定义的数据”,下面有个“数据定义文件名”,这里就是人为设置把生成的全局变量统一放在哪个文件里面,这里是放在global_MCU_CAN_TX.c和.h里面。这是为了方便检查,模仿实际项目中的代码规范,提高效率。
26.模型部分,人为设计不合理的地方,matlab在生成代码的时候,会自动给你优化掉
27.实际工作中,主要任务就是改模型,不会去改代码。改完后替换,编译,烧录即可
28.在低耦合高类聚系统中,如果两个独立系统需要用到共同的变量,只需要把这个变量的源头引用到不同的系统中即可了,即定义源头,再引用。如此可各个独立模块协同工作。
29.MCU AI模块,专门做模拟信号采集,可以把采集值转换成真实值。也就是看原理图数据手册,看原始信号对应的单位关系,然后转换。一旦都转成真实值了,就可以专心做算法即可了。
这个MCU AI模块,一般是硬件厂商搞得。
====================================================================================================================================
4 上位机接收怎么搞
1.菊花链上可以挂不同模块的东西,也可以走CAN
2. 高压电线盒不能太大,主板不能太小;如果从高压盒引出线,会导致信号衰减的问题,尤其是电流信号。所以目前很多项目会在高压盒里放板子来就地处理。
3. 补充: 被动均衡---芯片里面有个MOS管,直接通过它放电了;主动均衡---用电容/电感/或者DC/DC,来充电。一个放电一个充电。但是被动均衡因为要控制MOS管,所以被动均衡都是需要芯片硬件支持的;主动均衡则一般不靠芯片而是靠软件来实现了,因为需要额外做一个电路。但是主动均衡不但成本高了很多,而且稳定性差(尤其是DC/DC容易烧),因为多了很多电容电感,并且控制策略的复杂性降低了可靠性;并且主动均衡虽然电池不容易发热,但是把控制上的压力和不稳定性转到了板子上,很容易导致从板板子被烧。
电池本身电流和功率大的情况下,BMS被动均衡能起到的作用有限,如100AH的电池,只能用100mA来均衡,是杯水车薪。
4. 均衡算法,主要就是围绕开启和关闭来展开的。
上位机CAN接收怎么搞:
BMS主板一方面接受从板信息,一方面接受上位机(即PC)的信息,所以需要CAN1和CAN2 两个。
a)需要接受的CAN有两个,因此用两个dbc,不要放一块
b)因为是要搞两路CAN,那就是要两个模型+两个dbc
c)(补充)如果需要增加更高的父目录,在dbc建立的CANdb里面点network node,点new新建即可,也是在这里加上位机
d)具体的建模过程和之前一样
e)CAN接受需要在中断里面接受
关键在集成部分:
0):CAN_MSG是matlab自身定义的一种数据类型,从它里面生成的一些数据诸如CAN_MSG.ID ,CAN_MSG.Length等这些对象,我们要对他从外部进行赋值,来完成数据的一个传递和集成。
1):CAN_MSG在我们上层是最终的信号,携带数据。但是这个CAN_MSG的数据类型,是上层matlab里面的,底层是不知道这个数据类型的,所以我们需要在集成时候给他添加一个过程。 也就是把CAN_MSG下的这些length ,ID,extend这些值的赋值过程加进来。
怎么加?需要去到底层里面,MCU对应的发送/接受的主流程函数.c文件里,找到带step的主函数,
找到类似这样:
if((8==CAN_MSG.Length)&&(CAN_MSG.ID != INVALID_CAN_ID)) {
if(( 33 == CAN_MSG.ID)&&(0U== CAN_MSG.Extended)) {
{
/* ------START Unpacking signal 0------
* startBit = 6
*length =2
*desiredSignalByteLayout = BIGENDIAN
*dataType =UNSIGNED
*factor =1.0
*offset =0.0
*-------------------------------------------------*/
这里便是生成的代码里面,预留给你赋值往里填的。就是在这里集成。
我们需要把以上的都进行赋值,并且加上一个CAN_MSG.DATA[0,7],全部做好赋值即可。
(这个位置,在项目里,一般在Hal层的Callback函数里)
==========具体怎么找到在哪加呢?打开代码看定义=========
1): 先去看底层mcu生成的代码里的.c文件里面找global,找他里面的全局信号的定义。
我们知道CAN报文一句报文包含id,length,是否extend帧,以及8个数据。matlab里面,根据can报文的这个结构,专门搞了个结构体类型CAN_MESSAGE_BUS,它的里面的对象变量名就是CAN_MSG, CAN报文所包含的这些信息,都被放入了这个里面。这个结构体会在生成代码时候自动生成。
这个CAN_MESSAGE_BUS和CAN_MSG都被放入了上面说的底层MCU的.c里面的global全局变量里面,形如:
/* Definition for custom storage class: Global */
CAN_MESSAGE_BUS CAN_MSG; /* '<Root> /CAN_MSG' */
unit16_T VCU_SEND_ENABLE; /* '<S3> /CAN Unpack' */
unit8_T VCU_SEND_HEART; /* '<S3> /CAN Unpack' */
unit8_T VCU_SEND_MODE; /* '<S3>/CAN Unpack '*/
int16_T VCU_SEND_RPM_REF; /* '<S3>/CAN Unpack '*/
这里,我们先把CAN_MESSAGE_BUS CAN_MSG; 这里手动复制。
然后进到keil里面的底层代码里面,找到MCU的代码,找到它里面的hal层代码,进到里面,到它hal层里面的负责CAN接收的回调函数,这个回调函数就是中断函数,形如:
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
int i; //用循环记得这里补一个int i
if (hcan->Instance==CAN2)
{
HAL_CAN_GetRxMessage(hcan,CAN_FILTER_FiFO0,&CanRxMsg,RxData);
ReadID = CanRxMsg.StdId; //这里的ReadID就是CAN在递送数据,所以我们加在它后面
/*加在这里*/
CAN_MSG.ID = ReadID; //给ID,把底层读到的递送给CAN_MSG
for(i=0;i<8;i++) //用容器来接底层的8个数据
{
CAN_MSG.Data[i] = RxData[i]; //给数据,右边是底层的,左边是应用层的
}
CAN_MSG.length = CanRxMsg.DLC; //给长度
/*加在这里*/
MCU_CAN_RX_ISR_step();
}
CanRxMsg.StdId=0;
CanRxMsg.ExtId =0;
HAL_CAN_ActivateNotification(hcan,CAN_IT_RX_FIFO0_MSG_PENDING);
}
( 在此之前,别忘了先去这个文件里面的头部,找到声明的地方,在别的extern的地方,
extern CAN_MESSAGE_BUS CAN_MSG; 把它声明一下。这样一来相当于是引用了它这个应用层的变量结构体)
2):回到Hal层回调函数里面这个主函数:
HAL_CAN_GetRxMessage(hcan,CAN_FILTER_FIFO0,&CanRxMsg,RxData);
还需要找到里面的变量CanRxMsg,它的长度和定义,右击它,跳转到它的定义处
会跳到另一个.h里面的头部定义的 CAN_RxHeaderTypeDef CanRXMsg;右击再跳会看到它是一个结构体对象,它上面的结构体里面封装了
unit32_t DLC //Specifies the length of the frame that will be transmitted
那么这个就是它的长度。把这个长度赋值给应用层的CAN的length即可:
CAN_MSG.Length = CanRxMsg.DLC;
3): (补充)
a. 上面这段函数,后面的那些赋0,是进出中断的时候,清中断的流程
b. 项目里的中断函数一般会给你指定一个中断函数名,底层往里填即可
c. 前面追函数时候提到的 CAN_RxHeaderTypeDef CanRxMsg,说明CanRxMsg是按照CAN_RxHeaderTypeDef自己定义的,底层的hal库一般会给出一个类型要求,我们按照它这个要求定义即可。
CubeMax本身会生成所有的底层代码,但是中断则需要自己手写,因为中断里要做什么只有自己知道。
代码集成:
1.生成和仿真一般搞两个模型,把第一个copy一下即可
2.如果模型是结构体,那么它模型是两个圈
如何着手生成代码的集成:
1)对于每个模型,只需关系两个函数即可: 初始化+ step主函数
2)初始化函数:上电只执行一次
step函数: 放到主循环里,根据底层给的时钟周期定时执行
怎么做:
假如一个项目有多个模型组成,A,B,C,D四个
1.先找到main函数(这个一般是手写代码),因为单片机执行时候会自动跑到main函数开始的地方
main函数里面分两部分: 前面是初始化部分,后面是主任务的动作for循环部分
2.找到A ,B,C,D四个模块,
把他们的初始化函数都放入main里面的初始化部分
把他们的step部分函数放入main的主循环部分
这样就完成了集成目标。
但是也需要对他们进行调试和分配,比如哪个模块执行多久时间片
同时也要对他们的中断进行配置。
但是这些配置和分配都是围绕前面两个放入进行的。
3.中断函数不能放入主循环,放入应用层中断某某(app)_step里面,它可以是CAN_RX,也可以是ADC_ISR,这些都可以中断
4.集成过程的架构流程大致如:
a) ABCDE五个模块。其中ABCD四个是主功能模型,他们是定时执行的;E是中断模型,不是定时的
b)main函数里面,最先开始先跑CPU即底层初始化;
紧接着就是A,B,C,D,的初始化;
再紧接着就是写一个for(;;)死循环,里面写入ABCD的step循环步骤(加时间调度);
然后出main函数
c)在main函数外面,写E模块的中断函数,如果中断是CAN_ISR,就在CAN_ISR里面放入E的中断模块,
如果是ADC_ISR也一样,把E中断模块函数放进去。(这个E里面是中断具体的内容动作)
-----------------------------------------------------BMS上下电-----------------------
一个经典的BMS高压部分一般包括 直流充电桩/高压附件PTC(热空调) /AC空调/DCDC变压器/逆变器
,后面四个除了直流充电桩都是高压的负载。
1.上下电的控制,有的厂家用BMS控制,有的用VCU整车控制器控制
2.插枪后的工作流程见 第四期第七课34:30秒
总结下就是: 高压区连了很多高压负载,那么:
上电时,需要预充
下电时,a)车速要降下来,电流要降下来 b)电机/PTC/空调不能使能,静止掉 c)最后要放电
(补充:放掉电容里的电,尤其是电机控制系统里的大电容)
d)主动放电完后,可以真正下电,发送shutdown信号给负载控制器
------------------------上下电依照流程表建模实践部分------------------------------------
1.单片机运行的时候,一般是让它以定时调度的系统运行的,不是一直运行的,是运行一会会停一会,即工作时间最好是小于50%,这有个波长。matlab仿真也是一样可以设置波长,这个可以在matlab里设置 ,在“建模”--“模型设置”--“求解器”--“固定步长”,一般设置为固定步长,离散。采样时间自己看情况,如果有几个标准,就选最小的那个
2.根据流程图,确定哪些是输入哪些是输出,都有哪些信号 ,把这些都抽象出来。
3.stateflow和simulink怎么用,什么时候用什么?
如果次数多,相互转换频繁,需要来回切换,比如VCU里的驾驶前进,后退--->用stateflow
每次都要重新计算,或者一次性的,往复比较少的 --->用simulink
在simulink里面,一般可以用merge模块来避免状态的切换。
4.如果在模型里需要多个地方引用它的,则从它里面连一根goto出来,方便之后
5.建模默认1为有效位,0为无效
6.拖模块的时候,输出数据类型选择那里永远不能用internal rule,这个只仿真时候允许用 ,因为如果是常值的话,单片机上可能跑不了。要么继承inherit via back propagation,要么指定数据类型single 等
7.搭建模型时候,先考虑正常情况,再考虑非正常情况
8.流程部分,要搞清楚各个信号直接的依赖关系,谁是谁控制,谁给谁信号
9.(补充)看门狗代码本质就是在循环任务第一行调用clear WDT()清零看门狗喂狗;并且在进入循环任务前把看门狗时间赋值和打开看门狗 WDR time=50ms, WDR=1
看门狗硬件芯片一般四个引脚,2个是正和地,一个输入输出,输入WDI接MCU的GPIO,输出WDO接MCU的RESET
具体看操作视频,没什么好讲的,看模仿实践
----------------------------绝缘监测建模操作-------------------------------------
1.目前主要是注入法和电桥法,绝大部分电桥法用的多。注入采样精度受Y电容影响,并且只能注入总负(总负到低压地)
2.电桥法的优点:总正和总负对低压地都可以测量;精度和成本都有优势
大致流程:
1.先闭合总正总负的开关S1 ,S2,来建立平衡电桥。
2.读取两个采样电阻电压Vp Vn,来看两个绝缘电阻谁大谁小,谁电压高谁的电阻就高。谁的高,就闭合掉那一侧的开关S,因为它没问题。这样闭合就建立了不平衡电桥
具体后面的见视频,第四期第9课
我们的方法:运用累加器实现状态保存,代替statflow10:00分钟
之后都是演示建模实践过程
-----------------------充电算法建模---------------------------------------------------
1.目前充电算法没有一个常用统一的,目前最经典的是三段式的,这是老的:
锂电池特性:小电流充的时候,总容量会升高 ;大电流充的时候,总容量会降低。(见3:20秒图表)
所以快充和慢充是两种不同算法,这里我们说的是慢充。(也就是充电电流倍率1.0C以下的,充电电流十几,几十安培,3.3或6.6KW ;快充则是可100A,30KW或是几十上百KW的)
充电倍率1.0C以上的就是快充:
三段式:先是恒流恒压充电:刚开始电压低时候控制着电流,使用恒流充;电压起来后,进入恒压充电;最后阶段是涓流充电,慢慢补满
为了更加精确,现在更多是多段式,也就是随着时间推移电流阶梯性越来越小,电压总体不变,见6:08秒处图表。
为什么会多段式?因为充电电流和温度是强相关关系;跟SOC也相关;和MIN和MAX的单体电压,还和绝缘阻抗和压差也有关。
为什么和单体min和max有关呢?比如一个单体被充到了3.4V,那算过充了,此时必须停了。因为过充会鼓包。 同样的如果一个电池电压太低了,那么它也不能充太快,最好办法是单独拿出来充(电池组里差异如果到0.5V就算是非常大了,尽量不要充,直接把坏的单体取出来)。
这里需要掌握的是影响充的几个要素:
1-温度
2-SOC
3-单体最高最低
4-绝缘阻抗 :太低不能参加充电
5-压差:最高单体电压-最低单体电压
6-温差:最高单体温度-最低单体温度
最终我们想达到的理想状态就是每节电池 电压和温度都一样。
建模之前,列一个表格,把这些因素都考虑进去。然后把这6个因素,每个作为一个系数输出比如k1,k2
最后高一个总系数比如说是COFF,让它等于k1 ,k2 等等全部一起的乘积。
这样一来的话,只要有一个降低,其他都会降低,有两个降低,其他也是降低更多
接着我们根据根据多段式的工作过程,对应调整这些系数。
关于SOC和充电电流倍率关系,见12:59表。1 C充电倍率就是加入电池100AH, 1C就是100A, 0.1C就是10A充电电流。
关于多段式不同阶段对应的策略,14:35秒表格
注意: 1.输入超出表的范围时候,取边界值。(点击模块,在模块参数里设)
2.假设A,B模型都需要查表,但是在模块设置里面,如果二者的算法部分都一样的话,则会造成二者生成代码的时候生成同一个函数,会产生编译报错;
所以,如果多个模型都用查表,尽量规避每个模型都使用同一种方法的情况。
牢记:
a)同一个查表模型,可以用同一种算法
b)不同模型,查表算法要尽量不同。否则无法集成编译 (不影响仿真)
ps:不同的查表算法,只影响查表结果的快慢,但是结果都是一样的;
如果太多,则去控制模型数量。
3.Matlab里面,所有输入输出,加减乘除,尽量保持数据类型一致。无符号和无符号,整数和整数,小数和小数,如果不一样,就加一个数据类型转换。
a)首先,整型里面分为8 ,16 ,32位,一般不考虑64位,对应的255 ,65535 ,42E ,对应[-128~127],
[-32768~32768] ,[-21E~21E]
所以选择数据类型的时候,要心理清楚它的物理意义是多少,再按上面去选择。
bool类型也是整型一种,只有0和1,但是编译器里面经常报错,尽量转成整型8位即可。特别是logic模块里面,比如位操作,与和非,很多输入输出都是bool,一定要转换成int8型。不转必报错
b)再者,小数部分, 分定点fixdt 和浮点。
定点如 (1,32,16) , 1代表有符号的,共占了32个bit,其中小数部分占了16位,定点现在随着单片机越来越便宜基本不用。
浮点,基本都选single。single代表了10的38次方左右,足够。
c)数据类型永远不要选internal rule,实在不知道数据类型选back即可。
d)用数组的时候,一定要记得输入和输出的维数要统一,输入是5维数组,输出也得是5维数组。
e)表格里输入的数组写的时候单向递增写,不要递减,也不要一会增一会减。形如in1_tab=[2000;2100;2700;3500;3650]; 输出不可能规定递增,不需考虑。
stateflow相对于simulink好处是,它可以保存状态,如果用simulink,则每次都要计算。所以simulink只能做简单的状态,状态不能太多,适合不太关心历史状态的情况。simulink最大缺点就是历史状态不好保存。
比方说 A模块里 a=3,b=2, B模块里面 a=k ,b=m。simulink里面如果从A跳到了B,那么A里面的a=3 ,b=2就释放了,因为simulink是一个线性的逻辑;如果是用的stateflow的话,从A跳到B后这个A里面的a=3 ,b=2不会被释放,等再从B跳回A状态的时候,a=3 ,b=2还在那里。stateflow是一个针对状态的形式。
--------------第四期第11 充电建模 具体操作演示部分---------------------------------
1.先根据流程表,把设计分为3个大部分。其中,中间的部分,因为20,30,40,50是均匀的,我们可以用查表。 其中2.5V一部分;充电准备一部分,但我们不清楚它的输入变量哪里来,我们先设置一个名为充电准备ok情况,然后输出肯定就是充电电流; 还有一个输入就是SOC。总结一下就是以上3个输入,和一个输出,即充电电流。
2.简单来说就是要抽象出输入输出是什么。
具体见演示
---------------12 SOC仿真测试-------------------------------------------------------------------
今天来新班子,讲解拿到新板子,新项目如何着手。
1.先打开keil,在Project--CAN--下面会看到hal库里面的文件,这里是在HalLib文件夹下,文件名都是stm32h7xxx_hal_xxx.c,这些都是hal库里的文件。这,就是底层。
2.从hal库文件这里向上拉,在它的上面,同一个目录下,看到有个user文件夹,下面有个main.c,进去里面,找到主循环。
3.我们需要做的是新建一个文件夹,叫app,把matlab生成的代码放入app文件夹,在回到main里面调度它就行了。
回到今天主体:SOC验证。
1.怎么验证SOC:
首先要明白soc常用的工况是哪些?
1)放电:电量足时如何放;电量低时如何放
2)充电:充电桩时,包括快充和慢充,包括电量低和电量足情况;能量回收时,包括电量低和电量足情况
(补充:汽车电机本身有两种模式,一种是电动做功模式;一种是发电模式)
3)温度
4)大电流和小电流充电:大电流时候总容量减小,小电流时候总容量增高
5)电压:电压低的时候会自动复位(复位来尝试恢复BMS功能)
2.需要特定的工况,并且可以手动微调,可以用signal builder模块
3.如果发现仿真有误差,回去检查相应的输入输出数据类型,比如定点模式fixdt没有浮点模式single精准,所以就会造成误差。
如果改完后发现类型不匹配,就加个转换convert模块即可。
剩下全是建模过程演示
--------------------------------13均衡建模怎么建-----------------------------------------
1.扭矩和车速的方向不一致,就是回收,也就是负扭矩。MCU需要VCU给扭矩信号才能开启回收。
2.回收时候的信号和充电桩充电时候给的信号是一样吗?不一样,充电都是要充电侧电压高于电池这点不变,但是回收时候电压也就十几二十安培,充电桩充至少有个100安培
3.回收时候的负扭矩,和回收时候的充电安倍的关系几乎是恒定的,并且是由VCU设计决定的,和BMS没关系。BMS侧只负责积分即可,即根据回收充电电流,积分计算出回收了多少电。
4. 行驶里程和能耗是反向积分关系。电量太高高于90%一般不开启回收,会充爆。
5.在BMS里,只要保障电流有正负,电压 恒为正即可。即积分/回收发电时候,电流是正,放电时候为负,即可。
6.MCU控制充放电,BMS只对接在高压电池上的电流电压做积分。(MCU和DC/DC,冷热空调一样,是BMS上的一个负载,但是只有MCU或充电机可以做充电,其余都是耗电的。MCU回去采集接在高压电池上的电流电压信号来计算出正负总功率)
7.动能回收充电和前面充电桩充电区别就是把前面充电桩充电的拉高拉低(跳变)部分去掉就可以,其他都一样。