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

news2024/11/13 15:06:58

目录

前言

一、OpenMV代码

二、STM32端接收数据

1.配置串口

2.接收数据并解析

总结



前言

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

        建议参考内容:

        OpenMV巡线小车 | 星瞳科技

        项目实例 · 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 struct

sensor.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,                       #帧头1
                   0xBB,                       #帧头2
                   int(x), # up sample by 4    #数据1
                   int(y)) # up sample by 4    #数据2
    myuart.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()-180
        else:
            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");
        }
    }
    /* 若有错误重新等待接收帧头 */
    else
        state = 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.coloradmin.cn/o/1939083.html

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

相关文章

Java周总结7.20day

一&#xff0c;异常 异常 &#xff1a;指的是程序在运行过程中报错&#xff0c;然后停止运行&#xff0c;控制台显示错误。 注意事项&#xff1a;异常本身是一个类&#xff0c;出现异常会创建一个异常类的对象并抛出&#xff0c; public class DemoTest { public static void …

python—爬虫爬取电影页面实例

下面是一个简单的爬虫实例&#xff0c;使用Python的requests库来发送HTTP请求&#xff0c;并使用lxml库来解析HTML页面内容。这个爬虫的目标是抓取一个电影网站&#xff0c;并提取每部电影的主义部分。 首先&#xff0c;确保你已经安装了requests和lxml库。如果没有安装&#x…

海思arm-hisiv400-linux-gcc 交叉编译rsyslog 记录心得

需要编译rsyslog,参考海思3536平台上rsyslog交叉编译、使用-CSDN博客和rsyslog移植&#xff08;亲测成功&#xff09;_rsyslog交叉编译-CSDN博客 首先下载了要用到的一些库的源码&#xff0c;先交叉编译这些库 原来是在centos6上交叉编译的&#xff0c;结果编译时报缺少软件要…

使用vue3模拟element-ui中el-tabs的实现

一. 最终实现 组件没有背景颜色, 为了凸显组件文字,才设置了背景颜色 二. 使用 <wq-tabs v-model"activeName" style"background:grey; padding: 20px"><wq-tab-pane label"User" name"first">User</wq-tab-pane&g…

多任务高斯过程数学原理和Pytorch实现示例

高斯过程其在回归任务中的应用我们都很熟悉了&#xff0c;但是我们一般介绍的都是针对单个任务的&#xff0c;也就是单个输出。本文我们将讨论扩展到多任务gp&#xff0c;强调它们的好处和实际实现。 本文将介绍如何通过共区域化的内在模型(ICM)和共区域化的线性模型(LMC)&…

驱动LSM6DS3TR-C实现高效运动检测与数据采集(10)----融合磁力计进行姿态解算

驱动LSM6DS3TR-C实现高效运动检测与数据采集.10--融合磁力计进行姿态解算 概述视频教学样品申请源码下载硬件准备DataLogFusion磁力计校准过程初始化磁力计MFX_Arithmetic_Init卡尔曼滤波算法演示 概述 MotionFX库包含用于校准陀螺仪、加速度计和磁力计传感器的例程。 将磁力计…

【网络】windows和linux互通收发

windows和linux互通收发 一、windows的udp客户端代码1、代码剖析2、总体代码 二、linux服务器代码三、成果展示 一、windows的udp客户端代码 1、代码剖析 首先我们需要包含头文件以及lib的一个库&#xff1a; #include <iostream> #include <WinSock2.h> #inclu…

swiftui中onChange函数的使用,监听变量的变化

在 SwiftUI 中&#xff0c;onChange 修饰符用于在指定值发生变化时执行某些操作。它允许你监听一个状态或绑定值的变化&#xff0c;并在变化发生时运行一些代码。这个功能非常适合需要对状态变化做出响应的场景。 使用示例&#xff1a; struct AppStorageTest: View {State p…

友力科技数据中心搬迁方案

将当前运行机房中的所有设备、应用系统安全搬迁至新数据中心机房&#xff0c;实现平滑切换、平稳过渡&#xff0c;最大限度地降低搬迁工作对业务的影响。 为了确保企事业单位能够顺利完成数据中心机房搬迁工作&#xff0c;我们根据实际经验提供了4个基本原则&#xff0c;希望能…

【Linux】编辑器vscode与linux的联动

1.vscode简单学习 vscode是编辑器&#xff0c;可以写各种语言的程序 下载链接&#xff1a;Download Visual Studio Code - Mac, Linux, Windows 来用一下vscode 我们保存了就能在我们的那个文件夹里面看到这个 这个就是编辑器&#xff0c;跟我们的文本文件好像差不多&#…

RPM、YUM 安装 xtrabackup 8 (mysql 热备系列一)包含rpm安装 mysql 8 配置主从

RPM安装 percona-xtrabackup-80-8.0.35-30.1.el7.x86_64.rpm 官网&#xff1a; https://www.percona.com/ 下载地址&#xff1a; https://www.percona.com/downloads wget https://downloads.percona.com/downloads/percona-distribution-mysql-ps/percona-distribution-mysq…

51单片机14(独立按键实验)

一、按键介绍 1、按键是一种电子开关&#xff0c;使用的时候&#xff0c;只要轻轻的按下我们的这个按钮&#xff0c;按钮就可以使这个开关导通。 2、当松开这个手的时候&#xff0c;我们的这个开关&#xff0c;就断开开发板上使用的这个按键&#xff0c;它的内部结构&#xff…

从千台到十万台,浪潮信息InManage V7解锁智能运维密码

随着大模型技术的深度渗透&#xff0c;金融行业正经历着前所未有的智能化变革。从“投顾助手”精准导航投资蓝海&#xff0c;到“智能客服”秒速响应客户需求&#xff0c;大模型以其对海量金融数据的深度挖掘与高效利用&#xff0c;正显著提升金融服务的智能化水准&#xff0c;…

Java:拦截器简介和应用示例(多个拦截器+校验token是否为空)

JAVA 拦截器 简介 拦截器和过滤器均可以拦截http请求&#xff0c;过滤器偏向于基础设施工作&#xff0c;拦截器偏向于业务&#xff0c;拦截器允许在执行Controller之前做验证预处理&#xff0c;在Controller执行之后对返回对象做加工处理。可以用于&#xff1a;权限检查、日志…

2014年全国大学生数学建模竞赛C题生猪养殖管理(含word论文和源代码资源)

文章目录 一、部分题目二、部分论文三、部分源代码四、完整word版论文和源代码 一、部分题目 2014高教社杯全国大学生数学建模竞赛题目 C题 生猪养殖场的经营管理 某养猪场最多能养10000头猪&#xff0c;该养猪场利用自己的种猪进行繁育。养猪的一般过程是&#xff1a;母猪配…

第3关 -- Git 基础知识

任务1: 破冰活动&#xff1a;自我介绍 任务2: 实践项目&#xff1a;构建个人项目 MeiHuaYiShu

【BUG】已解决:ModuleNotFoundError: No module named ‘_ctypes‘

已解决&#xff1a;ModuleNotFoundError: No module named ‘_ctypes‘ 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷分享知识&#xff0c;武汉城…

【Langchain大语言模型开发教程】记忆

&#x1f517; LangChain for LLM Application Development - DeepLearning.AI 学习目标 1、Langchain的历史记忆 ConversationBufferMemory 2、基于窗口限制的临时记忆 ConversationBufferWindowMemory 3、基于Token数量的临时记忆 ConversationTokenBufferMemory 4、基于历史…

双笼转子感应电机建模仿真(2):任意速旋转坐标系下xy/xy数学模型及仿真模型

1.概述 2. 双笼转子三相感应电机数学模型 2.1. 定子基准下ABC/qd数学模型 2.2. 任意速旋转坐标系下xy/xy数学模型 2.3. 空间矢量数学模型 3. 双笼转子三相感应电动机仿真模型 3.1 基于任意速xy/xy坐标系数学模型(1)~(5)的仿真模型 3.2. 基于任意速xy/xy坐标系中瞬态等效电…

MATLAB图像处理分析基础(一)

一、引言 MATLAB软件得到许多数字图像处理学生、老师和科研工作者的喜爱&#xff0c;成为数字图像处理领域不可或缺的工具之一&#xff0c;其与其他软件相比有以下诸多显著优点。首先&#xff0c;MATLAB 拥有强大的内置函数库&#xff0c;涵盖了图像读取、显示、处理及分析的全…