今天尝试了使用Openmv用串口发送数据,32接收,遇到了一些坑,但是最后还是实现了,难住我的地方并不是关于传输的代码,而是那个板子串口3不知道因为什么原因接收到的数据是错误的,这个原因正在寻找,找到了再记录。
Python提供了便捷的将数据打包的方法。我使用的方法就是将数据以二进制的方式打包然后通过串口逐字节发送。
struct模块的pack(fmt, v1, v2, ...) 函数提供了按照给定的格式(fmt),把数据封装成字符串(实际上是类似于c结构体的字节流)的功能,关与格式,有一个表定义了所有支持的字符及数据格式,如下:
Format | C Type | Python | 字节数 |
---|
x | pad byte | no value | 1 |
c | char | string of length 1 | 1 |
b | signed char | integer | 1 |
B | unsigned char | integer | 1 |
? | _Bool | bool | 1 |
h | short | integer | 2 |
H | unsigned short | integer | 2 |
i | int | integer | 4 |
I | unsigned int | integer or long | 4 |
l | long | integer | 4 |
L | unsigned long | long | 4 |
q | long long | long | 8 |
Q | unsigned long long | long | 8 |
f | float | float | 4 |
d | double | float | 8 |
s | char[] | string | 1 |
p | char[] | string | 1 |
P | void * | long |
microPython的串口使用方法也是很简单的,代码如下:
uart = pyb.UART(3, 115200) #串口3,波特率115200
uart.init(115200, bits=8, parity=None, stop=1) #8位数据位,无校验位,1位停止位
所以我在openmv的代码中定义了一个函数,来将传入的俩个参数打包然后通过串口发送,代码如下:
def send_data_packet(x, y):
temp = struct.pack("<bbii", #格式为俩个字符俩个整型
0xAA, #帧头1
0xAE, #帧头2
int(x), # up sample by 4 #数据1
int(y)) # up sample by 4 #数据2
uart.write(temp) #串口发送
为什么不直接通过串口发送字符串然后使用sscanf来解析呢:串口发送字符串(ASCAII编码)的方式比较简单, 用C语言的sscanf()语句解析从语法上是完全可以的, 但是在实际工程上测试,解析不是很稳定,易丢数据。 ASCAII编码易出错,缺乏纠错功能。所以我采用二进制传输的,整数直接发送,浮点数放大去除小数位,然后以C语言的int,short,char的拆分逐8位形式逐位发送。 接收以后先计算校验累加,再重组。这种方式长期使用稳定可靠。
这样发出来的数据(int,short型)都是低位的字节在前,比如发送整型数9,得到的数据为(0x09 0x00 0x00 0x00)
所以32端的解析函数为:
void Optical_Flow_Receive_Prepare(u8 data)
{
/* 局部静态变量:接收缓存 */
static u8 RxBuffer[10];
/* 数据长度 *//* 数据数组下标 */
static u8 _data_cnt = 0;
/* 接收状态 */
static u8 state = 0;
/* 帧头1 */
if(state==0&&data==TITLE1)
{
state=1;
}
/* 帧头2 */
else if(state==1&&data==TITLE2)
{
state=2;
_data_cnt = 0;
}
/* 接收数据租 */
else if(state==2)
{
RxBuffer[++_data_cnt]=data;
if(_data_cnt>=8)
{
state = 0;
Data_Processing(RxBuffer,_data_cnt);
}
}
/* 若有错误重新等待接收帧头 */
else
state = 0;
}
void Data_Processing(u8 *data_buf,u8 num)
{
int theta_org,rho_org;
/* 读取偏移角度原始数据 */
theta_org = (int)(*(data_buf+1)<<0) | (int)(*(data_buf+2)<<8) | (int)(*(data_buf+3)<<16) | (int)(*(data_buf+4)<<24) ;
theta_err = theta_org;
/* 读取偏移尺寸原始数据 */
rho_org = (int)(*(data_buf+5)<<0) | (int)(*(data_buf+6)<<8) | (int)(*(data_buf+7)<<16) | (int)(*(data_buf+8)<<24) ;
rho_err = rho_org;
}
通过这样的方式就能将Openmv计算的数据通过串口发送给32,过段时间我会做一个基于openmv+32的寻线小车,单双轨的寻线算法已经弄好了,做完以后我会发博客记录。