42减速步进电机|一起来造个六轴步进电机机械臂吧——SmallArmRobot版

日期:2023-07-11 03:01:58浏览量:239

深圳市鑫希田机电有限公司(艾德克尔ADDKA)是集工业自动化零部件产品、互联网、供应链服务于一体的综合性工厂直销+电商平台, 2005年创立于粤港澳大湾区四大中心城市之一 、国家物流枢纽、国际性综合交通枢纽 、国际科技产业创新中心 、中国三大全国性金融中心之一 深圳市,以代理销售日本松下、三菱、ABB等工业自动化传动产品,为使产品质量不断提高,引进一批高素质的专业技术人员,引进100台/套 日本哈马仪滚齿机、精密全自动磨床、热处理设备、CNC加工中心等生产设备;日本TIT精密齿轮检测设备、铬氏硬度仪、维氏硬度仪等,至力研发、生产高效、节能、环保型的工业传动产品。 2020年为适应客户需要,满足客户期望一站式采购工业自动化零部件需求,公司转型升级,旨在构建以“工业部件+工厂+互联网+供应链”为主体的全新工业品营销方式,打造工业自动化零部件自主生产、线上线下交易、服务、技术支持一体化平台。具有高性价比,正品保证,快速出货,免费3D下载等特点。我们多样化的产品种类与充足的库存使客户可以安心、便捷地搜寻和购买到合适的产品。、充足的现货储备,所有产品质量保障, 深圳市鑫希田机电有限公司为客户提供专业的采购服务,节省客户的时间和成本。

前言

不会吧不会吧,不会还有人不知道SmallArmRobot机械臂的吧~

不过不知道也没关系,看完了图片,你会心动的!

看起来是一个相当帅气的桌面级机械臂,而且还是步进电机的机械臂。这个机械臂和古月大大的Anno机械臂觉得有的一拼,所以你懂得~

话不多说,先看效果!

看起来效果是相当的nice!这里的模型功能包是我使用雪铭大佬的资料,大家可以古月学院找到相关的课程内容,这个课程还是免费的哦~(*)

当然啦,我肯定不会只是甘心来玩玩仿真的,要搞就搞一波大的,撸起袖子就是造!

这一大堆的飞线请自动忽略,还有就是不要问我为啥视频是快手的,俺毕竟能力有限,剪辑视频的活还搞不来~

制造机械臂

咱们现在就开始来造这个SmallArmRobot机械臂!

造这个机械臂首先肯定要有实物,这个机械臂的模型在网上大家是可以下载。我在这里为大家提供百度网盘的下载链接。

提取码:a7mk

大家下载知乎可以通过3D打印的方式来做这个机械臂,同时你还需要准备一大堆型号超多的螺丝,工具什么的也要准备好,还有就是准备六个步进电机,2个57步进电机、1个42步进电机、2个28步进电机和1个20步进电机。组装的教程及相关的BOM表,都在链接里面为大家提供。

当然,大家也可以小资一把,直接从咸鱼采购一个机械臂实物,现在咸鱼的价格差不多是在600到800之间,只有机械臂主体就可以的,驱动板我是重新设计了的(开源大佬提供的使用有些难受)。有条件的小伙伴可以把侧板和底板换成不锈钢板,看起来不仅更帅气,而且也增加了配重和稳定性。有的大佬做的是这样的,我看了着实羡慕~

反正不管怎么样,搞个机械臂实物出来就对了!SmallArmRobot机械臂的成本相对来说还是比较搞的,毕竟六个步进电机已经给摆在这了,3D打印件更是一大堆~

42减速步进电机

然后就是我们的驱动板,开源大大们使用的是Arduino Mega的3D打印机的板子,各式各样的的飞线,虽然有外壳,但是我个人觉得还是比较乱,所以我将整个驱动板进行了全新的设计~

还是使用Arduino Mega2560开发板,做了一块扣在上面的扩展板。电机驱动使用了3个DRV8825和3个TB6600,DRV8805驱动的小电机的位置,我将控制细分的引脚通过Arduino Mega的IO口进行控制,实现软件控制细分的效果(TB6600我也想这样玩,但是总不能把TB6600拆开飞出来几条线吧~)

DRV8825驱动这里,我将EN引脚通过10K的电阻进行上拉,EN默认一直会处于高电平状态,同时我将细分引脚(M0、M1、M2)通过10K的电阻进行下拉,细分引脚一直会默认处于低电平状态,在12V和GNG之间,使用了一个35V 100uF电容和一个0.1uF电容进行并联进行滤波,提升电机驱动电压的稳定,在5V个GND之间使用了一个0.1uF的电容进行滤波,保证模块信号电压稳定。其余引脚全部引出。

这里为大家提供DRV8825细分表一份。

TB6600的驱动相对就简单了的,只是简单的引出现即可。这里,也是大家刚刚看到一大堆飞线的位置(肯定比他们的少)。

这里是我们的供电电路,机械臂工作电压为12V,这是我使用了XL4016的IC进行12V转5V 8A的功能。别问我为啥留的5V 8A的,比较Jetson Nano彻底跑起来都差不多5V 5A,要是这时候再有个来充手机电的,我觉得5V 8A很有必要!

这里使用了一个5.5-2.1的DC头作为12V供电接口,接开关电源的输出。在12V位置使用470uF和1uF电容并联的方式进行滤波;VC是内测电压调整,这里哦我们使用个1uF接到12V即可;FB是分压反馈引脚,检测当前的输出电压并进行调整;SW为功率输出引脚。

在SW功率输出后,我们需要使用一个快恢复二极管20100、一个47uH电感和一个1000uF的电容进行高频滤波处理,1uF电容作为输出滤波。

10K电阻和3.3K电阻作为分压检测使用,FB的检测电压是1.25V,10K电阻接5V,3.3K电阻接GND,则两电阻之间和GND的电压差值为5V*3.3/(3.3+10)≈1.25V(1:4的比例),当输出电压不足或者过高的情况下,XL4016会自动进行调整。

在使用的当中,有很多IO口并没有使用到,我们将按照3P的接线模式(S、V、G,信号线、供电正极、供电负极)预留出来,便于外接其他的传感器,比如气泵吸盘、舵机等等。

42减速步进电机

同时串口、IIC也均以4P的接线模式留出,可用于外接其他外界设备。

驱动板也预留出了两个USB供电接口,可以给大家的手机、充电宝等等充电。

我们所有IO相关的引脚功能如下。

很舒服,把模拟口、PWM和功能引脚更留出来了的,虽然SPI没能留出实在是有点遗憾。引脚功能相对比较工整,那么PCB布线的难度实在是一把辛酸史~

尽量保证布局的工整,留出了5个没有用到的IO口,大家可以再机械臂的末端介个气泵之类的控制啥的,两片铜皮是5V和GND,需要用5V供电直接焊上去。PCB留出了复位引脚,这里你可以接一个按键,当机械臂抽风(其实是你的代码写的抽风)的时候,直接让Arduino Mega进行复位。两个USB给Jetson Nano或者树莓派供电就很nice,给手机充电也是问题不大。

在供电的部分,我是使用了一个12V 8A的UPS模块,自己做了一块12V 3S的电池,六个步进电机功率实在是有点大,不过应该不会超过100W,12V 8A应该是够用的。

开发ROS机械臂

大家将机械臂和驱动板连接好之后,就可以开始程序的测试,先在Arduino写代码,测试每个电机运行是否存在问题,没有问题的话,就开始开发我们的ROS机械臂。

ROS的部位我们有三个功能包,分别是smallarmrobot_description模型功能包、smallarmrobot_moveit_config功能包、smallarmrobot_driver驱动功能包组成。其中smallarmrobot_description功能包是从雪铭大佬的的leaf_description修改得到的,大家可以自己在古月居搜寻一下。而smallarmrobot_moveit_config功能包是通过moveit_setup_assistant配置得到,这里不熟悉的同学可以选择古月学院下的《MoveIt可视化配置及仿真指南》教程进行学习,这里我不做过多的介绍。

(*)

42减速步进电机

在ROS的机械臂开发当中,关于机械臂关节角度的数值是在joint_stats话题的position数据当中,通过订阅joint_state话题的的position数据获取机械臂当前各个关节的弧度制,将其转换为角度值,并驱动步进电机执行到对应的位置即可。具体代码如下。

#!/usr/bin/env python#coding:utf-8 #导入rospy库import rospy #joint_state的msg是属于sensorfrom sensor_msgs.msg import JointState #调用StandardFirmata协议from pyfirmata import ArduinoMega,util #导入时间函数import time #导入IO配置函数,自定义from IO_config import * #步进电机驱动引脚声明Joint_STEP = [Joint1_STEP,Joint2_STEP,Joint3_STEP,Joint4_STEP,Joint5_STEP,Joint6_STEP]  #脉冲引脚声明Joint_DIR = [Joint1_DIR,Joint2_DIR,Joint3_DIR,Joint4_DIR,Joint5_DIR,Joint6_DIR] #方向引脚声明Joint_EN = [Joint1_EN,Joint2_EN,Joint3_EN,Joint4_EN,Joint5_EN,Joint6_EN]    #使能驱动引脚声明 #减速比系数声明,这里有减速带,需要重新计算joint_pro = [joint1_pro,joint2_pro,joint3_pro,joint4_pro,joint5_pro,joint6_pro]  #标记量声明joint_pul_flag = [joint1_pul_flag,joint2_pul_flag,joint3_pul_flag,joint4_pul_flag,joint5_pul_flag,joint6_pul_flag]  #脉冲标记joint_dir_flag = [joint1_dir_flag,joint2_dir_flag,joint3_dir_flag,joint4_dir_flag,joint5_dir_flag,joint6_dir_flag]  #方向标记joint_value = [joint1_value,joint2_value,joint3_value,joint4_value,joint5_value,joint6_value]   #当前角度值 #脉冲限位joint_min_pul = [joint1_min_pul,joint2_min_pul,joint3_min_pul,joint4_min_pul,joint5_min_pul,joint6_min_pul] #最小脉冲值joint_max_pul = [joint1_max_pul,joint2_max_pul,joint3_max_pul,joint4_max_pul,joint5_max_pul,joint6_max_pul] #最大脉冲值 #通过StandardFirmata协议来实例化一个ArduinoMega的对象board,传入参数端口号和波特率,默认8N1模式board = ArduinoMega("/dev/ttyUSB0",baudrate=115200) #使能驱动处于低电平board.digital[Joint1_EN].write(0)board.digital[Joint2_EN].write(0)board.digital[Joint3_EN].write(0)board.digital[Joint4_EN].write(0)board.digital[Joint5_EN].write(0)board.digital[Joint6_EN].write(0) '''函数名称:value_driver函数功能:控制对应的关节旋转到指定的角度值输入参数:joint为关节编号,angle为该关节目标角度值'''def value_driver(joint,angle):    #如果当前的脉冲迭代超出可运行范围,步进电机不执行,输出提示信息。这里是为了避免过转导致机械臂卡住    if joint_pul_flag[joint] < joint_min_pul[joint] - 30 or joint_pul_flag[joint] > joint_max_pul[joint] + 30:        print("ERROR.Beyond the limit...")    else:        diff_value = 0  #角度差值变量声明        step = 0    #需要的部署变量声明                #如果目标角度angle小于当前角度值        if angle < joint_value[joint]:                 joint_dir_flag[joint] = 0   #对应关节方向标记为0            board.digital[Joint_DIR[joint]].write(0)    #方向引脚为低电平            diff_value = joint_value[joint] - angle #计算角度差值            print("角度值减小.") #输出提示信息        else:            joint_dir_flag[joint] = 1   #对应关节方向标记为1            board.digital[Joint_DIR[joint]].write(1)    #方向引脚为高电平            diff_value = angle - joint_value[joint] #计算角度差值            print("角度值增加.") #输出提示信息        print("角度差值为:" + str(diff_value))   #输出计算好的角度差值                step = int(diff_value/joint_pro[joint]) #步数=角度值/减速比        print("需要脉冲数量:" + str(step) + ".")  #输出提示信息,需要的脉冲数量                #发送指定数量的脉冲进行驱动执行        while step > 0:            board.digital[Joint_STEP[joint]].write(1)            time.sleep(0.01)            board.digital[Joint_STEP[joint]].write(0)            time.sleep(0.01)            step = step - 1        print("脉冲执行完毕.")    #输出提示信息                step = int(diff_value/joint_pro[joint])        if joint_dir_flag[joint] == 0:            joint_pul_flag[joint] = joint_pul_flag[joint] - step    #更新当前脉冲标识        else:            joint_pul_flag[joint] = joint_pul_flag[joint] + step        print("脉冲计数迭代完毕.当前脉冲数为" + str(joint_pul_flag[joint]) + ".") #输出提示信息,脉冲累计量                joint_value[joint] = angle  #角度值迭代        print("角度迭代完毕.当前角度为" + str(joint_value[joint]) + ".")   #输出提示信息,当前角度值 '''函数名称:callback函数功能:作为回调函数执行'''    def callback(data):  joint6_angle = data.position[0]*360/6.28+90 #对应的关节弧度值转角度值值转    #判断当前角度值是否越界  if joint6_angle<0:        #如果当前角度值小于0,则角度值为0,避免出现负数    joint6_angle = 0     elif joint6_angle>180:        #如果当前角度值大于180,则角度值为180,避免出现角度超出    joint6_angle = 180  rospy.loginfo(rospy.get_caller_id() + ']--->Joint6 Angle :%d', joint6_angle)    #ros下输出提示信息  #value_driver(5,joint6_angle)   #角度值执行        #下同  joint5_angle = data.position[1]*360/6.28+90  if joint5_angle<0:    joint5_angle = 0  elif joint5_angle>180:    joint5_angle = 180  rospy.loginfo(rospy.get_caller_id() + ']--->Joint5 Angle :%d', joint5_angle)  value_driver(4,joint5_angle)   joint4_angle = data.position[2]*360/6.28+90  if joint4_angle<0:    joint4_angle = 0  elif joint4_angle>180:    joint4_angle = 180  rospy.loginfo(rospy.get_caller_id() + ']--->Joint4 Angle :%d', joint4_angle)  value_driver(3,joint4_angle)   joint3_angle = data.position[3]*360/6.28+90  if joint3_angle<0:    joint3_angle = 0  elif joint3_angle>180:    joint3_angle = 180  rospy.loginfo(rospy.get_caller_id() + ']--->Joint3 Angle :%d', joint3_angle)  value_driver(2,joint3_angle)   joint2_angle = data.position[4]*360/6.28+90  if joint2_angle<0:    joint2_angle = 0  elif joint2_angle>180:    joint2_angle = 180  rospy.loginfo(rospy.get_caller_id() + ']--->Joint2 Angle :%d', joint2_angle)  value_driver(1,joint2_angle)   joint1_angle = data.position[5]*360/6.28+90  if joint1_angle<0:    joint1_angle = 0  elif joint1_angle>180:    joint1_angle = 180  rospy.loginfo(rospy.get_caller_id() + ']--->Joint1 Angle :%d', joint1_angle)  value_driver(0,joint1_angle)  def driver():  rospy.init_node('SmallArmRobot_Driver', anonymous=True) #初始化节点,命名为SmallArmRobot_Driver  rospy.Subscriber('joint_states', JointState, callback)  #订阅joint_states话题,类型为JointState,当订阅到该话题执行callback函数  rospy.spin() if __name__ == '__main__':  driver()board.exit()

这里需要注意的是关于value_driver函数功能的理解。

这是我之前在验证的时候所截图的数据,value_dirver的作用就是将步进电机处理成舵机的方式,给角度值就转动到指定的角度值。目前我设计的算法存在的误差很大,而且细分引脚的动态切换效果也没有开发出来,这也是下一阶段我要完成的任务。大家也可以去浏览下SmallArmRobot官方提供的驱动代码,精度还是较高的。

# -*- coding: utf-8 -*-"""Created on Fri Oct 16 19:37:56 2020 @author: 嘉""" '''''''''''''''''''''''''Arduino Mega引脚IO声明'''''''''''''''''''''''''Joint1_DIR = 51Joint1_STEP = 50Joint1_MS3 = 49Joint1_MS2 = 48Joint1_MS1 = 47Joint1_EN = 46 Joint2_DIR = 45Joint2_STEP = 44Joint2_MS3 = 43Joint2_MS2 = 42Joint2_MS1 = 41Joint2_EN = 40 Joint3_EN = 39Joint3_MS1 = 38Joint3_MS2 = 37Joint3_MS3 = 36Joint3_STEP = 35Joint3_DIR = 34 Joint4_EN = 32Joint4_DIR = 31Joint4_STEP = 30 Joint5_EN = 28Joint5_DIR = 27Joint5_STEP = 26 Joint6_EN = 24Joint6_DIR = 23Joint6_STEP = 22 '''''''''''''''减速比例系数'''''''''''''''joint1_pro = 1.8joint2_pro = 0.8joint3_pro = 0.6joint4_pro = 0.375joint5_pro = 0.42joint6_pro = 0.375 '''''''''''''''标记变量声明'''''''''''''''joint1_pul_flag = 0joint1_dir_flag = 0joint1_value = 0 joint2_pul_flag = 105joint2_dir_flag = 0joint2_value = 90 joint3_pul_flag = 150joint3_dir_flag = 0joint3_value = 90 joint4_pul_flag = 230joint4_dir_flag = 0joint4_value = 90 joint5_pul_flag = 210joint5_dir_flag = 0joint5_value = 90 joint6_pul_flag = 240joint6_dir_flag = 0joint6_value = 90 '''''''''''''''限位标记声明'''''''''''''''joint1_min_pul = 0joint1_max_pul = 200 joint2_min_pul = 0joint2_max_pul = 210 joint3_min_pul = 0joint3_max_pul = 300 joint4_min_pul = 0joint4_max_pul = 460 joint5_min_pul = 0joint5_max_pul = 420 joint6_min_pul = 0joint6_max_pul = 480

这个位置是我们的IO_config文件的内容,主要是一些参数的定义。里面涉及到的减速比的计算大家可以推算一下,其实就是一个脉冲在当前的减速履带下可以让机械臂转到多少度,可能一个脉冲看不出角度。我是让对应关节分别在0度、90度、180度等情况下,统计需要多少个脉冲,做了一个除法来获取了减速比。步数=角度值/减速比。

大家可以来运行下smallarmrobot_description模型功能包,通过进度条来控制SmallArmRobot的各个关节,也可以在smallarmrobot_moveit_config功能包的demo.launch下来体验一下运动规划,大牛们也可以来自己使用moveit编程接口来控制机械臂~

欢迎大家就步进电机控制的算法做出自己的设计,也欢迎大家在已有的基础上进行自己的创意开发。共同学习,共同进步!

相关资料可通过以下链接下载,链接失效请联系古月居公众号!

提取码:b647

《Movelt玩转双臂机器人》在ROS当中开发机械臂不仅仅只是让机械臂动起来,更多的是要来学习MoveIt!编程接口的使用。此次教程将带领大家一起来设计一款基于MoveIt!的双臂机械臂,同时我们也会来设计一个示教仪来操控我们的机械臂。

(扫描二维码查看课程详情)

以上内容为用户投稿,如有侵权请联系我们删除!