王涛 发表于 2017-2-18 09:41:17

如何用FPGA实现直线插补和圆弧插补控制多轴联动?

本帖最后由 王涛 于 2017-2-18 14:01 编辑

本人想做一个脱机的CNC系统用的是ARM+FPGA架构。ARM端做UI和G代码解析以及前瞻处理和路径规划,FPGA实现直线插补控制和圆弧插补控制多轴联动。现在ARM 端的程序基本OK。问题就在FPGA这边有做过的能不给点提示要怎么搞?
ARM用的是STM32F4开DSP和FPU速度感觉还可以,FPGA的DDA插补模块希望有直线插补和圆弧插补两部分,两种插补方式在一次插补过程中,只能有一种处于工作状态。直线插补能够实现3个轴的脉冲输出,完成二维或三维的直线轨迹,而圆弧插补是实现两轴的脉冲输出,实现二维的圆弧轨迹。

下面是直线插补
`timescale 1ns/100ps
module dda(s_clk,start,x_start,x_end,puls_x,sign_x,
                     y_start,y_end,puls_y,sign_y);
                                                         
inputs_clk,start;                                 //s_clk为时钟信号,start=1时正常运行
output reg puls_x,sign_x;                //puls_x为输出脉冲信号,sign_x为工作方式信号(正转还是反转)
output reg puls_y,sign_y;      
input x_start,x_end;               //为输入坐标信号
input y_start,y_end;

reg coun_x=0;
reg state_x;
reg coun_y=0;
reg state_y;

parameter S0 = 1'h0,
          S1 = 1'h1,
                         S2 = 1'h2,
                         S3 = 1'h3;
                        
parameter M0 = 1'h0,
          M1 = 1'h1,
                         M2 = 1'h2,
                         M3 = 1'h3;

always@(posedge s_clk)
begin
if(!start)
    begin
         puls_x = 0;
                sign_x = 0;
                state_x = S0;
                if(x_end >=x_start)
                  begin
                  sign_x = 1'b1;
                         coun_x = x_end - x_start;
                        end
       else
      begin
          sign_x = 1'b0;
          coun_x = x_start - x_end;
      end                        
      
         end
else
    begin
      case(state_x)
                  
                        S0:
                           begin
                           if(coun_x)
                                     begin
                                          coun_x = coun_x-4'b0001;
                                                 puls_x = 1'b1;
                                                 state_x = S1;
                                                 end
                                        end
                                       
                                 S1:
                                     begin
                                     puls_x = 1'b0;
                                          state_x = S2;
                                          end
                                          
                                 S2:
               begin
                  if(coun_x)
                                     begin
                                          coun_x = coun_x-4'b0001;
                                                 puls_x = 1'b1;
                                                 state_x = S3;
                                                 end
                                       //else          state_x <= S0;
                              
                                        end                                          
                                       
                                        S3:
                                     begin
                                     puls_x = 1'b0;
                                          state_x = S0;
                                          end
                        
                        default: puls_x =1'bZ;
                        
               endcase
      end
end

/*--------------Y轴方向-----------------------------*/

always@(posedge s_clk)
begin
if(!start)
    begin
         puls_y = 0;
                sign_y = 0;
                state_y = S0;
                if(y_end >=y_start)
                  begin
                  sign_y = 1'b1;
                         coun_y = y_end - y_start;
                        end
       else
      begin
          sign_y = 1'b0;
          coun_y = y_start - y_end;
      end                        
      
         end
else
    begin
      case(state_y)
                  
                        M0:
                           begin
                           if(coun_y)
                                     begin
                                          coun_y = coun_y-4'b0001;
                                                 puls_y = 1'b1;
                                                 state_y = S1;
                                                 end
                                        end
                                       
                                 M1:
                                     begin
                                     puls_y = 1'b0;
                                          state_y = S2;
                                          end
                                          
                                 M2:
               begin
                  if(coun_y)
                                     begin
                                          coun_y = coun_y-4'b0001;
                                                 puls_y = 1'b1;
                                                 state_y = S3;
                                                 end                     
                                        end                                          
                                       
                                        M3:
                                     begin
                                     puls_y = 1'b0;
                                          state_y = S0;
                                          end
                        
                        default: puls_y =1'bZ;
                        
               endcase
      end
end

endmodule      
                                          
下面为仿真效果

(原文件名:fz.JPG)

asj1989 发表于 2017-2-18 10:08:55

lz你好,我最近也在研究这个

wye11083 发表于 2017-2-18 10:36:06

其实你这可以上运动控制芯片了,就是芯片比较贵。插补都可以通过查表去做,耗不了几个资源。多轴联动应该是控制轨迹吧,这个我不清楚。(PS:我也准备做一款控制系统,我前一段买了台DIY的桌面贴片机,精度惨不忍睹,准备改选成高精度全光学定位、超高速运动控制等一体化控制系统,目标是达到600PCS的贴片速度)

huangguimina4 发表于 2017-2-18 10:52:05

这个工程感觉挺大,能动很容易,但是要实现减速,插补,运动规划就难了。而且没有这些根本没多大实用价值

whatcanitbe 发表于 2017-2-18 21:31:42

顶,支持你继续。

bulejeans 发表于 2017-2-21 17:30:14

fpga 做这个是费力不讨好,插补运算要用到乘除法,挺耗资源的,做产品的话不如专用型dsp

SuBingEn 发表于 2017-2-21 18:09:56

LinuxCNC之类的不是挺成熟的了吗,直接用就好了

王涛 发表于 2017-2-22 10:33:08

本帖最后由 王涛 于 2017-2-22 10:37 编辑

SuBingEn 发表于 2017-2-21 18:09
LinuxCNC之类的不是挺成熟的了吗,直接用就好了

请问有在嵌入式上跑的LINUXCNC吗?有这方面的资料吗?如果有的话给个链接参考一下,谢谢。其实AVR上的GRBL就是一个很好的开源数控方案,里面就有直线和圆弧插补我移植到F4 168M上跑OS开FPU和DSP速度可以,用的是bresenham画线算法。属于软件插补,这里想用FPGA做硬件插补。

ibmx311 发表于 2017-2-22 10:41:31

我一直反对这种折腾,根本没有意义。因为你最后还是要带上电机才有意义。先不要说插补了,怎样调试电机先要搞清楚再回过头来看插补,就会发现以前的算法比较幼稚。另外,调试这个必须要有一个平台,起码20W起步吧。因为如果你的机架不行,你电机的刚性就调不上去,调高一点都嗡嗡响。刚性调不上去你滞后就大,滞后都大了,折腾各种插补干啥。然后电机的品种那就多了去了,起码典型的十几种要试一下吧,每一种的前馈调起来都区别很大。把条件准备好了,基本在你资金完全不成问题的情况下要18个月。然后再去研究插补,否则都是纸上谈兵。

王涛 发表于 2017-2-22 11:03:52

ibmx311 发表于 2017-2-22 10:41
我一直反对这种折腾,根本没有意义。因为你最后还是要带上电机才有意义。先不要说插补了,怎样调试电机先要 ...

多读点书再聊。

ibmx311 发表于 2017-2-22 11:18:20

不就是起步走吗,你要咋地。你把你带上加减速的跑的最好的亮出来看看。

王涛 发表于 2017-2-22 11:27:29

本帖最后由 王涛 于 2017-2-22 14:21 编辑

ibmx311 发表于 2017-2-22 11:18
不就是起步走吗,你要咋地。你把你带上加减速的跑的最好的亮出来看看。

最烦你这种一副高高在上不屑一顾的人

ibmx311 发表于 2017-2-22 11:30:43

自己感觉能做的不错的,都基本是没有测试条件的。最终平台要用激光干涉仪和激光跟踪仪看。这两件买到手130多就不见了。如果只是一个齐步走根本就不用这样折腾。这两件东西我十年前就自己花钱买了。到时候就知道了,就算是两轴的直线插补不用几年你都做不好。光是测试方案,就不知道做了多少。

y595906642 发表于 2017-2-22 12:08:54

ibmx311是老司机 听他的没错

3DA502 发表于 2017-2-22 12:19:45

本帖最后由 3DA502 于 2017-2-22 12:21 编辑

王涛 发表于 2017-2-22 11:27
最烦你这种一副高高在上不屑一顾的人,这种人要么就是书读的少不知道自己不知道浮躁,要么就是岁数太小幼 ...

小屁孩   

你态度不对,骂人之前至少要看看这个人发过什么帖子

li_fccc 发表于 2017-2-22 12:20:44

grblmarlin   linuxcnc 可以学习学习实用都不行   不接设备试试,都不知道问题在哪,反向间隙都有好几种方式

ibmx311 发表于 2017-2-22 12:32:00

反向间隙肯定是都会有的,只不过设备越精密越不明显而已。全新的大畏卧加反向间隙0.5丝左右,全新的DMG5轴反向间隙也差不多是这个数。这样的数据可以补也可以不补。惯量较大的时候有微量的反向间隙不见得是坏事。这些东西都没有电机带来的危害大。就电机而言,无论其编码器吹牛逼是多好,其实装配上就不可能达到很高的形位公差,垂直度稍微差一点,就极大的恶化了定位精度,所以好一点的机器都要用光栅尺再闭环。

王涛 发表于 2017-2-22 12:37:54

本帖最后由 王涛 于 2017-2-22 14:21 编辑

3DA502 发表于 2017-2-22 12:19
小屁孩   

你态度不对,骂人之前至少要看看这个人发过什么帖子

看来都是老工程师了,可惜不是工程师的老师,我并没有骂人.

ibmx311 发表于 2017-2-22 12:46:28

王涛 发表于 2017-2-22 12:37
看来都是老工程师了,可惜不是工程师的老师,我并没有骂人,什么事情喜欢习惯性否定,其实这种人已经老态 ...

我是一把年纪了,不过每天仍然在搬铁,就是这个苦逼的命,不会有翻身之日了。
不过,我一直信奉一句话,我们是绝对不可能超越前人的。
当然了,前人是一定会被超越的,但一定不是我们。

3DA502 发表于 2017-2-22 12:54:19

王涛 发表于 2017-2-22 12:37
看来都是老工程师了,可惜不是工程师的老师,我并没有骂人,什么事情喜欢习惯性否定,其实这种人已经老态 ...

先驱翻翻google 万方吧   DDA这个算法有讲义    灌水论文一大堆
页: [1]
查看完整版本: 如何用FPGA实现直线插补和圆弧插补控制多轴联动?