不会吧不会吧,不会还有人不知道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_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 = 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的分享
评论(2)
您还未登录,请登录后发表或查看评论