草庐IT

openmv识别物体并与单片机通信(STM32)

牧子川 2023-08-11 原文

openmv识别物体并与单片机通信(STM32)

OPENMV端

物体识别

感光元件

 img = sensor.snapshot() #存储摄像头所拍摄的图像并保存在img变量中

寻找色块

 blobs = img.find_blobs([red_thresholds]) #find_blobs函数可以找到色块。

find_blobs函数:此函数参数较多,一般只用第一个参数就可以找到需要的色块。thresholds是颜色的阈值,是一个列表,这个列表可以有多个颜色阈值。
一个颜色阈值的结构是这样的:

thresholds= (minL, maxL, minA, maxA, minB, maxB) #元组里面的数值分别是L A B 的最大值和最小值。

画图

image.draw_cross(x, y, size=5, color=White) #在图像中画一个十字

x,y:是坐标
size:是两侧的尺寸
color:画十字的颜色

image.draw_rectangle(rect_tuple, color=White) #在图像中画一个矩形框

rect_tuple 的格式是 (x, y, w, h)
color:画矩形框的颜色
sensor-感光元件具体介绍
find_blobs函数具体介绍
画图具体介绍

距离判断

实际长度和摄像头里的像素成反比

距离

距离 = k / 直径的像素

K1 = 500   #每次改变物体,K值都要重新计算 K1 = 距离(25cm已知)*直径像素Lm(20)
Lm = (max_blob.w() + max_blob.h())/2 #色块的长与宽 直径像素点个数
length = K1 / Lm

实际距离

实际距离 = k * 直径的像素
相同距离测不同物体的宽和长的长度

K2 = 0.16  #实际距离 = k * 直径的像素,K2 = 实际大小(宽4cm已知)/宽像素b[2]25)
K3 = 0.16  #实际距离 = k * 直径的像素,K3 = 实际大小(长4cm已知)/长像素b[3]25)
width = K2 * max_blob.w()
height = K3 * max_blob.h()

k1值计算:先已知一个长度length,在计算出直径像素点个数Lm。根据公式得到k = lenght * Lm计算出k1。通过改变物体(与计算k1值的物体为同一个)的距离就可以得到物体到openmv的距离。
k2,k3值计算:先得到一个已知物体的实际长和宽,在得到这个物体长和宽的像素。根据公式实际距离 = k * 直径的像素来得到k2,k3。改变不同的物体就可以知道该物体的实际长和宽。
OpenMV测距具体介绍
视频介绍

串口发送

from pyb import UART #模块导入
uart = UART(3,115200) #串口配置
uart.init(9600, bits=8, parity=None, stop=1)
data = bytearray([0xb3,0xb3,max_blob[5],max_blob[6],max_blob[3],0x0d,0x0a]) #要发送的数据
uart.write(data) #数据发送

openmv发送16进制数据需要转换为字节的形式,假设要发送 0x50,0x600,0x70,0x80这几个16进制数据代码如下:

uart = UART(3, 115200) 
uart.init(9600, bits=8, parity=None, stop=1)
data=bytearray([0x50,0x60,0x70,0x80])
uart.write(data)

STM32段

串口接收

串口2配置

  GPIO_InitTypeDef GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
	 
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);  //使能GPIOA时钟
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); //使能USART2
	
  USART_DeInit(USART2);
	
  //USART2_TX   GPIOA.2
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
  GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化GPIOA.2
   
  //USART2_RX	GPIOA.3
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA.3
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化GPIOA.3  

  //Usart2 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ;//抢占优先级3
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能
  NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
 
   //USART 初始化设置
  USART_InitStructure.USART_BaudRate = bound;//串口波特率
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
  USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
  USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式

  USART_Init(USART2,&USART_InitStructure); //初始化串口2
  USART_ITConfig(USART2,USART_IT_RXNE, ENABLE);//开启串口接受中断
  USART_Cmd(USART2,ENABLE);                    //使能串口2

数据处理

	static u8 state = 0;
	if(state == 0 && data == 0xb3)
	{
		state = 1;
		openmv[0] = data;
	}
	else if(state == 1 && data == 0xb3)
	{
		state = 2;
		openmv[1] = data;
	}
	else if(state == 2)
	{
		state = 3;
		openmv[2] = data;
	}
	else if(state == 3)
	{
		state = 4;
		openmv[3] = data;
	}
	else if(state == 4)
	{
		state = 5;
		openmv[4] = data;
	}
	else if(state == 5)
	{
		state = 6;
		openmv[5] = data;
	}
	else if(state == 6) // 检测是否接收到结束标志
	{
		if(data == 0x0a)
		{
			state = 0;
			LED0 =~ LED0;
			openmv[6] = data;
			Openmv_Data();
			data = 0;
		}
		else if(data != 0x0a)
		{
			state = 0;
			for(i = 0;i < 7;i++)
			{
				openmv[i] = 0x00;
			}
		}
	}
	else
	{
		state = 0;
		data = 0;
		LED0 = 1;
		for(i = 0;i < 7;i++)
		{
			openmv[i] = 0x00;
		}
	}

数据显示

在oled上显示需要的数据

	OLED_ShowString(0,0,"OpenMV-X:"); 
	OLED_ShowNum(70,00,OpenMV_X,3,12);
	OLED_ShowString(0,2,"OpenMV-Y:"); 	
	OLED_ShowNum(70,2,OpenMV_Y,3,12);		 
	OLED_ShowString(0,4,"Distance:");  
	OLED_ShowNum(68,4,Distance,3,12);
	OLED_ShowString(90,4,"cm");

Openmv与STM32连线

Openmv端:TXD(P4),RXD(P5),GND。TXD是发送端,RXD是接收端,GND是地线。
STM32端:TXD(PA2),RXD(PA3),GND。
如何连线:OpenMV的RXD连到STM32的TXD;OpenMV的TXD连到STM32的RXD;把OpenMV的GND与STM32的GND相连接。

实验现象

识别到红色物体

openmv打印输出数据

STM32还未接收到数据

STM32接收到数据并在oled上显示

注:当stm32上电后,oled上显示数据为0且红灯亮蓝灯灭,当openmv识别到物体并发送数据到stm32时,红灯亮蓝灯闪烁且oled实时显示数据;当openmv未识别到物体时,oled显示上次识别到的数据且红蓝灯亮。


在进行串口配置时,OpenMV和STM32的串口的波特率、奇偶位、停止位等都需要相同,否则传送数据不会成功。


源码获取

GitHub Opwnmv object recognition

有关openmv识别物体并与单片机通信(STM32)的更多相关文章

  1. 报告回顾丨模型进化狂飙,DetectGPT能否识别最新模型生成结果? - 2

    导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri

  2. [Vuforia]二.3D物体识别 - 2

    之前说过10之后的版本没有3dScan了,所以还是9.8的版本或者之前更早的版本。 3d物体扫描需要先下载扫描的APK进行扫面。首先要在手机上装一个扫描程序,扫描现实中的三维物体,然后上传高通官网,在下载成UnityPackage类型让Unity能够使用这个扫描程序可以从高通官网上进行下载,是一个安卓程序。点到Tools往下滑,找到VuforiaObjectScanner下载后解压数据线连接手机,将apk文件拷入手机安装然后刚才解压文件中的Media文件夹打开,两个PDF图打印第一张A4-ObjectScanningTarget.pdf,主要是用来辅助扫描的。好了,接下来就是扫描三维物体。将瓶

  3. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  4. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  5. ruby-on-rails - 在 heroku 的 .fonts 文件夹中包含自定义字体,似乎无法识别它们 - 2

    Heroku支持人员告诉我,为了在我的Web应用程序中使用自定义字体(未安装在系统中,您可以在bash控制台中使用fc-list查看已安装的字体)我必须部署一个包含所有字体的.fonts文件夹里面的字体。问题是我不知道该怎么做。我的意思是,我不知道文件名是否必须遵循heroku的任何特殊模式,或者我必须在我的代码中做一些事情来考虑这种字体,或者如果我将它包含在文件夹中它是自动的......事实是,我尝试以不同的方式更改字体的文件名,但根本没有使用该字体。为了提供更多详细信息,我们使用字体的过程是将PDF转换为图像,更具体地说,使用rghostgem。并且最终图像根本不使用自定义字体。在

  6. ruby-on-rails - 没有这样的文件或目录 - 用 Mini Magick 识别 - 2

    在我让另一个人重做我的前端UI之前,我的Rails应用程序运行平稳。我已经尝试解决此错误3天了。这是错误:Nosuchfileordirectory-identifyExtractedsource(aroundline#59):575859606162@post=Post.find(params[:id])authorize@postif@post.update_attributes(post_params)flash[:notice]="Postwasupdated."redirect_to[@topic,@post]else{"utf8"=>"✓","_method"=>"patc

  7. ruby - 使用 ruby​​ 识别阵列上的运行 - 2

    如果我们有一个数组array=[1,1,0,0,2,3,0,0,0,3,3,3]我们如何识别给定数字的运行(具有相同值的连续数字的数量)?例如:run_pattern_for(array,0)->2run_pattern_for(array,3)->1run_pattern_for(array,1)->1run_pattern_for(array,2)->0没有2的运行,因为没有连续出现2。3有一个运行,因为只有一个幻影以树为连续数字。 最佳答案 尝试:classArraydefcount_runs(element)chunk{|n

  8. STM32的HAL和LL库区别和性能对比 - 2

    LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L

  9. 最新版人脸识别小程序 图片识别 生成二维码签到 地图上选点进行位置签到 计算签到距离 课程会议活动打卡日常考勤 上课签到打卡考勤口令签到 - 2

    技术选型1,前端小程序原生MINA框架cssJavaScriptWxml2,管理后台云开发Cms内容管理系统web网页3,数据后台小程序云开发云函数云开发数据库(基于MongoDB)云存储4,人脸识别算法基于百度智能云实现人脸识别一,用户端效果图预览老规矩我们先来看效果图,如果效果图符合你的需求,就继续往下看,如果不符合你的需求,可以跳过。1-1,登录注册页可以看到登录页有注册入口,注册页如下我们的注册,需要管理员审核,审核通过后才可以正常登录使用小程序1-2,个人中心页登录成功以后,我们会进入个人中心页我们在个人中心页可以注册人脸,因为我们做人脸识别签到,需要先注册人脸才可以进行人脸比对,进

  10. ruby-on-rails - 尝试登录和使用 heroku 时无法识别 ruby​​.exe - 2

    当尝试创建一个heroku应用程序并通过git推送到它时,我收到以下错误:$herokucreate'"C:\ProgramFiles\ruby-1.9.2\bin\ruby.exe"isnotrecognizedasaninternalorexternalcommand,operableprogramorbatchfile.但是,$ruby-vruby1.9.3p125[i386-mingw32]我已经检查了PATH环境,它肯定包含“C:\ProgramFiles(x86)\ruby-1.9.2\bin”。同样有趣的是,当导航到该目录时,它实际上并不包含名为ruby​​.exe的文件

随机推荐