第18章-综合以上功能 基于stm32的智能小车(远程控制、避障、循迹) 基于stm32f103c8t6/HAL库/CubeMX/超详细,包含代码讲解和原理图

news2024/11/18 1:35:27

这个是全网最详细的STM32项目教学视频。
第一篇在这里:
视频在这里

STM32智能小车V3-STM32入门教程-openmv与STM32循迹小车-stm32f103c8t6-电赛 嵌入式学习 PID控制算法 编码器电机 跟随

第18章-综合以上功能

18-按键和app按钮切换功能

根据上面介绍,我们的模式可以有:

**OLED显示模式: 速度、里程、电压、超声波数据、MPU6050俯仰角、横滚角、航向角 数据显示在OLED上和通过串口发送蓝牙APP **

PID循迹模式:红外对管PID循迹

手机遥控普通运动模式:遥控前、后、左、右加速运动

超声波避障模式

PID跟随模式:超声波PID定距离跟随

手机遥控角度闭环模式:MPU6050角度PID控制

可以设置标志位通过按键改变标志位,以实现功能切换。

定义一个全局变量,

uint8_t g_ucMode = 0; 
//小车运动模式标志位 0:显示功能、1:PID循迹模式、2:手机遥控普通运动模式、3.超声波避障模式、4:PID跟随模式、5:遥控角度闭环

在这里插入图片描述

uint8_t g_ucMode = 0; //小车运动模式标志位

在gpio.h声明一下

在这里插入图片描述

extern uint8_t g_ucMode ; //小车运动模式标志位

按键中断回调函数里面补充按下按键后的处理

先不进行消抖,如果后面KEY1 KEY2效果不好再消抖
在这里插入图片描述

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin == KEY1_Pin) //判断一下那个引脚触发中断
	{
		//这里编写触发中断后要执行的程序
		if(g_ucMode == 5) g_ucMode = 1;//g_ucMode模式是0 1 2 3 4 5 
		else
		{
			g_ucMode+=1;
		}
		HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
	}
	if(GPIO_Pin == KEY2_Pin) //判断一下那个引脚触发中断
	{
		//这里编写触发中断后要执行的程序
		g_ucMode=0;
		HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
	}
}

然后主函数显示当前处于的模式

然后判断当前模式 执行不同代码

方法:一个功能一个功能的添加代码,添加好一个调试测试一下,然后再添加下一个

下面这个就是我们主函数的代码。

	sprintf((char *)OledString," g_ucMode:%d",g_ucMode);//显示g_ucMode 当前模式
	OLED_ShowString(0,6,OledString,12);	//显示在OLED上
	
	sprintf((char *)Usart3String," g_ucMode:%d",g_ucMode);//蓝牙APP显示
	HAL_UART_Transmit(&huart3,( uint8_t *)Usart3String,strlen(( const  char  *)Usart3String),50);//阻塞式发送通过串口三输出字符 strlen:计算字符串大小
	
	if(g_ucMode == 0)
	{
	//0LED显示功能
		sprintf((char*)OledString, "V1:%.2fV2:%.2f", Motor1Speed,Motor2Speed);//显示速度
		OLED_ShowString(0,0,OledString,12);//这个是oled驱动里面的,是显示位置的一个函数,
		
		sprintf((char*)OledString, "Mileage:%.2f", Mileage);//显示里程
		OLED_ShowString(0,1,OledString,12);//这个是oled驱动里面的,是显示位置的一个函数,
		
		sprintf((char*)OledString, "U:%.2fV", adcGetBatteryVoltage());//显示电池电压
		OLED_ShowString(0,2,OledString,12);//这个是oled驱动里面的,是显示位置的一个函数,
		
		sprintf((char *)OledString,"HC_SR04:%.2fcm\r\n",HC_SR04_Read());//显示超声波数据
		OLED_ShowString(0,3,OledString,12);//这个是oled驱动里面的,是显示位置的一个函数,
		
		sprintf((char *)OledString,"p:%.2f r:%.2f \r\n",pitch,roll);//显示6050数据 俯仰角 横滚角
		OLED_ShowString(0,4,OledString,12);//这个是oled驱动里面的,是显示位置的一个函数,
		
		sprintf((char *)OledString,"y:%.2f  \r\n",yaw);//显示6050数据  航向角
		OLED_ShowString(0,5,OledString,12);//这个是oled驱动里面的,是显示位置的一个函数,
		
	//蓝牙APP显示
		sprintf((char*)Usart3String, "V1:%.2fV2:%.2f", Motor1Speed,Motor2Speed);//显示速度
		HAL_UART_Transmit(&huart3,( uint8_t *)Usart3String,strlen(( const  char  *)Usart3String),50);//阻塞式发送通过串口三输出字符 strlen:计算字符串大小
		//阻塞方式发送可以保证数据发送完毕,中断发送不一定可以保证数据已经发送完毕才启动下一次发送
		sprintf((char*)Usart3String, "Mileage:%.2f", Mileage);//显示里程
		HAL_UART_Transmit(&huart3,( uint8_t *)Usart3String,strlen(( const  char  *)Usart3String),50);//阻塞式发送通过串口三输出字符 strlen:计算字符串大小
		
		sprintf((char*)Usart3String, "U:%.2fV", adcGetBatteryVoltage());//显示电池电压
		HAL_UART_Transmit(&huart3,( uint8_t *)Usart3String,strlen(( const  char  *)Usart3String),50);//阻塞式发送通过串口三输出字符 strlen:计算字符串大小
		
		sprintf((char *)Usart3String,"HC_SR04:%.2fcm\r\n",HC_SR04_Read());//显示超声波数据
		HAL_UART_Transmit(&huart3,( uint8_t *)Usart3String,strlen(( const  char  *)Usart3String),50);//阻塞式发送通过串口三输出字符 strlen:计算字符串大小
		
		sprintf((char *)Usart3String,"p:%.2f r:%.2f \r\n",pitch,roll);//显示6050数据 俯仰角 横滚角
		HAL_UART_Transmit(&huart3,( uint8_t *)Usart3String,strlen(( const  char  *)Usart3String),50);//阻塞式发送通过串口三输出字符 strlen:计算字符串大小
		
		sprintf((char *)Usart3String,"y:%.2f  \r\n",yaw);//显示6050数据  航向角
		HAL_UART_Transmit(&huart3,( uint8_t *)Usart3String,strlen(( const  char  *)Usart3String),50);//阻塞式发送通过串口三输出字符 strlen:计算字符串大小
	
		//获得6050数据
		while(mpu_dmp_get_data(&pitch,&roll,&yaw)!=0){}  //这个可以解决经常读不出数据的问题
		
		//显示模式电机停转
		motorPidSetSpeed(0,0);
	}
	if(g_ucMode == 1)
	{
	///****    红外PID循迹功能******************/
	g_ucaHW_Read[0] = READ_HW_OUT_1;//读取红外对管状态、这样相比于写在if里面更高效
	g_ucaHW_Read[1] = READ_HW_OUT_2;
	g_ucaHW_Read[2] = READ_HW_OUT_3;
	g_ucaHW_Read[3] = READ_HW_OUT_4;

	if(g_ucaHW_Read[0] == 0&&g_ucaHW_Read[1] == 0&&g_ucaHW_Read[2] == 0&&g_ucaHW_Read[3] == 0 )
	{
//		printf("应该前进\r\n");//注释掉更加高效,减少无必要程序执行
		g_cThisState = 0;//前进
	}
	else if(g_ucaHW_Read[0] == 0&&g_ucaHW_Read[1] == 1&&g_ucaHW_Read[2] == 0&&g_ucaHW_Read[3] == 0 )//使用else if更加合理高效
	{
//		printf("应该右转\r\n");
		g_cThisState = -1;//应该右转
	}
	else if(g_ucaHW_Read[0] == 1&&g_ucaHW_Read[1] == 0&&g_ucaHW_Read[2] == 0&&g_ucaHW_Read[3] == 0 )
	{
//		printf("快速右转\r\n");
		g_cThisState = -2;//快速右转
	}
	else if(g_ucaHW_Read[0] == 1&&g_ucaHW_Read[1] == 1&&g_ucaHW_Read[2] == 0&&g_ucaHW_Read[3] == 0)
	{
//		printf("快速右转\r\n");
		g_cThisState = -3;//快速右转
	}
	else if(g_ucaHW_Read[0] == 0&&g_ucaHW_Read[1] == 0&&g_ucaHW_Read[2] == 1&&g_ucaHW_Read[3] == 0 )
	{
//		printf("应该左转\r\n");
		g_cThisState = 1;//应该左转	
	}
	else if(g_ucaHW_Read[0] == 0&&g_ucaHW_Read[1] == 0&&g_ucaHW_Read[2] == 0&&g_ucaHW_Read[3] == 1 )
	{
//		printf("快速左转\r\n");
		g_cThisState = 2;//快速左转
	}
	else if(g_ucaHW_Read[0] == 0&&g_ucaHW_Read[1] == 0&&g_ucaHW_Read[2] == 1&&g_ucaHW_Read[3] == 1)
	{
//	    printf("快速左转\r\n");
		g_cThisState = 3;//快速左转
	}
	g_fHW_PID_Out = PID_realize(&pidHW_Tracking,g_cThisState);//PID计算输出目标速度 这个速度,会和基础速度加减

	g_fHW_PID_Out1 = 3 + g_fHW_PID_Out;//电机1速度=基础速度+循迹PID输出速度
	g_fHW_PID_Out2 = 3 - g_fHW_PID_Out;//电机1速度=基础速度-循迹PID输出速度
	if(g_fHW_PID_Out1 >5) g_fHW_PID_Out1 =5;//进行限幅 限幅速度在0-5之间
	if(g_fHW_PID_Out1 <0) g_fHW_PID_Out1 =0;
	if(g_fHW_PID_Out2 >5) g_fHW_PID_Out2 =5;
	if(g_fHW_PID_Out2 <0) g_fHW_PID_Out2 =0;
	if(g_cThisState != g_cLastState)//如何这次状态不等于上次状态、就进行改变目标速度和控制电机、在定时器中依旧定时控制电机
	{
		motorPidSetSpeed(g_fHW_PID_Out1,g_fHW_PID_Out2);//通过计算的速度控制电机
	}
	
	g_cLastState = g_cThisState;//保存上次红外对管状态	

	}
	if(g_ucMode == 2)
	{
		//***************遥控模式***********************//
		//遥控模式的控制在串口三的中断里面
	}
	if(g_ucMode == 3)
	{
		//******超声波避障模式*********************//
避障逻辑
		if(HC_SR04_Read() > 25)//前方无障碍物
		{
			motorPidSetSpeed(1,1);//前运动
			HAL_Delay(100);
		}
		else{	//前方有障碍物
			motorPidSetSpeed(-1,1);//右边运动 原地	
			HAL_Delay(500);
			if(HC_SR04_Read() > 25)//右边无障碍物
			{
				motorPidSetSpeed(1,1);//前运动
				HAL_Delay(100);
			}
			else{//右边有障碍物
				motorPidSetSpeed(1,-1);//左边运动 原地
				HAL_Delay(1000);
				if(HC_SR04_Read() >25)//左边无障碍物
				{
					 motorPidSetSpeed(1,1);//前运动
					HAL_Delay(100);
				}
				else{
					motorPidSetSpeed(-1,-1);//后运动
					HAL_Delay(1000);
					motorPidSetSpeed(-1,1);//右边运动
					HAL_Delay(50);
				}
			}
		}
	}
	if(g_ucMode == 4)
	{
	//**********PID跟随功能***********//
		g_fHC_SR04_Read=HC_SR04_Read();//读取前方障碍物距离
		if(g_fHC_SR04_Read < 60){  //如果前60cm 有东西就启动跟随
			g_fFollow_PID_Out = PID_realize(&pidFollow,g_fHC_SR04_Read);//PID计算输出目标速度 这个速度,会和基础速度加减
			if(g_fFollow_PID_Out > 6) g_fFollow_PID_Out = 6;//对输出速度限幅
			if(g_fFollow_PID_Out < -6) g_fFollow_PID_Out = -6;
			motorPidSetSpeed(g_fFollow_PID_Out,g_fFollow_PID_Out);//速度作用与电机上
		}
		else motorPidSetSpeed(0,0);//如果前面60cm 没有东西就停止
		HAL_Delay(10);//读取超声波传感器不能过快
	}
	if(g_ucMode == 5)
	{
	//*************MPU6050航向角 PID转向控制*****************//

		sprintf((char *)Usart3String,"pitch:%.2f roll:%.2f yaw:%.2f\r\n",pitch,roll,yaw);//显示6050数据 俯仰角 横滚角 航向角
		HAL_UART_Transmit(&huart3,( uint8_t *)Usart3String,strlen(( const  char  *)Usart3String),0xFFFF);//通过串口三输出字符 strlen:计算字符串大小	
	   
	   //mpu_dmp_get_data(&pitch,&roll,&yaw);//返回值:0,DMP成功解出欧拉角
		while(mpu_dmp_get_data(&pitch,&roll,&yaw)!=0){}  //这个可以解决经常读不出数据的问题
		
		
		g_fMPU6050YawMovePidOut = PID_realize(&pidMPU6050YawMovement,yaw);//PID计算输出目标速度 这个速度,会和基础速度加减

		g_fMPU6050YawMovePidOut1 = 1.5 + g_fMPU6050YawMovePidOut;//基础速度加减PID输出速度
		g_fMPU6050YawMovePidOut2 = 1.5 - g_fMPU6050YawMovePidOut;
		if(g_fMPU6050YawMovePidOut1 >3.5) g_fMPU6050YawMovePidOut1 =3.5;//进行限幅
		if(g_fMPU6050YawMovePidOut1 <0) g_fMPU6050YawMovePidOut1 =0;
		if(g_fMPU6050YawMovePidOut2 >3.5) g_fMPU6050YawMovePidOut2 =3.5;
		if(g_fMPU6050YawMovePidOut2 <0) g_fMPU6050YawMovePidOut2 =0;
		motorPidSetSpeed(g_fMPU6050YawMovePidOut1,g_fMPU6050YawMovePidOut2);
	
	}

可以测试上面的代码 然后没有问题后,我们添加一个通过蓝牙APP按钮切换模式代码
在这里插入图片描述

		if(g_ucUsart3ReceiveData == 'J') //改变模式
		{
			if(g_ucMode == 5) g_ucMode = 1;//g_ucMode模式是0 1 2 3 4 5 
			else
			{
				g_ucMode+=1;
			}
		}
		if(g_ucUsart3ReceiveData == 'K') g_ucMode=0;//设置为显示模式

然后对应APP也要添加 按钮设置
在这里插入图片描述
我们
按键没有消抖效果不好,我们消抖一下
在这里插入图片描述
我们增加了 HAL延时和再次判断电平

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin == KEY1_Pin) //判断一下那个引脚触发中断
	{
		HAL_Delay(10);//延时消抖 主要
		if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_SET)//判断KEY1引脚仍为高电平
		{
			//这里编写触发中断后要执行的程序
			if(g_ucMode == 5) g_ucMode = 1;//g_ucMode模式是0 1 2 3 4 5 
			else
			{
				g_ucMode+=1;
			}
			HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
		}
	}
	if(GPIO_Pin == KEY2_Pin) //判断一下那个引脚触发中断
	{
		HAL_Delay(10);//延时消抖
		if(HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == GPIO_PIN_RESET)//判断KEY2引脚仍为低电平
		{
			//这里编写触发中断后要执行的程序
			g_ucMode=0;
			HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
		}
	}
}

但是测试不能执行中断,程序异常卡死了

原因是HAL_Delay使用的是sysTick 中断优先级在软件初始化是默认最低的,比外部中断优先级低,所以HAL_Delay不能在外部中断服务函数中调用。

所以我们可以通过提高sysTick 中断的优先级,提高的比HAL_Delay高。
在这里插入图片描述
然后我们提高至 如下图
在这里插入图片描述
然后编译烧录测试按键是否更加稳定。
下面的章节我们讲解视觉,RTOS系统,电磁循迹等功能

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

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

相关文章

ADS基础教程15 - 设计加密保护IP

设计加密保护IP 一、引言二、IP的生成与调用1.IP生成2.IP的调用 一、引言 介绍如何ADS中如何对设计好的原理图进行加密形成IP&#xff0c;然偶进行调用的过程。 二、IP的生成与调用 1.IP生成 (1)选择一个已经调试好的原理图&#xff0c;在菜单栏中选择Tools–>Encode De…

Aws CodeCommit代码仓储库

1 创建IAM用户 IAM创建admin用户&#xff0c;增加AWSCodeCommitFullAccess权限 2 创建存储库 CodePipeline -> CodeCommit -> 存储库 创建存储库 3 SSH 1) window环境 3.1.1 上载SSH公有秘钥 生成SSH秘钥ID 3.1.2 编辑本地 ~/.ssh 目录中名为“config”的 SSH 配置文…

从零学爬虫:使用比如说说解析网页结构

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言 二、网页结构概述 示例&#xff1a;查看网页结构 三、使用比如说说解析网页 1.…

ThingsBoard网关在燃气泄漏监测中的应用

据不完全统计&#xff0c;全国城市燃气企业的供销差率大约在3%~4%&#xff0c;也就意味着越多的天然气销量就有越多的天然气损失。城市燃气企业计量管理已经接近最不利的状态&#xff0c;开展有效的计量管理势在必行。 智慧燃气综合管理系统 在燃气管网中部署智能传感器、数据采…

2024年03月 Python(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,共50分) 第1题 在Python中,hex(2023)的功能是?( ) A:将十进制数2023转化成十六进制数 B:将十进制数2023转化成八进制数 C:将十六进制数2023转化成十进制数 D:将八进制数2023转化成十进制数 答案:A …

C语言 | Leetcode C语言题解之第116题填充每个节点的下一个右侧节点指针

题目&#xff1a; 题解&#xff1a; struct Node* connect(struct Node* root) {if (root NULL) {return root;}// 从根节点开始struct Node* leftmost root;while (leftmost->left ! NULL) {// 遍历这一层节点组织成的链表&#xff0c;为下一层的节点更新 next 指针stru…

【Linux-RTC】

Linux-RTC ■ rtc_device 结构体■ RTC 时间查看与设置■ 1、时间 RTC 查看■ 2、设置 RTC 时间 ■ rtc_device 结构体 Linux 内核将 RTC 设备抽象为 rtc_device 结构体 rtc_device 结构体&#xff0c;此结构体定义在 include/linux/rtc.h 文件中 ■ RTC 时间查看与设置 ■ 1…

超市信息管理系统(java+swing+jdbc+msyql)

商品管理模块 进货管理&#xff1a;记录进货信息&#xff0c;包括商品条码、价格设定、数量等。 库存管理&#xff1a;管理商品的库存情况&#xff0c;提供库存量查询和更新功能。 商品信息管理&#xff1a;商品的基本信息管理&#xff0c;如商品名、规格、生产厂商等。 销…

基于stm32和HC_SR04超声波模块的测距和报警

基于stm32和HC_SR04超声波模块的测距和报警 目录 **基于stm32和HC_SR04超声波模块的测距和报警****一.工作原理****二.功能实现****HC_SR04初始化和读取距离****使用呼吸灯表示距离远近****主函数编写** **三.效果****四.关于modbus和串口RS485****五.总结** 一.工作原理 (1)采…

设计模式 20 中介者模式 Mediator Pattern

设计模式 20 中介者模式 Mediator Pattern 1.定义 中介者模式&#xff08;Mediator Pattern&#xff09;是一种行为型设计模式&#xff0c;它通过封装对象之间的交互&#xff0c;促进对象之间的解耦合。中介者模式的核心思想是引入一个中介者对象&#xff0c;将系统中对象之间…

【IC】良率模型-yield model

缺陷密度Default Density&#xff08;D0&#xff09;&#xff0c;表示单位面积的缺陷数D。 单位面积有M个部件&#xff0c;一个部件的平均失效率为&#xff1a; 一个面积为A的系统&#xff08;芯片&#xff09;良率&#xff1a; Possion模型&#xff1a; 当M趋于无穷时&…

秋招突击——算法打卡——5/27——复习{寻找特定中位数}——新做:{最长回文字串、Z 字形变换}

文章目录 复习——寻找特定中位数新作——最长回文子串个人思路分析实现代码参考学习和上述思路相同&#xff0c;枚举中心点字符串哈希二分 新作——Z 字形变换个人做法思路分析实现代码 参考解法分析总结 复习——寻找特定中位数 第一次的链接&#xff1a;寻找中位数本来以为…

香橙派OrangePi AIpro上手初体验

一、前言 非常感谢能够收到CSDN和香橙派的OrangePi AIpro开发板评测活动的邀请&#xff1b;收到的OrangePi AIpro实物如下所示&#xff1a; 二、OrangePi AIpro介绍 通过查询香橙派官网可以了解到OrangePi AIpro的相关信息如下&#xff1a;OrangePi AIPro 开发板是香橙派联合…

浙江大学数据结构MOOC-课后习题-第七讲-图4 哈利·波特的考试

题目汇总 浙江大学数据结构MOOC-课后习题-拼题A-代码分享-2024 题目描述 代码展示 照着教程视频来的&#xff0c;没啥好说的捏 #include <cstdlib> #include <iostream>#define MAXSIZE 100 #define IFINITY 65535 typedef int vertex; typedef int weightType;/…

【StableDiffusion】SD1.4、1.5、2.0、2.1 和 SDXL0.9-1.0、SDXL turbo 等的区别

总览 1.基础sd base model家族&#xff1a;SD1.4、SD1.5、SD1.5-LCM、SD2.0、SD2.0-768、SD2.1、SD2.1-768、SD2.1-UNCLIP 2.升级sdxl base model家族&#xff1a;SDXL0.9、SDXL1.0、SDXL1.0-LCM、SDXL-DISTILLED、SDXL-TURBO 3.专门用于视频生成的 SVD 家族&#xff1a;SVD、…

洪师傅代驾系统开发 支持公众号H5小程序APP 后端Java源码

代驾流程图 业务流程图 管理端设置 1、首页装修 2、师傅奖励配置 师傅注册后,可享受后台设置的新师傅可得的额外奖励; 例:A注册了师傅,新人奖励可享受3天,第一天的第一笔订单完成后可得正常佣金佣金*奖励比例 完成第二笔/第三笔后依次可得正常佣金佣金*奖励比例 完成的第四…

城市空气质量数据爬取分析可视化

城市空气质量数据爬取分析可视化 一、效果展示二、完整代码2.1 数据爬取代码2.2 数据分析代码一、效果展示 先来看一下数据情况以及可视化效果,本项目使用了pyecharts绘制了日历图、雷达图、折线图、柱状图、饼图和平行坐标系。完整代码附后: 数据如下: 日历图: 饼图: …

Docker基础篇之常用命令

文章目录 1. 帮助启动类命令2. 镜像命令3. 容器命令4. 总结 1. 帮助启动类命令 启动docker&#xff1a; systemctl start docker停止docker&#xff1a; systemctl stop docker重启docker&#xff1a; systemctl restart docker查看docker 的运行状态&#xff1a; systemc…

ubuntu 22.04 appearance设置没有dock选项

1、问题描述 解决办法可以直接跳到后面见2 下图是我同学电脑的appearance界面选项&#xff0c;她有Dock的界面显示。 下面是我的界面&#xff0c; 没有Dock&#xff1a; 然后各种app的界面都在最底下&#xff0c;而且每次只能点击左上角的activities才能显示。 但是如果不打开某…

YoloV8实战:各种图绘制汇总(mAP50、mAP50-95、loss、PR_curve、F1_curve)|科研必备|绘图神器

摘要 本文的内容是告诉大家如何绘制mAP50、mAP50-95、loss、PR_curve、F1_curve等图像,方便大家写论文。 绘制mAP50、mAP50-95、loss等图。 先上效果,如下图: 首先将,训练的result.csv汇总到一个文件夹下面(这样方便寻找),要不然找起来太麻烦。如下图: 我都放到re…