赞
踩
如果要控制电机的闭环角度和速度的话,在不用编码器的情况下,最简单的是用步进电机,控制输出的脉冲数,就可以控制角度,控制脉冲直接的间隔,就可以控制速度
两项可以通过万用表查是否导通,导通的两根就是同向的
同相两线接反那么电机就会反向,和无刷电机两根相线调换一样
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原理图
常见问题
4988可以驱动的电机跟尺寸关系不大,主要与工作电流有关,理论上电流小于2A的步进电机都是可以驱动的,不论是42还是57电机。
如果4988芯片上没有加散热片,电流最好在1.2A以下。如果加散热片,电流可以达到2A。
相电流的大小跟步进电机的扭力有直接关系,如果感觉你的步进电机扭力不足,可以加大4988板子的电流配置。驱动板是通过一个小的电位器来实现对输出电流的配置的。可以通过用万用表测量电位器中间管脚的电位。电位和电流的关系满足下面的公式:Vref = A*0.8.也就是如果你想配置电机工作电流为1A,则电位应该配置在0.8V。默认的元件配置可以将电流调节到1.5A,如果需要更大电流需要修改电路中的R1,将30K的阻值改为20K(左右),就可以将电流调节到2A左右。
用PID控制进行角度闭环
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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
使用方法
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)
采用等腰梯形加减速方法
先取一个比原来转速高一点的值,这样就留出了时间给加减速
然后已知梯形的面积(一共要转的圈数),梯形的下底长度(一共的时间),还有梯形的高(最高转速)
就可以计算出最高转速的时间,剩下的时间/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
指定加减速的时间
-- 方向引脚,使能引脚,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)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。