本文作者水平尚且有限,如有不对的地方,期待您的指正。
我参考了一些文章,很多博主是用stm32做下位机来做控制,但我目前还未接触,所以用的51单片机。
萌发了一个想法,做智能捡网球的小车,先从机械臂上做起,机械臂上的细节也很多,一个一个问题慢慢克服。
K210视觉机械臂的设想:
K210摄像头是固定的,要夹取的物品也是静止不动的
C51端利用最小单片机系统,控制舵机,一个机械臂由多个舵机("手臂关节")组成。
工作原理:K210识别出要夹取的物体并将所要夹取的物体横纵坐标值(X,Y)传输给51单片机,X和Y的值通过数学计算,控制舵机的上下左右平移,到达目标位置,实现夹取的功能。
构想图如下:
上面是一个整体的畅想,一步一步来,这篇文章仅谈如何实现C51和K210的通信,实现将坐标传送过去,并能接收到。
k210发送数据:
from machine import UART,Timer
from fpioa_manager import fm
import time
fm.register(6, fm.fpioa.UART1_RX, force=True)
fm.register(7, fm.fpioa.UART1_TX, force=True)
hengzuobiao = 256
zongzuobiao = 257
class K210_transmit():
head1 = 0xAA
x = hengzuobiao
y = zongzuobiao
head2 = 0xAA
mo = 0xab
K210 = K210_transmit()
def K210_data():
data=bytearray([K210.head1,
K210.x>>8,K210.x,
K210.y>>8,K210.y,
K210.head2,K210.mo])
return data
uart = UART(UART.UART1, 9600, read_buf_len=4096)
while True:
uart.write(K210_data()) #数据回传
time.sleep(1)
坐标值先直接给出:hengzuobiao = 256 zongzuobiao = 257。我们先实现通信,后续再做K210端返回识别物体的坐标。
代码解析:k210能自由映射引脚,我将引脚6设为RXD,引脚7设为TXD。定义了一个类,用来保存串口要发送的信息。设计了head1 = 0xAA 和 mo = 0xab 将核心数据"夹住",这样的话,在51端,我们就可以判断是否接收到了这一串数据。
uart = UART(UART.UART1, 9600, read_buf_len=4096)
串口的初始化配置,k210共两个串口,这个是串口一,波特率设置的是9600,因为我这边出厂的HC-05蓝牙模块没有内部修改,一直是9600,为保持一致。(HC-05蓝牙用在后面的测试),uart.write()用来发送。
实验心得:一步一步来,到这一步的时候,我们有些担心是否现在发送的数据就是上面代码的值?这个发送有没有出错?先确认这一步的发送是正确的,这样等我们慢慢往后搭建下一步接收的时候,就不用再去找之前发送的问题了;这里我用HC-05蓝牙模块来测试数据的发送。HC-05蓝牙模块的使用超级简单入门,如有疑问,可以参考我这篇文章: C51单片机利用HC-05蓝牙模块实现手机点灯_良辰353的博客
启动运行K210那边的程序,接线图与现象图如下:
从现象可见,数据发送成功!我们的核心数据在里面! X = 01 *256 + 00 = 256; Y =01 *256 +01 = 257
可以看见我们的每一个发送的数据包是七位数据。
在这之前,绕进了一个坑,因为k210在发送数据的时候只能发字符串类的,就是uart.write(),直接发256,257是发不过去的。然后思路就是把257,257转为"256","257",发过去在提取出来整型,可51端那里,用不了atoi()函数,这是一个可以把字符型转为整型的函数,在C编译器能用,在Keil里会提醒少一个文件,去网上找也有,全是付费下载的,我真的晕...后来参考其他博主看到这个方法了。打包在一起,又都是整型,在51端,做个乘256的计算就OK了,非常nice!
C51接收数据:
#include <REGX52.H>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define MAX_SIZE 8
unsigned char Buffer[MAX_SIZE];
unsigned char dat;
unsigned int x,y;
unsigned int Receive_count = 0;
void UART_init()
{
TMOD = 0x20;
TH1 = 0xfd;
TL1 = 0xfd;
SM0 = 0;
SM1 = 1;
REN = 1;
TR1 = 1;
EA = 1;
ES =1 ;
}
void UART_SendByte(unsigned char Byte)
{
SBUF = Byte;
while(TI == 0);
TI = 0;
}
char putchar(char c)//閲嶅畾鍚?
{
UART_SendByte(c);
return c;
}
void main()
{
UART_init();
while(1)
{
}
}
void UART_INTERRUPT() interrupt 4
{
dat = SBUF;
RI = 0;//手动置0是下一次能够进入中断的关键
if(dat != 0xab)//判断是否接收完成我的那串数据了?
{
Buffer[Receive_count] = dat;
Receive_count ++;
if(Receive_count == MAX_SIZE)
{
x = Buffer[1]*256+Buffer[2];
y = Buffer[3]*256+Buffer[4];
if(Buffer[0] == 0xAA && Buffer[5] == 0xAA && x == 256 && y == 257)
{
printf("the test was successful");
}
else
{
printf("the test failed!");
}
}
}
}
这里先总结一下我学习到的51单片机的串口通信:
void UART_init()
{
TMOD = 0x20;
TH1 = 0xfd;
TL1 = 0xfd;
SM0 = 0;
SM1 = 1;
REN = 1;
TR1 = 1;
EA = 1;
ES =1 ;
}
串口的初始化,可以自己在 stc-isp上勾选生成,勾选9600波特率,这点要切记,两单片机之间的通信,波特率必须保持一致。模式一,八位数据等,EA,ES是总中断。
如图你可以看到51单片机串口通信的工作流程,RX和TX分别是发送数据和接收数据,比如,本来RI和TI两个管理着一个"闸门",内部配置好的RI和TI都是0,当接收到数据时,系统会将RI自动置1,只要我们将后面的"闸门"配置好都接通,这时就是打开中断了,就可以写中断函数(51的串口通信中断是interrupt 4),同理发送数据的时候是TI=1 ,同样地打开中断。但是寄存器SBUF一次性只能存一个字节的数据,如果像前面我们发的七个数据都想过去,就需要进入中断函数后,再手动置0,等待下一个数据发送时,RX---->致RI = 1再进中断,再提取数据。
SBUF寄存器的介绍:SBUF是用来存取数据的,在51单片机的系统内部,但dat=SBUF 和SBUF=dat是不一样的,dat = SBUF是我们自己创的一个变量dat来存装接收到的数据,SBUF=dat则是将数据发送出去,是同一个SBUF,但是功能不同,参考文章中有讲,底层配置时其实是两个的,这里不多再深探索。
定义一个数组用来存装每次传来的数据是很关键的一步,我之前以为dat = SBUF就可以一次性把数据都接来了,然后我就自以为的定义了一个dat[7],以为数据分别装进每个[0],[1],[2]里面了,后来怎么都提不出来,因为根本就没有dat[2],dat[3]这些数!记住,我们的中断函数一次性接收到一个字节的数据后就跳出中断了,所以我们想提取出我们的核心数据,就要写个数组Buffer[],每次接收到一个数据后就赶紧把它存进去,这时候,我们K210发送的数据mo = 0xab就有作用了,作为我们发送的一串数据的末尾,就能用来判断数据的发送完成。
void UART_SendByte(unsigned char Byte)
{
SBUF = Byte;
while(TI == 0);
TI = 0;
}
char putchar(char c)
{
UART_SendByte(c);
return c;
}
这两段函数是为了实现printf函数,比如说我们写printf("Hello,world");先将寄存器SBUF为"H",TI = 0表示接收完成,while(TI ==0);是判断是否接收完成,如果没有完成,就是TI ==0,让程序在循环里在等等,然后退出循环后,将TI打成0,等'e',进入....最后实现打印在串口通信助手上的效果,可参考之前有写的一篇51的printf()51单片机也能用printf()函数进行调试_良辰353的博客
终于到这一刻了!x,y就是我们想要的坐标值。
接线图:
一键启动发送数据
HEX显示不勾选,因为我们发的是字符串数据
波特率9600同C51同K210
外界问题总结:
烧录HEX文件时,串口调试器要关闭,因为此时是PC连了51占用了串口。
烧录时,先拔开与K210的接线,因为K210在通电,会干扰到相接的51的引脚。文章来源:https://www.toymoban.com/news/detail-631704.html
现象:文章来源地址https://www.toymoban.com/news/detail-631704.html
到了这里,关于K210视觉机械臂发送坐标值(与下位机通信)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!