无刷直流电机控制----霍尔信号篇
0赞
发表于 7/30/2012 10:24:22 AM
阅读(20580)
无刷电机相比有刷电机的最大区别就是用电子开关替代了内部的电刷。电刷所带来的是易损坏,难维修,还有内部碳粉沉积多之后给电机带来的堵转等一系列问题。曾经拆过很多损坏的有刷电机,80%以上的损坏原因是内部电刷断了。这也是我萌生这次这个方案的主要原因之一。任何事物都是有利有弊的。外围电路的简单和方便实用带来的是软件处理的复杂度。这就是电子开关带来的软件设计。同比无传感器换相也是增加了软件复杂度。
霍尔信号的电子传感器是依靠电磁感应原理利用霍尔元件的集成电路完成电子定子或者转子的测位的。
霍尔信号根据在电机安装位置的不同,有2种不同的时序图,分别是60度和120度。这个要根据电机的厂家提供的资料。
我这次选型的电机是60度。
时序图如下:

s1-s6分别对应6个状态,每一个状态的电气角度是60度。
霍尔信号在这里不仅要用来换向。还要用测速,提高电机控制系统的测速反馈。
先来说换向。s1-s6代表6个状态,每个状态对应6个开关管的开启和关闭。

上图为6个状态对应霍尔信号逻辑电平和对应6个开关管的开关逻辑状态。
软件部分这里很好处理,简单的状态机就可以实现了。
但是,不要忘记我们的集成模块是dvr8312,它的控制接口为pwm_a pwm_b,pwm_c rst_a,rst_b,rst_c,并不是对应6个开关管。

这是dvr8312手册上给出的用常规6个开关管信号的逻辑图。我们就按手册的来。
程序如下:
`timescale 1ns / 1ps
module PWM_ctrl(clk,rst_n,
pwm_ah,pwm_bh,pwm_ch,
rst_an,rst_bn,rst_cn,
hall_a,hall_b,hall_c
);
input clk;
input rst_n;
input hall_a; //三相霍尔信号
input hall_b;
input hall_c;
output pwm_ah; //a相输出
output pwm_bh; //b相输出
output pwm_ch; //c相输出
output rst_an; //rst_a输出
output rst_bn; //rst_b输出
output rst_cn; //rst_c输出
//---------------------------------------------------------------------
//霍尔换相 分为6状态 每状态只有2相通电
// s1 s2 s3 s4 s5 s6
//hall_a 1 1 1 0 0 0
//hall_b 0 0 1 1 1 0
//hall_c 1 0 0 0 1 1
//pwm_ah 1 1 0 0 0 0
//pwm_al 0 0 0 1 1 0
//pwm_bh 0 0 1 1 0 0
//pwm_bl 1 0 0 0 0 1
//pwm_ch 0 0 0 0 1 1
//pwm_cl 0 1 1 0 0 0
//----------------------------------------------------------------------
reg [2:0] hall1;
reg [2:0] hall2;
reg pwm_ahr;
reg pwm_bhr;
reg pwm_chr;
reg pwm_alr;
reg pwm_blr;
reg pwm_clr;
//reg [9:0] ctrl_reg;
reg pwm_reg;
reg [9:0] cnt;
parameter ctrl_reg = 200;
always@(posedge clk or negedge rst_n)
if(!rst_n)begin
pwm_reg <= 1'b0;
cnt <= 10'b0;
end
else begin
if(cnt <=ctrl_reg)
pwm_reg <= 1'b1;
else pwm_reg <= 1'b0;
end
always @(posedge clk or negedge rst_n)
if(!rst_n) cnt <= 10'b0;
else cnt <= cnt + 1'b1;
always @(posedge clk or negedge rst_n)
if(!rst_n)begin
hall1 <= 3'b0;
hall2 <= 3'b0;
end
else begin
hall1 <= {hall_a,hall_b,hall_c};
hall2 <= hall1;
end
//------------------------------------------------------------------------
always @(posedge clk or negedge rst_n)
if(!rst_n)begin
pwm_ahr <= 1'b0;
pwm_bhr <= 1'b0;
pwm_chr <= 1'b0;
pwm_alr <= 1'b0;
pwm_blr <= 1'b0;
pwm_clr <= 1'b0;
end
else begin
case(hall2)
3'b101:begin
pwm_ahr <= pwm_reg;
pwm_bhr <= 1'b0;
pwm_chr <= 1'b0;
pwm_alr <= 1'b0;
pwm_blr <= pwm_reg;
pwm_clr <= 1'b0;
end
3'b100:begin
pwm_ahr <= pwm_reg;
pwm_bhr <= 1'b0;
pwm_chr <= 1'b0;
pwm_alr <= 1'b0;
pwm_blr <= 1'b0;
pwm_clr <= pwm_reg;
end
3'b110:begin
pwm_ahr <= 1'b0;
pwm_bhr <= pwm_reg;
pwm_chr <= 1'b0;
pwm_alr <= 1'b0;
pwm_blr <= 1'b0;
pwm_clr <= pwm_reg;
end
3'b010:begin
pwm_ahr <= 1'b0;
pwm_bhr <= pwm_reg;
pwm_chr <= 1'b0;
pwm_alr <= pwm_reg;
pwm_blr <= 1'b0;
pwm_clr <= 1'b0;
end
3'b011:begin
pwm_ahr <= 1'b0;
pwm_bhr <= 1'b0;
pwm_chr <= pwm_reg;
pwm_alr <= pwm_reg;
pwm_blr <= 1'b0;
pwm_clr <= 1'b0;
end
3'b001:begin
pwm_ahr <= 1'b0;
pwm_bhr <= 1'b0;
pwm_chr <= pwm_reg;
pwm_alr <= 1'b0;
pwm_blr <= pwm_reg;
pwm_clr <= 1'b0;
end
default:;
endcase
end
assign rst_an = pwm_ahr | pwm_alr;
assign rst_bn = pwm_bhr | pwm_blr;
assign rst_cn = pwm_chr | pwm_clr;
assign pwm_ah = pwm_ahr;
assign pwm_bh = pwm_bhr;
assign pwm_ch = pwm_chr;
module PWM_ctrl(clk,rst_n,
pwm_ah,pwm_bh,pwm_ch,
rst_an,rst_bn,rst_cn,
hall_a,hall_b,hall_c
);
input clk;
input rst_n;
input hall_a; //三相霍尔信号
input hall_b;
input hall_c;
output pwm_ah; //a相输出
output pwm_bh; //b相输出
output pwm_ch; //c相输出
output rst_an; //rst_a输出
output rst_bn; //rst_b输出
output rst_cn; //rst_c输出
//---------------------------------------------------------------------
//霍尔换相 分为6状态 每状态只有2相通电
// s1 s2 s3 s4 s5 s6
//hall_a 1 1 1 0 0 0
//hall_b 0 0 1 1 1 0
//hall_c 1 0 0 0 1 1
//pwm_ah 1 1 0 0 0 0
//pwm_al 0 0 0 1 1 0
//pwm_bh 0 0 1 1 0 0
//pwm_bl 1 0 0 0 0 1
//pwm_ch 0 0 0 0 1 1
//pwm_cl 0 1 1 0 0 0
//----------------------------------------------------------------------
reg [2:0] hall1;
reg [2:0] hall2;
reg pwm_ahr;
reg pwm_bhr;
reg pwm_chr;
reg pwm_alr;
reg pwm_blr;
reg pwm_clr;
//reg [9:0] ctrl_reg;
reg pwm_reg;
reg [9:0] cnt;
parameter ctrl_reg = 200;
always@(posedge clk or negedge rst_n)
if(!rst_n)begin
pwm_reg <= 1'b0;
cnt <= 10'b0;
end
else begin
if(cnt <=ctrl_reg)
pwm_reg <= 1'b1;
else pwm_reg <= 1'b0;
end
always @(posedge clk or negedge rst_n)
if(!rst_n) cnt <= 10'b0;
else cnt <= cnt + 1'b1;
always @(posedge clk or negedge rst_n)
if(!rst_n)begin
hall1 <= 3'b0;
hall2 <= 3'b0;
end
else begin
hall1 <= {hall_a,hall_b,hall_c};
hall2 <= hall1;
end
//------------------------------------------------------------------------
always @(posedge clk or negedge rst_n)
if(!rst_n)begin
pwm_ahr <= 1'b0;
pwm_bhr <= 1'b0;
pwm_chr <= 1'b0;
pwm_alr <= 1'b0;
pwm_blr <= 1'b0;
pwm_clr <= 1'b0;
end
else begin
case(hall2)
3'b101:begin
pwm_ahr <= pwm_reg;
pwm_bhr <= 1'b0;
pwm_chr <= 1'b0;
pwm_alr <= 1'b0;
pwm_blr <= pwm_reg;
pwm_clr <= 1'b0;
end
3'b100:begin
pwm_ahr <= pwm_reg;
pwm_bhr <= 1'b0;
pwm_chr <= 1'b0;
pwm_alr <= 1'b0;
pwm_blr <= 1'b0;
pwm_clr <= pwm_reg;
end
3'b110:begin
pwm_ahr <= 1'b0;
pwm_bhr <= pwm_reg;
pwm_chr <= 1'b0;
pwm_alr <= 1'b0;
pwm_blr <= 1'b0;
pwm_clr <= pwm_reg;
end
3'b010:begin
pwm_ahr <= 1'b0;
pwm_bhr <= pwm_reg;
pwm_chr <= 1'b0;
pwm_alr <= pwm_reg;
pwm_blr <= 1'b0;
pwm_clr <= 1'b0;
end
3'b011:begin
pwm_ahr <= 1'b0;
pwm_bhr <= 1'b0;
pwm_chr <= pwm_reg;
pwm_alr <= pwm_reg;
pwm_blr <= 1'b0;
pwm_clr <= 1'b0;
end
3'b001:begin
pwm_ahr <= 1'b0;
pwm_bhr <= 1'b0;
pwm_chr <= pwm_reg;
pwm_alr <= 1'b0;
pwm_blr <= pwm_reg;
pwm_clr <= 1'b0;
end
default:;
endcase
end
assign rst_an = pwm_ahr | pwm_alr;
assign rst_bn = pwm_bhr | pwm_blr;
assign rst_cn = pwm_chr | pwm_clr;
assign pwm_ah = pwm_ahr;
assign pwm_bh = pwm_bhr;
assign pwm_ch = pwm_chr;
//-----------------------------------------------------------------------------
endmodule
endmodule
如果要换向的话,只需要改变状态切换顺序就可以。这里就不详细说了。
简要说明,软件思路,计数器计数,pwm_reg为经过控制算法处理后的控制量,和计数器进行比较,如果小于输出高电平,大于输出低电平。

占空比为50%时。可以明显看到每个换向状态只有2个管开,而且分别对应一上一下。
具体计数器的位数选择我会在以后的系统连接中作说明。
没有整个系统的联系这个位数是无法确定的。位数也同样决定了时钟频率。
