当前位置:   article > 正文

lua驱动步进电机加减速PID控制_步进电机pid控制

步进电机pid控制

驱动步进电机

如果要控制电机的闭环角度和速度的话,在不用编码器的情况下,最简单的是用步进电机,控制输出的脉冲数,就可以控制角度,控制脉冲直接的间隔,就可以控制速度

  • 两项可以通过万用表查是否导通,导通的两根就是同向的

  • 同相两线接反那么电机就会反向,和无刷电机两根相线调换一样

  • A4988的DIR和STEP都没有上下拉,如果悬空,那么电机会乱转

  • DIR和STEP都是高阻态,如果对地有阻值,那么就是模块坏了

  • 如果电机发热,那么将电流调低,逆时针调低,顺时针调高

  • 光驱的步进电机 步距角好像不是1.8°,查资料说是18度

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IBb5NVnb-1648295122324)(C:\Users\87698\AppData\Roaming\Typora\typora-user-images\image-20211226173854011.png)]

  • 开了16细分下 转一圈要20*16=320个脉冲 精细度是18/16=

  • A4988原理图

    • img
    • VMOT:电源正(8~35V),供电机
      GND:电机接地
      2B,2A:电机绕组2控制引脚
      1A.1B:电机绕组1控制引脚
      VDD:驱动板电源正(3~5V)
      GND:驱动板地
      ENABLE:引脚低电平,A4988才能进行电机驱动工作(悬空为默认状态,可以正常工作),高电平,A4988将不会经行电机驱动工作
      MS1,MS2,MS3:用来改变驱动模式具体如图
      REST:低电平有效,A4988将经行复位,默认为高,可以正常工作
      SLEEP:低电平经行低能耗睡眠状态,无需使用时可与REST连接,则保持正常工作不会进入低能耗状态。
      STEP:步进引脚,根据脉冲经行动作
      DIR:方向引脚,低:顺时针,高:逆时针
    • 还可以通过MS1到3,控制细分,也就是物理步进值的几分之几
    • img
  • 常见问题

    1、4988驱动板可以驱动57电机吗?

    4988可以驱动的电机跟尺寸关系不大,主要与工作电流有关,理论上电流小于2A的步进电机都是可以驱动的,不论是42还是57电机。

    2、可以驱动多大的电流?

    如果4988芯片上没有加散热片,电流最好在1.2A以下。如果加散热片,电流可以达到2A。

    4、如何调节相电流?

    相电流的大小跟步进电机的扭力有直接关系,如果感觉你的步进电机扭力不足,可以加大4988板子的电流配置。驱动板是通过一个小的电位器来实现对输出电流的配置的。可以通过用万用表测量电位器中间管脚的电位。电位和电流的关系满足下面的公式:Vref = A*0.8.也就是如果你想配置电机工作电流为1A,则电位应该配置在0.8V。默认的元件配置可以将电流调节到1.5A,如果需要更大电流需要修改电路中的R1,将30K的阻值改为20K(左右),就可以将电流调节到2A左右。

  • 用PID控制进行角度闭环

    • 全局变量记录实时的角度
    • 将目标角度和实时角度做PID,得到速度
    • 速度的倒数作为每个脉冲的延时时间
    • 每发一次脉冲,更具方向实时角度±1

42步进电机

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YGGWLamP-1648295122331)(C:\Users\87698\AppData\Roaming\Typora\typora-user-images\image-20220102204817156.png)]

步距角1.8°,在16分频下,16*200=3200pps=1rps=60rpm

最高转速当他是2000pps=2000/200=10rps=600rpm

实测在500ms转3圈就不动了,也就是6rps,360rpm

步进电机驱动类

function setpMotor( dir,en,step )
	local t = {}
	t.last_angle = 0
	t.DIR = gpio.setup(dir, 0)
	t.EN = gpio.setup(en, 0)
	t.STEP = step

	--使能电机
	t.enable = function ()
		t.EN(0)
	end

	--失能电机
	t.disable = function ()
		t.EN(1)
	end

	-- 以指定的速度向dir方向旋转(rpm)
	t.rotate = function (dir,rpm)
		t.DIR(dir)
		local pulse = (rpm/60)*3200
		pwm.open(t.STEP,pulse,50)
	end

	-- 停止旋转
	t.stop = function ()
		pwm.close(t.STEP)
	end

	-- 设为角度零点
	t.clearAngle = function ()
		t.last_angle = 0
	end

	-- 在time的时间内(单位ms)内旋转电机到指定的角度(单位°)
	t.angle = function (angle,time)
		if angle > t.last_angle then
			t.DIR(0)
		else
			t.DIR(1)
		end
		local diff = math.abs(angle-t.last_angle)
		local pulse = (diff/360)*3200*(1000/time)
		pwm.open(t.STEP,pulse,50)
		sys.wait(time)
		pwm.close(t.STEP)
		t.last_angle = angle
	end
	return t
end

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

使用方法

sys.taskInit(function()
	-- PWM4 --> PA7-7
	-- PWM3 --> PB3-19
	-- PWM2 --> PB2-18
	-- PWM1 --> PB1-17
	-- PWM0 --> PB0-16
    -- dir引脚,en引脚,step通道
	step_motor = setpMotor(pin.PB02,pin.PB05,0)
    while 1 do
        -- 以120rpm逆时针旋转
    	step_motor.rotate(0,120)
    	sys.wait(3000)
        -- 停止旋转
    	step_motor.stop()
    	sys.wait(1000)
        -- 用500ms转到360°
    	step_motor.angle(360,500)
		sys.wait(1000)
		step_motor.angle(0,500)
		sys.wait(1000)
		step_motor.angle(360,2000)
		sys.wait(1000)
		step_motor.angle(-360,1000)
		sys.wait(1000)
    end
end)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

步进电机角度加减速控制

采用等腰梯形加减速方法

先取一个比原来转速高一点的值,这样就留出了时间给加减速

然后已知梯形的面积(一共要转的圈数),梯形的下底长度(一共的时间),还有梯形的高(最高转速)

就可以计算出最高转速的时间,剩下的时间/2,就是加速和减速各自的时间

然后就可以循环指定次数,每次输出的频率按照第几次等比例乘上最高转速

结束加速后,按最高转速旋转对应的时间,最后等比减速

  • 缺点:计算加减速等比延时的时候会有小数,精度会丢失,电机最后会比原来的少走
  • 优点:没有最少运行时间限制,加减速时间通过实时计算得到
-- 方向引脚,使能引脚,PWM通道
function setpMotor( dir,en,step,precison)
	local t = {}
	t.last_angle = 0
	t.DIR = gpio.setup(dir, 0)
	t.EN = gpio.setup(en, 0)
	t.STEP = step
	-- 加减速精度 只在角度控制上使用 变换5次速度后到达最高速度
	t.precison = precison
	-- 少走的补偿 单位是脉冲 因为单片机进行开关和调度都要时间,所以会少走
	t.compensate = 10
	--使能电机
	t.enable = function ()
		t.EN(0)
	end

	--失能电机
	t.disable = function ()
		t.EN(1)
	end

	-- 以指定的速度向dir方向旋转(rps)
	t.rotate = function (dir,rps)
		t.DIR(dir)
		local pulse = (rps)*3200
		pwm.open(t.STEP,pulse,50)
	end

	-- 停止旋转
	t.stop = function ()
		pwm.close(t.STEP)
	end

	-- 设为角度零点
	t.clearAngle = function ()
		t.last_angle = 0
	end

	-- 在time的时间内(单位ms)内旋转电机到指定的角度(单位°)
	t.angle = function (angle,time)
		if angle > t.last_angle then
			t.DIR(0)
		else
			t.DIR(1)
		end
		local diff = math.abs(angle-t.last_angle)/360
		-- rps
		local t_all = time/1000
        -- 计算匀速状态下,最低的速度
		local v_normal = diff/t_all
		-- v_max应该在1~2倍v_normal之间,低了会少走,多了会多走,1.5会比较合适
		local v_max = 1.5*v_normal
        -- 以全速运转的时间
		local t_v_max = (2*diff)/v_max - t_all
        -- 加减速的时间
		local t_accel = diff/v_max/2

		local pulse = 0
		--log.info("info",t_all,v_normal,v_max,t_v_max,t_accel)
        -- 加速
		for i=1,t.precison do
			pulse = ((i*v_max)/t.precison)*3200 + t.compensate
            -- 用floor将float去掉小数转成整数,不然会报错
            -- 但是这样会丢失精度,造成少走
			pwm.open(t.STEP,math.floor(pulse),50)
            -- 延时用floor会减去小数,就是0.xms,会造成少走
			sys.wait(math.floor(t_accel*1000/t.precison))
            -- 每次open之前都要close
			pwm.close(t.STEP)
		end
		
        -- 匀速
		pulse = v_max*3200
		pwm.open(t.STEP,math.floor(pulse),50)
		sys.wait(math.floor(t_v_max*1000))
		pwm.close(t.STEP)

        --减速
		for i=1,t.precison do
			pulse = (((t.precison-i)*v_max)/t.precison)*3200 + t.compensate
			pwm.open(t.STEP,math.floor(pulse),50)
			sys.wait(math.floor(t_accel*1000/t.precison))
			pwm.close(t.STEP)
		end

		
		t.last_angle = angle
	end
	return t
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90

设置加减速时间的控制

指定加减速的时间

  • 优点:加减速的时候,延时整数时间,就不会丢步
  • 缺点:有最小运行时间限制,当加减速设置为300ms时,旋转的最小时间必须>600ms,不然不会进入匀速区域,而且,只有加减速的600ms完成后,才会停止,会多走
-- 方向引脚,使能引脚,PWM通道
function setpMotor( dir,en,step,accel_time,one_change)
	local t = {}
	t.last_angle = 0
	t.DIR = gpio.setup(dir, 0)
	t.EN = gpio.setup(en, 0)
	t.STEP = step
	t.one_change = one_change
	-- 加减速时间 (s)
	t.accel_time = accel_time/1000

	--使能电机
	t.enable = function ()
		t.EN(0)
	end

	--失能电机
	t.disable = function ()
		t.EN(1)
	end

	-- 以指定的速度向dir方向旋转(rps)
	t.rotate = function (dir,rps)
		t.DIR(dir)
		local pulse = (rps)*3200
		pwm.open(t.STEP,pulse,50)
	end

	-- 停止旋转
	t.stop = function ()
		pwm.close(t.STEP)
	end

	-- 设为角度零点
	t.clearAngle = function ()
		t.last_angle = 0
	end

	-- 在time的时间内(单位ms)内旋转电机到指定的角度(单位°)
	t.angle = function (angle,time)
		if angle > t.last_angle then
			t.DIR(0)
		else
			t.DIR(1)
		end
		-- diff->S
		local diff = math.abs(angle-t.last_angle)/360
		-- t_all->T (s)
		local t_all = time/1000
		local v_max = diff/(t_all-t.accel_time)
		local t_v_max = t_all-2*t.accel_time

		local pulse = 0
		log.info("info",t_all,v_max,t_v_max)

		local loop_times = t.accel_time*1000/t.one_change
		for i=1,loop_times do
			pulse = ((i*v_max)/loop_times)*3200
			pwm.open(t.STEP,math.floor(pulse),50)
			sys.wait(t.one_change)
			pwm.close(t.STEP)
		end
		
		pulse = v_max*3200
		pwm.open(t.STEP,math.floor(pulse),50)
		sys.wait(math.floor(t_v_max*1000))
		pwm.close(t.STEP)

		for i=1,loop_times do
			pulse = (((loop_times-i)*v_max)/loop_times)*3200
			pwm.open(t.STEP,math.floor(pulse),50)
			sys.wait(t.one_change)
			pwm.close(t.STEP)
		end

		
		t.last_angle = angle
	end
	return t
end


step_motor = setpMotor(pin.PB02,pin.PB05,0,300,10)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/929626
推荐阅读
相关标签
  

闽ICP备14008679号