首页 > 分享 > 用K210和stm32做一只桌面小机器人

用K210和stm32做一只桌面小机器人

        一直想尝试自己动手diy一个像Loona、Vector、Comoz等一样的宠物机器人,毕竟在网上见识过这类产品的人都知道它们的功能是非常神奇的存在,宠物机器人内置了丰富人机交互功能,会有情绪波动,会对人撒娇,会调皮捣蛋搞破坏,让人感觉仿佛这些真的是有生命的小精灵。然而这些产品的售价也不菲,而且网上许多购买过该产品的用户后来也都转二手卖出了,原因之一就是虽然这些宠物机器人有着像真宠物一样的行为,可实际时间久了就会发现其实它的功能来来回回就那几样,这时过了新鲜感的用户逐渐意识到机器人的一个一个表现其实不过是一串又一串预先配置的冷冰冰的代码罢了,因而自然也不会再被其所吸引。由于目前技术所限,宠物机器人还不足以真正做到“有生命”,这就是目前这一类产品的缺陷所在。

        我想自己做一个,其中一方面就是为了能自由开发和更新升级机器的功能,另一方面也是想尝试用自己的想法去仿一个简单的宠物行为,探索其中的奥妙。当然,我目前是刚刚入手,想做到像上述的产品那样的功能还是十分困难的,在这一个项目中,我计划设定的功能都是比较简单的,目前想的是先实现简单的交互后再慢慢升级,探索开发复杂的功能。当然这个小机器人同时也是我给女朋友准备的礼物,女孩子当然是无法拒绝一只乖巧可爱富有活力的小“宠物”的。

硬件说明

        以K210为主控,以迷你版的stm32为协处理器,K210与stm32采用串口通信。K210主要用于处理图像识别等大计算量的任务,stm32则是用于控制底层执行器,这次的执行器布置比较简单,只有两个舵机,一个负责让机器人抬头低头,一个负责左右转。

K210视觉识别模块

         这里K210是在一款名为K210视觉识别模块的产品中,在某橙色软件可以搜到。该产品可以外形像一个小相机,自带了摄像头和LCD屏幕。在购买到手把玩一段时间后我发现恰好拆了亚克力板把摄像头扭向下,整个相机倒过来,恰好就可以做一个小机器人的头,摄像头做眼睛,屏幕做脸,而其中内置的K210芯片,能够跑轻量级视觉算法,恰巧能做机器人的大脑。

K210视觉识别模块

迷你stm32

        这款stm32尺寸只有25.40*22.86mm大小,可以说是非常小巧玲珑了,非常适合用来做小体积的项目,它芯片的具体型号是stm32f103c8t6,其实就是最小系统板常用的那款型号。

mini_stm32

stm32扩展板

        这是自己绘制的用于连接的扩展板,结构非常简单,就两个舵机接口,以及串口通信接口,还有两个电源引脚线。

扩展板

舵机

        用的是MG90s,非常常见的小舵机。(某宝直接截的图,忽略图中的水印哈哈哈哈)

mg90s

软件说明

        程序主要是在K210官方例程的基础上改的,大体的布局就是K210跑视觉算法将相应的参数如识别出的人脸位置以及长度宽度,还有两个舵机的转角通过串口通信传输给stm32,而stm32则是将来自K210的转角值输入两个舵机中,从而是K210这颗大脑能指挥两个关节行动。

表情图像说明

    表情图像用的是B站一位up主何时登陆何时还 开源的oled表情包,详情可点击下面链接。开源代码教程stm32的oled表情显示

      不过我这边不像视频那样做,我直接把表情图像存入SD卡,再让K210从SD卡中读取图片并显示在LCD上,当然本质上都是一样的,就是逐帧显示照片形成动画。

所用表情图像

stm32程序说明

        stm32所用的程序也是在官方例程的基础上改的,比较简单,只是增加了两个舵机函数,让stm32不断地执行从K210读取到转角命令。以下是stm32的主程序代码,其余全部源码将在项目完成后公开。 

#include "AllHeader.h"

char buff_com[50];

msg_k210 k210_msg;

int main()

{

SystemInit();

Servo_Init1();

delay_init();

led_int();

USART2_init(115200);

LED = 0;

while(1)

{OLED_ShowNum(4, 1, k210_msg.class_n, 3);

if (k210_msg.class_n != 0)

{

if(k210_msg.class_n == 5)

{

Servo_SetAngle1(k210_msg.p1);

Servo_SetAngle0(k210_msg.p0);

k210_msg.class_n = 0;

delay_ms(10);

}

}

}

}

K210程序说明 

        K210使用的编译软件是CanMV,以下代码的主要功能是让机器人醒着的时候盯着人看,当醒着的时间到4000秒(约67分钟)时,它会进入睡眠状态,当睡够3000秒即50分钟时会自然苏醒,当然睡眠状态下也可以通过触碰触摸屏将它唤醒。

import sensor, image, time, lcd

import touchscreen as ts

from maix import KPU

from modules import ybserial

import binascii

import gc

import random

serial = ybserial()

file_template = "/sd/EMO/{:04d}.bmp"

img_paths_mode1 = []

sleep =[]

for i in range(8):

img_paths_mode1.append(file_template.format(i))

for i in range(10, 22, 1):

sleep.append(file_template.format(i))

img_paths_mode2 = [

"/sd/EMO/{:04d}.bmp".format(i) for i in range(0, 38, 5)

]

def choose_display_mode():

s=random.random()

if s < 0.7:

print(s)

return img_paths_mode1

else:

print(s)

return img_paths_mode2

def str_int(data_str):

bb = binascii.hexlify(data_str)

bb = str(bb)[2:-1]

hex_1 = int(bb[0])*16

hex_2 = int(bb[1],16)

return hex_1+hex_2

def send_data(x,y,w,h,p0,p1,msg):

start = 0x24

end = 0x23

length = 5

class_num = 0x05

class_group = 0xBB

data_num = 0x00

fenge = 0x2c

crc = 0

data = []

low = x & 0xFF

high = x >> 8& 0xFF

data.append(low)

data.append(fenge)

data.append(high)

data.append(fenge)

low = y & 0xFF

high = y >> 8& 0xFF

data.append(low)

data.append(fenge)

data.append(high)

data.append(fenge)

low = w & 0xFF

high = w >> 8& 0xFF

data.append(low)

data.append(fenge)

data.append(high)

data.append(fenge)

low = h & 0xFF

high = h >> 8& 0xFF

data.append(low)

data.append(fenge)

data.append(high)

data.append(fenge)

low = p0 & 0xFF

high = p0 >> 8 & 0xFF

data.append(low)

data.append(fenge)

data.append(high)

data.append(fenge)

low = p1 & 0xFF

high = p1 >> 8 & 0xFF

data.append(low)

data.append(fenge)

data.append(high)

data.append(fenge)

if msg !=None:

for i in range(len(msg)):

hec = str_int(msg[i])

data.append(hec)

data.append(fenge)

data_num = len(data)

length += len(data)

send_merr = [length,class_num,class_group,data_num]

for i in range(data_num):

send_merr.append(data[i])

for i in range(len(send_merr)):

crc +=send_merr[i]

crc = crc%256

send_merr.insert(0,start)

send_merr.append(crc)

send_merr.append(end)

global send_buf

send_buf = send_merr

last_time = time.time()

send_buf = []

x_ = 0

y_ = 0

w_ = 0

h_ = 0

p0_= 100

p0_0= 100

p1_= 57

p1_1= 57

k0=0.06

k1=0.04

X0=160

Y0=120

i = 0

sleepy =1

current_img_paths = choose_display_mode()

lcd.init()

ts.init()

status_last = ts.STATUS_IDLE

sensor.reset()

sensor.set_pixformat(sensor.RGB565)

sensor.set_framesize(sensor.QVGA)

sensor.skip_frames(time = 100)

clock = time.clock()

od_img = image.Image(size=(320,256))

anchor = (0.893, 1.463, 0.245, 0.389, 1.55, 2.58, 0.375, 0.594, 3.099, 5.038, 0.057, 0.090, 0.567, 0.904, 0.101, 0.160, 0.159, 0.255)

kpu = KPU()

kpu.load_kmodel("/sd/KPU/yolo_face_detect/yolo_face_detect.kmodel")

kpu.init_yolo2(anchor, anchor_num=9, img_w=320, img_h=240, net_w=320, net_h=256, layer_w=10, layer_h=8, threshold=0.7, nms_value=0.3, classes=1)

img_paths = [

"/sd/EMO/{:04d}.bmp".format(i) for i in range(0,511,2)

]

print(img_paths)

while True:

gc.collect()

clock.tick()

img = sensor.snapshot()

a = od_img.draw_image(img, 0,0)

od_img.pix_to_ai()

kpu.run_with_output(od_img)

dect = kpu.regionlayer_yolo2()

fps = clock.fps()

for l in dect :

a = img.draw_rectangle(l[0],l[1],l[2],l[3], color=(0, 255, 0))

x_ = l[0]

y_ = l[1]

w_ = l[2]

h_ = l[3]

p0_=round(p0_-(x_ +(h_/2)-X0)*k0+1)

p1_=round(p1_+(y_ +(w_/2)-Y0)*k0+1.5)

print(p0_)

print((x_ +(h_/2)-X0)*k0+1)

if sleepy==0:

if p0_>180:

p0_0=180

p0_=p0_0

elif p0_<50:

p0_0=50

p0_=p0_0

else:

p0_0=p0_

if p1_>82:

p1_1=82

p1_=p1_1

elif p1_<57:

p1_1=57

p1_=p1_1

else:

p1_1=p1_

else:

p0_0=100

p1_1=82

print(p0_0)

send_data(x_,y_,w_,h_,p0_0,p1_1,None)

serial.send_bytearray(send_buf)

print(p0_0)

(status, j, k) = ts.read()

if status_last != status:

print(status, j, k)

status_last = status

if status == ts.STATUS_MOVE:

sleepy=0

if sleepy==1:

if i <len(sleep):

img_path = sleep[i]

img_read = image.Image(img_path)

img2 = img_read.resize(300, 150)

img2 = img2.rotation_corr(z_rotation=180)

i=i+1

lcd.display(img2)

else:

i=0

else:

if i <len(current_img_paths):

img_path = current_img_paths[i]

img_read = image.Image(img_path)

img2 = img_read.resize(300, 150)

img2 = img2.rotation_corr(z_rotation=180)

i=i+1

lcd.display(img2)

else:

i=0

current_img_paths = choose_display_mode()

current_time = time.time()

if (current_time - last_time >= 4000)and(sleepy==0):

last_time = current_time

sleepy=1

print("I fall asleep", time.time())

elif (current_time - last_time >= 3000)and(sleepy==1):

last_time = current_time

sleepy=0

print("I wake up", time.time())

time.sleep(0.01)

kpu.deinit()

效果展示

为了突出效果,视频中我把机器人的睡眠时间和清醒时间都调短了,大约每过五六秒就会睡着,视频里看起来像是它要睡觉但我一直骚扰它。

结构说明

        如图是用solidworks建的模型,结构比较简单,仅两个自由度,一个在头部,用于抬头和低头,一个在身体,用于转身。

三维图

        如图为头部剖视图,里面放置了K210模块和舵机,灰色部分是轴承座。

头部剖视图

        如下图为身体的剖视图,ministm32安置在“心部”,可以说是它的心脏了,下边的舵机用于转动整个机身,再往下则是身体通过轴承与底座连接在一起。

身体剖视图

 组装

组装ing-1 组装ing-2 组装ing-3 完成组装~ smile~ 关灯扮鬼脸~ 最终效果

相关知识

[DIY]用STM32实现桌面宠物功能#开源
基于STM32的智能物流机器人控制设计
AI智能新物种,桌面级别电子宠物来了,乐天派桌面机器人体验
基于STM32的智能宠物监测自动喂养
STM32单片机做智能宠物狗项目
年轻人的第一台桌面电子宠物!乐天派桌面机器人功能详解
用Python写个桌面挂件,手把手带你做只桌面宠物~
赛博宠物:桌面娱乐机器人的新革命
Python实现桌面挂件,做一只可爱的桌面宠物~
stm32毕设项目选题大全

网址: 用K210和stm32做一只桌面小机器人 https://m.mcbbbk.com/newsview747581.html

所属分类:萌宠日常
上一篇: 武隆县宠物保健品企业大全
下一篇: 宠物智能机器人的设计与实现