文章目录
- 前言
- 一、基本功能
- 二、主要代码
- 1.图像处理部分
- 2.舵机驱动部分
前言
本人第一次在csdn上发技术类文章,原谅在此多说一些废话。项目是自己的毕设,比较简单还望不要见笑,如果发现有什么问题欢迎指正。发文章的目的一方面是希望用自己微薄的能力的帮助有需要的人,另一方面想要记录下自己一步一步走过的痕迹,我不知道自己还能走多久,但只要我还在做这些东西就会记录下来,一起努力前进吧。
一、基本功能
主控采用的是树莓派4b,机械臂采用的是社团现成的幻尔机械臂,因为用不到六自由度所以把旋转机械手的舵机拆了下来,摄像头用的是淘宝买的树莓派摄像头20块左右,还买了支架和补光灯用来架设摄像头,夹取平台是自己建模用3d打印机打出来的。
基本功能就是在有物块在平台上时机械臂会自动夹取物体放置在指定位置,主要用到的就是OpenCV的一些库函数和像素点坐标转换一些简单数学运算以及舵机的控制。
二、主要代码
在写代码实现功能之前要先安装好树莓派的一些库,有以下几个东西需要安装好或调试好,安装好OpenCV的库(当时我搞了好长时间),开启摄像头功能,要能用摄像头显示视频,熟悉树莓派的一些基本使用,像是gpio,i2c之类的。
1.图像处理部分
写代码之前一些库的引用
import RPi.GPIO as GPIO
import cv2 as cv
import time
import math
import numpy as np
具体代码,其中摄像头的画面进行了一些截取,只显示放置平台部分方便后续处理,得到的图片坐标是物块在截取图片中以左上角为起点的像素点坐标,我采用的的等比缩放的方法得到实际坐标,即画面尺寸和实际尺寸之间有一定比例,后续要想得到机械臂坐标系坐标还要进行进一步转化。
#获取视频物体坐标
cap = cv.VideoCapture(0)#选择摄像头
ret,frame = cap.read()
zero = frame[115:365,195:445]#截取画面尺寸
cv.imwrite("tupian.jpg",zero)#存储图片
zero0 = cv.imread("/home/pi/Desktop/tupian.jpg",1)
zero1 = cv.GaussianBlur(zero0,(5,5),0)#高斯滤波
zero2 = cv.cvtColor(zero1,cv.COLOR_BGR2GRAY)#颜色空间转换
ret,zero3 = cv.threshold(zero2,110,255,cv.THRESH_BINARY_INV)#设置阈值,二值化处理
kai0 = np.ones((5,5),np.uint8)
zero4 = cv.morphologyEx(zero3,cv.MORPH_OPEN,kai0,iterations=3)#开运算
#判断是否有物体
if(np.mean(zero4)>0):
print("object")
contours,hierarchy = cv.findContours(zero4,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)#轮廓拟合
cnt0 = contours[0]
rect0 = cv. minAreaRect(cnt0)
box0 = cv.boxPoints(rect0)
box0 = np.int0(box0)
zero5 = cv.drawContours(zero0,[box0],0,(0,0,255),3)#画矩形框
M0 = cv.moments(cnt0)# 计算第一条轮廓的各阶矩,字典形式
center_x0 = int(M0['m10']/M0['m00'])
center_y0 = int(M0['m01']/M0['m00'])
cv. circle(zero0,(center_x0,center_y0),7,128,-1)#绘制中心点
str0 = '(' +str(center_x0)+',' +str(center_y0)+')'#把坐标转化为字符串
cv.putText(zero0,str0,(center_x0-50,center_y0+40),cv.FONT_HERSHEY_SIMPLEX,1,(255,0,0),2,cv.LINE_AA)#坐标点位绘制在图片上
print(center_x0,center_y0)#输出像素点坐标
#没有物体输出
else:
print("No object")
#关闭摄像头
cap.release()
cv.destroyAllWindows()
中间的转动角度计算与每个人的机械臂夹取方式与运动轨迹规划有关,且本人并没有学过机器人运动学相关知识这部分代码就不展示了,当时看了另一篇博客从中得到启发延伸到自己5自由度的机械臂。
2.舵机控制部分
原先的想法是用舵机驱动板PCA9685来驱动舵机,好处就是只需要用i2c通信就可以输出16路可控pwm,但由于在树莓派上下载的库始终效果不好,而且源码不好修改最终放弃了,值得一提的是因为操作不当还把树莓派的电源芯片烧了,好在最后修好了。
PCA9685
最后只能用树莓派引脚输出PWM和外接稳压电源来控制舵机,发送完pwm之后要进行消抖要不然数字舵机会不停抖动,由于代码过长且许多都是重复只有参数不同,所以只展示一部分。
GPIO.setmode(GPIO.BOARD)#GPIO采用BOAED模式
GPIO.setwarnings(False)#清除报错
#设置引脚
pins_0 = 12 #GPIO.1云台
pins_1 = 16 #GPIO.4下关节
pins_2 = 18 #GPIO.5上关节
pins_3 = 22 #GPIO.6调整关节
pins_4 = 32 #GPIO.26夹取关节
#引脚为输出模式
GPIO.setup(pins_0,GPIO.OUT)
GPIO.setup(pins_1,GPIO.OUT)
GPIO.setup(pins_2,GPIO.OUT)
GPIO.setup(pins_3,GPIO.OUT)
GPIO.setup(pins_4,GPIO.OUT)
#设置PWM频率为50Hz
pwm0 = GPIO.PWM(pins_0,50)
pwm1 = GPIO.PWM(pins_1,50)
pwm2 = GPIO.PWM(pins_2,50)
pwm3 = GPIO.PWM(pins_3,50)
pwm4 = GPIO.PWM(pins_4,50)
#初始/无动作姿态
pwm0.start(6.55)
pwm1.start(10.23)
pwm2.start(4.077)
pwm3.start(3.56)
pwm4.start(5)
time.sleep(0.2)#消抖
pwm0.ChangeDutyCycle(0)
pwm1.ChangeDutyCycle(0)
pwm2.ChangeDutyCycle(0)
pwm4.ChangeDutyCycle(0)
time.sleep(1)
实物图
还有许多功能可以改进,譬如多颜色识别等等,由于后续还有考试需要准备所以暂时只能做到这里。