视觉巡线小车——STM32+OpenMV(三)

目录

前言

一、OpenMV代码

二、STM32端接收数据

1.配置串口

2.接收数据并解析

总结



前言

         通过视觉巡线小车——STM32+OpenMV(二),已基本实现了减速电机的速度闭环控制。要使小车能够自主巡线,除了能够精准的控制速度之外,还需要得到小车偏离黑线的差值——即位置偏差。本文将通过OpenMV得到该偏差。

        建议参考内容:

        OpenMV巡线小车 | 星瞳科技

        项目实例 · OpenMV中文入门教程

 系列文章请查看:视觉巡线小车——STM32+OpenMV系列文章 


一、OpenMV代码

        1、初始化外设,如串口等;

        2、运行主要代码,拍照,图像二值化处理,线性回归处理,得到黑线与OpenMV中心线之间的像素点偏差以及偏离角度。

        线性回归算法的原理是寻找一条最佳的直线来拟合数据点集。在视 觉巡线中,这些数据点就是二值化图像中代表线条的像素点。算法会计算这些像素点 的平均值、方差等统计量,并通过最小二乘法等来找到一条最佳的直线。

        3、将得到数据打包,并发送给STM32。

THRESHOLD = (0, 23, -128, 127, -128, 127) # Grayscale threshold for dark things...
import sensor, image, time
from pyb import LED
from machine import UART
import structsensor.reset()
sensor.set_vflip(False)   # 设置OpenMV图像“水平方向进行翻转”
sensor.set_hmirror(False) # 设置OpenMV图像“竖直方向进行翻转”sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQQVGA) # 80x60 (4,800 pixels) - O(N^2) max = 2,3040,000.# 线性回归算法的运算量大,越小的分辨率识别的效果越好,运算速度越快#sensor.set_windowing([0,20,80,40])
sensor.skip_frames(time = 2000)     # WARNING: If you use QQVGA it may take seconds
clock = time.clock()                # to process a frame sometimes.myuart = UART(1, 115200)
# OpenMV RT 只有串口UART(1),对应P4-TX P5-RX; OpenMV4 H7 Plus, OpenMV4 H7, OpenMV3 M7 的UART(1)是P0-RX P1-TX
myuart.init(115200, bits=8, parity=None, stop=1)  #8位数据位,无校验位,1位停止位def send_data_packet(x, y):temp = struct.pack(">bbii",                #格式为小端模式俩个字符俩个整型0xAA,                       #帧头10xBB,                       #帧头2int(x), # up sample by 4    #数据1int(y)) # up sample by 4    #数据2myuart.write(temp)#串口发送
while(True):clock.tick()img = sensor.snapshot().binary([THRESHOLD])''' 截取一张图片,进行 “阈值分割”阈值分割函数image.binary()对图像进行二值化(binary:二元的;由两部分组成的)得到的效果是:将阈值颜色变成白色,非阈值颜色变成黑色'''line = img.get_regression([(100,100)], robust = True)#调用线性回归函数# 对所有的阈值像素进行线性回归# 线性回归的效果就是将我们视野中“二值化”分割后的图像回归成一条直线if (line):rho_err = abs(line.rho())-img.width()/2# 计算我们的直线相对于中央位置偏移的距离(偏移的像素)# abs()函数:返回数字的绝对值  line.rho():返回霍夫变换后的直线p值。if line.theta()>90:theta_err = line.theta()-180else:theta_err = line.theta()# 进行坐标的变换:y轴方向为0°,x轴正方向为90°,x轴负方向为-90°img.draw_line(line.line(), color = 127)print(rho_err,line.magnitude(),theta_err)#line.magnitude()返回一个表示“线性回归效果”的值,这个值越大,线性回归效果越好;# 如果越接近于0,说明我们的线性回归效果越接近于一个圆,效果越差if line.magnitude()>8:send_data_packet(rho_err,theta_err)LED(1).off()else:LED(1).on()LED(2).off()else:LED(2).on()pass#print(clock.fps())

处理前后结果对比:

二、STM32端接收数据

1.配置串口

         由于OpenMV与STM32之间采用串口通讯,所以同样需要在CubeMX进行配置:

 同理也需要开启中断,这里不再赘述,参考上一篇文章。

2.接收数据并解析

        需要加入以下代码,进行初始化:

//全局变量
unsigned char OpenMV_Buf;
int theta_org,rho_org;//初始化处加入
HAL_UART_Receive_IT(&huart2,&OpenMV_Buf,1);

        在串口2中断回调函数中处理如下:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart->Instance == USART2 ){
//       printf("OK\n");Rec_proce(OpenMV_Buf);                 HAL_UART_Receive_IT(&huart2,&OpenMV_Buf,1); }
}
void Rec_proce(u8 data)
{/* 局部静态变量:接收缓存 */static u8 RxBuffer[10];/* 数据长度 *//* 数据数组下标 */static u8  data_cnt = 0;/* 接收状态 */static u8 state = 0;/* 帧头1 */if(state==0&&data==0xAA){state=1;}/* 帧头2 */else if(state==1&&data==0xBB){state=2;data_cnt = 0;}/* 接收数据租 */else if(state==2){RxBuffer[data_cnt++]=data;if(data_cnt>=8){state = 0; rho_org   = (int)((RxBuffer[0]<<24) | (RxBuffer[1]<<16) | (RxBuffer[2]<<8) | (RxBuffer[3]));  theta_org = (int)((RxBuffer[4]<<24) | (RxBuffer[5]<<16) | (RxBuffer[6]<<8) | (RxBuffer[7]));            printf("%d,%d\n",rho_org,theta_org);
//            for(int i=0;i<8;i++) printf("%d",RxBuffer[i]);
//            printf("\n\n\n\n");}}/* 若有错误重新等待接收帧头 */elsestate = 0;
}

         如果要使用printf进行打印输出,则需要加入以下代码,这里以串口3为例,如下:

#include <stdio.h>
int fputc(int ch,FILE *f)
{while((USART3->SR & 0x40) == 0);USART3->DR = (uint8_t)ch;return ch;
}

总结

通过本文,使用OpenMV得到中心线偏离黑线的像素点偏差和角度偏差,再将数据打包通过串口发送给STM32,最后在STM32上将数据解析出来,以便后续控制运用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/47583.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hadoop3:MR程序处理小文件的优化办法(uber模式)

一、解决方案 1、在数据采集的时候&#xff0c;就将小文件或小批数据合成大文件再上传HDFS&#xff08;数据源头&#xff09; 2、Hadoop Archive&#xff08;存储方向&#xff09; 是一个高效的将小文件放入HDFS块中的文件存档工具&#xff0c;能够将多个小文件打包成一个HAR…

深入理解 Linux Zero-copy 原理与实现策略图解

用户态和内核态 一般来说&#xff0c;我们在编写程序操作 Linux I/O 之时十有八九是在用户空间和内核空间之间传输数据&#xff0c;因此有必要先了解一下 Linux 的用户态和内核态的概念。 从宏观上来看&#xff0c;Linux 操作系统的体系架构分为用户态和内核态&#xff08;或者…

SourceCodester v1.0 SQL 注入漏洞(CVE-2023-2130)

前言 CVE-2023-2130是一个影响SourceCodester Purchase Order Management System v1.0的SQL注入漏洞。此漏洞的存在是由于应用程序未能正确过滤和验证用户输入&#xff0c;使得攻击者可以通过SQL注入来执行任意SQL命令&#xff0c;从而对数据库进行未授权的访问和操作。 在利…

15Kg级无人机降落伞系统技术详解

15Kg级无人机降落伞系统由以下几个主要部分组成&#xff1a; 1. 降落伞主体&#xff1a;采用轻质高强度的材料制成&#xff0c;能够承受无人机在降落过程中产生的冲击力&#xff0c;并确保无人机平稳安全地着陆。 2. 伞绳与连接机构&#xff1a;伞绳负责连接降落伞主体与无人机…

1-2、truffle与webjs亲密接触(truffle智能合约项目实战)

1-2、truffle与webjs亲密接触&#xff08;truffle智能合约项目实战&#xff09; 5&#xff0c;web3调用智能合约6&#xff0c;Ganache 5&#xff0c;web3调用智能合约 在前面已经完成简单的合约编写 使用web3调用此函数 Web端的代码使用web3进行智能合约的访问 首先在cmd以…

使用9种方法隐藏和显示元素

<!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>使用9种方法隐藏和显示元素</title><sty…

火影评论词云图

背景介绍 词云图(Word cloud)又称文字云,是一种文本数据的图片视觉表达方式,一般是由词汇组成类似云的图形,用于展示大量文本数据。 我收集了豆瓣网站上火影博人传下方的网友评论&#xff0c;以评论为数据基础制作了词云图。 准备工作 安装两个模块&#xff1a;词云模块和结…

verilog行为建模(四):过程赋值

目录 1.两类过程赋值2.阻塞与非阻塞赋值语句行为差别举例13.阻塞与非阻塞赋值语句行为差别举例24.阻塞与非阻塞赋值语句行为差别举例35.举例4&#xff1a;非阻塞赋值语句中延时在左边和右边的差别 微信公众号获取更多FPGA相关源码&#xff1a; 1.两类过程赋值 阻塞过程赋值执…

HTML零基础自学笔记(上)-7.18

HTML零基础自学笔记&#xff08;上&#xff09; 参考&#xff1a;pink老师一、HTML, Javascript, CSS的关系是什么?二、什么是HTML?1、网页&#xff0c;网站的概念2、THML的基本概念3、THML的骨架标签/基本结构标签 三、HTML标签1、THML标签介绍2、常用标签图像标签&#xff…

网易易盾图标点选验证码识别代码

简介 网易图标点选一直都是一个大难题&#xff0c;如上图所示。难点之一是图标变幻莫测&#xff0c;很难刷出有重复的图标&#xff0c;所以使用传统等等方式去标注、识别具有较大的难度。 经过我们大量的数据标注&#xff0c;终于完成了这款验证码的识别。 目前我们提供两种识…

Shell程序设计

各位看官&#xff0c;从今天开始&#xff0c;我们进入新的专栏Shell学习&#xff0c;Shell 是操作系统的命令行界面&#xff0c;它允许用户通过输入命令与操作系统交互。常见的 Shell 有 Bash 和 Zsh&#xff0c;它们可以执行用户输入的命令或运行脚本文件。Shell 广泛应用于系…

昇思25天学习打卡营第5天 | 数据集

在探索MindSpore深度学习框架中的数据集处理过程&#xff0c;我对其数据加载和处理流程有了深入的了解。MindSpore提供了一套功能强大的工具&#xff0c;可以有效地处理和转换数据&#xff0c;确保了数据预处理的效率和质量。以下是我从本次学习中得到的几点主要心得&#xff1…

[算法题]重排字符串

题目链接: 重排字符串 首先找出出现次数最多的字符和其出现次数, 如果该字符的出现次数大于 (字符串的长度 1) / 2, 那么该字符串必然不能重排, 如果该字符的出现次数小于等于 (字符串的长度 1) / 2, 是可以重排的, 重排方式如下图所示: 先以间隔的方式将出现次数最多的字符…

MRD、BRD、PRD

MRD、BRD、PRD是产品开发过程中不同的文档类型&#xff0c;‌它们各自具有特定的目的和内容&#xff0c;‌以支持产品从概念到实现的各个阶段。‌ MRD&#xff08;‌Market Requirement Document&#xff09;‌&#xff0c;‌即市场需求文档&#xff0c;‌侧重于市场和用户需求…

宇航人今年部分瓶装饮料铅浓度超标,采购成本连年大增

《港湾商业观察》廖紫雯 日前&#xff0c;内蒙古宇航人沙产业股份有限公司&#xff08;以下简称&#xff1a;宇航人&#xff09;递表港交所&#xff0c;保荐机构为中银国际&#xff0c;宇航人国内运营主体为内蒙古宇航人高技术产业有限责任公司、内蒙古宇航人沙产业股份有限公…

【SASS/SCSS(三)】样式的复用与动态计算(@mixin和@function)

目录 一、mixin 1、定义复用的样式代码&#xff0c;接受传参&#xff0c;搭配include使用。 位置传参 关键词传参 ...语法糖接受传入的任意参数 2、在mixin中使用content&#xff0c;获取外部对mixin的追加内容 二、function 三、字符串——值得注意的点 很多时候&#…

Python酷库之旅-第三方库Pandas(037)

目录 一、用法精讲 116、pandas.Series.div方法 116-1、语法 116-2、参数 116-3、功能 116-4、返回值 116-5、说明 116-6、用法 116-6-1、数据准备 116-6-2、代码示例 116-6-3、结果输出 117、pandas.Series.truediv方法 117-1、语法 117-2、参数 117-3、功能 …

【初阶数据结构】深度解析七大常见排序|掌握底层逻辑与原理

初阶数据结构相关知识点可以通过点击以下链接进行学习一起加油&#xff01;时间与空间复杂度的深度剖析深入解析顺序表:探索底层逻辑深入解析单链表:探索底层逻辑深入解析带头双向循环链表:探索底层逻辑深入解析栈:探索底层逻辑深入解析队列:探索底层逻辑深入解析循环队列:探索…

原来隐藏一个DOM元素可以有这么多种方式,最后一种你肯定不知道

我们在日常编码的时候&#xff0c;隐藏一个 dom 元素有很多种方式&#xff0c;今天我们来盘点一下隐藏 dom 元素有哪些方式&#xff0c;最后一种&#xff0c;你绝对没有用过。 display: none 作为经常用来隐藏元素的 css 属性&#xff0c;display: none 相信大家并不陌生&…

【常见开源库的二次开发】基于openssl的加密与解密——MD5算法源码解析(五)

一、MD5算法分析 &#xff1a; 1.1 关于MD5 “消息摘要”是指MD5&#xff08;Message Digest Algorithm 5&#xff09;算法。MD5是一种广泛使用的密码散列函数&#xff0c;它可以生成一个128位&#xff08;16字节&#xff09;的散列值。 RFC 1321: MD5由Ronald Rivest在1992…