【DIY】基于OpenMV的STM32追球小车

2023-05-16

目录:

  • 总体设计
    • 1.基础硬件DIY设计
      • 1)整体原理图
      • 2)PCB电路
    • 2.OpenMV简单识别程序设计 与 STM32控制程序设计
      • 1)OpenMV简单识别程序设计【microPython】
      • 2)STM32控制程序设计 【C语言】
          • ①对OpenMV发送的数据包进行解析
          • ②小车的简单PID控制
          • ③系统状态设定
    • 3.效果展示
      • 1)整体效果图
  • Github项目地址、设计下载

本帖相关分享资料整理【程序+原理图-手工PCB】,最后有下载链接

注:本文仅用于学习交流分享,[若有不妥之处,请指正,感谢]

关键词:【OpenMV】【颜色识别】【PID】【STM32】
最后面有程序与原理图PCB分享

用到的工具有

  • openMV IDE
  • Keil 5 编译器
  • Altium Designer

实现的小功能有:
①设别颜色小球,并自动追寻小球
②简单测试与颜色小球的粗略距离,并且在小球10cm处停车
③按键调节PID参数以及调节识别的颜色

总体设计

1.基础硬件DIY设计
2.openMV简单识别程序设计 与 单片机控制程序设计
3.效果展示

1.基础硬件DIY设计

电路硬件:
[MCU] STM32F103C8T6最小系统板
[稳压电源]【L7805】 7.2V稳压5.0V 【AMS1117-3.3】5.0V稳压3.3V
[外围电路] 按键、蜂鸣器、OLED、干簧管

1)整体原理图

在这里插入图片描述

2)PCB电路

在这里插入图片描述

2.OpenMV简单识别程序设计 与 STM32控制程序设计

1)OpenMV简单识别程序设计【microPython】

在这里插入图片描述
识别小球颜色并通过串口定时发送小球坐标与距离的数据包

#2018.8.2   【microPython】
import sensor, image, time , pyb
from pyb import UART
from pyb import Timer
from pyb import LED
import json

led = pyb.LED(3) # Red LED = 1, Green LED = 2, Blue LED = 3, IR LEDs = 4.
thresholds = [(27, 67, 19, 91, 45, 76), # 红色
              #(21, 75, 3, -38, 34, 68), # 绿色
              (27, 90, -3, -28, 31, 125),
              (0, 30, 0, 64, -128, 0)]  # generic_blue_thresholds
threshold_index = 1 # 0 for red, 1 for gre9en, 2 for blue


sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)   #320*240
sensor.skip_frames(time = 100)
sensor.set_auto_gain(False) # must be turned off for color tracking
sensor.set_auto_whitebal(False) # must be turned off for color tracking
clock = time.clock()
uart = UART(3, 115200)
uart.init(115200, bits=8, parity=None, stop=1, timeout_char=1000) # 使用给定参数初始化

def tick(timer):            # we will receive the timer object when being called
    global data
    if blobs:
        print("Find")
        print('you send:',output_str)
        uart.write(data)


tim = Timer(4, freq=10)      # create a timer object using timer 4 - trigger at 1Hz
tim.callback(tick)          # set the callback to our tick function


def find_max(blobs):
    max_size=0
    for blob in blobs:
        if blob[2]*blob[3] > max_size:
            max_blob=blob
            max_size = blob[2]*blob[3]
    return max_blob

def Uart_Receive():   #UART接收 改变框小球的颜色阈值
    global threshold_index
    if uart.any():
        temp_data = uart.readchar()
        if temp_data==0:   #红色
           threshold_index=0

           print(temp_data,threshold_index)
        elif temp_data==1:
           threshold_index=1
           print(temp_data,threshold_index)


while(True):
    clock.tick()
    img = sensor.snapshot()
    Uart_Receive()
    blobs = img.find_blobs([thresholds[threshold_index]])
    if blobs:

        max_blob = find_max(blobs)
        b = max_blob[0] #方框元组
        L = (max_blob[2]+max_blob[3])/2
        l=int(1000/L)
        #x_error = max_blob[5]-img.width()/2   #求横向偏差
        x_error = max_blob[5]-img.width()/2

        img.draw_rectangle(max_blob[0:4])        # 画矩形
        img.draw_cross(max_blob[5], max_blob[6]) # 画十字

        #发送 小球的(x,y,l,n)
        #x为横坐标,y为纵坐标,l为粗略的距离,n为小球颜色(0:红 1:绿)
        output_str="%d,%d,%d,%d" % (max_blob.cx(),max_blob.cy(),l,threshold_index) #10进制字符包
        checkout=0xAA+0x55+0x07+int(max_blob.cx()/2)+max_blob.cy()+l+threshold_index
        data = bytearray([0xAA,0x55,0x07,int(max_blob.cx()/2),max_blob.cy(),l,threshold_index,0x00,0x00,checkout])#转成16进制
        #uart.write(data)
        time.sleep(1)
        led.on()
    else:
        print("NO FIND")
        data = bytearray([0xAA,0x55,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x06])
        uart.write(data)
        led.off()
图3 抓取到绿色小球
图4 抓取到红色小球

2)STM32控制程序设计 【C语言】

①对OpenMV发送的数据包进行解析
void USART1_IRQHandler(void)                	//串口1中断服务程序
{
	uint8 i=0,j=0;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  
	{//接收中断
		control_data[data_number]=USART_ReceiveData(USART1);
			data_number++; 
				if(data_number<(MAX_DATA_LENS+4))                   
				 {  //定义数据长度未包括包头和包长3个字节,+4
					if(control_data[0]==0xaa)//数据包包头字节
					{
						if(data_number>3)
						{
							if(control_data[1]==0x55)
							{	
								if(data_number>=(control_data[2]+3))  
								{//接收完数据包(第三个字节为数据长度,数据长度不包含开头和校验字)
							  	 for(i=0;i<=(data_number-2);i++) 
								 {
									j +=control_data[i];
								 }
								if(j==control_data[data_number-1]) //判断校验是否成功
							   	 {
									j=0;
								   recv1_data_ok=1;   //接收到正确完整数据包标志位置              
								 }
								 else
								{
									recv1_data_ok=0;
								}
								j=0;
								data_number=0;													
							}
						}
					else
					{
						recv1_data_ok=0;
						data_number=0;
					}
				}
			}
			else
			{ 
				recv1_data_ok=0;
				data_number=0;
			}
		}
		else
		{
			recv1_data_ok=0;
			data_number=0;
		}
			
    } 

} 
②小车的简单PID控制
#include "my_include.h"

extern CAR_STATUS_e car_mode;
extern moty_duty run_duty;
extern u8 control_data[MAX_DATA_LENS];
extern float C_P; //cameraP
extern float C_D; //cameraD
extern int16 ser_duty;
extern int16 x_error;
extern int16 last_x_error; 
extern uint8 ball_colcor;
extern uint8 BEEP_ON_OFF;

extern uint8 out_edge;//出界

void Car_mode_control()//小车简单控制逻辑单元
{

		if(control_data[3]<50 && control_data[3]!=0) //左出界
		{
			out_edge=Left;
		}
		else if(control_data[3]>110 && control_data[3]!=0) //右出界
		{
			out_edge=Right;
		}

		
		//--------------------车位状态判断-----------------//
		if(out_edge==Left && control_data[4]==0 && control_data[5]==0)
		{
			car_mode=finding_L;
		}
		else if(out_edge==Right && control_data[4]==0 && control_data[5]==0)
		{
			car_mode=finding_R;
		}
		else if (control_data[3]>0 && control_data[4]>0 && control_data[5]>0)
		{
			car_mode=run;
		}
		if(control_data[5]<=12 && control_data[5]>=3)
		{
				LED1=0;
				car_mode=stop;
		}
		else {LED1=1;}
		
		if(Boma4==0)//强制菜单
		{
			car_mode=stop;
		}
		//寻找小球的 色号(0为红,1为绿)	

		if(Boma3==0)
		{
			BEEP_ON_OFF=OFF;
		}
		else {BEEP_ON_OFF=ON;}
}


void PWM_updata()//速度控制中心
{

		if(car_mode == run)
		{
				TIM_SetCompare1(TIM1,run_duty.Speed_Duty_R);	//右为  TIM1  CH1
				TIM_SetCompare4(TIM1,run_duty.Speed_Duty_L);  //左为  TIM1  CH4
		}
		else if(car_mode == finding_R)
		{
				TIM_SetCompare1(TIM1,1400);	//右为  TIM1  CH1
				TIM_SetCompare4(TIM1,1400); //左为  TIM1  CH4
		}
		else if(car_mode == finding_L)
		{
				TIM_SetCompare1(TIM1,1500);	//右为  TIM1  CH1
				TIM_SetCompare4(TIM1,1500); //左为  TIM1  CH4
		}
	  else if(car_mode == stop)
		{
				TIM_SetCompare1(TIM1,0);	//右为  TIM1  CH1
				TIM_SetCompare4(TIM1,0);  //左为  TIM1  CH4
		}
}




void PD_control()
{
	last_x_error=x_error;
	x_error=control_data[3]-80;
	ser_duty = C_P*x_error-C_D*(last_x_error-x_error);

	run_duty.Speed_Duty_R=1550-ser_duty;//正为正转
	run_duty.Speed_Duty_L=1350-ser_duty;
	//左边FTM波//限幅	
	run_duty.Speed_Duty_L=run_duty.Speed_Duty_L<1300?1300:run_duty.Speed_Duty_L;
	run_duty.Speed_Duty_L=run_duty.Speed_Duty_L>1600?1600:run_duty.Speed_Duty_L;
	//右边FTM波//限幅	
   run_duty.Speed_Duty_R=run_duty.Speed_Duty_L<1300?1300:run_duty.Speed_Duty_R;
	run_duty.Speed_Duty_R=run_duty.Speed_Duty_L>1600?1600:run_duty.Speed_Duty_R;

}
③系统状态设定
typedef struct D  //速度结构体
{
	int16 Speed_Duty_L;
	int16 Speed_Duty_R;
}moty_duty;


typedef enum   //枚举小车简单状态
{
	finding_R=4,
	finding_L=3,
	run=2,
	stop=1,
	error=0,
}
CAR_STATUS_e;  //车子状态 

typedef enum
{
	mode_ON_OFF=0,
	car_run=1,
	flash=2,   
	picture=3,

}
MENU_LIST_e; //OLED菜单

3.效果展示

    DESIGN
May 31 12:00 June 12:00 Tue 02 12:00 Wed 03 12:00 Thu 04 12:00 部分功能验证 原理图 PCB 程序设计 小车整体搭建 设计制作步骤

1)整体效果图

OLED页面设计
OELD可通过拨码开关切换页面

①在OLED上显示小球的实时坐标【x,y】以及距离 l
② 显示小球在摄像头中的坐标并在屏幕上用“x”表示出来

调试界面
预留五个调试按键

①可调节PD参数
②切换追踪小球颜色阈值

图1 小车整体效果图
图2 小车整体效果图

附【Download】:
程序+硬件(原理图+PCB):

Github项目地址、设计下载

Dwfish 淹死的鱼 2018.1在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【DIY】基于OpenMV的STM32追球小车 的相关文章

  • 51单片机 数码管中断操作

    实践目的 1 掌握中断的概念和思想 2 掌握51单片机中断系统和相关软硬件设计 实践内容 1 利用单片机的P0口接数码管的字段脚 P1 0脚接共阴极 P3 2 P3 3引脚接独立按键产生外部中断信号 编写程序 当程序正常运行时数码管显示H字
  • 在地址“0xXXXXXX”处中断,没有可用的调试信息,或在程序代码之外

    配置 使用 Nucleo L476RG 使用 GNU ARM Eclipse 我从 STM32CubeMX 生成了一个极简代码 我已经在我的板载 ST Link 中刷新了 J link 驱动程序 一直在尝试为我的代码运行调试器 但我的程序计
  • GCC - 如何停止链接 malloc?

    我正在努力将我的代码缩减到最小的骨架大小 我使用的是只有 32k 闪存的 STM32F0 需要很大一部分闪存用于数据存储 我的代码已经有大约 20k 闪存大小 其中一些是由于使用了 STM32 HAL 函数 我可以在以后需要时对其进行解释和
  • 如何让printf在STM32F103上工作?

    我是 STM32F103 世界的新手 我有一个STM32F103的演示代码 我正在使用arm none eabi来编译它 我尝试了在谷歌上可以找到的内容 但到目前为止没有任何效果 我已经花了三天时间来解决这个问题 任何人都可以给我一个运行良
  • 优化 ARM Cortex M3 代码

    我有一个 C 函数 它尝试将帧缓冲区复制到 FSMC RAM 这些函数将游戏循环的帧速率降低至 10FPS 我想知道如何分析反汇编的函数 我应该计算每个指令周期吗 我想知道CPU把时间花在哪里 在哪个部分 我确信该算法也是一个问题 因为它的
  • 137-基于stm32单片机智能保温杯控制装置Proteus仿真+源程序

    资料编号 137 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DS18B20传感器 电机 制作一个基于stm32单片机智能保温杯控制装置Proteus仿真 2 通过DS18b20传感器检测当前保温杯水的温度 并且
  • rt-thread studio中新建5.0不能用

    文章目录 一 版本对比 二 文件和文件夹打斜杠 在使用RT Thread studio创建新工程5 0版本的时候 结果发现新建完成之后程序不能正常运行 但是创建4 10版本的时候却能运行 那肯定是新版本出现了BUG 一 版本对比 首先对比了
  • STM32F103

    提示 来源正点原子 参考STM32F103 战舰开发指南V1 3PDF资料 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 提示 这里可以添加本文要记录的大概内容 开发环境硬件普中科技 接线图在g
  • STM32 GPIO工作原理详解

    STM32 GPIO介绍 1 STM32引脚说明 GPIO是通用输入 输出端口的简称 是STM32可控制的引脚 GPIO的引脚与外部硬件设备连接 可实现与外部通讯 控制外部硬件或者采集外部硬件数据的功能 以STM32F103ZET6芯片为例
  • SHT10温湿度传感器——STM32驱动

    实验效果 硬件外观 接线 3 3V供电 IIC通讯 代码获取 查看下方 END
  • 解决KEIL编译慢问题

    两种方案 使用v6版本的ARM Compiler 如果v6版本编译不过 必须使用v5版本的 则可以勾选掉Browse Information选项 提升很明显 1分多钟能优化到几秒 看代码量 但是这个有个弊端 在KEIL中会影响函数跳转 建议
  • 解决KEIL编译慢问题

    两种方案 使用v6版本的ARM Compiler 如果v6版本编译不过 必须使用v5版本的 则可以勾选掉Browse Information选项 提升很明显 1分多钟能优化到几秒 看代码量 但是这个有个弊端 在KEIL中会影响函数跳转 建议
  • 在 Atollic TrueStudio、STM32CubeMX 中导入 C 库

    我目前正在开发 STM32F767ZI Nucleo 板和一个小安全芯片 microchip atecc508a 通过 i2c 连接进行连接 该芯片有一个可用的库加密验证库 https github com MicrochipTech cr
  • 1.69寸SPI接口240*280TFT液晶显示模块使用中碰到的问题

    1 69寸SPI接口240 280TFT液晶显示模块使用中碰到的问题说明并记录一下 在网上买了1 69寸液晶显示模块 使用spi接口 分辨率240 280 给的参考程序是GPIO模拟的SPI接口 打算先移植到FreeRtos测试 再慢慢使用
  • 毕设开题分享 单片机智能教室系统(智能照明+人数统计)

    1 简介 Hi 大家好 今天向大家介绍一个学长做的单片机项目 单片机智能教室系统 智能照明 人数统计 大家可用于 课程设计 或 毕业设计 项目分享 https gitee com feifei1122 simulation project
  • CMSIS & STM32,如何开始? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想在 STM32 上使用 CMSIS 启动项目 网上一搜 没找到具体的教程 有些使用 SPL 开始项
  • STM32 Nucleo 上的上升沿中断多次触发

    我正在使用 STM32 NUCLEO F401RE 微控制器板 我有一个扬声器 经过编程 当向上 向下推操纵杆时 可以按设定的量改变频率 我的问题是 有时 通常 当向上 向下推动操纵杆时 频率会增加 减少多次 这意味着 ISR 正在执行多次
  • 嵌入式 C++11 代码 — 我需要 volatile 吗?

    采用 Cortex M3 MCU STM32F1 的嵌入式设备 它具有嵌入式闪存 64K MCU固件可以在运行时重新编程闪存扇区 这是由闪存控制器 FMC 寄存器完成的 所以它不像a b那么简单 FMC 获取缓冲区指针并将数据刻录到某个闪存
  • STM32 上的 ADC 单次转换

    我正在研究 STM32 F103x 上的 ADC 编程 并从最简单的情况 单次转换开始 测量内部温度传感器 连接到 ADC1 的值 并使用 USART 将其发送到 COM 端口 目标似乎很明确 但是当我尝试将源代码下载到闪存时 它不会向 C
  • STM32 上的位置无关代码 - 指针

    我已成功在 STM32 上构建并运行位置无关的代码 向量表和 GOT 已修补 一切正常 但我对这样的代码有问题 double myAdd double x return x 0 1 double ptrmyAdd double myAdd

随机推荐

  • 【Android抓包】Ubuntu mitmProxy配置

    Ubuntu 安装 mitmProxy 直接使用编译好的二进制包 参考 xff1a https cuiqingcai com 31053 html Linux E4 B8 8B E7 9A 84 E5 AE 89 E8 A3 85 直接下载
  • 【CSDN】查看自己的CSDN积分

    查看自己的CSDN积分 如何查看自己的CSDN博客积分 CSDN藏的比较深 xff0c 链接如下 xff1a https mp csdn net mp blog analysis article all CSDN博客积分与博客等级 参考 x
  • 【符号输入】打出撇号′

    打出撇号 撇号 xff08 apostrophe xff09 xff1a 搜狗输入法调成中文 xff0c 输入fen xff0c 第5个就是撇号
  • 【Android安全】xiaomi手机关闭adb安装应用时的确认提示

    xiaomi手机关闭adb安装应用时的确认提示 为了自动化测试 xff0c 需要关闭adb安装应用时的确认提示 需要分两步来关闭 xff1a 首先 xff0c 开发者选项 gt 启动MIUI优化 gt 关闭 xff08 第一步过后授权管理
  • 【python】报错UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte in position : illegal multibyte

    python读文件时报错 xff1a Traceback span class token punctuation span most recent call last span class token punctuation span F
  • STM32介绍

    目录 STM32 分类 STM8 和 STM32 分类 STM32 命名方法 STM32F103RCT6 寻找 IO 的功能 存储器映射 存储器 Block0 内部区域功能划分 存储器 Block1 内部区域功能划分 存储器 Block2
  • Putty串口打开无反应

    第一次使用putty的串口 xff0c 可能理所当然认为在Serial那里设置好参数 xff0c 然后点击Open就行了 但是显然不是 xff0c Putty的UI设计有问题 xff0c 不管你点击哪一个项 xff0c Open按钮始终都存
  • 【Android安全】r0capture使用

    r0capture使用 下载地址 xff1a https github com r0ysue r0capture 手机端启动frida server PC端安装frida client 命令 xff1a python r0capture s
  • MobaXterm或Xshell连接不上虚拟机ubuntu

    MobaXterm使用教程 xff1a MobaXterm官网下载 MobaXterm使用教程1 MobaXterm使用教程2 Xshell 使用教程 xff1a 恒源云远程登录Linux实例 包含下载地址和使用教程 Xshell使用教程
  • 591 标签验证器(模拟、栈匹配括号)

    1 问题描述 xff1a 给定一个表示代码片段的字符串 xff0c 你需要实现一个验证器来解析这段代码 xff0c 并返回它是否合法 合法的代码片段需要遵守以下的所有规则 xff1a 代码必须被合法的闭合标签包围 否则 xff0c 代码是无
  • 算法:最长公共子序列

    10 8算法实验报告 最长公共子序列 题目 输出两个字符串的最长公共子序列 要求1 不使用辅助数组 span class token comment 要求1 xff1a 不使用辅助数组 span span class token keywo
  • 呆呆和你谈谈入职CVTE一个月的感受

    呆呆和你谈谈入职CVTE一个月的感受 你盼世界 xff0c 我盼望你无bug Hello 大家好 xff01 我是霖呆呆 xff01 啊啊啊啊啊 至6 18日入职新公司CVTE已经一个多月了 xff0c 在 你盼世界 xff0c 我盼望你无
  • 编程就是调用API?如何成为造轮子的程序员

    是 xff0c 编程就是调用各种API 什么是API xff0c 就是别人把较复杂的代码封装成一个个函数 xff0c 你不用管函数怎么实现的 xff0c 直接用就好 从这个角度讲 xff0c 使用所有库 xff0c 框架 xff0c 模板
  • 【电赛】2019电子设计竞赛 纸张计数显示装置(F题)

    点击 Github项目地址 设计下载 内含 xff1a 电赛论文 程序设计 机械结构设计 硬件电路设计 综合测评相关设计 交互显示设计 设计详细说明 2019年全国大学生电子设计竞赛 纸张计数显示装置 xff08 F题 xff09 本科组
  • 【ARM裸板】LCD硬件原理、时序及初始化

    文章目录 1 LCD与OLED的区别2 LCD原理2 1 颜色如何确定 xff1f 2 2 LCD如何 行扫描 xff1f 2 3 如何跳到下一行进行 行扫描 xff1f 2 4 如何进行下一个 场扫描 xff1f 3 LCD时序4 LCD
  • 【电赛】2019电赛纸张计数显示装置Github仓库说明

    Github项目地址 设计下载 内含 xff1a 电赛论文 程序设计 机械结构设计 硬件电路设计 综合测评相关设计 交互显示设计 设计详细说明 纸张计数显示装置Github仓库说明 x1f604 个人主页 x1f57a 电赛论文 x1f4d
  • 【Linux】mjpg-streamer 源码分析

    文章目录 1 总体流程2 主进程的源码分析2 1 参数接收与解析2 2 获取参数2 3 调用输入函数2 3 1 程序手动中断信号2 3 2 strchr 函数2 3 3 strndup 函数2 3 4 分离参数 3 输入通道源码分析3 1
  • STM32之TIM 舵机控制PWM

    目录 大概步骤 定时器介绍 输入通道 输入滤波器和边沿检测器 捕获通道 定时器初始化结构体详解 1 TIM TimeBaseInitTypeDef 定时器基本初始化结构体 TIM OCInitTypeDef 定时器比较输出初始化结构体 3
  • 【树莓派】树莓派采用MJPG-Streamer双摄推流至上位机,实测延时低至200ms[CSI摄像头+USB摄像头]

    树莓派采用MJPG Streamer双摄推流至上位机 实测延时低至200ms CSI摄像头 43 USB摄像头 总体流程1 硬件连接与软件及驱动配置1 xff09 检测是否存在USB摄像头设备2 xff09 安装 MJPG Streamer
  • 【DIY】基于OpenMV的STM32追球小车

    目录 xff1a 总体设计1 基础硬件DIY设计1 xff09 整体原理图2 xff09 PCB电路 2 OpenMV简单识别程序设计 与 STM32控制程序设计1 xff09 OpenMV简单识别程序设计 microPython 2 xf