FPGA实现电机位置环、速度环双闭环PID控制

一、设计思路

主要设计思路就是根据之前写的一篇FPGA实现电机转速PID控制,前面已经实现了位置环的控制,思想就是通过电机编码器的当前位置值不断地修正PID去控制速度。

那为了更好的实现控制,可以在位置环后加上速度环,实现电机位置环、速度环双闭环PID控制。

位置环作为外环,通过编码器计数通过PID输出速度;位置环输出的速度作为目标速度输入速度环,与编码器测速的当前速度进行PID计算,从而完成电机的双PID控制。

​​

二、位置环控制

位置环的控制在前面已经实现,再次不再赘述。

三、速度环控制

速度环作为内环,目标值为位置环输出的速度,当前值为编码器测速的速度。

这里就有了一个问题,编码器怎么样才能测到电机速度?

这就和电机的最大频率有关,编码器通过AB相位的波形去进行计数和正反转的判断,那么就需要知道电机转一圈所输出的脉冲个数以及空载最大转速,通过这两个参数计算出编码器的电机最大频率,即每秒会有多少个脉冲。因此要对时钟进行分频,这是对50MHZ时钟分频成100HZ,即时钟周期10ms进行一次PID输出。

cpp 复制代码
always @(posedge clk or negedge reset_n) begin
   if (~reset_n) begin
      clk100 <= 1'b0;
      clk_counter <= 32'd0;
   end else if (clk_counter == 32'd249999)begin
      //分频系数M=时钟输入频率/时钟输出频率,偶分频计数器值N=M/2;奇分频计数器值N=M-1/2
      clk100 <= ~clk100;
      clk_counter <= 32'd0;
   end else begin
      clk_counter <= clk_counter + 1;
   end
end

速度环的PID计算同位置环一样

cpp 复制代码
always @(posedge clk100 or negedge reset_n) begin
   if (~reset_n) begin
      error      <= 0;
      integral   <= 0;
      prev_error <= 0;
      derivative <= 0;
      pidoutput  <= 0;
   end else begin

      //target位置环输出的速度,current当前编码器值
      error <= target - current;

      // 将累积误差控制合理范围内
      integral <= integral + error;
      if(integral >= $signed(32'd500)) begin
         integral <= $signed(32'd500);
      end else if(integral <= $signed(-32'd500M)) begin
         integral <= $signed(-32'd500);
      end else begin
         integral <= integral;
      end

      derivative <= error - prev_error;

      // 计算PID输出
      p <= error * kp;
      i <= integral * ki;
      d <= derivative * kd;
      pidoutput <= (p + i + d) / 1000;
      
   end
end

四、编码器测速

编码器模块也需要加入测速代码,有两种测速方法:一种是两次位置值相减,得出电机速度;另一种是编码器计数,得出电机速度。

这里用第二种编码器计数,在速度环中每10ms输出一次PID值,那么在测速模块就每10ms将速度编码器置零重新计数,因此可以根据速度环传入的清零信号clear进行清零,即clk100。当clk100状态发生变化时,clear信号为1,清零速度计数。

cpp 复制代码
always@(posedge clk or negedge reset_n) begin
	if(!reset_n) begin
		delay0 <= 1'b0;
		delay1 <= 1'b0;		
	end else begin
		delay0 <= clk100;
		delay1 <= delay0;
	end
end
assign clear  = (delay0 & (~delay1));

always @(posedge clk or negedge reset_n) begin
	if (~reset_n) begin
		counter <= 0;
	end
	else if (clear) begin
		counter <= 0;
	end 
	else if(pulse) begin
		if(direction) begin
			if(counter < $signed(32'h8000))
				counter <= counter + 1;
		end 
		else if(!direction) begin
			if(counter > $signed(-32'h8000))
				counter <= counter - 1;
		end 
		else begin
			counter <= 0;     
		end   
	end
end

五、整体结构

整体的RTL图如图所示。

相关推荐
星夜离尘563 小时前
UART 串口通信:从帧格式到收发回显(附完整 Verilog 实操)
fpga开发
单片机杂货铺6 小时前
基于单片机的智能粮仓控制系统设计与实现
stm32·单片机·嵌入式硬件·物联网·计算机外设·51单片机·课程设计
指尖的爷6 小时前
RKNN转化环境搭建(rknn_toolkit2新版本)
嵌入式硬件·深度学习·物联网·目标检测
梁朝辉6 小时前
滴泪的曲线(Curved)还是直线(Line)什么区别,都应用于什么场景!
嵌入式硬件·硬件工程
clear sky .8 小时前
stm32H7进入HardFault_Handler机制
stm32·单片机·嵌入式硬件
仲南音8 小时前
Xilinx FPGA—— DDR4读写
fpga开发
小僧景贤8 小时前
STM32 GPIO 详解(含寄存器、HAL 库、电气特性、低功耗深度剖析)
stm32·单片机·嵌入式硬件
远翔调光芯片^1382879887211 小时前
从参数到应用:FP7208如何以0.2V精密反馈提升LED驱动性能
科技·单片机·嵌入式硬件·智能家居·能源
碧海银沙音频科技研究院11 小时前
4 BES2710编译环境搭建方法
嵌入式硬件·算法
思尔芯S2C13 小时前
思尔芯RCF RTL自动分割工具,助力大规模AI/HPC芯片原型验证
人工智能·fpga开发·内存模型·自动编译·ddr5·prototyping·原型验证