基于STM32的甲醛检测

news2025/5/11 19:06:46

一、制作目标

        以正点原子的miniSTM32F103RCT6开发板为主控,使用甲醛传感器检测环境空气中的甲醛含量(以mg/m^3为单位)、C02含量(以ppm为单位)和总有机挥发物含量TVOC(以mg/m^3为单位)在OLED显示。

二、实物结果

三、元件清单

1、正点原子miniSTM32F103RCT6开发板

2、OLED屏

3、甲醛传感器(三合一VOC/CO2/甲醛气体传感器空气质量监测模块气敏检测模组)

https://item.taobao.com/item.htm?id=756709656786&pisk=grQLOnNOrR2hGd7ps6riqr1NfWPMvlfF_95jrLvnVOBOeshhx3vkVUBVH3guYexJyO9G-pfHRQt5EtsHdMvoyaBNp20kRT4JFsSaapAh-bd5f93lx6vhXbLFSM0kKJ8RNtY8n-40o65euUw0n3Kbdh8XMvgIE3g6fUARj6inG65ezLGiFoj1TbK6vFzBNLN95QdkNUtIPdi6QQmBFT9BfAOvgUT5F3M6fBAqPXTWOdN9GInSdUiIfVOvgYi5FUN95BJ6FUtCF1G7ukpuIKuR0j_AkZern43RWBKpe4vtylFkTHdh9dej1NU2vK1BB4wcj0Wyed7bIlCNEM6H_TUYBEsVBaKXyyH29G1v5pYbRVTh86sXVZwrV6TepF_CDbg56epBXwKEpRpf81_25h4bM1_NK67OZbaWstv1TwT8lS8pRpT9_a2ZRLI1VwxezvwJUNC1RgIynZbvORMc5snQ65nr4HOZBakipsJIIIR9n5Vi40-OpCp065nr4HOw6KVN30oyX9C..&spm=tbpc.boughtlist.suborder_itemtitle.1.67b12e8d0IqUS6

四、甲醛传感器技术参数

五、硬件接线

如图,OLED屏的SDA和SCL分别接PB7、PB6,甲醛传感器的+5引脚接开发板的5V、G引脚接GND、A引脚接单片机的PA9、B引脚接单片机的PA10。

六、工程建立过程

1、cubeMX配置

(1)系统和时钟配置

(2)OLED屏的硬件IIC通信配置

(3)串口及DMA配置

2、程序代码片段

(1)main函数中

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_I2C1_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	
	OLED_Init();
	OLED_Clear();
//	HAL_UART_Receive_IT(&huart1,rec_buf,9);//接收数据
	
	__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);    /* 开启串口空闲中断 */
  HAL_UART_Receive_DMA(&huart1, (uint8_t*)Uart1_RxBuff, UART_RX1_BUFFSIZE);   /* 开启DMA传输 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		
		if (Uart1Flag)
		{
			Uart1Flag = 0;
			TVOC=(Uart1_Data[2]*256+Uart1_Data[3])*0.001;
			CH2O=(Uart1_Data[4]*256+Uart1_Data[5])*0.001;
			CO2=(Uart1_Data[6]*256+Uart1_Data[7]);		
		}
	

		
		OLED_ShowCHinese(16, 0, 0);
    OLED_ShowCHinese(32, 0, 1);
    OLED_ShowCHinese(48, 0, 2);
		OLED_ShowCHinese(64, 0, 3);
		OLED_ShowCHinese(80, 0, 4);
		OLED_ShowCHinese(96, 0, 5);//甲醛检测系统
//		OLED_ShowString(8, 1, "CH2O Detect", 12);//OLED屏第一行显示烟雾检测字符串
		OLED_ShowString(0, 3, "CO2:    ppm", 12);//OLED屏第三行显示MQ2的ADC_Value采样值字符串
	  OLED_ShowNum(32, 3, CO2, 4, 12); //OLED屏第三行显示ADC采集值
		
		
		OLED_ShowString(0, 4, "TVOC:", 12);//OLED屏第四行显示MQ2的ADC_Volt采样电压字符串
		TVOC100=TVOC*100;//将采样电压扩大100倍		
		sprintf((char*)str_buff, "%d.%d%dmg/m^3",  TVOC100/100, (TVOC100%100/10),  TVOC100%10);//格式化输出扩大100倍的采样电压
    OLED_ShowString(40, 4,(uint8_t *)str_buff,12);//OLED屏第四行显示采集的电压值
	
		
		CH2O1000=CH2O*1000;  //将烟雾含量值扩大100倍		
		
		OLED_ShowString(0, 5, "CH2O:", 12);//OLED屏第五行显示烟雾字符串
	  sprintf((char*)str_buff, "%d.%d%d%dmg/m^3",  (CH2O1000/1000),(CH2O1000%1000/100),(CH2O1000%100/10),(CH2O1000%10));//格式化输出扩大100倍的烟雾浓度
    OLED_ShowString(40, 5,(uint8_t *)str_buff,12);//OLED屏第五行显示显示烟雾ppm浓度值


		HAL_Delay(500);//每隔500ms刷新一次数据显示
		

  }
  /* USER CODE END 3 */
}

(2)OLED.C(使用单片机的硬件IIC通信)

#include "oled.h"
#include "oledfont.h"

//OLED的显存
//存放格式如下.
//[0]0 1 2 3 ... 127	
//[1]0 1 2 3 ... 127	
//[2]0 1 2 3 ... 127	
//[3]0 1 2 3 ... 127	
//[4]0 1 2 3 ... 127	
//[5]0 1 2 3 ... 127	
//[6]0 1 2 3 ... 127	
//[7]0 1 2 3 ... 127 			   

/**
 * @brief	OLED写入命令
 * @param cmd - 待写入命令
 * @note	移植时,请使用自己的底层API实现 
*/
static void OLED_Write_Cmd(uint8_t cmd)
{
	uint8_t buf[2];
	buf[0] = 0x00;	//control byte
	buf[1] = cmd;
	
	//使用HAL库的API实现
	HAL_I2C_Master_Transmit(&hi2c1, 0x78, buf, 2, 0xFFFF);
}
/**
 * @brief	OLED写入数据
 * @param cmd - 待写入数据
 * @note	移植时,请使用自己的底层API实现 
*/
static void OLED_Write_Dat(uint8_t dat)
{
	uint8_t buf[2];
	buf[0] = 0x40; //control byte
	buf[1] = dat;
	
	//使用HAL库的API实现
	HAL_I2C_Master_Transmit(&hi2c1, 0x78, buf, 2, 0xFFFF);
}

/**
 * @brief	OLED设置显示位置
 * @param x - X方向位置
 * @param y - Y方向位置
*/
void OLED_Set_Pos(uint8_t x, uint8_t y)
{ 	
	OLED_Write_Cmd(0xb0+y);
	OLED_Write_Cmd(((x&0xf0)>>4)|0x10);
	OLED_Write_Cmd((x&0x0f)|0x01);
}   	  
/**
 * @brief	OLED开启显示
*/ 
void OLED_Display_On(void)
{
	OLED_Write_Cmd(0X8D);  //SET DCDC命令
	OLED_Write_Cmd(0X14);  //DCDC ON
	OLED_Write_Cmd(0XAF);  //DISPLAY ON
}
/**
 * @brief	OLED关闭显示
*/   
void OLED_Display_Off(void)
{
	OLED_Write_Cmd(0X8D);  //SET DCDC命令
	OLED_Write_Cmd(0X10);  //DCDC OFF
	OLED_Write_Cmd(0XAE);  //DISPLAY OFF
}		   			 
/**
 * @brief	OLED清屏函数(清屏之后屏幕全为黑色)
*/ 
void OLED_Clear(void)
{  
	uint8_t i,n;		    
	for(i=0;i<8;i++)  
	{  
		OLED_Write_Cmd(0xb0+i);    //设置页地址(0~7)
		OLED_Write_Cmd(0x00);      //设置显示位置—列低地址
		OLED_Write_Cmd(0x10);      //设置显示位置—列高地址   
		for(n=0;n<128;n++)
		{
			OLED_Write_Dat(0);
		}			
	}
}
/**
 * @brief	OLED显示全开(所有像素点全亮)
*/
void OLED_On(void)
{  
	uint8_t i,n;
	for(i=0;i<8;i++)
	{  
		OLED_Write_Cmd(0xb0+i);    //设置页地址(0~7)
		OLED_Write_Cmd(0x00);      //设置显示位置—列低地址
		OLED_Write_Cmd(0x10);      //设置显示位置—列高地址   
		for(n=0;n<128;n++)
		{
			OLED_Write_Dat(1);
		}			
	}
}
/**
 * @brief	在指定位置显示一个ASCII字符
 * @param x - 0 - 127
 * @param y - 0 - 7
 * @param chr  - 待显示的ASCII字符
 * @param size - ASCII字符大小
 * 				字符大小有12(6*8)/16(8*16)两种大小
*/
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t size)
{   
	uint8_t c=0,i=0;
	
	c = chr-' ';	
	if(x > 128-1)
	{
		x=0;
		y++;
	}
	
	if(size ==16)
	{
		OLED_Set_Pos(x,y);	
		for(i=0;i<8;i++)
		{
			OLED_Write_Dat(F8X16[c*16+i]);
		}
		OLED_Set_Pos(x,y+1);
		for(i=0;i<8;i++)
		{
			OLED_Write_Dat(F8X16[c*16+i+8]);
		}
	}
	else
	{	
		OLED_Set_Pos(x,y);
		for(i=0;i<6;i++)
		{
			OLED_Write_Dat(F6x8[c][i]);
		}
	}
}
/**
 * @brief	OLED 专用pow函数
 * @param m - 底数
 * @param n - 指数
*/
static uint32_t oled_pow(uint8_t m,uint8_t n)
{
	uint32_t result=1;	 
	while(n--)result*=m;    
	return result;
}	
/**
 * @brief	在指定位置显示一个整数
 * @param x - 0 - 127
 * @param y - 0 - 7
 * @param num - 待显示的整数(0-4294967295)
 * @param	len - 数字的位数 
 * @param size - ASCII字符大小
 * 				字符大小有12(6*8)/16(8*16)两种大小
*/
void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size)
{         	
	uint8_t t,temp;
	uint8_t enshow=0;						   
	for(t=0;t<len;t++)
	{
		temp=(num/oled_pow(10,len-t-1))%10;
		if(enshow==0&&t<(len-1))
		{
			if(temp==0)
			{
				OLED_ShowChar(x+(size/2)*t,y,' ',size);
				continue;
			}else enshow=1; 
		 	 
		}
	 	OLED_ShowChar(x+(size/2)*t,y,temp+'0',size); 
	}
} 
/**
 * @brief	在指定位置显示一个字符串
 * @param x - 0 - 127
 * @param y - 0 - 7
 * @param chr - 待显示的字符串指针
 * @param size - ASCII字符大小
 * 				字符大小有12(6*8)/16(8*16)两种大小
*/
void OLED_ShowString(uint8_t x,uint8_t y,char *chr,uint8_t size)
{
	uint8_t j=0;
	while (chr[j]!='\0')
	{		OLED_ShowChar(x,y,chr[j],size);
			x+=8;
			if(x>120){x=0;y+=2;}
			j++;
	}
}
/**
 * @brief	在指定位置显示一个汉字
 * @param x  - 0 - 127
 * @param y  - 0 - 7
 * @param no - 汉字在中文字库数组中的索引(下标)
 * @note	中文字库在oledfont.h文件中的Hzk数组中,需要提前使用软件对汉字取模
*/
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no)
{      			    
	uint8_t t,adder=0;
	OLED_Set_Pos(x,y);	
    for(t=0;t<16;t++)
		{
				OLED_Write_Dat(Hzk[2*no][t]);
				adder+=1;
     }	
		OLED_Set_Pos(x,y+1);	
    for(t=0;t<16;t++)
			{	
				OLED_Write_Dat(Hzk[2*no+1][t]);
				adder+=1;
      }					
}
/**
 * @brief	在指定位置显示一幅图片
 * @param x1,x2  - 0 - 127
 * @param y1,y2  - 0 - 7(8表示全屏显示)
 * @param BMP - 图片数组地址
 * @note	图像数组BMP存放在bmp.h文件中
*/
void OLED_DrawBMP(uint8_t x0, uint8_t y0,uint8_t x1, uint8_t y1,uint8_t BMP[])
{ 	
 uint16_t j=0;
 uint8_t x,y;
  
  if(y1%8==0)
	{
		y=y1/8;
	}		
  else
	{
		y=y1/8+1;
	}
	for(y=y0;y<y1;y++)
	{
		OLED_Set_Pos(x0,y);
    for(x=x0;x<x1;x++)
	  {      
	    	OLED_Write_Dat(BMP[j++]);	    	
	  }
	}
} 

/**
 * @brief	OLED初始化
*/			    
void OLED_Init(void)
{ 	

	HAL_Delay(500);

	OLED_Write_Cmd(0xAE);//--display off
	OLED_Write_Cmd(0x00);//---set low column address
	OLED_Write_Cmd(0x10);//---set high column address
	OLED_Write_Cmd(0x40);//--set start line address  
	OLED_Write_Cmd(0x81); // contract control
	OLED_Write_Cmd(0xFF);//--128   
	OLED_Write_Cmd(0xA1);//set segment remap 
	OLED_Write_Cmd(0xC8);//Com scan direction
	OLED_Write_Cmd(0xA6);//--normal / reverse
	OLED_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
	OLED_Write_Cmd(0x3F);//--1/32 duty
	OLED_Write_Cmd(0xD3);//-set display offset
	OLED_Write_Cmd(0x00);//
	OLED_Write_Cmd(0xD5);//set osc division
	OLED_Write_Cmd(0x80);
	OLED_Write_Cmd(0xD9);//Set Pre-Charge Period
	OLED_Write_Cmd(0xF1);//
	OLED_Write_Cmd(0xDA);//set com pin configuartion
	OLED_Write_Cmd(0x12);//
	OLED_Write_Cmd(0xDB);//set Vcomh
	OLED_Write_Cmd(0x40);//
	OLED_Write_Cmd(0x20);
	OLED_Write_Cmd(0x02);
	OLED_Write_Cmd(0x8D);//set charge pump enable
	OLED_Write_Cmd(0x14);//
	OLED_Write_Cmd(0xA4);
	OLED_Write_Cmd(0xA6);
	OLED_Write_Cmd(0xAF);//--turn on oled panel
	
	OLED_Clear();
	OLED_Set_Pos(0,0);
}

(3)串口空闲中断+DMA读取甲醛传感器的数据

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
	  if (RESET != __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)) // 判断是否是空闲中断
    {
        __HAL_UART_CLEAR_IDLEFLAG(&huart1);                                     // 清除空闲中断标志
        HAL_UART_DMAStop(&huart1);                                              // 停止本次DMA传输
        uartCnt = UART_RX1_BUFFSIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx); // 计算接收到的数据长度
        memcpy(Uart1_Data, Uart1_RxBuff, uartCnt);
        Uart1Flag = 1;
        HAL_UART_Receive_DMA(&huart1, (uint8_t *)Uart1_RxBuff, UART_RX1_BUFFSIZE); // 重启开始DMA传输
    }

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

七、程序源码工程下载链接

https://download.csdn.net/download/jacklood/90804813

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

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

相关文章

洛图报告中的 FSHD 是什么?—— 解密九天画芯推动的三色光源显示技术

目录 一、洛图报告新焦点&#xff1a;FSHD 为何成为显示产业重要突破方向&#xff1f; &#xff08;一&#xff09;洛图报告核心结论&#xff1a;从技术突围到产业重构 二、技术解析&#xff1a;FSHD 如何重构显示底层逻辑&#xff1f; &#xff08;一&#xff09;物理架构…

【MySQL】事务(重点)

目录 一、什么是事务&#xff1a; 二、事务的前置知识了解 引擎是否支持事务 事务的提交方式 事务操作的前置准备&#xff1a; 三、事务回滚&#xff1a; 四、事务崩溃&#xff1a; 原子性&#xff1a; 持久性&#xff1a; 五、自动提交和手动提交&#xff1a; 六、…

Linux:线程同步与互斥

目录 线程互斥 锁 初始化 销毁 加锁 解锁 线程同步 条件变量 初始化 销毁 等待条件满足 唤醒等待 pthread_cond_signal pthread_cond_broadcast 生产者消费者模型 3种关系 2种角色 1个交易场所 POSIX信号量 初始化 销毁 等待 发布 线程互斥 互斥相关…

每天五分钟机器学习:拉格朗日对偶函数

本文重点 在数学优化领域,拉格朗日对偶函数作为连接原始约束问题与对偶问题的核心纽带,展现了将复杂约束优化转化为无约束优化的方式。 数学表达 原始问题建模 拉格朗日函数构造 此时的目标就是: 先假设w为常数,让拉格朗日函数对橙子变量λ求极大值,消掉λ之后,在对λ求…

AutoGen 框架解析:微软开源的多人 Agent 协作新范式

一、引言 在大语言模型&#xff08;LLM&#xff09;快速发展的今天&#xff0c;复杂任务的自动化协作需求日益增长。微软开源的AutoGen 框架&#xff08;GitHub Star 超 10 万&#xff09;提供了一种基于多智能体对话的协作范式&#xff0c;通过自然语言交互实现多角色 Agent …

【bibtex4word】在Word中高效转换bib参考文献,Texlive环境安装bibtex4word插件

前言 现已退出科研界&#xff0c;本人水货一个。希望帮到有缘人 本篇关于如何将latex环境中的参考文献bib文件转化为word&#xff0c;和一些踩坑记录。 可以看下面的资料进行配置&#xff0c;后面的文字是这些资料的补充说明。 参考文章&#xff1a;https://blog.csdn.net/g…

单片机-STM32部分:10-2、逻辑分析仪

飞书文档https://x509p6c8to.feishu.cn/wiki/VrdkwVzOnifH8xktu3Bcuc4Enie 安装包如下&#xff1a;根据自己的系统选择&#xff0c;目前这个工具只有window版本哦 安装方法比较简单&#xff0c;都按默认下一步即可&#xff0c;注意不要安装到中文路径哦。 其余部分参考飞书文档…

计算机网络基础科普

IP地址是计算机网络中标识设备的唯一地址 IPv4&#xff08;32位&#xff09;IPv6&#xff08;128位&#xff09; 1.IPv4&#xff08;32位&#xff09; 简介&#xff1a;IPv4&#xff08;Internet Protocol version 4&#xff09;是互联网协议&#xff08;IP&#xff09;的…

阿里云CDN的源站配置:权重的详解

在阿里云CDN中为静态资源域名cdn.example.com配置源站时&#xff0c;权重设置需根据实际架构和目标灵活调整。以下是具体建议和配置步骤&#xff1a; 一、权重的核心作用 在阿里云CDN中&#xff0c;源站权重用于控制多个源站之间的流量分配比例&#xff0c;适用于以下场景&…

虚幻引擎5-Unreal Engine笔记之显卡环境设置使开发流畅

虚幻引擎5-Unreal Engine笔记之显卡环境设置使开发流畅 code review! 文章目录 虚幻引擎5-Unreal Engine笔记之显卡环境设置使开发流畅1.电源管理2.显卡优先设置3.拯救者支持FnQ性能模式切换&#xff0c;建议开发前切至“野兽模式”或高性能模式。4.NVIDIA 驱动设置5.VS2022中…

【Linux】冯诺依曼体系结构和操作系统的理解

目录 冯诺依曼体系结构一个例子来深入理解 初识操作系统操作系统的作用设计操作系统的目的操作系统之上和之下分别有啥 管理的精髓&#xff0c;先描述&#xff0c;再组织 冯诺依曼体系结构 我们知道&#xff0c;计算机这个东西发明出来就是帮助人们快速解决问题的。那如果我们想…

计网学习笔记———网络

&#x1f33f;网络是泛化的概念 网络是泛化的概念 &#x1f342;泛化理解 网络的概念在生活中无处不在举例&#xff1a;社交网络、电话网路、电网、计算机网络 &#x1f33f;网络的定义 定义&#xff1a; 离散的个体通过通讯手段连成群体&#xff0c;实现资源的共享与交流、个…

数据集-目标检测系列- 烟雾 检测数据集 smoke >> DataBall

数据集-目标检测系列- 消防 浓烟 检测数据集 smoke>> DataBall 数据集-目标检测系列- 烟雾 检测数据集 smoke &#xff1e;&#xff1e; DataBall * 相关项目 1&#xff09;数据集可视化项目&#xff1a;gitcode: https://gitcode.com/DataBall/DataBall-detections-10…

【单片机毕业设计15-基于stm32c8t6的智能酒窖系统设计】

【单片机毕业设计15-基于stm32c8t6的智能酒窖系统设计】 前言一、功能介绍二、硬件部分三、软件部分总结 前言 &#x1f525;这里是小殷学长&#xff0c;单片机毕业设计篇15-基于stm32c8t6的智能酒窖系统设计 &#x1f9ff;创作不易&#xff0c;拒绝白嫖可私 一、功能介绍 ----…

【Bluedroid】蓝牙 HID 设备服务注册流程源码解析:从初始化到 SDP 记录构建

本文围绕蓝牙 HID&#xff08;人机接口设备&#xff09;服务注册流程&#xff0c;详细解析从 HID 服务启用、设备初始化、L2CAP 通道注册到 SDP&#xff08;服务发现协议&#xff09;记录构建的全流程。通过分析关键函数如btif_hd_service_registration、BTA_HdEnable、HID_Dev…

TWAS、GWAS、FUSION

全基因组关联研究&#xff08;GWAS&#xff0c;Genome-Wide Association Study&#xff09;是一种统计学方法&#xff0c;用于在全基因组水平上识别与特定性状或疾病相关的遗传变异。虽然GWAS可以识别与性状相关的遗传信号&#xff0c;但它并不直接揭示这些遗传变异如何影响生物…

测试一下多模态提取图片中文字的能力

测试一下多模态提取图片中文字的能力 原图片&#xff0c; 提取结果&#xff0c; 各位嘉宾&#xff0c;大家好&#xff01;明天&#xff08;5月11日&#xff09;9:00-12:00将在大连市高新园区星火亚庭32号A座一层二楼设置咖啡厅等六个小水活动。请大家积极安排时间&#xff0c;…

(51单片机)LCD显示红外遥控相关数字(Delay延时函数)(LCD1602教程)(Int0和Timer0外部中断教程)(IR红外遥控模块教程)

前言&#xff1a; 本次Timer0模块改装了一下&#xff0c;注意&#xff01;&#xff01;&#xff01;今天只是简单的实现一下&#xff0c;明天用次功能显示遥控密码锁 演示视频&#xff1a; 在审核 源代码&#xff1a; 如上图将9个文放在Keli5 中即可&#xff0c;然后烧录在…

物品识别 树莓派4 YOLO v11

让树莓派可以识别身边的一些物品 python3 -m venv --system-site-packages yolooo source yolooo/bin/activate 树莓派换清华源&#xff0c;bookworm 下面这条命令将安装 OpenCV 以及运行 YOLO 所需的基础设施 pip install ultralytics 还会安装大量其他软件包&#xff0c…

【计算机视觉】3DDFA_V2中表情与姿态解耦及多任务平衡机制深度解析

3DDFA_V2中表情与姿态解耦及多任务平衡机制深度解析 1. 表情与姿态解耦的技术实现1.1 参数化建模基础1.2 解耦的核心机制1.2.1 基向量正交化设计1.2.2 网络架构设计1.2.3 损失函数设计 1.3 实现代码解析 2. 多任务联合学习的权重平衡2.1 任务定义与损失函数2.2 动态权重平衡策略…