步进电机sin曲线加速及FPGA实现

一、原理

(一)实现步骤:

确定加速参数:包括起始频率、最大频率、加速时间(或加速段步数)等。

生成正弦加速曲线:在加速过程中,我们期望频率按照正弦曲线从起始频率增加到最大频率。注意,这里我们通常使用正弦曲线的一半(0到π/2)或者一个完整的周期(0到π)来作为加速曲线,具体取决于需求。

使用FPGA生成步进电机脉冲:根据当前频率输出脉冲,同时按照一定的时间间隔更新频率值,使得频率遵循正弦加速曲线。

(二)具体实现:

假设我们使用0到π/2的正弦曲线来加速,那么频率的变化可以表示为:

f(t) = f0 + (f_max - f0) * sin(π/2 * t / T)

其中,f0是起始频率,f_max是最大频率,T是加速总时间,t是当前时间。

但是,在数字系统中,我们通常使用离散的时间点,因此我们可以将加速过程分为N个步骤,每个步骤的时间为Δt,那么第n个步骤的频率为:

f(n) = f0 + (f_max - f0) * sin(π/2 * n / N)

然而,步进电机的控制是通过脉冲周期(或频率)来控制的,所以我们实际上需要控制每个脉冲的周期。因此,我们可以将加速过程分为M个脉冲,每个脉冲的周期随着正弦曲线变化。

另一种方法是:我们并不每个脉冲都改变频率,而是将加速过程分为多个阶段,每个阶段内输出一定数量的脉冲,且每个阶段的频率按照正弦曲线变化。

但是,为了更精细的控制,我们可以每个脉冲都更新频率(即每个脉冲的周期都不同)。这样,我们需要一个实时计算正弦函数的能力,或者预先计算好正弦表(Sine Table)存储在FPGA的ROM中。

(三)步骤:

预先计算正弦表:将0到π/2的正弦函数离散化,存储在一个ROM中。例如,将0到π/2分为1024个点,计算每个点的正弦值。

确定加速过程中的频率变化范围:起始频率f0和最大频率f_max,以及加速过程的总步数(即脉冲数)M。

每个脉冲周期T(n) = 1 / f(n) = 1 / [ f0 + (f_max - f0) * sin(π/2 * n / M) ]

但是,由于我们使用正弦表,索引index = n * (表大小-1) / M,然后查表得到正弦值,再计算频率。

然而,在FPGA中,我们通常使用计数器来生成脉冲。具体来说,我们可以使用一个计数器,其计数上限由当前频率决定。例如,我们有一个基准时钟clk,频率为f_clk,那么生成脉冲的频率f_out = f_clk / (count_max)。因此,count_max = f_clk / (f_out)。

所以,我们需要根据当前频率f(n)计算count_max(n) = f_clk / (f(n))。

但是,由于f(n)是变化的,且我们使用正弦曲线,所以count_max(n) = f_clk / ( [f0 + (f_max - f0) * sin(π/2 * n / M)])

(四)实现结构:

状态机:控制加速、匀速、减速等状态。

脉冲生成:使用一个计数器,当计数达到count_max时,翻转脉冲信号,并重新加载计数器。同时,在每次脉冲后更新频率(即更新count_max值)。

频率更新:在加速状态下,每产生一个脉冲,就更新一次频率。我们使用一个相位累加器(或者步进计数器)n,从0到M-1,然后通过查表得到当前的正弦值,计算出当前的频率,再转换为count_max。

注意:由于正弦函数在0到π/2是单调递增的,所以加速过程是平滑的。

步骤:

在空闲状态,等待start信号。

进入加速状态后,每产生一个脉冲,step_counter加1,直到达到M。

每个脉冲后,根据step_counter计算当前在正弦表中的位置,查表得到正弦值,然后计算当前频率,再转换为count_max。

脉冲生成:pulse_counter从0计数到current_count_max,然后输出一个脉冲,并重置pulse_counter,同时更新频率(即更新current_count_max)。

注意:由于计算频率和count_max涉及除法和乘法,可能需要使用FPGA内的DSP资源,或者采用近似计算。

另一种简化方法:预先计算count_max表,存储在ROM中,这样就不需要实时计算。

这里我们采用实时计算,但为了简化,我们可以假设f0和f_max的值是固定的,并且M也是固定的,这样我们可以预先计算好count_max表,存储在ROM中。这样在加速过程中,我们只需要根据step_counter从ROM中读取count_max值即可。

考虑到灵活性,我们也可以使用实时计算,但这样会消耗较多的逻辑资源。

这里我们给出一个使用预计算ROM的方法:

步骤:

使用MATLAB或其他工具计算count_max表,并生成ROM初始化文件(.coe或.mif)。

在FPGA中实例化一个ROM,深度为M,宽度为count_max值的位宽。

在加速过程中,step_counter作为ROM的地址,读取count_max值。

这种方法的好处是节省了实时计算所需的逻辑资源,而且速度更快。

二、FPGA实现

verilog加速过程核心代码如下:

cpp 复制代码
always@(posedge clk)
begin
	if (rst) 
	begin
		state 		<= IDLE;
		cnt_prt		<= 0;
		romen		<= 0;
		romaddr		<= 14'd16383;
		addrswfg_up	<= 0;
	end
	else
	begin
		case(state)
			IDLE:
			begin
				if(work_en_po | addrswfg_up)
				begin
					state 		<= DELAY;
					cnt_prt		<= 0;
					romen		<= 1;
					romaddr		<= romaddr + speed_mult;
					addrswfg_up	<= 0;
				end
				else
				begin
					state 		<= IDLE;
					cnt_prt		<= 0;
					romen		<= 0;
					romaddr		<= 14'd16383;
					addrswfg_up	<= 0;
				end
			end			
			DELAY:
			begin
				if(cnt_prt == dly_value - 1)
				begin
					state 		<= CNT;
					cnt_prt		<= cnt_prt + 1;
					romen		<= 0;//////////////////////
					romaddr		<= romaddr;
					addrswfg_up	<= 0;
				end
				else
				begin
					state 		<= DELAY;
					cnt_prt		<= cnt_prt + 1;
					romen		<= 1;//////////////////////
					romaddr		<= romaddr;
					addrswfg_up	<= 0;
				end
			end
			CNT:
			begin
				if(cnt_prt == quoeitnt - 1)
				begin
					state 		<= IDLE;
					cnt_prt		<= 0;
					romen		<= 0;
					romaddr		<= romaddr;
					if(romaddr == 14'd16383)
					begin
						addrswfg_up	<= 0;
					end
					else
					begin
						addrswfg_up	<= 1;
					end
				end
				else
				begin
					state 		<= CNT;
					cnt_prt		<= cnt_prt + 1;
					romen		<= 0;
					romaddr		<= romaddr;
					addrswfg_up	<= 0;
				end
			end
			default:
			begin
				state 		<= IDLE;
				cnt_prt		<= 0;
				romen		<= 0;
				romaddr		<= 14'd16383;
				addrswfg_up	<= 0;
			end
		endcase
	end
end

三、实现效果

加速如下:

"加速---匀速---减速"如下:

四、注意

(一)减速

ROM地址反着读即可。

(二)除法器IP核

商的位宽和被除数的位宽一致,位于高位,余数的位宽和除数的位宽一致,位于低位。如下:

cpp 复制代码
div_gen_0 u_div_gen_0(
    .aclk 							( clk			),
    .s_axis_divisor_tvalid 			( div_vin		),
    .s_axis_divisor_tdata 			( divisor		),//16bit
    .s_axis_dividend_tvalid 		( div_vin		),
    .s_axis_dividend_tdata 			( dividend		),//32bit
    .m_axis_dout_tvalid 			( div_vout		),
    .m_axis_dout_tdata 				( div_out		) //48bit
  );
assign quoeitnt = div_out[47:16];
assign intrmd   = div_out[15:0];

(三)步进脉冲形式

(1)步进电机的每个步进脉冲需要两个边沿(上升沿和下降沿)来构成一个完整的方波周期。但是,在步进电机驱动中,我们通常只关心脉冲的上升沿(或者下降沿)来触发步进电机走一步。

(2)脉宽

1)典型脉冲宽度范围

最小脉冲宽度:通常 1-5μs(微秒)

常用脉冲宽度:2-10μs

最大脉冲宽度:一般不超过 50μs

2)具体驱动器要求示例

五、参考

FPGA驱动步进电机-Sin曲线加速

相关推荐
yrx0203071 天前
STM32F103通过L298N驱动两相4线步进电机【42步进电机】
stm32·单片机·嵌入式硬件·步进电机
硅农深芯1 天前
六大核心芯片:MCU/SOC/DSP/FPGA/NPU/GPU 的区别与应用解析
单片机·嵌入式硬件·fpga开发
9527华安1 天前
FPGA纯verilog实现JESD204B协议,基于AD9081数据接收,提供2套工程源码和技术支持
fpga开发·jesd204b·ad9081
FPGA技术实战1 天前
基于XADC IP核的FPGA芯片温度读取设计
网络协议·tcp/ip·fpga开发
丸子的蓝口袋1 天前
FPGA DONE信号震荡
fpga开发
CinzWS1 天前
基于Cortex-M3 SoC的eFuse模块--实现与验证考量
fpga开发·架构·efuse
jumu2021 天前
CEEMDAN - SE:神奇的信号处理组合
fpga开发
坏孩子的诺亚方舟1 天前
FPGA系统架构设计实践6_工程实现概述
fpga开发·xilinx·实现
FPGA小c鸡1 天前
Verilog核心语法速查:可综合写法、运算符陷阱与SV增强(附模板)
fpga开发
步达硬件1 天前
【FPGA】Verilog HDL编辑、RTL仿真、网表生成主流软件
fpga开发