FPGA:双线轨丝杠式升降台(及A4988与42步进电机原理)(同时包含51及32程序)

本文讲述了作者在制作智能剥壳机和升降台过程中,如何应用双线轨丝杆式升降结构,42步进电机(特别是A4988驱动模块)的选型、接线和编程,包括C语言、Python和Verilog实例。适合初学者理解步进电机工作原理与驱动技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


日常·唠嗑

3月份在做智能剥壳机的时候,就遇到了丝杠问题。想着通过挤压的方式把坚果的外壳压碎,但那时候对丝杠原理还不是很理解,最后不了了之。现在省电,需要给车子做一个升降台,再一次回到了曾经没有攻克的难题……


一、双线轨丝杆式升降

双线轨丝杆式升降一般由步进电机,T8丝杆,联轴器,上下轴承片,导轨及轴承座组成。这种组合,一般承重能力强,精度高。多用于3D打印机或者高精度机床等等。(汽修厂升降的升降机与这个结构也有异曲同工之妙)双线轨丝杆式升降台如下图所示:
在这里插入图片描述

某宝的上的配套升降台(有效行程1米)价格一般在400左右,较为昂贵,但是性能稳定,无需经过多次调试就可以直接用。我做的项目,升降距离不需要太长,且要求整个机构体积较小,所以我利用零件自己组装。
T8丝杆:
在这里插入图片描述
42步进电机(6线):
在这里插入图片描述
A4988驱动模块:
在这里插入图片描述
联轴器:
在这里插入图片描述
成果图: 有点丑,不过还好经过多次测试能用。
在这里插入图片描述

二、42步进电机

1、常见问题

初次接触步进电机肯定会有很多疑问,比如4线步进电机与6线步进电机的差别,该如何接线,步进电机的电压该怎么解决,12V可以吗(第一次接触,我朋友跟我说,电机功率很大,90W,并且电压要30V,比赛要带上电源器,我当场人就傻),像我第一次接触就一直在纠结用什么驱动模块(当时我了解的就只有TB6600,可是这东西太大了啊),后来了解到了拇指大的A4988一样可以实现驱动。

2.型号参数

(42BYGH) 两相四线步进电机,步距角为 1.8 °, 200 个脉冲转动一圈。(这个参数很重要!!!下面写程序需要用到)下图为电机与模块接线(这个图是与Arduino接线,但是与别的板卡接线是一样的):
在这里插入图片描述

三、A4988驱动模块

A4988 是一款带转换器和过流保护的 DMOS 微步驱动器,该产品可在全、半、1/4、1/8 及 1/16 步进模式时操作双极步进电动机,输出驱动性能可达 35 V 及 ±2 ,A4988 包括一个固定关断时间电流稳压器,该稳压器可在慢或混合衰减模式下工作。转换器是 A4988 易于实施的关键。只要在“步进”输入中输入一个脉冲,即可驱动电动机产生微步。无须进行相位顺序表、高频率控制行或复杂的界面编程。A4988 界面非常适合复杂的微处理器不可用或过载的应用。

麻雀虽小五脏俱全,虽然模块只有拇指大,我对引脚做了笔记,下面看看每个引脚的名称及作用。

在这里插入图片描述

1、STEP 、 DIR 分别连接单片机的两个控制端口; EN 可以使用单片机端口控制,也可以直接连接 GND 使能;
2、 MS1 、 MS2 、MS3 按照上一节“步进模式设置”,接高低电平,设置步进模式,来选择不同的步距角。 设置脉冲的频率,来控制旋转速度。步进电机走一步是1.8度,一圈就是200步。例如使用1/16步进,则需要走3200步才等于一圈。
3、 2B 、2A 、 1A 、 1B 分别接步进电机红、蓝、黑、绿线。 VMOT 、 GND 接 12V
4、左右直流电源(电压大小更具步进电机不同,选择合适电压)。VDD 、 GND 接 3.3V 或 5V 。
5、 sleep,reset:通常短接;
长篇大论讲了一堆,主要是想让大家看懂这个模块的具体功能。但是实际运用中,如果,不是特别精细的控制,可以直接选择全步进的工作方式(MS1,MS2,MS3,三个引脚全部悬空,即为全步进模式,那样的话就只要控制STEP,DIR两个引脚即可)

四、程序设计

1、C语言(51单片机)

#include"reg52.h"
#include <intrins.h>
sbit dir=P1^0;
sbit step=P1^1;
#define uint  unsigned int
void Delay_xms(uint x);

void Delay1000us()		//@11.0592MHz
{
	unsigned char i, j;

	_nop_();
	i = 2;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}

void Delay_xms(uint x)
{
 uint i,j;
 for(i=0;i<x;i++)
  for(j=0;j<112;j++);
}


void main()
{
	uint x,y;
	dir=1;//电机正转
	
 for( y = 0; y<6; y++) { //修改y值可以改变电机转的圈数
	 for( x = 0; x <=200; x++) {     //一个圈200个脉冲
     step=1; 
     Delay1000us();
     step=0;
     Delay1000us(); 
  }
}	
 Delay_xms(1500);
	
	  dir=0;//电机反转
  for( y = 0; y<6; y++) { 
	  for( x = 0; x <=200; x++) {     
     step=1; 
     Delay1000us();//时间长短会影响电机运动
     step=0;
     Delay1000us(); 
  }
}
	 Delay_xms(1500);
	

2、Python(STM32)

from pyb import Pin, delay

p_dir = Pin('Y1', Pin.OUT_PP)
p_step = Pin('Y2', Pin.OUT_PP)

while True:

    p_dir.high

    for y in range(0, 6):
        for x in range(0, 201):
            p_step.high()
            pyb.udelay(1000)

            p_step.low()
            pyb.udelay(1000)

    pyb.delay(1500)
    p_dir.low

    for y in range(0, 6):
        for x in range(0, 201):
            p_step.high()
            pyb.udelay(1000)

            p_step.low()
            pyb.udelay(1000)

    pyb.delay(1500)

3、Verilog(FPGA)

module step1 (clk0,reset,out,der,x);//状态机module
input clk0,reset,der,x;
output[3:0] out;
reg[3:0] out;
reg[2:0] current;
reg[2:0] current1;
parameter s0=3'b000,s1=3'b001,s2=3'b010,
    s3=3'b011,s4=3'b100,s5=3'b101,
    s6=3'b110,s7=3'b111;
always@(posedge clk0 or negedge reset )
 begin
  if(!reset)
   begin
    current<=s0;
   end
  else   
   case(current)
    s0:
        begin
      if(!der)
       begin
        current<=s7;
        current1<=s7;
       end
      else
       begin
        current<=s1;
        current1<=s1;
       end
        end
    s1:
     begin
      if(!der)
       begin
        current<=s0;
        current1<=s0;
       end
      else
       begin
        current<=s2;
        current1<=s2;
       end
     end
    s2:
     begin
      if(!der)
       begin
        current<=s1;
        current1<=s1;
       end
      else
       begin
        current<=s3;
        current1<=s3;
       end
     end
    s3:
     begin
      if(!der)
       begin
        current<=s2;
        current1<=s2;
       end
      else
       begin
        current<=s4;
        current1<=s4;
       end       
     end
    s4:
     begin
      if(!der)
       begin
        current<=s3;
        current1<=s3;
       end
      else
       begin
        current<=s5;
        current1<=s5;
       end
     end
    s5:
     begin
      if(!der)
       begin
        current<=s4;
        current1<=s4;
       end
      else
       begin
        current<=s6;
        current1<=s6;
       end
     end
    s6:
     begin
      if(!der)
       begin
        current<=s5;
        current1<=s5;
       end
      else
       begin
        current<=s7;
        current1<=s7;
       end
     end
    s7:
     begin
      if(!der)
       begin
        current<=s6;
        current1<=s6;
       end
      else
       begin
        current<=s0;
        current1<=s0;
       end
     end 
   endcase     
 end
always@(current1 )//or clk0
begin
  case(current1)
   s0:
    begin
     out<=4'b1001;     
    end
   s1:
    begin
     out<=4'b0001;    
    end
   s2:
    begin
     out<=4'b0011;
    end
   s3:
    begin
     out<=4'b0010;
    end
   s4:
    begin
     out<=4'b0110;
    end
   s5:
    begin
     out<=4'b0100;
    end
   s6:
    begin
     out<=4'b1100;
    end
   s7:
    begin
     out<=4'b1000;
    end
  endcase  
end
endmodule 
module step2 (clk1,a,adj);//分频module
input clk1;
input[5:0] adj;
output a;
reg a;
reg[25:0] cnt;
reg[15:0] counter;
wire[5:0] adj;
reg[2:0] temp;
always @(posedge clk1)
begin
 temp=adj[5]+adj[4]+adj[3]+adj[2]+adj[1]+adj[0];
 if(temp==3'd6)
  begin
  if(cnt <= 32000)  cnt <= cnt+1'b1;//0.5MS 1MS 2MS 4MS  8MS   4000 8000 16000 32000 64000
       else 
     begin 
    cnt <=26'b0;
    a=~a;
     end
     end
 else if(temp==3'd5)
   begin
    if(cnt <= 16000)  cnt <= cnt+1'b1;//0.5MS 1MS 2MS 4MS  8MS   4000 8000 16000 32000 64000
    else 
     begin 
      cnt <=26'b0;
      a=~a;
     end
   end
  else if(temp==3'd4)
    begin
     if(cnt <= 12000)  cnt <= cnt+1'b1;//0.5MS 1MS 2MS 4MS  8MS   4000 8000 16000 32000 64000
     else 
      begin 
       cnt <=26'b0;
       a=~a;
      end
    end
   else if(temp==3'd3)
     begin
      if(cnt <= 10000)  cnt <= cnt+1'b1;//0.5MS 1MS 2MS 4MS  8MS   4000 8000 16000 32000 64000
      else 
       begin 
        cnt <=26'b0;
        a=~a;
       end
     end
    else if(temp==3'd2)
      begin
       if(cnt <= 8000)  cnt <= cnt+1'b1;//0.5MS 1MS 2MS 4MS  8MS   4000 8000 16000 32000 64000
       else 
        begin 
         cnt <=26'b0;
         a=~a;
        end
      end
     else if(temp==3'd1)
     begin
      if(cnt <= 6000)  cnt <= cnt+1'b1;//0.5MS 1MS 2MS 4MS  8MS   4000 8000 16000 32000 64000
      else 
       begin 
        cnt <=26'b0;
        a=~a;
       end
     end
     else if(temp==3'd0)
      begin
       if(cnt <= 4000)  cnt <= cnt+1'b1;//0.5MS 1MS 2MS 4MS  8MS   4000 8000 16000 32000 64000
       else 
        begin 
         cnt <=26'b0;
         a=~a;
        end
      end
 
end
endmodule 
module step (clk,reset,out,der,d);//总体模块d[5:0]调速控制端口 用6个拨码开关表示 全1速度最慢 全0时速度最快 其中1(0)的个数能表示电机速度的快慢
input clk ,reset,der,d;
output [3:0]out;
wire p;
wire[5:0] d;
step2 l1 (clk,p,d);//clk系统时钟
step1 l2 (p,reset ,out,der);//reset停止转动  out[3:0]电机控制输出端口  der正反方向控制端
endmodule 




endmodule

注: 3点56分,实在太困了,Verilog的程序留着下次再更新(就当留个彩蛋,哈哈哈)。还有一些需要注意地方,可能一时没想到,也留着下次一起更新。

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千歌叹尽执夏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值