文章目录
- 前言
- 一、四足步态
- 二、视觉抓取
- 三、远程遥控
谢绝转载,无作者许可不可用做其他用途(如教育展示产品、课程设计或毕业设计等)
前言
衔接上一篇文章,这篇文章主要来介绍项目的初步实现
一、四足步态
可以知道,该四足机器人由八个舵机组成,其中大腿四个(①②③④),小腿四个(⑤⑥⑦⑧),如下图所示:
- 第一,组装。在组装时先将每个舵机的状态调到90°,按90°状态进行组装。
- 第二,角度。你需要知道这八个舵机点位的的转动区间,比如哪个点是0°,哪个点是180°,做好记录后才能更方便的去设计。
- 第三,运动分析。其实可参考小猫的步态,通过观察发现有两种走法,一是在同一时刻有三支腿是同时踩在地上的只有一只腿提起来摆动,二是同一时刻成对角的两条腿动,两两交替行走。
我这里设计用成对角的两条腿交替运动的方法,需要注意的是在每次移动时都要将小腿提起来,再摆动大腿,然后放下小腿,这样才能控制移动到你想要的方向,具体设计如下:
- 首先初始化各点位状态。这里初始化也是有讲究的,需要根据你想要移动的幅度去设计,可以45°,可以90°等,这里我选用45°,即大腿初始化位置如下图所示,小腿初始化皆为90°。
void Init(void)
{
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL1, period, angle_90); //大腿
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL2, period, angle_90);
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL3, period, angle_135);
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL4, period, angle_45);
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL1, period, angle_90); //小腿
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL2, period, angle_90);
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL3, period, angle_90);
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL4, period, angle_90);
}
- 向前迈进
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL1, period, angle_45);
rt_thread_mdelay(100);
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL1, period, angle_0);
rt_thread_mdelay(100);
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL1, period, angle_90);
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL4, period, angle_45);
rt_thread_mdelay(100);
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL4, period, angle_90);
rt_thread_mdelay(100);
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL4, period, angle_90);
rt_thread_mdelay(400);
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL4, period, angle_45);
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL1, period, angle_45);
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL3, period, angle_45);
rt_thread_mdelay(100);
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL3, period, angle_90);
rt_thread_mdelay(100);
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL3, period, angle_90);
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL2, period, angle_45);
rt_thread_mdelay(100);
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL2, period, angle_180);
rt_thread_mdelay(100);
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL2, period, angle_90);
rt_thread_mdelay(400);
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL3, period, angle_135);
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL2, period, angle_135);
- 原地转圈。让每只脚顺/逆时针移动90°,然后同时摆动大腿点位
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL1, period, angle_45);
rt_thread_mdelay(100);
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL1, period, angle_90);
rt_thread_mdelay(100);
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL1, period, angle_90);
rt_thread_mdelay(100);
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL2, period, angle_45);
rt_thread_mdelay(100);
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL2, period, angle_180);
rt_thread_mdelay(100);
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL2, period, angle_90);
rt_thread_mdelay(100);
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL3, period, angle_45);
rt_thread_mdelay(100);
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL3, period, angle_180);
rt_thread_mdelay(100);
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL3, period, angle_90);
rt_thread_mdelay(100);
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL4, period, angle_45);
rt_thread_mdelay(100);
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL4, period, angle_90);
rt_thread_mdelay(100);
rt_pwm_set(pwm3_dev, PWM_DEV_CHANNEL4, period, angle_90);
rt_thread_mdelay(400);
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL1, period, angle_0);
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL2, period, angle_90);
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL3, period, angle_90);
rt_pwm_set(pwm2_dev, PWM_DEV_CHANNEL4, period, angle_0);
二、视觉抓取
通过OpenMV摄像头去识别物块且区分颜色,利用机械臂去抓取物块并放置于不同盒子里,摄像头视角可实时在PC/iPhone显示。
- 1. 摄像头
(1) WiFi无线图传
import sensor, image, time, network, usocket, sys
SSID ='Bit_Dong' # Network SSID
KEY ='1234567890' # Network key (must be 10 chars)
HOST = '' # Use first available interface
PORT = 8080 # Arbitrary non-privileged port
sensor.reset()
sensor.set_framesize(sensor.QQVGA)
sensor.set_pixformat(sensor.GRAYSCALE)
wlan = network.WINC(mode=network.WINC.MODE_AP)
wlan.start_ap(SSID, key=KEY, security=wlan.WEP, channel=2)
def start_streaming(s):
client, addr = s.accept()
client.settimeout(2.0)
data = client.recv(1024)
client.send("HTTP/1.1 200 OK\r\n" \
"Server: OpenMV\r\n" \
"Content-Type: multipart/x-mixed-replace;boundary=openmv\r\n" \
"Cache-Control: no-cache\r\n" \
"Pragma: no-cache\r\n\r\n")
clock = time.clock()
while (True):
clock.tick() # Track elapsed milliseconds between snapshots().
frame = sensor.snapshot()
cframe = frame.compressed(quality=35)
header = "\r\n--openmv\r\n" \
"Content-Type: image/jpeg\r\n"\
"Content-Length:"+str(cframe.size())+"\r\n\r\n"
client.send(header)
client.send(cframe)
while (True):
s = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM)
try:
s.bind([HOST, PORT])
s.listen(5)
s.settimeout(3)
start_streaming(s)
except OSError as e:
s.close()
(2) 色块识别
①寻找最大色块
def find_max(blobs):
max_size=0
for blob in blobs:
if blob[2]*blob[3] > max_size:
max_blob=blob
max_size = blob[2]*blob[3]
return max_blob
②颜色辨识,读取20次判断结果,取众数并传到MCU
for i in range(20):
for blob in img.find_blobs([thresholds[0]], roi=ROI, x_stride=10, y_stride=5,pixels_threshold=10, area_threshold=10, merge=True): #模板匹配函数
x=blob.area()
for blob in img.find_blobs([thresholds[1]], roi=ROI, x_stride=10, y_stride=5,pixels_threshold=10, area_threshold=10, merge=True): #模板匹配函数
y=blob.area()
if x>y:
x_num+=1
else:
y_num+=1
if x_num>y_num:
uart.write("1")
else:
uart.write("2")
- 2. 机械臂
我这里为四自由度的舵机,抓取释放可分为如下四个步骤进行。
(1)初始化
rt_pwm_set(pwm4_dev, PWM_DEV_CHANNEL1, period, angle_90);
rt_thread_mdelay(100);
rt_pwm_set(pwm4_dev, PWM_DEV_CHANNEL2, period, angle_90);
rt_thread_mdelay(100);
rt_pwm_set(pwm4_dev, PWM_DEV_CHANNEL3, period, angle_135);
rt_thread_mdelay(100);
rt_pwm_set(pwm4_dev, PWM_DEV_CHANNEL4, period, angle_90);
rt_thread_mdelay(400);
(2)向下抓取
rt_pwm_set(pwm4_dev, PWM_DEV_CHANNEL1, period, angle_45); /* 爪子打开*/
rt_thread_mdelay(100);
rt_pwm_set(pwm4_dev, PWM_DEV_CHANNEL2, period, angle_180);
rt_thread_mdelay(100);
rt_pwm_set(pwm4_dev, PWM_DEV_CHANNEL4, period, angle_90);
rt_thread_mdelay(400);
(3)抓到搬运
rt_pwm_set(pwm4_dev, PWM_DEV_CHANNEL1, period, angle_110); /* 爪子闭紧*/
rt_thread_mdelay(300);
rt_pwm_set(pwm4_dev, PWM_DEV_CHANNEL2, period, angle_90);
rt_thread_mdelay(100);
(4)放盒回正
rt_pwm_set(pwm4_dev, PWM_DEV_CHANNEL4, period, angle_165);
rt_thread_mdelay(400);
rt_pwm_set(pwm4_dev, PWM_DEV_CHANNEL1, period, angle_45);
rt_thread_mdelay(400);
三、远程遥控
MCU之间采用蓝牙进行通信
- 遥控器
通过用ADC采集四个电位器信息和按键键值控制四足机器人或机械臂运动。
1. 数据采集
rt_uint8_t typeId=key_sw1_status;
uploadpackT.linear = value[0]/22.75; // 4095/22.75=180°
uploadpackT.angular = value[1]/22.75;
uploadpackT.vra = value[2]/22.75;
uploadpackT.vrb = value[3]/22.75;
uploadpackT.switch_code = key_sw2_status;
2. 打包
int8_t pack(ProtocolBufferT *handler,uint8_t type, void* src, uint16_t size, uint8_t** dest,uint16_t* dest_size )
{
assert(size+7 < handler->max_size);
assert(type>0 && type < 128);
handler->data[0] = PROTO_HEAD0;
handler->data[1] = PROTO_HEAD1;
handler->data[2] = size & 0xff;
handler->data[3] = size >> 8;
handler->data[4] = type;
memcpy(handler->data+5, src, size );
handler->pack_len = size;
uint16_t sum = calc_sum(handler);
handler->data[size+5] = sum & 0xff;
handler->data[size+6] = sum >> 8;
handler->data_ptr = size+7 ;
if (dest) (*dest) = handler->data;
if (dest_size) (*dest_size) = handler->data_ptr;
return 0;
}
3. 验包
int8_t check_pack(ProtocolBufferT *handler)
{
int8_t check_header = 1;
do {
check_header = 0;
if (!(handler->data[0] == PROTO_HEAD0 && handler->data[1] == PROTO_HEAD1))
{
update_next_header(handler,1);
check_header = 1;
}
if (handler->data_ptr < 5 ) {
handler->status = 0;
return 0;
}
handler->pack_len = *((uint16_t*) (&handler->data[2]));
if (handler->pack_len + 7 >= handler->max_size)
{
update_next_header(handler,1);
check_header = 1;
}
} while(check_header);
if (handler->data_ptr < handler->pack_len +7 ) {
handler->status = 0;
return 0;
}
uint16_t checksum = handler->data[handler->pack_len + 5] + (handler->data[handler->pack_len + 6]<<8);
uint16_t sum = calc_sum(handler);
if (sum == checksum)
{
handler->status = 1;
handler->type = handler->data[4];
return handler->type;
}
// else checksum failed
printf("checksum failed\n");
for(int i = 0 ; i < handler->pack_len; ++i) {
printf("%02x ", handler->data[i]);
}
update_next_header(handler,1);
handler->status = 0;
return 0;
}
技术交流,联系下方wx即可