当前位置:   article > 正文

练习一年半,菜鸟fpga工程师入职后的第一个小项目——伺服电机驱动脉冲采样计数_fpga驱动脉冲伺服

fpga驱动脉冲伺服

自学fpga,练习一年半,终于从一名车间操作工转行到fpga工程师。入职后领导鉴于我的技术水平(毕竟练习时长不到两年半),所以安排了他口中的小任务——电机信号采样并输出电机转速,任务不难,但还是慌了,下面是我的项目历程。

一、任务分析。

 电机的驱动脉冲是一对频率相同的周期性方波,这对周期性方波在相位上相差90度,根据A、B的相位情况判断转动方向,项目使用的电机速率是4000个脉冲一转。现在要输出当前电机的转速、方向,只需对A、B信号采样计数即可。

这样一个小项目,本来没啥可说的,只是一点涉及到抖动的过滤,实际上在信号传输中会产生很多噪声,这些都干扰了信号的采集,所以首先得对输入的信号滤波。

二、代码实现

首先对接收到的信号进行滤波,这里设置了一个阈值,即如果方波的带宽少于5us则视为杂波脉冲,就要将此杂波脉冲屏蔽,然后将滤波后的波形描绘出来。描绘出波形后,对此波形进行边沿计数(这里采取对上升沿计数),计数4000次。在开始对所描绘的波形上升沿计数的时候,同时开始对系统时钟的周期计数(系统时钟周期已知,这里按照开发板为20ns)。由获得4000个采样波形周期的总时间,确定电机的转动周期。

具体代码与注释如下:

  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 2021/07/17 17:11:41
  7. // Design Name:
  8. // Module Name: get_signal
  9. // Project Name:
  10. // Target Devices:
  11. // Tool Versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //
  21. module get_signal(
  22. input sys_clock,
  23. input rst_n,
  24. input signalA,
  25. input signalB
  26. );
  27. //参数定义
  28. parameter SYSCLK_TIME=20; //系统时钟的周期
  29. parameter DELAY_TIME=26'd25_000; //上电后延时一段时间
  30. parameter NUMBER_pluse=4000;
  31. //上电延时
  32. reg [25:0]cnt_delay=0;//延时计数器,
  33. always@(posedge sys_clock or negedge rst_n) begin
  34. if (!rst_n)
  35. cnt_delay<=0;
  36. else if (cnt_delay>= DELAY_TIME) //延时时间有待确认,这里设置成0.5ms,仿真时候可以简化
  37. cnt_delay<=cnt_delay;
  38. else
  39. cnt_delay<=cnt_delay+1;
  40. end
  41. //将两个信号打两拍寄存
  42. reg r0_signalA;
  43. reg r1_signalA;
  44. reg r1_signalB;
  45. reg r0_signalB;
  46. always@(posedge sys_clock )
  47. begin //思考:这时候打拍子,在复位时,寄存器需要清零吗
  48. r0_signalA<=signalA;
  49. r1_signalA<=r0_signalA;
  50. end
  51. always@(posedge sys_clock )
  52. begin
  53. r0_signalB<=signalB;
  54. r1_signalB<=r0_signalB;
  55. end
  56. //获得输入信号的上升沿(使用assign还是使用always块?根据testbench可以看出差别来)
  57. reg raise_A; //A上升沿
  58. reg raise_B; //B上升沿
  59. reg fall_A; //A下降沿
  60. reg fall_B; //B下降沿
  61. always@(posedge sys_clock or negedge rst_n) begin
  62. if (!rst_n)
  63. raise_A<=0;
  64. else if ({r1_signalA,r0_signalA}== 2'b01)
  65. raise_A<=1;
  66. else
  67. raise_A<=0;
  68. end
  69. always@(posedge sys_clock or negedge rst_n) begin
  70. if (!rst_n)
  71. raise_B<=0;
  72. else if ({r1_signalB,r0_signalB}== 2'b01)
  73. raise_B<=1;
  74. else
  75. raise_B<=0;
  76. end
  77. //获得两输入信号的下降沿
  78. always@(posedge sys_clock or negedge rst_n) begin
  79. if (!rst_n)
  80. fall_A<=0;
  81. else if ({r1_signalA,r0_signalA}== 2'b10)
  82. fall_A<=1;
  83. else
  84. fall_A<=0;
  85. end
  86. always@(posedge sys_clock or negedge rst_n) begin
  87. if (!rst_n)
  88. fall_B<=0;
  89. else if ({r1_signalB,r0_signalB}== 2'b10)
  90. fall_B<=1;
  91. else
  92. fall_B<=0;
  93. end
  94. /***************************** 第一步:先把滤波后的信号描绘出来*****************************/
  95. //signalA
  96. reg [15:0]cnt;
  97. always@(posedge sys_clock or negedge rst_n) begin
  98. if (!rst_n)
  99. cnt<=0;
  100. else if (cnt_delay>= DELAY_TIME) begin
  101. if (raise_A||fall_A)
  102. cnt<=0;
  103. else
  104. cnt<=cnt+1;
  105. end
  106. else
  107. cnt<=cnt;
  108. end
  109. reg signalA_sample;
  110. always@(posedge sys_clock or negedge rst_n) begin
  111. if (!rst_n)
  112. signalA_sample<=0;
  113. else if (cnt==250)
  114. signalA_sample<=signalA;
  115. else
  116. signalA_sample<=signalA_sample;
  117. end
  118. //signalB
  119. reg [15:0]cntB;
  120. always@(posedge sys_clock or negedge rst_n) begin
  121. if (!rst_n)
  122. cntB<=0;
  123. else if (cnt_delay>= DELAY_TIME) begin
  124. if (raise_B||fall_B)
  125. cntB<=0;
  126. else
  127. cntB<=cntB+1;
  128. end
  129. else
  130. cntB<=cntB;
  131. end
  132. reg signalB_sample;
  133. always@(posedge sys_clock or negedge rst_n) begin
  134. if (!rst_n)
  135. signalB_sample<=0;
  136. else if (cntB== 250)
  137. signalB_sample<=signalB;
  138. else
  139. signalB_sample<=signalB_sample;
  140. end
  141. /*************************然后对滤波得到的信号脉冲计数,4000次,并得到总的时间**********************/
  142. //signalA部分脉冲计数器
  143. reg [15:0]cnt_sample_pulseA=0 ;
  144. always@(posedge signalA_sample or negedge rst_n) begin
  145. if (!rst_n)
  146. cnt_sample_pulseA<=0;
  147. else if (cnt_sample_pulseA==NUMBER_pluse+1)
  148. cnt_sample_pulseA<=cnt_sample_pulseA;
  149. else
  150. cnt_sample_pulseA<=cnt_sample_pulseA+1;
  151. end
  152. //signalB部分脉冲计数器
  153. reg [15:0]cnt_sample_pulseB=0 ;
  154. always@(posedge signalB_sample or negedge rst_n) begin
  155. if (!rst_n)
  156. cnt_sample_pulseB<=0;
  157. else if (cnt_sample_pulseB==NUMBER_pluse+1)
  158. cnt_sample_pulseB<=cnt_sample_pulseB;
  159. else
  160. cnt_sample_pulseB<=cnt_sample_pulseB+1;
  161. end
  162. //触发计时计数器开始对系统时钟计时计数,直到出现4000个脉冲后不再计数,保持不变
  163. reg[39:0]Motor_time; //电机转动一圈的总时间
  164. reg[39:0]cnt1=0;
  165. always@(posedge sys_clock or negedge rst_n) begin
  166. if (!rst_n)begin
  167. cnt1<=0;
  168. Motor_time<=0;end
  169. else if(cnt_sample_pulseA)begin //第一个有效脉冲出现后开始计数
  170. if (cnt_sample_pulseA == NUMBER_pluse+1)begin //这里是PULSE_CNT 还是PULSE_CNT+1;
  171. cnt1<=cnt1;
  172. Motor_time<=(cnt1*SYSCLK_TIME);end //电机转动周期就是Motor_time乘以sys_clock的周期,乘法也可转化成移位(cnt1<<4+cnt1<<2)
  173. else begin
  174. cnt1<=cnt1+1;
  175. Motor_time<=0;end
  176. end
  177. else
  178. cnt1<=cnt1;
  179. end
  180. /**********************第三部分:比较两路信号的先后顺序*****************/
  181. //延时完成后立即计时,分别到A、B上升沿来时停止计时
  182. reg [20:0] cnt_Araise=0;
  183. reg [20:0] cnt_Braise=0;
  184. always@(posedge sys_clock or negedge rst_n)begin
  185. if (!rst_n)
  186. cnt_Araise<=0;
  187. else if (cnt_delay>=DELAY_TIME)begin
  188. if (cnt_sample_pulseA)
  189. cnt_Araise<=cnt_Araise;
  190. else
  191. cnt_Araise<=cnt_Araise+1;end
  192. else
  193. cnt_Araise<=0;
  194. end
  195. always@(posedge sys_clock or negedge rst_n)begin
  196. if (!rst_n)
  197. cnt_Braise<=0;
  198. else if (cnt_delay>=DELAY_TIME)begin
  199. if (cnt_sample_pulseB)
  200. cnt_Braise<=cnt_Braise;
  201. else
  202. cnt_Braise<=cnt_Braise+1;end
  203. else
  204. cnt_Braise<=0;
  205. end
  206. //最后比较信号信号顺序确定电机方向
  207. wire Motor_direction;
  208. assign Motor_direction=(cnt_sample_pulseA&cnt_sample_pulseB)?(!(cnt_Braise>cnt_Araise)):0; // 1代表正转,0代表反转
  209. //探针
  210. ila_0 your_instance_name (
  211. .clk(sys_clock), // input wire clk
  212. .probe0(signalA), // input wire [0:0] probe0
  213. .probe1(signalB), // input wire [0:0] probe1
  214. .probe2(Motor_direction), // input wire [0:0] probe2
  215. .probe3(Motor_time) // input wire [39:0] probe3
  216. );
  217. endmodule

三、仿真

(1)这里给出功能仿真所用到的testbench如下。

这里主要产生了系统时钟,以及两路有90度相位差的带有毛刺的方波信号。

  1. `timescale 1ns / 1ps
  2. module test_bench( );
  3. reg sys_clock;
  4. reg rst_n;
  5. reg signalA;
  6. reg signalB;
  7. get_signal get_signal(
  8. .sys_clock(sys_clock),
  9. .rst_n(rst_n),
  10. .signalA(signalA),
  11. .signalB(signalB)
  12. );
  13. initial sys_clock=0;
  14. always #10 sys_clock=~sys_clock; //产生50M的系统时钟信号
  15. initial signalA=0; //生成带毛刺噪声的10KHz信号
  16. always
  17. begin
  18. #20000 signalA =~signalA;
  19. #2000 signalA =~signalA;
  20. #20000 signalA =~signalA;
  21. #4000 signalA =~signalA;
  22. #4000 signalA =~signalA;
  23. #20000 signalA =~signalA;
  24. #2000 signalA =~signalA;
  25. #20000 signalA =~signalA;
  26. #4000 signalA =~signalA;
  27. #4000 signalA =~signalA;
  28. end
  29. initial begin
  30. signalB=0;
  31. # 25000
  32. repeat(10000)
  33. begin
  34. #20000 signalB =~signalB;
  35. #2000 signalB =~signalB;
  36. #20000 signalB =~signalB;
  37. #4000 signalB =~signalB;
  38. #4000 signalB =~signalB;
  39. #20000 signalB =~signalB;
  40. #2000 signalB =~signalB;
  41. #20000 signalB =~signalB;
  42. #4000 signalB =~signalB;
  43. #4000 signalB =~signalB;
  44. end
  45. end
  46. initial begin
  47. rst_n=1;
  48. # 5000
  49. rst_n=1;
  50. # 10000000
  51. $stop;
  52. end
  53. endmodule

(2)下面是仿真的结果,可以看出滤波效果达到预期,输出的电机转动周期也与预期相同。

 

今天的分享就这样,欢迎一起讨论进步哦。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/330795
推荐阅读
相关标签
  

闽ICP备14008679号