一起来造个六轴步进电机机械臂吧

您所在的位置:网站首页 树莓派机械臂教程 一起来造个六轴步进电机机械臂吧

一起来造个六轴步进电机机械臂吧

2024-04-12 18:14| 来源: 网络整理| 查看: 265

一起来造个六轴步进电机机械臂吧——SmallArmRobot版 Li-Jianghao 分类:创客DIY教程 发布时间 2021.07.04阅读数 11521 评论数 2

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

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

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

话不多说,先看效果!!!

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

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

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

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

造这个机械臂首先肯定要有实物,这个机械臂的模型在网上大家是可以下载。我在这里为大家提供百度网盘的下载链接。https://pan.baidu.com/s/1nIB4dy-eBiX7VpYNtvFQFA提取码:a7mk --来自百度网盘超级会员V4的分享

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

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

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

然后就是我们的驱动板,开源大大们使用的是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,信号线、供电正极、供电负极)预留出来,便于外接其他的传感器,比如气泵吸盘、舵机等等。

同时串口、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应该是够用的。

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

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

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

#!/usr/bin/env python #coding:utf-8 #导入rospy库 import rospy #joint_state的msg是属于sensor from 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_angle180: #如果当前角度值大于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_angle180: 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_angle180: 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_angle180: 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_angle180: 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_angle180: 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 = 51 Joint1_STEP = 50 Joint1_MS3 = 49 Joint1_MS2 = 48 Joint1_MS1 = 47 Joint1_EN = 46 Joint2_DIR = 45 Joint2_STEP = 44 Joint2_MS3 = 43 Joint2_MS2 = 42 Joint2_MS1 = 41 Joint2_EN = 40 Joint3_EN = 39 Joint3_MS1 = 38 Joint3_MS2 = 37 Joint3_MS3 = 36 Joint3_STEP = 35 Joint3_DIR = 34 Joint4_EN = 32 Joint4_DIR = 31 Joint4_STEP = 30 Joint5_EN = 28 Joint5_DIR = 27 Joint5_STEP = 26 Joint6_EN = 24 Joint6_DIR = 23 Joint6_STEP = 22 '''''''''''''' '减速比例系数' '''''''''''''' joint1_pro = 1.8 joint2_pro = 0.8 joint3_pro = 0.6 joint4_pro = 0.375 joint5_pro = 0.42 joint6_pro = 0.375 '''''''''''''' '标记变量声明' '''''''''''''' joint1_pul_flag = 0 joint1_dir_flag = 0 joint1_value = 0 joint2_pul_flag = 105 joint2_dir_flag = 0 joint2_value = 90 joint3_pul_flag = 150 joint3_dir_flag = 0 joint3_value = 90 joint4_pul_flag = 230 joint4_dir_flag = 0 joint4_value = 90 joint5_pul_flag = 210 joint5_dir_flag = 0 joint5_value = 90 joint6_pul_flag = 240 joint6_dir_flag = 0 joint6_value = 90 '''''''''''''' '限位标记声明' '''''''''''''' joint1_min_pul = 0 joint1_max_pul = 200 joint2_min_pul = 0 joint2_max_pul = 210 joint3_min_pul = 0 joint3_max_pul = 300 joint4_min_pul = 0 joint4_max_pul = 460 joint5_min_pul = 0 joint5_max_pul = 420 joint6_min_pul = 0 joint6_max_pul = 480

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

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

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

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

链接:https://pan.baidu.com/s/1cEUfMHaa4bICSXhsn6B4xg 提取码:b647 --来自百度网盘超级会员V4的分享

控制系统运动规划硬件电路嵌入式从零开始

原创文章作者:Li-Jianghao。如若转载,请注明出处:古月居 https://www.guyuehome.com/34362

打赏 0

点赞 2

收藏 1

分享

微信 微博 QQ 图片 上一篇:树莓派Pico教程来啦——一起来点亮个LED吧 下一篇:在ROS系统下使用cv_bridge实现移动侦测——基于课程《ROS机器视觉开发入门》


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3