5791|12

32

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

Simulink与ModelSim联合仿真实现BLDC六步方波闭环控制系统 [复制链接]

 
本帖最后由 瓜弟 于 2020-2-13 17:50 编辑

    在某些场合下,使用的核心处理器不含电机控制相关外设,同时又对系统的实时性有较高要求,我们可以使用FPGA来实现这部分外设功能,如PWM生成、ADC输出采集与简单处理、电场角度判断等。本贴介绍利用Simulink与ModelSim联合仿真,实现BLDC六步方波闭环控制系统的仿真。


    本仿真使用的软件如下:

            MatLab 2018a;

            ModelSim SE-64 10.04 (不同版本的Matlab对于ModelSim版本有具体要求)

Matlab与ModelSim的联合仿真配置过程可参考https://blog.csdn.net/u012151773/article/details/43833287 本文不再重述。


图1 电源、逆变桥、电机

图2 闭环控制环路

图3 转子转速、转子转角、电磁转矩

    在图2中,左侧的speed_loop模块利用PI实现对电机转速的闭环控制,由图可见,目标转速为2000RPM。图2中间的BLDC_Controller实现六步换向的方波生成(非PWM),由于BLDC电机正反转逻辑不同,故在模块speed_loop与模块BLDC_Controller之间进行了目标转矩的方向判断。图2右边的ModelSim模块实现了PWM生成,该PWM生成后直接送入图1中的三项逆变桥中。

    电流的闭环控制的计算比较简单,代码如下:

float speed_loop(float CurrentSpeed, float TargetSpeed)
{
	par_SpeedLoopPID.Goal = TargetSpeed;
	pid_calculate(&par_SpeedLoopPID, TargetSpeed - CurrentSpeed);
	return (par_SpeedLoopPID.Output)/100;
}

    其中,函数pid_calculate()与PID参数结构体如下

typedef struct PID_data_Struct
{
	float Kp;
	float Ki;
	float Kd;
	float Integral;
	float Difference;
	
	float IntegralHighLimit;
	
	float Goal;
	float Err;
	float LastErr;
	float Output;
} pid_data;
//////////////////////////////////////////////////////////////////////////////
void pid_calculate(pid_data * PidDat, float ErrDat)
{
	PidDat->LastErr = PidDat->Err;
	PidDat->Err = ErrDat;
	PidDat->Difference = PidDat->Err - PidDat->LastErr;
	PidDat->Integral = PidDat->Integral + PidDat->Err;
	PidDat->Integral = (PidDat->Integral > PidDat->IntegralHighLimit)? 
						PidDat->IntegralHighLimit : PidDat->Integral;
	PidDat->Integral = (PidDat->Integral < (-(PidDat->IntegralHighLimit)))? 
						(-(PidDat->IntegralHighLimit)) : PidDat->Integral;
	
	PidDat->Output =  PidDat->Kp * PidDat->Err
					+ PidDat->Ki * PidDat->Integral
					+ PidDat->Kd * PidDat->Difference;
}

    模块BLDC_Controller中的六步换向序列生成的代码如下

void PWM_generator(int Angle, float Duty, unsigned char Direction, 
				   char *A_duty, char *B_duty, char *C_duty)
{
	Angle = Angle % 360;
	if(Angle < 0)
		Angle = Angle + 360;
	if((Angle >= 330)||(Angle < 30))
	{
		if(Direction == ROTATION_DIRECTION_FORWARD)
		{
			*A_duty = 0;
			*B_duty = 100 * Duty;
			*C_duty = -1;
		}
		else
		{
			*A_duty = 0;
			*B_duty = -1;
			*C_duty = 100 * Duty;
		}
	}
	else if((Angle >= 30) && (Angle <90))
	{
		if(Direction == ROTATION_DIRECTION_FORWARD)
		{
			*A_duty = -1;
			*B_duty = 100 * Duty;
			*C_duty = 0;
		}
		else
		{
			*A_duty = 100 * Duty;
			*B_duty = -1;
			*C_duty = 0;
		}
	}
	else if((Angle >= 90) && (Angle <150))
	{
		if(Direction == ROTATION_DIRECTION_FORWARD)
		{
			*A_duty = -1;
			*B_duty = 0;
			*C_duty = 100 * Duty;
		}
		else
		{
			*A_duty = 100 * Duty;
			*B_duty = 0;
			*C_duty = -1;
		}
	}
	else if((Angle >= 150) && (Angle <210))
	{
		if(Direction == ROTATION_DIRECTION_FORWARD)
		{
			*A_duty = 0;
			*B_duty = -1;
			*C_duty = 100 * Duty;
		}
		else
		{
			*A_duty = 0;
			*B_duty = 100 * Duty;
			*C_duty = -1;
		}
	}
	else if((Angle >= 210) && (Angle <270))
	{
		if(Direction == ROTATION_DIRECTION_FORWARD)
		{
			*A_duty = 100 * Duty;
			*B_duty = -1;
			*C_duty = 0;
		}
		else
		{
			*A_duty = -1;
			*B_duty = 100 * Duty;
			*C_duty = 0;
		}
	}
	else if((Angle >= 270) && (Angle <330))
	{
		if(Direction == ROTATION_DIRECTION_FORWARD)
		{
			*A_duty = 100 * Duty;
			*B_duty = 0;
			*C_duty = -1;
		}
		else
		{
			*A_duty = -1;
			*B_duty = 0;
			*C_duty = 100 * Duty;
		}
	}
}

    使用Verilog实现PWM生成的代码如下(懒得写死区控制)

`timescale 100ns/100ns
//PWM基波 20KHz
module six_step_PWM_generator 
	(
		input wire[7:0] A_duty,
		input wire[7:0] B_duty,
		input wire[7:0] C_duty,
		input wire RSTn,
		input wire CLK_4MHz,
		
		output wire At,
		output wire Ab,
		output wire Bt,
		output wire Bb,
		output wire Ct,
		output wire Cb
	); 
parameter DeadZoneTime = 4; //4*250ns = 1us;
parameter PWM_CounterMax = 99;

	reg[7:0] A_reg;
	reg[7:0] B_reg;
	reg[7:0] C_reg;
	
	reg At_reg;
	reg Ab_reg;
	reg Bt_reg;
	reg Bb_reg;
	reg Ct_reg;
	reg Cb_reg;
	
	reg[7:0] PWM_Counter;
	reg PWM_Counter_UpDown;	//1: up; 0: down
	always @(posedge CLK_4MHz)
	begin
		if(PWM_Counter_UpDown)
		begin
			PWM_Counter = PWM_Counter + 8'h01;
			if(PWM_Counter >= 8'd99)
			begin
				PWM_Counter_UpDown = 1'b0;
			end
		end
		else	
		begin
			PWM_Counter = PWM_Counter - 8'h01;
			if(PWM_Counter == 8'h00)
			begin
				PWM_Counter_UpDown = 1'b1;
			end
		end
	end
	
	initial
	begin
		A_reg = 8'h00;
		B_reg = 8'h00;
		C_reg = 8'h00;
		At_reg = 1'b0;
		Ab_reg = 1'b0;
		Bt_reg = 1'b0;
		Bb_reg = 1'b0;
		Ct_reg = 1'b0;
		Cb_reg = 1'b0;
		PWM_Counter = 7'h00;
		PWM_Counter_UpDown = 1'b1;
	end
	
	always @ (negedge RSTn)
	begin
		A_reg = 8'h00;
		B_reg = 8'h00;
		C_reg = 8'h00;
		At_reg = 1'b0;
		Ab_reg = 1'b0;
		Bt_reg = 1'b0;
		Bb_reg = 1'b0;
		Ct_reg = 1'b0;
		Cb_reg = 1'b0;
		PWM_Counter = 7'h00;
		PWM_Counter_UpDown = 1'b1;
	end
	
	assign At = At_reg;
	assign Ab = Ab_reg;
	assign Bt = Bt_reg;
	assign Bb = Bb_reg;
	assign Ct = Ct_reg;
	assign Cb = Cb_reg;
	
	always #1
	begin
		if(A_duty == 0)
		begin
			At_reg = 1'b0;
			Ab_reg = 1'b0;
		end
		else if(A_duty == 8'hFF)
		begin
			At_reg = 1'b0;
			Ab_reg = 1'b1;
		end
		else
		begin
			Ab_reg = 1'b0;
			if(PWM_Counter < A_duty)
				At_reg = 1'b1;
			else
				At_reg = 1'b0;
		end
		
		
		if(B_duty == 0)
		begin
			Bt_reg = 1'b0;
			Bb_reg = 1'b0;
		end
		else if(B_duty == 8'hFF)
		begin
			Bt_reg = 1'b0;
			Bb_reg = 1'b1;
		end
		else
		begin
			Bb_reg = 1'b0;
			if(PWM_Counter < B_duty)
				Bt_reg = 1'b1;
			else
				Bt_reg = 1'b0;
		end
		
		
		if(C_duty == 0)
		begin
			Ct_reg = 1'b0;
			Cb_reg = 1'b0;
		end
		else if(C_duty == 8'hFF)
		begin
			Ct_reg = 1'b0;
			Cb_reg = 1'b1;
		end
		else
		begin
			Cb_reg = 1'b0;
			if(PWM_Counter < C_duty)
				Ct_reg = 1'b1;
			else
				Ct_reg = 1'b0;
		end
		
		
	end
	
endmodule

    通过上述代码,实现了BLDC电机的闭环控制。其中隐藏的问题,望各位指正!
此内容由EEWORLD论坛网友瓜弟原创,如需转载或用于商业用途需征得作者同意并注明出处

BLDC.zip

1.84 MB, 下载次数: 76

Simulink、ModelSim、BLDC

最新回复

内容很不错,精品   详情 回复 发表于 2022-5-23 19:53

赞赏

1

查看全部赞赏

点赞(1) 关注(5)
 
 

回复
举报

7452

帖子

2

TA的资源

五彩晶圆(高级)

沙发
 

问题是转起来了吗?来个动图。

点评

仿真呀,咋转呢?你是指实物?  详情 回复 发表于 2020-2-14 00:36
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 
 

回复

7452

帖子

2

TA的资源

五彩晶圆(高级)

板凳
 

麻痹,仿真,,,应该也能仿真转圈吧

点评

第三张图的第二行,就是转子的转动角度随时间变化的呀,0~360°  详情 回复 发表于 2020-2-14 16:42
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 
 

回复

32

帖子

1

TA的资源

一粒金砂(中级)

4
 
freebsder 发表于 2020-2-13 21:10 问题是转起来了吗?来个动图。

仿真呀,咋转呢?你是指实物?

 
 
 

回复

32

帖子

1

TA的资源

一粒金砂(中级)

5
 
freebsder 发表于 2020-2-13 21:11 麻痹,仿真,,,应该也能仿真转圈吧

第三张图的第二行,就是转子的转动角度随时间变化的呀,0~360°

 
 
 

回复

5979

帖子

8

TA的资源

版主

6
 

棒棒的!我来学习一下 

个人签名生活就是油盐酱醋再加一点糖,快活就是一天到晚乐呵呵的忙
===================================
做一个简单的人,踏实而务实,不沉溺幻想,不庸人自扰
 
 
 

回复

32

帖子

1

TA的资源

一粒金砂(中级)

7
 
chenzhufly 发表于 2020-2-14 21:28 棒棒的!我来学习一下 

柱哥帮我看下,Verilog代码里,At_reg这个寄存器同时在两个always里赋值,为啥编译没报错?

点评

组合逻辑,算是正常使用  详情 回复 发表于 2020-2-18 15:27
 
 
 

回复

7452

帖子

2

TA的资源

五彩晶圆(高级)

8
 

应该为瓜弟本篇受精。

个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 
 

回复

32

帖子

1

TA的资源

一粒金砂(中级)

9
 
 
 

回复

351

帖子

3

TA的资源

纯净的硅(初级)

10
 

不错,真的很干。。。。。

 
 
 

回复

1204

帖子

1

TA的资源

纯净的硅(初级)

11
 
瓜弟 发表于 2020-2-15 02:29 柱哥帮我看下,Verilog代码里,At_reg这个寄存器同时在两个always里赋值,为啥编译没报错?

组合逻辑,算是正常使用

 
 
 

回复

57

帖子

0

TA的资源

一粒金砂(中级)

12
 

很不错,谢谢!!!

个人签名坚持坚持再坚持。
 
 
 

回复

6

帖子

2

TA的资源

一粒金砂(初级)

13
 

内容很不错,精品

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表